[Rt-commit] rt branch, 4.0/apply-scrips-to-multiple-queues, updated. rt-4.0.4-129-g32612e6

Ruslan Zakirov ruz at bestpractical.com
Sat Dec 17 18:02:29 EST 2011


The branch, 4.0/apply-scrips-to-multiple-queues has been updated
       via  32612e65189baeac7f9d1ae5c3a9424d0cbe5176 (commit)
       via  a55859e3b0646be2aed6184ee2819ff25152611a (commit)
       via  d2bdcd1a0b2f027757c2a34845a447ea877de0cc (commit)
       via  17e853c96bd50a392ec68f89c5651903b1d01a9b (commit)
       via  e3548dac95147881e239d30d195f2fc1a135e0b1 (commit)
       via  f44e8be9d57ba2995a189834edddc0beefc8d0ad (commit)
       via  922e43eb2d2655230f8b23c621a023f267bbe210 (commit)
       via  711c5090d05856058650bf034177ac417bf31659 (commit)
       via  94dd0f4ef09f96a0cbdaf4e4f2ec2ce951833b46 (commit)
       via  0e7214d2df69b0b99d9347a453e95f948ba073e8 (commit)
       via  4b9bd60067c99bd618b16d6526fb770a0d8b22bb (commit)
      from  01a7fc4ca83b77aa23b48906660e345571cc7a7b (commit)

Summary of changes:
 etc/RT_Config.pm.in                     |    9 +--
 etc/schema.Oracle                       |   14 +++-
 etc/schema.Pg                           |   16 +++-
 etc/schema.SQLite                       |   14 +++-
 etc/schema.mysql                        |   14 +++-
 lib/RT/CustomField.pm                   |   84 ++---------------
 lib/RT/CustomFields.pm                  |   63 +-----------
 lib/RT/ObjectCustomField.pm             |    6 +
 lib/RT/ObjectScrip.pm                   |  160 +++++++++++++++++++++++++++++++
 lib/RT/ObjectScrips.pm                  |   20 ++++
 lib/RT/Record/ApplyAndSort.pm           |  141 +++++++++++++++++++++++++++
 lib/RT/Scrip.pm                         |  104 ++++++++++----------
 lib/RT/Scrips.pm                        |   52 +++++++---
 lib/RT/SearchBuilder/ApplyAndSort.pm    |   91 +++++++++++++++++
 share/html/Admin/Elements/EditScrip     |    2 +-
 share/html/Admin/Elements/EditScrips    |  126 +++++++++++++++++-------
 share/html/Elements/RT__Scrip/ColumnMap |   68 +++++++++++++
 17 files changed, 735 insertions(+), 249 deletions(-)
 create mode 100644 lib/RT/ObjectScrip.pm
 create mode 100644 lib/RT/ObjectScrips.pm

- Log -----------------------------------------------------------------
commit 4b9bd60067c99bd618b16d6526fb770a0d8b22bb
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Dec 13 04:04:11 2011 +0400

    extract some code from CustomField.pm into new modules

diff --git a/lib/RT/CustomField.pm b/lib/RT/CustomField.pm
index 820f6ee..5e13ced 100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@ -1086,9 +1086,7 @@ sub SetLookupType {
     my $lookup = shift;
     if ( $lookup ne $self->LookupType ) {
         # Okay... We need to invalidate our existing relationships
-        my $ObjectCustomFields = RT::ObjectCustomFields->new($self->CurrentUser);
-        $ObjectCustomFields->LimitToCustomField($self->Id);
-        $_->Delete foreach @{$ObjectCustomFields->ItemsArrayRef};
+        RT::ObjectCustomField->new($self->CurrentUser)->DeleteAll( CustomField => $self );
     }
     return $self->_Set(Field => 'LookupType', Value =>$lookup);
 }
@@ -1286,7 +1284,6 @@ Takes an object
 
 =cut
 
-
 sub AddToObject {
     my $self  = shift;
     my $object = shift;
@@ -1300,26 +1297,9 @@ sub AddToObject {
         return ( 0, $self->loc('Permission Denied') );
     }
 
-    if ( $self->IsApplied( $id ) ) {
-        return ( 0, $self->loc("Custom field is already applied to the object") );
-    }
-
-    if ( $id ) {
-        # applying locally
-        return (0, $self->loc("Couldn't apply custom field to an object as it's global already") )
-            if $self->IsApplied( 0 );
-    }
-    else {
-        my $applied = RT::ObjectCustomFields->new( $self->CurrentUser );
-        $applied->LimitToCustomField( $self->id );
-        while ( my $record = $applied->Next ) {
-            $record->Delete;
-        }
-    }
-
     my $ocf = RT::ObjectCustomField->new( $self->CurrentUser );
-    my ( $oid, $msg ) = $ocf->Create(
-        ObjectId => $id, CustomField => $self->id,
+    my ( $oid, $msg ) = $ocf->Apply(
+        CustomField => $self->id, ObjectId => $id,
     );
     return ( $oid, $msg );
 }
diff --git a/lib/RT/Record/ApplyAndSort.pm b/lib/RT/Record/ApplyAndSort.pm
index 943417c..09bf582 100644
--- a/lib/RT/Record/ApplyAndSort.pm
+++ b/lib/RT/Record/ApplyAndSort.pm
@@ -52,6 +52,46 @@ sub Create {
     );
 }
 
