[Rt-commit] rt branch, 4.0/apply-scrips-to-multiple-queues, created. rt-4.0.4-118-g01a7fc4

Ruslan Zakirov ruz at bestpractical.com
Mon Dec 12 11:29:30 EST 2011


The branch, 4.0/apply-scrips-to-multiple-queues has been created
        at  01a7fc4ca83b77aa23b48906660e345571cc7a7b (commit)

- Log -----------------------------------------------------------------
commit 01a7fc4ca83b77aa23b48906660e345571cc7a7b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Dec 12 19:05:31 2011 +0400

    extract re-usable code from ObjectCustomField[s]
    
    Two new classes for records and collections

diff --git a/lib/RT/ObjectCustomField.pm b/lib/RT/ObjectCustomField.pm
index 45286ed..f2d47a7 100644
--- a/lib/RT/ObjectCustomField.pm
+++ b/lib/RT/ObjectCustomField.pm
@@ -45,93 +45,23 @@
 # those contributions and any derivatives thereof.
 #
 # END BPS TAGGED BLOCK }}}
-
-package RT::ObjectCustomField;
-
 use strict;
 use warnings;
 
+package RT::ObjectCustomField;
+use base 'RT::Record::ApplyAndSort';
 
 use RT::CustomField;
-use base 'RT::Record';
+use RT::ObjectCustomFields;
 
 sub Table {'ObjectCustomFields'}
 
-
-
-
-
-
-sub Create {
-    my $self = shift;
-    my %args = (
-        CustomField => 0,
-        ObjectId    => 0,
-        SortOrder   => undef,
-        @_
-    );
-
-    my $cf = $self->CustomFieldObj( $args{'CustomField'} );
-    unless ( $cf->id ) {
-        $RT::Logger->error("Couldn't load '$args{'CustomField'}' custom field");
-        return 0;
-    }
-
-    #XXX: Where is ACL check for 'AssignCustomFields'?
-
-    my $ObjectCFs = RT::ObjectCustomFields->new($self->CurrentUser);
-    $ObjectCFs->LimitToObjectId( $args{'ObjectId'} );
-    $ObjectCFs->LimitToCustomField( $cf->id );
-    $ObjectCFs->LimitToLookupType( $cf->LookupType );
-    if ( my $first = $ObjectCFs->First ) {
-        $self->Load( $first->id );
-        return $first->id;
-    }
-
-    unless ( defined $args{'SortOrder'} ) {
-        my $ObjectCFs = RT::ObjectCustomFields->new( RT->SystemUser );
-        $ObjectCFs->LimitToObjectId( $args{'ObjectId'} );
-        $ObjectCFs->LimitToObjectId( 0 ) if $args{'ObjectId'};
-        $ObjectCFs->LimitToLookupType( $cf->LookupType );
-        $ObjectCFs->OrderBy( FIELD => 'SortOrder', ORDER => 'DESC' );
-        if ( my $first = $ObjectCFs->First ) {
-            $args{'SortOrder'} = $first->SortOrder + 1;
-        } else {
-            $args{'SortOrder'} = 0;
-        }
-    }
-
-    return $self->SUPER::Create(
-        CustomField => $args{'CustomField'},
-        ObjectId    => $args{'ObjectId'},
-        SortOrder   => $args{'SortOrder'},
-    );
-}
-
-sub Delete {
-    my $self = shift;
-
-    my $ObjectCFs = RT::ObjectCustomFields->new($self->CurrentUser);
-    $ObjectCFs->LimitToObjectId($self->ObjectId);
-    $ObjectCFs->LimitToLookupType($self->CustomFieldObj->LookupType);
-
-    # Move everything below us up
-    my $sort_order = $self->SortOrder;
-    while (my $OCF = $ObjectCFs->Next) {
-        my $this_order = $OCF->SortOrder;
-        next if $this_order <= $sort_order; 
-        $OCF->SetSortOrder($this_order - 1);
-    }
-
-    $self->SUPER::Delete;
-}
-
+# XXX: Where is ACL check when we create a record?
 
 =head2 CustomFieldObj
 
 Returns the CustomField Object which has the id returned by CustomField
 
