+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',
+ );
+}
+
+=head2 LimitToApplied
+
+Limits collection to custom fields to listed objects or any corespondingly. Use
+zero to mean global.
+
+=cut
+
+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',
+ );
+}
+
+=head2 LimitToGlobalOrQueue QUEUEID
+
+DEPRECATED since CFs are applicable not only to tickets these days.
+
+Limits the set of custom fields found to global custom fields or those tied to the queue with ID QUEUEID
+
+=cut
+
+sub LimitToGlobalOrQueue {
+ my $self = shift;
+ my $queue = shift;
+ $self->LimitToGlobalOrObjectId( $queue );
+ $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
+}
+
+
+=head2 LimitToQueue QUEUEID
+
+DEPRECATED since CFs are applicable not only to tickets these days.
+
+Takes a queue id (numerical) as its only argument. Makes sure that
+Scopes it pulls out apply to this queue (or another that you've selected with
+another call to this method
+
+=cut
+
+sub LimitToQueue {
+ my $self = shift;
+ my $queue = shift;
+
+ $self->Limit (ALIAS => $self->_OCFAlias,
+ ENTRYAGGREGATOR => 'OR',
+ FIELD => 'ObjectId',
+ VALUE => "$queue")
+ if defined $queue;
+ $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
+}
+
+
+=head2 LimitToGlobal
+
+DEPRECATED since CFs are applicable not only to tickets these days.
+
+Makes sure that Scopes it pulls out apply to all queues
+(or another that you've selected with
+another call to this method or LimitToQueue)
+
+=cut
+
+sub LimitToGlobal {
+ my $self = shift;
+
+ $self->Limit (ALIAS => $self->_OCFAlias,
+ ENTRYAGGREGATOR => 'OR',
+ FIELD => 'ObjectId',
+ VALUE => 0);
+ $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
+}
+
+
+=head2 ApplySortOrder
+
+Sort custom fields according to thier order application to objects. It's
+expected that collection contains only records of one
+L<RT::CustomField/LookupType> and applied to one object or globally
+(L</LimitToGlobalOrObjectId>), otherwise sorting makes no sense.
+
+=cut
+
+sub ApplySortOrder {
+ my $self = shift;
+ my $order = shift || 'ASC';
+ $self->OrderByCols( {
+ ALIAS => $self->_OCFAlias,
+ FIELD => 'SortOrder',
+ ORDER => $order,
+ } );
+}
+
+
+=head2 ContextObject
+
+Returns context object for this collection of custom fields,
+but only if it's defined.
+
+=cut
+
+sub ContextObject {
+ my $self = shift;
+ return $self->{'context_object'};
+}
+
+
+=head2 SetContextObject
+
+Sets context object for this collection of custom fields.
+
+=cut
+
+sub SetContextObject {
+ my $self = shift;
+ return $self->{'context_object'} = shift;
+}
+
+
+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;
+}
+
+
+=head2 Next
+
+Returns the next custom field that this user can see.
+
+=cut
+
+sub Next {
+ my $self = shift;
+
+ my $CF = $self->SUPER::Next();
+ return $CF unless $CF;
+
+ $CF->SetContextObject( $self->ContextObject );
+
+ return $self->Next unless $CF->CurrentUserHasRight('SeeCustomField');
+ return $CF;
+}
+
+=head2 NewItem
+
+Returns an empty new RT::CustomField item
+Overrides <RT::SearchBuilder/NewItem> to make sure </ContextObject>
+is inherited.
+
+=cut
+
+sub NewItem {
+ my $self = shift;
+ my $res = RT::CustomField->new($self->CurrentUser);
+ $res->SetContextObject($self->ContextObject);
+ return $res;
+}
+
+RT::Base->_ImportOverlays();