+sub Apply {
+    my $self = shift;
+    my %args = (@_);
+
+    my $field = $self->TargetField;
+
+    my $tid = $args{ $field };
+    $tid = $tid->id if ref $tid;
+    $tid ||= $self->TargetObj->id;
+
+    my $oid = $args{'ObjectId'};
+    $oid = $oid->id if ref $oid;
+    $oid ||= 0;
+
+    if ( $self->IsApplied( $tid => $oid ) ) {
+        return ( 0, $self->loc("Is already applied to the object") );
+    }
+
+    if ( $oid ) {
+        # applying locally
+        return (0, $self->loc("Couldn't apply as it's global already") )
+            if $self->IsApplied( $tid => 0 );
+    }
+    else {
+        $self->DeleteAll( $field => $tid );
+    }
+
+    return $self->Create(
+        CustomField => $tid, ObjectId => $oid,
+    );
+}
+
+sub IsApplied {
+    my $self = shift;
+    my ($tid, $oid) = @_;
+    my $record = $self->new( $self->CurrentUser );
+    $record->LoadByCols( $self->TargetField => $tid, ObjectId => $oid );
+    return $record->id;
+}
+
 sub Delete {
     my $self = shift;
 
@@ -68,6 +108,21 @@ sub Delete {
     $self->SUPER::Delete;
 }
 
+sub DeleteAll {
+    my $self = shift;
+    my %args = (@_);
+
+    my $field = $self->TargetField;
+
+    my $id = $args{ $field };
+    $id = $id->id if ref $id;
+    $id ||= $self->TargetObj->id;
+
+    my $list = $self->CollectionClass->new( $self->CurrentUser );
+    $list->Limit( FIELD => $field, VALUE => $id );
+    $_->Delete foreach @{ $list->ItemsArrayRef };
+}
+
 =head2 Sorting scrips applications
 
 scrips sorted on multiple layers. First of all custom

commit 0e7214d2df69b0b99d9347a453e95f948ba073e8
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Dec 13 17:02:29 2011 +0400

    move *AppliedTo methods

diff --git a/lib/RT/CustomField.pm b/lib/RT/CustomField.pm
index 5e13ced..cad108c 100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@ -1189,18 +1189,8 @@ Doesn't takes into account if object is applied globally.
 
 sub AppliedTo {
     my $self = shift;
-
-    my ($res, $ocfs_alias) = $self->_AppliedTo;
-    return $res unless $res;
-
-    $res->Limit(
-        ALIAS     => $ocfs_alias,
-        FIELD     => 'id',
-        OPERATOR  => 'IS NOT',
-        VALUE     => 'NULL',
-    );
-
-    return $res;
+    return RT::ObjectCustomField->new( $self->CurrentUser )
+        ->AppliedTo( CustomField => $self );
 }
 
 =head1 NotAppliedTo
@@ -1215,48 +1205,8 @@ Doesn't takes into account if object is applied globally.
 
 sub NotAppliedTo {
     my $self = shift;
-
-    my ($res, $ocfs_alias) = $self->_AppliedTo;
-    return $res unless $res;
-
-    $res->Limit(
-        ALIAS     => $ocfs_alias,
-        FIELD     => 'id',
-        OPERATOR  => 'IS',
-        VALUE     => 'NULL',
-    );
-
-    return $res;
-}
-
-sub _AppliedTo {
-    my $self = shift;
-
-    my ($class) = $self->CollectionClassFromLookupType;
-    return undef unless $class;
-
-    my $res = $class->new( $self->CurrentUser );
-
-    # If CF is a Group CF, only display user-defined groups
-    if ( $class eq 'RT::Groups' ) {
-        $res->LimitToUserDefinedGroups;
-    }
-
-    $res->OrderBy( FIELD => 'Name' );
-    my $ocfs_alias = $res->Join(
-        TYPE   => 'LEFT',
-        ALIAS1 => 'main',
-        FIELD1 => 'id',
-        TABLE2 => 'ObjectCustomFields',
-        FIELD2 => 'ObjectId',
-    );
-    $res->Limit(
-        LEFTJOIN => $ocfs_alias,
-        ALIAS    => $ocfs_alias,
-        FIELD    => 'CustomField',
-        VALUE    => $self->id,
-    );
-    return ($res, $ocfs_alias);
+    return RT::ObjectCustomField->new( $self->CurrentUser )
+        ->NotAppliedTo( CustomField => $self );
 }
 
 =head2 IsApplied
diff --git a/lib/RT/ObjectCustomField.pm b/lib/RT/ObjectCustomField.pm
index f2d47a7..55c7a6d 100644
--- a/lib/RT/ObjectCustomField.pm
+++ b/lib/RT/ObjectCustomField.pm
@@ -56,6 +56,12 @@ use RT::ObjectCustomFields;
 
 sub Table {'ObjectCustomFields'}
 
+sub ObjectCollectionClass {
+    my $self = shift;
+    my %args = (@_);
+    return $args{'CustomField'}->CollectionClassFromLookupType;
+}
+
 # XXX: Where is ACL check when we create a record?
 
 =head2 CustomFieldObj
diff --git a/lib/RT/Record/ApplyAndSort.pm b/lib/RT/Record/ApplyAndSort.pm
index 09bf582..179583f 100644
--- a/lib/RT/Record/ApplyAndSort.pm
+++ b/lib/RT/Record/ApplyAndSort.pm
@@ -8,6 +8,8 @@ sub CollectionClass {
     return (ref($_[0]) || $_[0]).'s';
 }
 
+sub ObjectCollectionClass { die "should be subclassed" }
+
 sub TargetField {
     my $class = ref($_[0]) || $_[0];
     $class =~ s/.*::Object// or return undef;
@@ -92,6 +94,90 @@ sub IsApplied {
     return $record->id;
 }
 
+=head1 AppliedTo
+
+Returns collection with objects this custom field is applied to.
+Class of the collection depends on L</LookupType>.
+See all L</NotAppliedTo> .
+
+Doesn't takes into account if object is applied globally.
+
+=cut
+
+sub AppliedTo {
+    my $self = shift;
+
+    my ($res, $alias) = $self->_AppliedTo( @_ );
+    return $res unless $res;
+
+    $res->Limit(
+        ALIAS     => $alias,
+        FIELD     => 'id',
+        OPERATOR  => 'IS NOT',
+        VALUE     => 'NULL',
+    );
+
+    return $res;
+}
+
+=head1 NotAppliedTo
+
+Returns collection with objects this custom field is not applied to.
+Class of the collection depends on L</LookupType>.
+See all L</AppliedTo> .
+
+Doesn't takes into account if object is applied globally.
+
+=cut
+
+sub NotAppliedTo {
+    my $self = shift;
+
+    my ($res, $alias) = $self->_AppliedTo( @_ );
+    return $res unless $res;
+
+    $res->Limit(
+        ALIAS     => $alias,
+        FIELD     => 'id',
+        OPERATOR  => 'IS',
+        VALUE     => 'NULL',
+    );
+
+    return $res;
+}
+
+sub _AppliedTo {
+    my $self = shift;
+    my %args = (@_);
+
+    my $field = $self->TargetField;
+    my $target = $args{ $field } || $self->TargetObj;
+
+    my ($class) = $self->ObjectCollectionClass( $field => $target );
+    return undef unless $class;
+
+    my $res = $class->new( $self->CurrentUser );
+
+    # If target applied to a Group, only display user-defined groups
+    $res->LimitToUserDefinedGroups if $class eq 'RT::Groups';
+
+    $res->OrderBy( FIELD => 'Name' );
+    my $alias = $res->Join(
+        TYPE   => 'LEFT',
+        ALIAS1 => 'main',
+        FIELD1 => 'id',
+        TABLE2 => $self->Table,
+        FIELD2 => 'ObjectId',
+    );
+    $res->Limit(
+        LEFTJOIN => $alias,
+        ALIAS    => $alias,
+        FIELD    => $field,
+        VALUE    => $self->id,
+    );
+    return ($res, $alias);
+}
+
 sub Delete {
     my $self = shift;
 

commit 94dd0f4ef09f96a0cbdaf4e4f2ec2ce951833b46
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Dec 14 01:44:31 2011 +0400

    move more methods, now related to collections

diff --git a/lib/RT/CustomFields.pm b/lib/RT/CustomFields.pm
index a84d9aa..665a3f9 100644
--- a/lib/RT/CustomFields.pm
+++ b/lib/RT/CustomFields.pm
@@ -170,28 +170,6 @@ sub LimitToGlobalOrObjectId {
                  ENTRYAGGREGATOR => 'OR' ) unless $global_only;
 }
 
-sub _LimitToOCFs {
-    my $self = shift;
-    my @ids = @_;
-
-    my $ocfs_alias = $self->_OCFAlias( New => 1, Left => 1 );
-    if ( @ids ) {
-        # XXX: we need different EA in join clause, but DBIx::SB
-        # doesn't support them, use IN (X) instead
-        my $dbh = $self->_Handle->dbh;
-        $self->Limit(
-            LEFTJOIN   => $ocfs_alias,
-            ALIAS      => $ocfs_alias,
-            FIELD      => 'ObjectId',
-            OPERATOR   => 'IN',
-            QUOTEVALUE => 0,
-            VALUE      => "(". join( ',', map $dbh->quote($_), @ids ) .")",
-        );
-    }
-
-    return $ocfs_alias;
-}
-
 =head2 LimitToNotApplied
 
 Takes either list of object ids or nothing. Limits collection
@@ -202,17 +180,8 @@ zero to mean global.
 
 sub LimitToNotApplied {
     my $self = shift;
-    my @ids = @_;
-
-    my $ocfs_alias = $self->_LimitToOCFs(@ids);
-
-    $self->Limit(
-        ENTRYAGGREGATOR => 'AND',
-        ALIAS    => $ocfs_alias,
-        FIELD    => 'id',
-        OPERATOR => 'IS',
-        VALUE    => 'NULL',
-    );
+    return RT::ObjectCustomFields->new( $self->CurrentUser )
+        ->LimitTargetToNotApplied( $self => @_ );
 }
 
 =head2 LimitToApplied
@@ -224,17 +193,8 @@ zero to mean global.
 
 sub LimitToApplied {
     my $self = shift;
-    my @ids = @_;
-
-    my $ocfs_alias = $self->_LimitToOCFs(@ids);
-
-    $self->Limit(
-        ENTRYAGGREGATOR => 'AND',
-        ALIAS    => $ocfs_alias,
-        FIELD    => 'id',
-        OPERATOR => 'IS NOT',
-        VALUE    => 'NULL',
-    );
+    return RT::ObjectCustomFields->new( $self->CurrentUser )
+        ->LimitTargetToApplied( $self => @_ );
 }
 
 =head2 LimitToGlobalOrQueue QUEUEID
@@ -344,19 +304,8 @@ sub SetContextObject {
 
 sub _OCFAlias {
     my $self = shift;
-    my %args = ( New => 0, Left => 0, @_ );
-
-    return $self->{'_sql_ocfalias'} if $self->{'_sql_ocfalias'} && !$args{'New'};
-
-    my $alias = $self->Join(
-        $args{'Left'} ? (TYPE => 'LEFT') : (),
-        ALIAS1 => 'main',
-        FIELD1 => 'id',
-        TABLE2 => 'ObjectCustomFields',
-        FIELD2 => 'CustomField'
-    );
-    return $alias if $args{'New'};
-    return $self->{'_sql_ocfalias'} = $alias;
+    return RT::ObjectCustomFields->new( $self->CurrentUser )
+        ->JoinTargetToThis( $self => @_ );
 }
 
 
diff --git a/lib/RT/SearchBuilder/ApplyAndSort.pm b/lib/RT/SearchBuilder/ApplyAndSort.pm
index 960eaa7..5560b1a 100644
--- a/lib/RT/SearchBuilder/ApplyAndSort.pm
+++ b/lib/RT/SearchBuilder/ApplyAndSort.pm
@@ -32,6 +32,97 @@ sub LimitToObjectId {
     $self->Limit( FIELD => 'ObjectId', VALUE => $id );
 }
 
+=head2 LimitTargetToNotApplied
+
+Takes either list of object ids or nothing. Limits collection
+to custom fields to listed objects or any corespondingly. Use
+zero to mean global.
+
+=cut
+
+sub LimitTargetToNotApplied {
+    my $self = shift;
+    my $collection = shift;
+    my @ids = @_;
+
+    my $alias = $self->JoinTargetToApplied($collection => @ids);
+
+    $collection->Limit(
+        ENTRYAGGREGATOR => 'AND',
+        ALIAS    => $alias,
+        FIELD    => 'id',
+        OPERATOR => 'IS',
+        VALUE    => 'NULL',
+    );
+}
+
+=head2 LimitTargetToApplied
+
+Limits collection to custom fields to listed objects or any corespondingly. Use
+zero to mean global.
+
+=cut
+
+sub LimitTargetToApplied {
+    my $self = shift;
+    my $collection = shift;
+    my @ids = @_;
+
+    my $alias = $self->JoinTargetToApplied($collection => @ids);
+
+    $collection->Limit(
+        ENTRYAGGREGATOR => 'AND',
+        ALIAS    => $alias,
+        FIELD    => 'id',
+        OPERATOR => 'IS NOT',
+        VALUE    => 'NULL',
+    );
+}
+
+sub JoinTargetToApplied {
+    my $self = shift;
+    my $collection = shift;
+    my @ids = @_;
+
+    my $alias = $self->JoinTargetToThis( $collection, New => 1, Left => 1 );
+    return $alias unless @ids;
+
+    # XXX: we need different EA in join clause, but DBIx::SB
+    # doesn't support them, use IN (X) instead
+    my $dbh = $self->_Handle->dbh;
+    $collection->Limit(
+        LEFTJOIN   => $alias,
+        ALIAS      => $alias,
+        FIELD      => 'ObjectId',
+        OPERATOR   => 'IN',
+        QUOTEVALUE => 0,
+        VALUE      => "(". join( ',', map $dbh->quote($_), @ids ) .")",
+    );
+
+    return $alias;
+}
+
+sub JoinTargetToThis {
+    my $self = shift;
+    my $collection = shift;
+    my %args = ( New => 0, Left => 0, @_ );
+
+    my $table = $self->Table;
+    my $key = "_sql_${table}_alias";
+
+    return $collection->{ $key } if $collection->{ $key } && !$args{'New'};
+
+    my $alias = $collection->Join(
+        $args{'Left'} ? (TYPE => 'LEFT') : (),
+        ALIAS1 => 'main',
+        FIELD1 => 'id',
+        TABLE2 => $table,
+        FIELD2 => 'CustomField'
+    );
+    return $alias if $args{'New'};
+    return $collection->{ $key } = $alias;
+}
+
 =head2 NewItem
 
 Returns an empty new collection's item

commit 711c5090d05856058650bf034177ac417bf31659
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Dec 14 15:11:05 2011 +0400

    get rid of last mentions of CustomField in generic class

diff --git a/lib/RT/Record/ApplyAndSort.pm b/lib/RT/Record/ApplyAndSort.pm
index 179583f..82e5f30 100644
--- a/lib/RT/Record/ApplyAndSort.pm
+++ b/lib/RT/Record/ApplyAndSort.pm
@@ -82,7 +82,7 @@ sub Apply {
     }
 
     return $self->Create(
-        CustomField => $tid, ObjectId => $oid,
+        $field => $tid, ObjectId => $oid,
     );
 }
 
diff --git a/lib/RT/SearchBuilder/ApplyAndSort.pm b/lib/RT/SearchBuilder/ApplyAndSort.pm
index 5560b1a..a45a3e6 100644
--- a/lib/RT/SearchBuilder/ApplyAndSort.pm
+++ b/lib/RT/SearchBuilder/ApplyAndSort.pm
@@ -117,7 +117,7 @@ sub JoinTargetToThis {
         ALIAS1 => 'main',
         FIELD1 => 'id',
         TABLE2 => $table,
-        FIELD2 => 'CustomField'
+        FIELD2 => $self->RecordClass->TargetField,
     );
     return $alias if $args{'New'};
     return $collection->{ $key } = $alias;

commit 922e43eb2d2655230f8b23c621a023f267bbe210
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Dec 14 23:36:40 2011 +0400

    ObjectScrips table in schemas

diff --git a/etc/schema.Oracle b/etc/schema.Oracle
index 4bcae6c..751d03f 100755
--- a/etc/schema.Oracle
+++ b/etc/schema.Oracle
@@ -150,6 +150,19 @@ CREATE TABLE Scrips (
   	LastUpdated 	DATE  
 );
 
+CREATE SEQUENCE OBJECTSCRIPS_seq;
+CREATE TABLE ObjectScrips (
+	id		NUMBER(11,0)
+                 CONSTRAINT ObjectScrips_Key PRIMARY KEY,
+        Scrip       NUMBER(11,0)  NOT NULL,
+        ObjectId              NUMBER(11,0)  NOT NULL,
+	SortOrder	NUMBER(11,0) DEFAULT 0 NOT NULL,
+	Creator		NUMBER(11,0) DEFAULT 0 NOT NULL,
+	Created		DATE,
+	LastUpdatedBy	NUMBER(11,0) DEFAULT 0 NOT NULL,
+	LastUpdated	DATE
+);
+
 
 CREATE SEQUENCE ACL_seq;
 CREATE TABLE ACL (
diff --git a/etc/schema.Pg b/etc/schema.Pg
index 565f76b..7ab5ae2 100755
--- a/etc/schema.Pg
+++ b/etc/schema.Pg
@@ -242,6 +242,21 @@ CREATE TABLE Scrips (
 );
 
 
+CREATE SEQUENCE objectscrips_id_seq;
+
+CREATE TABLE ObjectCustomFields (
+  id INTEGER DEFAULT nextval('objectscrips_id_seq'),
+  Scrip integer NOT NULL,
+  ObjectId integer NOT NULL,
+  SortOrder integer NOT NULL DEFAULT 0  ,
+
+  Creator integer NOT NULL DEFAULT 0  ,
+  Created TIMESTAMP NULL  ,
+  LastUpdatedBy integer NOT NULL DEFAULT 0  ,
+  LastUpdated TIMESTAMP NULL  ,
+  PRIMARY KEY (id)
+
+);
 
 
 
diff --git a/etc/schema.SQLite b/etc/schema.SQLite
index 138971c..168ffcc 100755
--- a/etc/schema.SQLite
+++ b/etc/schema.SQLite
@@ -162,6 +162,19 @@ CREATE TABLE Scrips (
 
 --- }}}
 
+CREATE TABLE ObjectScrips (
+  id INTEGER NOT NULL  ,
+  Scrip int NOT NULL  ,
+  ObjectId integer NOT NULL,
+  SortOrder integer NOT NULL DEFAULT 0  ,
+
+  Creator integer NOT NULL DEFAULT 0  ,
+  Created DATETIME NULL  ,
+  LastUpdatedBy integer NOT NULL DEFAULT 0  ,
+  LastUpdated DATETIME NULL  ,
+  PRIMARY KEY (id)
+);
+
 --- {{{ ACL
 CREATE TABLE ACL (
   id INTEGER PRIMARY KEY  ,
diff --git a/etc/schema.mysql b/etc/schema.mysql
index c313aaf..a2eae6d 100755
--- a/etc/schema.mysql
+++ b/etc/schema.mysql
@@ -152,6 +152,19 @@ CREATE TABLE Scrips (
   PRIMARY KEY (id)
 ) ENGINE=InnoDB CHARACTER SET utf8;
 
+CREATE TABLE ObjectScrips (
+  id INTEGER NOT NULL  AUTO_INCREMENT,
+  Scrip integer NOT NULL  ,
+  ObjectId integer NOT NULL,
+  SortOrder integer NOT NULL DEFAULT 0  ,
+
+  Creator integer NOT NULL DEFAULT 0  ,
+  Created DATETIME NULL  ,
+  LastUpdatedBy integer NOT NULL DEFAULT 0  ,
+  LastUpdated DATETIME NULL  ,
+  PRIMARY KEY (id)
+) ENGINE=InnoDB CHARACTER SET utf8;
+
 
 CREATE TABLE ACL (
   id INTEGER NOT NULL  AUTO_INCREMENT,

commit f44e8be9d57ba2995a189834edddc0beefc8d0ad
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Dec 14 23:38:43 2011 +0400

    ObjectScrip[s] classes
    
    * scrips <-> queues many to many relation
    * custom sorting

diff --git a/lib/RT/ObjectScrip.pm b/lib/RT/ObjectScrip.pm
new file mode 100644
index 0000000..8773f30
--- /dev/null
+++ b/lib/RT/ObjectScrip.pm
@@ -0,0 +1,160 @@
+use strict;
+use warnings;
+
+package RT::ObjectScrip;
+use base 'RT::Record::ApplyAndSort';
+
+use RT::Scrip;
+use RT::ObjectScrips;
+
+sub Table {'ObjectScrips'}
+sub ObjectCollectionClass {'RT::Queues'}
+
+=head2 ScripObj
+
+Returns the Scrip Object which has the id returned by Scrip
+
+=cut
+
+sub ScripObj {
+    my $self = shift;
+    my $id = shift || $self->Scrip;
+    my $obj = RT::Scrip->new( $self->CurrentUser );
+    $obj->Load( $id );
+    return $obj;
+}
+
+sub Neighbors {
+    my $self = shift;
+    my %args = @_;
+
+    my $res = $self->CollectionClass->new( $self->CurrentUser );
+    return $res;
+}
+
+=head2 id
+
+Returns the current value of id.
+(In the database, id is stored as int(11).)
+
+
+=cut
+
+
+=head2 Scrip
+
+Returns the current value of Scrip.
+(In the database, Scrip is stored as int(11).)
+
+
+
+=head2 SetScrip VALUE
+
+
+Set Scrip to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, Scrip will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 ObjectId
+
+Returns the current value of ObjectId.
+(In the database, ObjectId is stored as int(11).)
+
+
+
+=head2 SetObjectId VALUE
+
+
+Set ObjectId to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, ObjectId will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 SortOrder
+
+Returns the current value of SortOrder.
+(In the database, SortOrder is stored as int(11).)
+
+
+
+=head2 SetSortOrder VALUE
+
+
+Set SortOrder to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, SortOrder will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 Creator
+
+Returns the current value of Creator.
+(In the database, Creator is stored as int(11).)
+
+
+=cut
+
+
+=head2 Created
+
+Returns the current value of Created.
+(In the database, Created is stored as datetime.)
+
+
+=cut
+
+
+=head2 LastUpdatedBy
+
+Returns the current value of LastUpdatedBy.
+(In the database, LastUpdatedBy is stored as int(11).)
+
+
+=cut
+
+
+=head2 LastUpdated
+
+Returns the current value of LastUpdated.
+(In the database, LastUpdated is stored as datetime.)
+
+
+=cut
+
+
+
+sub _CoreAccessible {
+    {
+
+        id =>
+		{read => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
+        Scrip =>
+		{read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
+        ObjectId =>
+		{read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
+        SortOrder =>
+		{read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+        Creator =>
+		{read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+        Created =>
+		{read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
+        LastUpdatedBy =>
+		{read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+        LastUpdated =>
+		{read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
+
+ }
+};
+
+RT::Base->_ImportOverlays();
+
+1;
diff --git a/lib/RT/ObjectScrips.pm b/lib/RT/ObjectScrips.pm
new file mode 100644
index 0000000..93817ed
--- /dev/null
+++ b/lib/RT/ObjectScrips.pm
@@ -0,0 +1,20 @@
+use strict;
+use warnings;
+
+package RT::ObjectScrips;
+use base 'RT::SearchBuilder::ApplyAndSort';
+
+use RT::Scrips;
+use RT::ObjectScrip;
+
+sub Table { 'ObjectScrips'}
+
+sub LimitToScrip {
+    my $self = shift;
+    my $id = shift;
+    $self->Limit( FIELD => 'Scrip', VALUE => $id );
+}
+
+RT::Base->_ImportOverlays();
+
+1;

commit e3548dac95147881e239d30d195f2fc1a135e0b1
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sun Dec 18 02:32:24 2011 +0400

    drop Queue column in Scrips and usage of it in most places

diff --git a/etc/schema.Oracle b/etc/schema.Oracle
index 751d03f..1f82447 100755
--- a/etc/schema.Oracle
+++ b/etc/schema.Oracle
@@ -142,7 +142,6 @@ CREATE TABLE Scrips (
 	CustomPrepareCode	CLOB,
 	CustomCommitCode	CLOB,
 	Stage		VARCHAR2(32),
-	Queue		NUMBER(11,0) DEFAULT 0 NOT NULL,
 	Template	NUMBER(11,0) DEFAULT 0 NOT NULL,
   	Creator 	NUMBER(11,0) DEFAULT 0 NOT NULL,
   	Created 	DATE,
diff --git a/etc/schema.Pg b/etc/schema.Pg
index 7ab5ae2..eb335e6 100755
--- a/etc/schema.Pg
+++ b/etc/schema.Pg
@@ -231,7 +231,6 @@ CREATE TABLE Scrips (
   CustomPrepareCode text NULL  ,
   CustomCommitCode text NULL  ,
   Stage varchar(32) NULL  ,
-  Queue integer NOT NULL DEFAULT 0  ,
   Template integer NOT NULL DEFAULT 0  ,
   Creator integer NOT NULL DEFAULT 0  ,
   Created TIMESTAMP NULL  ,
diff --git a/etc/schema.SQLite b/etc/schema.SQLite
index 168ffcc..bfb25c3 100755
--- a/etc/schema.SQLite
+++ b/etc/schema.SQLite
@@ -151,7 +151,6 @@ CREATE TABLE Scrips (
   CustomPrepareCode text NULL  ,
   CustomCommitCode text NULL  ,
   Stage varchar(32) NULL  ,
-  Queue integer NULL  ,
   Template integer NULL  ,
   Creator integer NULL  ,
   Created DATETIME NULL  ,
diff --git a/etc/schema.mysql b/etc/schema.mysql
index a2eae6d..db09c23 100755
--- a/etc/schema.mysql
+++ b/etc/schema.mysql
@@ -143,7 +143,6 @@ CREATE TABLE Scrips (
   CustomPrepareCode text NULL  ,
   CustomCommitCode text NULL  ,
   Stage varchar(32) CHARACTER SET ascii NULL  ,
-  Queue integer NOT NULL DEFAULT 0  ,
   Template integer NOT NULL DEFAULT 0  ,
   Creator integer NOT NULL DEFAULT 0  ,
   Created DATETIME NULL  ,
diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index 5d4e5e8..faaa062 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -170,7 +170,6 @@ sub Create {
         unless $condition->Id;
 
     my ( $id, $msg ) = $self->SUPER::Create(
-        Queue                  => $args{'Queue'},
         Template               => $template->Id,
         ScripCondition         => $condition->id,
         Stage                  => $args{'Stage'},
@@ -208,21 +207,10 @@ sub Delete {
 
 
 
-=head2 QueueObj
-
-Retuns an RT::Queue object with this Scrip's queue
-
-=cut
 
 sub QueueObj {
     my $self = shift;
 
-    if ( !$self->{'QueueObj'} ) {
-        require RT::Queue;
-        $self->{'QueueObj'} = RT::Queue->new( $self->CurrentUser );
-        $self->{'QueueObj'}->Load( $self->__Value('Queue') );
-    }
-    return ( $self->{'QueueObj'} );
 }
 
 
@@ -504,8 +492,7 @@ sub _Set {
     );
 
     unless ( $self->CurrentUserHasRight('ModifyScrips') ) {
-        $RT::Logger->debug(
-                 "CurrentUser can't modify Scrips for " . $self->Queue . "\n" );
+        $RT::Logger->debug( "CurrentUser can't modify Scrips" );
         return ( 0, $self->loc('Permission Denied') );
     }
 
@@ -528,9 +515,7 @@ sub _Value {
     my $self = shift;
 
     unless ( $self->CurrentUserHasRight('ShowScrips') ) {
-        $RT::Logger->debug( "CurrentUser can't modify Scrips for "
-                            . $self->__Value('Queue')
-                            . "\n" );
+        $RT::Logger->debug( "CurrentUser can't see scrip #". $self->__Value('id') );
         return (undef);
     }
 
@@ -882,24 +867,6 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 =cut
 
 
-=head2 Queue
-
-Returns the current value of Queue.
-(In the database, Queue is stored as int(11).)
-
-
-
-=head2 SetQueue VALUE
-
-
-Set Queue to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Queue will be stored as a int(11).)
-
-
-=cut
-
-
 =head2 Template
 
 Returns the current value of Template.
@@ -978,8 +945,6 @@ sub _CoreAccessible {
 		{read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'text', default => ''},
         Stage =>
 		{read => 1, write => 1, sql_type => 12, length => 32,  is_blob => 0,  is_numeric => 0,  type => 'varchar(32)', default => ''},
-        Queue =>
-		{read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         Template =>
 		{read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         Creator =>
diff --git a/share/html/Admin/Elements/EditScrip b/share/html/Admin/Elements/EditScrip
index 7319192..6ee5ae2 100755
--- a/share/html/Admin/Elements/EditScrip
+++ b/share/html/Admin/Elements/EditScrip
@@ -190,7 +190,7 @@ else {
     return (undef, loc("Couldn't load scrip #[_1]", $id))
         unless $scrip->id;
 
-    my @attribs = qw(Queue ScripAction ScripCondition Template Stage
+    my @attribs = qw(ScripAction ScripCondition Template Stage
         Description CustomPrepareCode CustomCommitCode CustomIsApplicableCode);
     my @results = UpdateRecordObject(
         AttributesRef   => \@attribs,

commit 17e853c96bd50a392ec68f89c5651903b1d01a9b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sun Dec 18 02:34:33 2011 +0400

    use new ApplySort API in Scrip[s] classes

diff --git a/lib/RT/Scrip.pm b/lib/RT/Scrip.pm
index faaa062..fbca34a 100644
--- a/lib/RT/Scrip.pm
+++ b/lib/RT/Scrip.pm
@@ -73,6 +73,9 @@ use RT::Queue;
 use RT::Template;
 use RT::ScripCondition;
 use RT::ScripAction;
+use RT::Scrips;
+use RT::ObjectScrip;
+
 use base 'RT::Record';
 
 sub Table {'Scrips'}
@@ -179,12 +182,15 @@ sub Create {
         CustomCommitCode       => $args{'CustomCommitCode'},
         CustomIsApplicableCode => $args{'CustomIsApplicableCode'},
     );
-    if ( $id ) {
-        return ( $id, $self->loc('Scrip Created') );
-    }
-    else {
-        return ( $id, $msg );
+    return ( $id, $msg ) unless $id;
+
+    unless ( $args{'Stage'} eq 'Disabled' ) {
+        my ($status, $msg) = RT::ObjectScrip->new( $self->CurrentUser )
+            ->Apply( Scrip => $self, ObjectId => $args{'Queue'} );
+        $RT::Logger->error( "Couldn't apply scrip: $msg" ) unless $status;
     }
+
+    return ( $id, $self->loc('Scrip Created') );
 }
 
 
@@ -205,15 +211,42 @@ sub Delete {
     return ( $self->SUPER::Delete(@_) );
 }
 
+sub IsAdded {
+    my $self = shift;
+    my $record = RT::ObjectScrip->new( $self->CurrentUser );
+    $record->LoadByCols( Scrip => $self->id, ObjectId => shift || 0 );
+    return $record->id;
+}
 
+sub AddedTo {
+    my $self = shift;
+    return RT::ObjectScrip->new( $self->CurrentUser )
+        ->AppliedTo( Scrip => $self );
+}
 
+sub NotAddedTo {
+    my $self = shift;
+    return RT::ObjectScrip->new( $self->CurrentUser )
+        ->NotAppliedTo( Scrip => $self );
+}
 
-sub QueueObj {
+sub AddToObject {
     my $self = shift;
+    my $object = shift;
 
+    my $rec = RT::ObjectScrip->new( $self->CurrentUser );
+    return $rec->Apply( Scrip => $self, ObjectId => $object );
 }
 
+sub RemoveFromObject {
+    my $self = shift;
+    my $object = shift;
 
+    my $rec = RT::ObjectScrip->new( $self->CurrentUser );
+    $rec->LoadByCols( Scrip => $self->id, ObjectId => $object );
+    return (0, $self->loc('Scrip is not applied') ) unless $rec->id;
+    return $rec->Delete;
+}
 
 =head2 ActionObj
 
@@ -555,18 +588,20 @@ sub HasRight {
                  Principal => undef,
                  @_ );
 
-    if ( $self->SUPER::_Value('Queue') ) {
-        return $args{'Principal'}->HasRight(
-            Right  => $args{'Right'},
-            Object => $self->QueueObj
-        );
-    }
-    else {
-        return $args{'Principal'}->HasRight(
-            Object => $RT::System,
+    my $queues = $self->AddedTo;
+    my $found = 0;
+    while ( my $queue = $queues->Next ) {
+        return 1 if $args{'Principal'}->HasRight(
             Right  => $args{'Right'},
+            Object => $queue,
         );
+        $found = 1;
     }
+    return $args{'Principal'}->HasRight(
+        Object => $RT::System,
+        Right  => $args{'Right'},
+    ) unless $found;
+    return 0;
 }
 
 
diff --git a/lib/RT/Scrips.pm b/lib/RT/Scrips.pm
index 46713b5..b69e7dc 100644
--- a/lib/RT/Scrips.pm
+++ b/lib/RT/Scrips.pm
@@ -70,6 +70,7 @@ use strict;
 use warnings;
 
 use RT::Scrip;
+use RT::ObjectScrips;
 
 use base 'RT::SearchBuilder';
 
@@ -85,14 +86,17 @@ another call to this method
 =cut
 
 sub LimitToQueue  {
-   my $self = shift;
-  my $queue = shift;
- 
-  $self->Limit (ENTRYAGGREGATOR => 'OR',
-		FIELD => 'Queue',
-		VALUE => "$queue")
-      if defined $queue;
-  
+    my $self = shift;
+    my $queue = shift;
+    return unless defined $queue;
+
+    my $alias = RT::ObjectScrips->new( $self->CurrentUser )
+        ->JoinTargetToThis( $self );
+    $self->Limit(
+        ALIAS => $alias,
+        FIELD => 'ObjectId',
+        VALUE => int $queue,
+    );
 }
 
 
@@ -106,12 +110,32 @@ another call to this method or LimitToQueue
 
 
 sub LimitToGlobal  {
-   my $self = shift;
- 
-  $self->Limit (ENTRYAGGREGATOR => 'OR',
-		FIELD => 'Queue',
-		VALUE => 0);
-  
+    my $self = shift;
+    return $self->LimitToQueue(0);
+}
+
+sub LimitToAdded {
+    my $self = shift;
+    return RT::ObjectScrips->new( $self->CurrentUser )
+        ->LimitTargetToApplied( $self => @_ );
+}
+
+sub LimitToNotAdded {
+    my $self = shift;
+    return RT::ObjectScrips->new( $self->CurrentUser )
+        ->LimitTargetToNotApplied( $self => @_ );
+}
+
+sub ApplySortOrder {
+    my $self = shift;
+    my $order = shift || 'ASC';
+    $self->OrderByCols( {
+        ALIAS => RT::ObjectScrips->new( $self->CurrentUser )
+            ->JoinTargetToThis( $self => @_ )
+        ,
+        FIELD => 'SortOrder',
+        ORDER => $order,
+    } );
 }
 
 # {{{ sub Next 

commit d2bdcd1a0b2f027757c2a34845a447ea877de0cc
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sun Dec 18 02:36:15 2011 +0400

    AdminURL column map for scrips
    
    use only one format string in the config

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index 1cf4f73..83ffaec 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -2466,13 +2466,8 @@ Set(%AdminSearchResultFormat,
         .q{,__AppliedTo__, __FriendlyType__, __FriendlyPattern__},
 
     Scrips =>
-        q{'<a href="__WebPath__/Admin/Queues/Scrip.html?id=__id__&Queue=__QueueId__">__id__</a>/TITLE:#'}
-        .q{,'<a href="__WebPath__/Admin/Queues/Scrip.html?id=__id__&Queue=__QueueId__">__Description__</a>/TITLE:Description'}
-        .q{,__Stage__, __Condition__, __Action__, __Template__},
-
-    GlobalScrips =>
-        q{'<a href="__WebPath__/Admin/Global/Scrip.html?id=__id__">__id__</a>/TITLE:#'}
-        .q{,'<a href="__WebPath__/Admin/Global/Scrip.html?id=__id__">__Description__</a>/TITLE:Description'}
+        q{'<a href="__AdminURL__">__id__</a>/TITLE:#'}
+        .q{,'<a href="__AdminURL__">__Description__</a>/TITLE:Description'}
         .q{,__Stage__, __Condition__, __Action__, __Template__},
 
     Templates =>
diff --git a/share/html/Elements/RT__Scrip/ColumnMap b/share/html/Elements/RT__Scrip/ColumnMap
index 8130ea6..c05fd19 100644
--- a/share/html/Elements/RT__Scrip/ColumnMap
+++ b/share/html/Elements/RT__Scrip/ColumnMap
@@ -98,6 +98,20 @@ my $COLUMN_MAP = {
 	attribute => 'Stage',
 	value     => sub { return $_[0]->Stage() },
     },
+
+    AdminURL => {
+	value     => sub {
+            my $queue = $_[0]->AppliedTo->First;
+            my $res = RT->Config->Get('WebPath') .'/Admin';
+            if ( $queue ) {
+                $res .= '/Queues/Scrip.html?Queue='. $queue->id .'&';
+            } else {
+                $res .= '/Global/Scrip.html?';
+            }
+            $res .= 'id='. $_[0]->id;
+            return $res;
+        },
+    },
 };
 
 </%ONCE>

commit a55859e3b0646be2aed6184ee2819ff25152611a
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sun Dec 18 02:38:10 2011 +0400

    column maps fro removing scrips and moving them

diff --git a/share/html/Elements/RT__Scrip/ColumnMap b/share/html/Elements/RT__Scrip/ColumnMap
index c05fd19..b8d6693 100644
--- a/share/html/Elements/RT__Scrip/ColumnMap
+++ b/share/html/Elements/RT__Scrip/ColumnMap
@@ -112,6 +112,60 @@ my $COLUMN_MAP = {
             return $res;
         },
     },
+    RemoveCheckBox => {
+        title => sub {
+            my $name = 'RemoveScrip';
+            my $checked = $m->request_args->{ $name .'All' }? 'checked="checked"': '';
+
+            return \qq{<input type="checkbox" name="${name}All" value="1" $checked
+                              onclick="setCheckbox(this.form, '$name', this.checked)" />};
+        },
+        value => sub {
+            my $id = $_[0]->id;
+            return '' if $_[0]->IsAdded;
+
+            my $name = 'RemoveScrip';
+            my $arg = $m->request_args->{ $name };
+
+            my $checked = '';
+            if ( $arg && ref $arg ) {
+                $checked = 'checked="checked"' if grep $_ == $id, @$arg;
+            }
+            elsif ( $arg ) {
+                $checked = 'checked="checked"' if $arg == $id;
+            }
+            return \qq{<input type="checkbox" name="$name" value="$id" $checked />}
+        },
+    },
+    Move => {
+        title => 'Move',
+        value => sub {
+            my $id = $_[0]->id;
+
+            my $context = $_[2] || 0;
+            return '' unless $_[0]->IsAdded( $context );
+
+            my $name = 'MoveCustomField';
+            my $args = $m->caller_args( 1 );
+            my @pass = ref $args->{'PassArguments'}
+                ? @{$args->{'PassArguments'}}
+                : ($args->{'PassArguments'});
+            my %pass = map { $_ => $args->{$_} } grep exists $args->{$_}, @pass;
+
+            my $uri = RT->Config->Get('WebPath') . $m->request_path;
+
+            my @res = (
+                \'<a href="',
+                $uri .'?'. $m->comp("/Elements/QueryString", %pass, MoveScripUp => $id ),
+                \'">', loc('[Up]'), \'</a>',
+                \' <a href="',
+                $uri .'?'. $m->comp("/Elements/QueryString", %pass, MoveScripDown => $id ),
+                \'">', loc('[Down]'), \'</a>'
+            );
+
+            return @res;
+        },
+    },
 };
 
 </%ONCE>

commit 32612e65189baeac7f9d1ae5c3a9424d0cbe5176
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Sun Dec 18 02:38:52 2011 +0400

    new UI for scrips management

diff --git a/share/html/Admin/Elements/EditScrips b/share/html/Admin/Elements/EditScrips
index 4654c6b..6fdca9b 100755
--- a/share/html/Admin/Elements/EditScrips
+++ b/share/html/Admin/Elements/EditScrips
@@ -50,70 +50,122 @@
 <form action="Scrips.html" method="post">
 <input type="hidden" class="hidden" name="id" value="<% $id %>" />
 
-<h2><&|/l&>Current Scrips</&></h2>
+<h2><&|/l&>On create scrips</&></h2>
+% my $scrips = $find_scrips->(Stage => 'TransactionCreate');
+<& /Elements/CollectionList, %common_applied_args, Collection => $scrips &>
+% unless ( $scrips->Count ) {
+<p><i><&|/l&>(No scrips)</&></i></p>
+% }
+
+<h2><&|/l&>Batch scrips</&></h2>
+% $scrips = $find_scrips->(Stage => 'TransactionBatch');
+<& /Elements/CollectionList, %common_applied_args, Collection => $scrips &>
+% unless ( $scrips->Count ) {
+<p><i><&|/l&>(No scrips)</&></i></p>
+% }
+
+<& /Elements/Submit,
+    Name => 'RemoveScrips',
+    Caption => loc("Un-apply selected scrips"),
+    Label => loc("Update"),
+&>
+
+<h2><&|/l&>Not applied scrips</&></h2>
+% $scrips = $find_scrips->(Applied => 0);
 <& /Elements/CollectionList,
-    OrderBy => 'Description',
-    Order => 'ASC',
-    Rows  => 100,
+    Rows => 50,
+    Page => 1,
     %ARGS,
-    Format => $Format,
-    DisplayFormat => "__CheckBox.{DeleteScrip}__, $Format",
-    Collection => $Scrips,
+    Collection => $scrips,
+    Format     => $Format,
+    DisplayFormat => "__CheckBox.{AddScrip}__, $Format",
     AllowSorting => 1,
-    PassArguments => [ qw(Query Format Rows Page Order OrderBy id) ],
+    PassArguments => [ qw(Format Rows Page Order OrderBy id) ],
 &>
-
-% if ( $Scrips->Count ) {
-<p><i><&|/l&>(Check box to delete)</&></i></p>
-% } else  {
+% unless ( $scrips->Count ) {
 <p><i><&|/l&>(No scrips)</&></i></p>
 % }
+
 <& /Elements/Submit,
-    Caption => loc("Delete selected scrips"),
-    Label => loc("Delete")
+    Name => 'AddScrips',
+    Caption => loc("Apply selected scrips"),
+    Label => loc("Update"),
 &>
+
 </form>
 
 <%init>
 my (@actions);
 
-my $Scrips = RT::Scrips->new($session{'CurrentUser'});
-
-my $QueueObj = RT::Queue->new($session{'CurrentUser'});
 if ( $id ) {
+    my $QueueObj = RT::Queue->new($session{'CurrentUser'});
     $QueueObj->Load( $id );
-    unless ( $QueueObj->id ) {
-        push @actions, loc("Couldn't load queue #[_1]", $id)
-    }
+    Abort(loc("Couldn't load queue #[_1]", $id)) unless $QueueObj->id;
 }
 
-if ($QueueObj->id) {
-    $Scrips->LimitToQueue($id);
-    $Format ||= RT->Config->Get('AdminSearchResultFormat')->{'Scrips'};
-}
-else {
-    $Scrips->LimitToGlobal();
-    $Format ||= RT->Config->Get('AdminSearchResultFormat')->{'GlobalScrips'};
+my $find_scrips = sub {
+    my %args = (Applied => 1, @_);
+    my $scrips = RT::Scrips->new($session{'CurrentUser'});
+    $scrips->Limit( FIELD => 'Stage', VALUE => $args{'Stage'} )
+        if $args{'Stage'};
+    my $method = $args{'Applied'}? 'LimitToAdded' : 'LimitToNotAdded';
+    $scrips->$method(0, $id);
+    $scrips->ApplySortOrder if $args{'Applied'};
+    return $scrips;
+};
+
+$Format ||= RT->Config->Get('AdminSearchResultFormat')->{'Scrips'};
+my $DisplayFormat = $Format;
+if ( $id ) {
+    $DisplayFormat = "__RemoveCheckBox__, $DisplayFormat";
+} else {
+    $DisplayFormat = "__CheckBox.{RemoveScrip}__, $DisplayFormat";
 }
+$DisplayFormat .= ", __Move__";
+
+my %common_applied_args = (
+    %ARGS,
+    Format => $Format,
+    DisplayFormat => $DisplayFormat,
+    Rows => 0,
+    Page => 1,
+    AllowSorting => 0,
+    PassArguments => [ qw(Format id) ],
+);
 
-# deal with modifying and deleting existing scrips
-# we still support DeleteScrip-id format but array is preferred
-foreach my $id ( grep $_, @DeleteScrip, map /^DeleteScrip-(\d+)/, keys %ARGS ) {
-    my $scrip = RT::Scrip->new($session{'CurrentUser'});
-    $scrip->Load( $id );
-    my ($retval, $msg) = $scrip->Delete;
-    if ($retval) {
-        push @actions, loc("Scrip deleted");
+if ( $RemoveScrips ) {
+    foreach my $sid ( @RemoveScrip ) {
+        my $scrip = RT::Scrip->new( $session{'CurrentUser'} );
+        $scrip->Load( $sid );
+        next unless $scrip->id;
+
+        my ($status, $msg) = $scrip->RemoveFromObject( $id );
+        push @actions, $msg;
     }
-    else {
+}
+
+if ( $AddScrips ) {
+    foreach my $sid ( @AddScrip ) {
+        my $scrip = RT::Scrip->new( $session{'CurrentUser'} );
+        $scrip->Load( $sid );
+        next unless $scrip->id;
+
+        my ($status, $msg) = $scrip->AddToObject( $id );
         push @actions, $msg;
     }
 }
+
 </%init>
 
 <%ARGS>
 $id => undef
 $title => undef
 $Format => undef
- at DeleteScrip => ()
+
+ at RemoveScrip => ()
+$RemoveScrips => undef
+
+ at AddScrip => ()
+$AddScrips => undef
+
 </%ARGS>

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


More information about the Rt-commit mailing list