-
 =cut
 
 sub CustomFieldObj {
@@ -142,148 +72,17 @@ sub CustomFieldObj {
     return $CF;
 }
 
-=head2 Sorting custom fields applications
-
-Custom fields sorted on multiple layers. First of all custom
-fields with different lookup type are sorted independently. All
-global custom fields have fixed order for all objects, but you
-can insert object specific custom fields between them. Object
-specific custom fields can be applied to several objects and
-be on different place. For example you have GCF1, GCF2, LCF1,
-LCF2 and LCF3 that applies to tickets. You can place GCF2
-above GCF1, but they will be in the same order in all queues.
-However, LCF1 and other local can be placed at any place
-for particular queue: above global, between them or below.
-
-=head3 MoveUp
-
-Moves custom field up. See </Sorting custom fields applications>.
-
-=cut
-
-sub MoveUp {
+sub Neighbors {
     my $self = shift;
+    my %args = @_;
 
-    my $ocfs = RT::ObjectCustomFields->new( $self->CurrentUser );
-
-    my $oid = $self->ObjectId;
-    $ocfs->LimitToObjectId( $oid );
-    if ( $oid ) {
-        $ocfs->LimitToObjectId( 0 );
-    }
-
-    my $cf = $self->CustomFieldObj;
-    $ocfs->LimitToLookupType( $cf->LookupType );
-
-    $ocfs->Limit( FIELD => 'SortOrder', OPERATOR => '<', VALUE => $self->SortOrder );
-    $ocfs->OrderByCols( { FIELD => 'SortOrder', ORDER => 'DESC' } );
-
-    my @above = ($ocfs->Next, $ocfs->Next);
-    unless ($above[0]) {
-        return (0, "Can not move up. It's already at the top");
-    }
-
-    my $new_sort_order;
-    if ( $above[0]->ObjectId == $self->ObjectId ) {
-        $new_sort_order = $above[0]->SortOrder;
-        my ($status, $msg) = $above[0]->SetSortOrder( $self->SortOrder );
-        unless ( $status ) {
-            return (0, "Couldn't move custom field");
-        }
-    }
-    elsif ( $above[1] && $above[0]->SortOrder == $above[1]->SortOrder + 1 ) {
-        my $move_ocfs = RT::ObjectCustomFields->new( RT->SystemUser );
-        $move_ocfs->LimitToLookupType( $cf->LookupType );
-        $move_ocfs->Limit(
-            FIELD => 'SortOrder',
-            OPERATOR => '>=',
-            VALUE => $above[0]->SortOrder,
-        );
-        $move_ocfs->OrderByCols( { FIELD => 'SortOrder', ORDER => 'DESC' } );
-        while ( my $record = $move_ocfs->Next ) {
-            my ($status, $msg) = $record->SetSortOrder( $record->SortOrder + 1 );
-            unless ( $status ) {
-                return (0, "Couldn't move custom field");
-            }
-        }
-        $new_sort_order = $above[0]->SortOrder;
-    } else {
-        $new_sort_order = $above[0]->SortOrder - 1;
-    }
-
-    my ($status, $msg) = $self->SetSortOrder( $new_sort_order );
-    unless ( $status ) {
-        return (0, "Couldn't move custom field");
-    }
-
-    return (1,"Moved custom field up");
-}
-
-=head3 MoveDown
-
-Moves custom field down. See </Sorting custom fields applications>.
-
-=cut
-
-sub MoveDown {
-    my $self = shift;
-
-    my $ocfs = RT::ObjectCustomFields->new( $self->CurrentUser );
-
-    my $oid = $self->ObjectId;
-    $ocfs->LimitToObjectId( $oid );
-    if ( $oid ) {
-        $ocfs->LimitToObjectId( 0 );
-    }
-
-    my $cf = $self->CustomFieldObj;
-    $ocfs->LimitToLookupType( $cf->LookupType );
-
-    $ocfs->Limit( FIELD => 'SortOrder', OPERATOR => '>', VALUE => $self->SortOrder );
-    $ocfs->OrderByCols( { FIELD => 'SortOrder', ORDER => 'ASC' } );
-
-    my @below = ($ocfs->Next, $ocfs->Next);
-    unless ($below[0]) {
-        return (0, "Can not move down. It's already at the bottom");
-    }
-
-    my $new_sort_order;
-    if ( $below[0]->ObjectId == $self->ObjectId ) {
-        $new_sort_order = $below[0]->SortOrder;
-        my ($status, $msg) = $below[0]->SetSortOrder( $self->SortOrder );
-        unless ( $status ) {
-            return (0, "Couldn't move custom field");
-        }
-    }
-    elsif ( $below[1] && $below[0]->SortOrder + 1 == $below[1]->SortOrder ) {
-        my $move_ocfs = RT::ObjectCustomFields->new( RT->SystemUser );
-        $move_ocfs->LimitToLookupType( $cf->LookupType );
-        $move_ocfs->Limit(
-            FIELD => 'SortOrder',
-            OPERATOR => '<=',
-            VALUE => $below[0]->SortOrder,
-        );
-        $move_ocfs->OrderByCols( { FIELD => 'SortOrder', ORDER => 'ASC' } );
-        while ( my $record = $move_ocfs->Next ) {
-            my ($status, $msg) = $record->SetSortOrder( $record->SortOrder - 1 );
-            unless ( $status ) {
-                return (0, "Couldn't move custom field");
-            }
-        }
-        $new_sort_order = $below[0]->SortOrder;
-    } else {
-        $new_sort_order = $below[0]->SortOrder + 1;
-    }
-
-    my ($status, $msg) = $self->SetSortOrder( $new_sort_order );
-    unless ( $status ) {
-        return (0, "Couldn't move custom field");
-    }
-
-    return (1,"Moved custom field down");
+    my $res = $self->CollectionClass->new( $self->CurrentUser );
+    $res->LimitToLookupType(
+        ($args{'CustomField'} || $self->CustomFieldObj)->LookupType
+    );
+    return $res;
 }
 
-
 =head2 id
 
 Returns the current value of id.
diff --git a/lib/RT/ObjectCustomFields.pm b/lib/RT/ObjectCustomFields.pm
index fa2a69e..bdb6511 100644
--- a/lib/RT/ObjectCustomFields.pm
+++ b/lib/RT/ObjectCustomFields.pm
@@ -45,48 +45,23 @@
 # those contributions and any derivatives thereof.
 #
 # END BPS TAGGED BLOCK }}}
-
-package RT::ObjectCustomFields;
-
 use strict;
 use warnings;
 
+package RT::ObjectCustomFields;
+use base 'RT::SearchBuilder::ApplyAndSort';
 
+use RT::CustomField;
 use RT::ObjectCustomField;
 
-use base 'RT::SearchBuilder';
-
 sub Table { 'ObjectCustomFields'}
 
-sub _Init {
-    my $self = shift;
-
-  # By default, order by SortOrder
-  $self->OrderByCols(
-	 { ALIAS => 'main',
-	   FIELD => 'SortOrder',
-	   ORDER => 'ASC' },
-	 { ALIAS => 'main',
-	   FIELD => 'id',
-	   ORDER => 'ASC' },
-     );
-
-    return ( $self->SUPER::_Init(@_) );
-}
-
-
 sub LimitToCustomField {
     my $self = shift;
     my $id = shift;
     $self->Limit( FIELD => 'CustomField', VALUE => $id );
 }
 
-sub LimitToObjectId {
-    my $self = shift;
-    my $id = shift || 0;
-    $self->Limit( FIELD => 'ObjectId', VALUE => $id );
-}
-
 sub LimitToLookupType {
     my $self = shift;
     my $lookup = shift;
@@ -139,17 +114,6 @@ sub _DoSearch {
     $self->SUPER::_DoSearch()
 }
 
-
-=head2 NewItem
-
-Returns an empty new RT::ObjectCustomField item
-
-=cut
-
-sub NewItem {
-    my $self = shift;
-    return(RT::ObjectCustomField->new($self->CurrentUser));
-}
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/lib/RT/Record/ApplyAndSort.pm b/lib/RT/Record/ApplyAndSort.pm
new file mode 100644
index 0000000..943417c
--- /dev/null
+++ b/lib/RT/Record/ApplyAndSort.pm
@@ -0,0 +1,227 @@
+use strict;
+use warnings;
+
+package RT::Record::ApplyAndSort;
+use base 'RT::Record';
+
+sub CollectionClass {
+    return (ref($_[0]) || $_[0]).'s';
+}
+
+sub TargetField {
+    my $class = ref($_[0]) || $_[0];
+    $class =~ s/.*::Object// or return undef;
+    return $class;
+}
+
+sub Create {
+    my $self = shift;
+    my %args = (
+        Scrip       => 0,
+        ObjectId    => 0,
+        SortOrder   => undef,
+        @_
+    );
+
+    my $tfield = $self->TargetField;
+
+    my $target = $self->TargetObj( $args{ $tfield } );
+    unless ( $target->id ) {
+        $RT::Logger->error("Couldn't load ". ref($target) ." '$args{'Scrip'}'");
+        return 0;
+    }
+
+    my $exist = $self->new($self->CurrentUser);
+    $exist->LoadByCols( ObjectId => $args{'ObjectId'}, $tfield => $target->id );
+    if ( $exist->id ) {
+        $self->Load( $exist->id );
+        return $self->id;
+    }
+
+    unless ( defined $args{'SortOrder'} ) {
+        $args{'SortOrder'} = $self->NextSortOrder(
+            $tfield  => $target,
+            ObjectId => $args{'ObjectId'},
+        );
+    }
+
+    return $self->SUPER::Create(
+        $tfield   => $target->id,
+        ObjectId  => $args{'ObjectId'},
+        SortOrder => $args{'SortOrder'},
+    );
+}
+
+sub Delete {
+    my $self = shift;
+
+    my $siblings = $self->Neighbors;
+    $siblings->LimitToObjectId( $self->ObjectId );
+    $siblings->Limit( FIELD => 'SortOrder', OPERATOR => '>', VALUE => $self->SortOrder );
+
+    # Move everything below us up
+    my $sort_order = $self->SortOrder;
+    while (my $record = $siblings->Next) {
+        $record->SetSortOrder($record->SortOrder - 1);
+    }
+
+    $self->SUPER::Delete;
+}
+
+=head2 Sorting scrips applications
+
+scrips sorted on multiple layers. First of all custom
+fields with different lookup type are sorted independently. All
+global scrips have fixed order for all objects, but you
+can insert object specific scrips between them. Object
+specific scrips can be applied to several objects and
+be on different place. For example you have GCF1, GCF2, LCF1,
+LCF2 and LCF3 that applies to tickets. You can place GCF2
+above GCF1, but they will be in the same order in all queues.
+However, LCF1 and other local can be placed at any place
+for particular queue: above global, between them or below.
+
+=head3 MoveUp
+
+Moves scrip up. See </Sorting scrips applications>.
+
+=cut
+
+sub MoveUp {
+    my $self = shift;
+
+    my $siblings = $self->Siblings;
+    $siblings->Limit( FIELD => 'SortOrder', OPERATOR => '<', VALUE => $self->SortOrder );
+    $siblings->OrderByCols( { FIELD => 'SortOrder', ORDER => 'DESC' } );
+
+    my @above = ($siblings->Next, $siblings->Next);
+    unless ($above[0]) {
+        return (0, "Can not move up. It's already at the top");
+    }
+
+    my $new_sort_order;
+    if ( $above[0]->ObjectId == $self->ObjectId ) {
+        $new_sort_order = $above[0]->SortOrder;
+        my ($status, $msg) = $above[0]->SetSortOrder( $self->SortOrder );
+        unless ( $status ) {
+            return (0, "Couldn't move scrip");
+        }
+    }
+    elsif ( $above[1] && $above[0]->SortOrder == $above[1]->SortOrder + 1 ) {
+        my $move_siblings = $self->Neighbors;
+        $move_siblings->Limit(
+            FIELD => 'SortOrder',
+            OPERATOR => '>=',
+            VALUE => $above[0]->SortOrder,
+        );
+        $move_siblings->OrderByCols( { FIELD => 'SortOrder', ORDER => 'DESC' } );
+        while ( my $record = $move_siblings->Next ) {
+            my ($status, $msg) = $record->SetSortOrder( $record->SortOrder + 1 );
+            unless ( $status ) {
+                return (0, "Couldn't move scrip");
+            }
+        }
+        $new_sort_order = $above[0]->SortOrder;
+    } else {
+        $new_sort_order = $above[0]->SortOrder - 1;
+    }
+
+    my ($status, $msg) = $self->SetSortOrder( $new_sort_order );
+    unless ( $status ) {
+        return (0, "Couldn't move scrip");
+    }
+
+    return (1,"Moved scrip up");
+}
+
+=head3 MoveDown
+
+Moves scrip down. See </Sorting scrips applications>.
+
+=cut
+
+sub MoveDown {
+    my $self = shift;
+
+    my $siblings = $self->Siblings;
+    $siblings->Limit( FIELD => 'SortOrder', OPERATOR => '>', VALUE => $self->SortOrder );
+    $siblings->OrderByCols( { FIELD => 'SortOrder', ORDER => 'ASC' } );
+
+    my @below = ($siblings->Next, $siblings->Next);
+    unless ($below[0]) {
+        return (0, "Can not move down. It's already at the bottom");
+    }
+
+    my $new_sort_order;
+    if ( $below[0]->ObjectId == $self->ObjectId ) {
+        $new_sort_order = $below[0]->SortOrder;
+        my ($status, $msg) = $below[0]->SetSortOrder( $self->SortOrder );
+        unless ( $status ) {
+            return (0, "Couldn't move scrip");
+        }
+    }
+    elsif ( $below[1] && $below[0]->SortOrder + 1 == $below[1]->SortOrder ) {
+        my $move_siblings = $self->Neighbors;
+        $move_siblings->Limit(
+            FIELD => 'SortOrder',
+            OPERATOR => '<=',
+            VALUE => $below[0]->SortOrder,
+        );
+        $move_siblings->OrderByCols( { FIELD => 'SortOrder', ORDER => 'ASC' } );
+        while ( my $record = $move_siblings->Next ) {
+            my ($status, $msg) = $record->SetSortOrder( $record->SortOrder - 1 );
+            unless ( $status ) {
+                return (0, "Couldn't move scrip");
+            }
+        }
+        $new_sort_order = $below[0]->SortOrder;
+    } else {
+        $new_sort_order = $below[0]->SortOrder + 1;
+    }
+
+    my ($status, $msg) = $self->SetSortOrder( $new_sort_order );
+    unless ( $status ) {
+        return (0, "Couldn't move scrip");
+    }
+
+    return (1,"Moved scrip down");
+}
+
+sub NextSortOrder {
+    my $self = shift;
+    my $siblings = $self->Siblings( @_ );
+    $siblings->OrderBy( FIELD => 'SortOrder', ORDER => 'DESC' );
+    return 0 unless my $first = $siblings->First;
+    return $first->SortOrder + 1;
+}
+
+sub TargetObj {
+    my $self = shift;
+    my $id   = shift;
+
+    my $method = $self->TargetField .'Obj';
+    return $self->$method( $id );
+}
+
+sub Neighbors {
+    my $self = shift;
+    return $self->CollectionClass->new( $self->CurrentUser );
+}
+
+sub Siblings {
+    my $self = shift;
+    my %args = @_;
+
+    my $oid = $args{'ObjectId'};
+    $oid = $self->ObjectId unless defined $oid;
+    $oid ||= 0;
+
+    my $res = $self->Neighbors( %args );
+    $res->LimitToObjectId( $oid );
+    $res->LimitToObjectId( 0 ) if $oid;
+    return $res;
+}
+
+RT::Base->_ImportOverlays();
+
+1;
diff --git a/lib/RT/SearchBuilder/ApplyAndSort.pm b/lib/RT/SearchBuilder/ApplyAndSort.pm
new file mode 100644
index 0000000..960eaa7
--- /dev/null
+++ b/lib/RT/SearchBuilder/ApplyAndSort.pm
@@ -0,0 +1,48 @@
+use strict;
+use warnings;
+
+package RT::SearchBuilder::ApplyAndSort;
+use base 'RT::SearchBuilder';
+
+sub RecordClass {
+    my $class = ref($_[0]) || $_[0];
+    $class =~ s/s$// or return undef;
+    return $class;
+}
+
+sub _Init {
+    my $self = shift;
+
+    # By default, order by SortOrder
+    $self->OrderByCols(
+         { ALIAS => 'main',
+           FIELD => 'SortOrder',
+           ORDER => 'ASC' },
+         { ALIAS => 'main',
+           FIELD => 'id',
+           ORDER => 'ASC' },
+    );
+
+    return $self->SUPER::_Init(@_);
+}
+
+sub LimitToObjectId {
+    my $self = shift;
+    my $id = shift || 0;
+    $self->Limit( FIELD => 'ObjectId', VALUE => $id );
+}
+
+=head2 NewItem
+
+Returns an empty new collection's item
+
+=cut
+
+sub NewItem {
+    my $self = shift;
+    return $self->RecordClass->new( $self->CurrentUser );
+}
+
+RT::Base->_ImportOverlays();
+
+1;

-----------------------------------------------------------------------


More information about the Rt-commit mailing list