+ my $obj = shift;
+ my $grouping = shift;
+
+ my $grouping_class = $self->NewItem->_GroupingClass($obj);
+
+ my $config = RT->Config->Get('CustomFieldGroupings');
+ $config = {} unless ref($config) eq 'HASH';
+ $config = $config->{$grouping_class} || [];
+ my %h = ref $config eq "ARRAY" ? @{$config} : %{$config};
+
+ if ( $grouping ) {
+ my $list = $h{$grouping};
+ unless ( $list and ref($list) eq 'ARRAY' and @$list ) {
+ return $self->Limit( FIELD => 'id', VALUE => 0, ENTRYAGGREGATOR => 'AND' );
+ }
+ $self->Limit(
+ FIELD => 'Name',
+ FUNCTION => 'LOWER(?)',
+ OPERATOR => 'IN',
+ VALUE => [map {lc $_} @{$list}],
+ CASESENSITIVE => 1,
+ );
+ } else {
+ my @list = map {@$_} grep defined && ref($_) eq 'ARRAY',
+ values %h;
+
+ return unless @list;
+
+ $self->Limit(
+ FIELD => 'Name',
+ FUNCTION => 'LOWER(?)',
+ OPERATOR => 'NOT IN',
+ VALUE => [ map {lc $_} @list ],
+ CASESENSITIVE => 1,
+ );
+ }
+ return;
+}
+
+
+=head2 LimitToLookupType
+
+Takes LookupType and limits collection.
+
+=cut
+
+sub LimitToLookupType {
+ my $self = shift;
+ my $lookup = shift;
+
+ $self->Limit( FIELD => 'LookupType', VALUE => "$lookup" );
+}
+
+=head2 LimitToChildType
+
+Takes partial LookupType and limits collection to records
+where LookupType is equal or ends with the value.
+
+=cut
+
+sub LimitToChildType {
+ my $self = shift;
+ my $lookup = shift;
+
+ $self->Limit( FIELD => 'LookupType', VALUE => "$lookup", OPERATOR => "ENDSWITH" );
+}
+
+
+=head2 LimitToParentType
+
+Takes partial LookupType and limits collection to records
+where LookupType is equal or starts with the value.
+
+=cut
+
+sub LimitToParentType {
+ my $self = shift;
+ my $lookup = shift;
+
+ $self->Limit( FIELD => 'LookupType', VALUE => "$lookup", OPERATOR => "STARTSWITH" );
+}
+
+=head2 LimitToObjectId
+
+Takes an ObjectId and limits the collection to CFs applied to said object.
+
+When called multiple times the ObjectId limits are joined with OR.
+
+=cut
+
+sub LimitToObjectId {
+ my $self = shift;
+ my $id = shift;
+ $self->Limit(
+ ALIAS => $self->_OCFAlias,
+ FIELD => 'ObjectId',
+ OPERATOR => '=',
+ VALUE => $id || 0,
+ ENTRYAGGREGATOR => 'OR'
+ );
+}
+
+=head2 LimitToGlobalOrObjectId
+
+Takes list of object IDs and limits collection to custom
+fields that are added to these objects or globally.
+
+=cut
+
+sub LimitToGlobalOrObjectId {
+ my $self = shift;
+ my $global_only = 1;
+
+
+ foreach my $id (@_) {
+ $self->LimitToObjectId($id);
+ $global_only = 0 if $id;
+ }
+
+ $self->LimitToObjectId(0) unless $global_only;
+}
+
+=head2 LimitToNotAdded
+
+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 LimitToNotAdded {
+ my $self = shift;
+ return RT::ObjectCustomFields->new( $self->CurrentUser )
+ ->LimitTargetToNotAdded( $self => @_ );