Master to 4.2.8
[usit-rt.git] / lib / RT / CustomFields.pm
CommitLineData
84fb5b46
MKG
1# BEGIN BPS TAGGED BLOCK {{{
2#
3# COPYRIGHT:
4#
320f0092 5# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
84fb5b46
MKG
6# <sales@bestpractical.com>
7#
8# (Except where explicitly superseded by other copyright notices)
9#
10#
11# LICENSE:
12#
13# This work is made available to you under the terms of Version 2 of
14# the GNU General Public License. A copy of that license should have
15# been provided with this software, but in any event can be snarfed
16# from www.gnu.org.
17#
18# This work is distributed in the hope that it will be useful, but
19# WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21# General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26# 02110-1301 or visit their web page on the internet at
27# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28#
29#
30# CONTRIBUTION SUBMISSION POLICY:
31#
32# (The following paragraph is not intended to limit the rights granted
33# to you to modify and distribute this software under the terms of
34# the GNU General Public License and is only of importance to you if
35# you choose to contribute your changes and enhancements to the
36# community by submitting them to Best Practical Solutions, LLC.)
37#
38# By intentionally submitting any modifications, corrections or
39# derivatives to this work, or any other work intended for use with
40# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41# you are the copyright holder for those contributions and you grant
42# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43# royalty-free, perpetual, license to use, copy, create derivative
44# works based on those contributions, and sublicense and distribute
45# those contributions and any derivatives thereof.
46#
47# END BPS TAGGED BLOCK }}}
48
49=head1 NAME
50
51 RT::CustomFields - a collection of RT CustomField objects
52
53=head1 SYNOPSIS
54
55 use RT::CustomFields;
56
57=head1 DESCRIPTION
58
59=head1 METHODS
60
61
62
63=cut
64
65
66package RT::CustomFields;
67
68use strict;
69use warnings;
70
af59614d 71use base 'RT::SearchBuilder';
84fb5b46
MKG
72
73use RT::CustomField;
74
84fb5b46
MKG
75sub Table { 'CustomFields'}
76
77sub _Init {
78 my $self = shift;
79
80 # By default, order by SortOrder
81 $self->OrderByCols(
af59614d
MKG
82 { ALIAS => 'main',
83 FIELD => 'SortOrder',
84 ORDER => 'ASC' },
85 { ALIAS => 'main',
86 FIELD => 'Name',
87 ORDER => 'ASC' },
88 { ALIAS => 'main',
89 FIELD => 'id',
90 ORDER => 'ASC' },
84fb5b46
MKG
91 );
92 $self->{'with_disabled_column'} = 1;
93
94 return ( $self->SUPER::_Init(@_) );
95}
96
af59614d
MKG
97=head2 LimitToGrouping
98
99Limits this collection object to custom fields which appear under a
100specified grouping by calling L</Limit> for each CF name as appropriate.
101
102Requires an L<RT::Record> object or class name as the first argument and
103accepts a grouping name as the second. If the grouping name is false
104(usually via the empty string), limits to custom fields which appear in no
105grouping.
106
107I<Caveat:> While the record object or class name is used to find the
108available groupings, no automatic limit is placed on the lookup type of
109the custom fields. It's highly suggested you limit the collection by
110queue or another lookup type first. This is already done for you if
111you're creating the collection via the L</CustomFields> method on an
112L<RT::Record> object.
113
114=cut
115
116sub LimitToGrouping {
117 my $self = shift;
118 my $obj = shift;
119 my $grouping = shift;
120
c33a4027
MKG
121 my $grouping_class = $self->NewItem->_GroupingClass($obj);
122
af59614d
MKG
123 my $config = RT->Config->Get('CustomFieldGroupings');
124 $config = {} unless ref($config) eq 'HASH';
c33a4027 125 $config = $config->{$grouping_class} || [];
af59614d
MKG
126 my %h = ref $config eq "ARRAY" ? @{$config} : %{$config};
127
128 if ( $grouping ) {
129 my $list = $h{$grouping};
130 unless ( $list and ref($list) eq 'ARRAY' and @$list ) {
131 return $self->Limit( FIELD => 'id', VALUE => 0, ENTRYAGGREGATOR => 'AND' );
132 }
133 foreach ( @$list ) {
134 $self->Limit( FIELD => 'Name', VALUE => $_, CASESENSITIVE => 0 );
135 }
136 } else {
137 my @list = map {@$_} grep defined && ref($_) eq 'ARRAY',
138 values %h;
139
140 return unless @list;
141 foreach ( @list ) {
142 $self->Limit(
143 FIELD => 'Name',
144 OPERATOR => '!=',
145 VALUE => $_,
146 ENTRYAGGREGATOR => 'AND',
147 CASESENSITIVE => 0,
148 );
149 }
150
151 }
152 return;
153}
154
84fb5b46
MKG
155
156=head2 LimitToLookupType
157
158Takes LookupType and limits collection.
159
160=cut
161
162sub LimitToLookupType {
163 my $self = shift;
164 my $lookup = shift;
165
166 $self->Limit( FIELD => 'LookupType', VALUE => "$lookup" );
167}
168
169=head2 LimitToChildType
170
171Takes partial LookupType and limits collection to records
172where LookupType is equal or ends with the value.
173
174=cut
175
176sub LimitToChildType {
177 my $self = shift;
178 my $lookup = shift;
179
180 $self->Limit( FIELD => 'LookupType', VALUE => "$lookup" );
181 $self->Limit( FIELD => 'LookupType', ENDSWITH => "$lookup" );
182}
183
184
185=head2 LimitToParentType
186
187Takes partial LookupType and limits collection to records
188where LookupType is equal or starts with the value.
189
190=cut
191
192sub LimitToParentType {
193 my $self = shift;
194 my $lookup = shift;
195
196 $self->Limit( FIELD => 'LookupType', VALUE => "$lookup" );
197 $self->Limit( FIELD => 'LookupType', STARTSWITH => "$lookup" );
198}
199
01e3b242
MKG
200=head2 LimitToObjectId
201
202Takes an ObjectId and limits the collection to CFs applied to said object.
203
204When called multiple times the ObjectId limits are joined with OR.
205
206=cut
207
208sub LimitToObjectId {
209 my $self = shift;
210 my $id = shift;
211 $self->Limit(
212 ALIAS => $self->_OCFAlias,
213 FIELD => 'ObjectId',
214 OPERATOR => '=',
215 VALUE => $id || 0,
216 ENTRYAGGREGATOR => 'OR'
217 );
218}
84fb5b46
MKG
219
220=head2 LimitToGlobalOrObjectId
221
222Takes list of object IDs and limits collection to custom
af59614d 223fields that are added to these objects or globally.
84fb5b46
MKG
224
225=cut
226
227sub LimitToGlobalOrObjectId {
228 my $self = shift;
229 my $global_only = 1;
230
231
232 foreach my $id (@_) {
01e3b242
MKG
233 $self->LimitToObjectId($id);
234 $global_only = 0 if $id;
84fb5b46
MKG
235 }
236
01e3b242 237 $self->LimitToObjectId(0) unless $global_only;
84fb5b46
MKG
238}
239
af59614d 240=head2 LimitToNotAdded
84fb5b46
MKG
241
242Takes either list of object ids or nothing. Limits collection
243to custom fields to listed objects or any corespondingly. Use
244zero to mean global.
245
246=cut
247
af59614d 248sub LimitToNotAdded {
84fb5b46 249 my $self = shift;
af59614d
MKG
250 return RT::ObjectCustomFields->new( $self->CurrentUser )
251 ->LimitTargetToNotAdded( $self => @_ );
84fb5b46
MKG
252}
253
af59614d 254=head2 LimitToAdded
84fb5b46
MKG
255
256Limits collection to custom fields to listed objects or any corespondingly. Use
257zero to mean global.
258
259=cut
260
af59614d 261sub LimitToAdded {
84fb5b46 262 my $self = shift;
af59614d
MKG
263 return RT::ObjectCustomFields->new( $self->CurrentUser )
264 ->LimitTargetToAdded( $self => @_ );
84fb5b46
MKG
265}
266
267=head2 LimitToGlobalOrQueue QUEUEID
268
af59614d
MKG
269Limits the set of custom fields found to global custom fields or those
270tied to the queue C<QUEUEID>, similar to L</LimitToGlobalOrObjectId>.
84fb5b46 271
af59614d 272Note that this will cause the collection to only return ticket CFs.
84fb5b46
MKG
273
274=cut
275
276sub LimitToGlobalOrQueue {
277 my $self = shift;
278 my $queue = shift;
279 $self->LimitToGlobalOrObjectId( $queue );
280 $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
281}
282
283
284=head2 LimitToQueue QUEUEID
285
af59614d
MKG
286Takes a numeric C<QUEUEID>, and limits the Custom Field collection to
287those only applied directly to it; this limit is OR'd with other
288L</LimitToQueue> and L</LimitToGlobal> limits.
84fb5b46 289
af59614d 290Note that this will cause the collection to only return ticket CFs.
84fb5b46
MKG
291
292=cut
293
294sub LimitToQueue {
295 my $self = shift;
af59614d
MKG
296 my $queue = shift;
297
298 $self->Limit (ALIAS => $self->_OCFAlias,
299 ENTRYAGGREGATOR => 'OR',
300 FIELD => 'ObjectId',
301 VALUE => "$queue")
302 if defined $queue;
303 $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
84fb5b46
MKG
304}
305
306
307=head2 LimitToGlobal
308
af59614d
MKG
309Limits the Custom Field collection to global ticket CFs; this limit is
310OR'd with L</LimitToQueue> limits.
84fb5b46 311
af59614d 312Note that this will cause the collection to only return ticket CFs.
84fb5b46
MKG
313
314=cut
315
316sub LimitToGlobal {
317 my $self = shift;
318
319 $self->Limit (ALIAS => $self->_OCFAlias,
320 ENTRYAGGREGATOR => 'OR',
af59614d
MKG
321 FIELD => 'ObjectId',
322 VALUE => 0);
84fb5b46
MKG
323 $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
324}
325
326
327=head2 ApplySortOrder
328
329Sort custom fields according to thier order application to objects. It's
330expected that collection contains only records of one
331L<RT::CustomField/LookupType> and applied to one object or globally
332(L</LimitToGlobalOrObjectId>), otherwise sorting makes no sense.
333
334=cut
335
336sub ApplySortOrder {
337 my $self = shift;
338 my $order = shift || 'ASC';
339 $self->OrderByCols( {
340 ALIAS => $self->_OCFAlias,
341 FIELD => 'SortOrder',
342 ORDER => $order,
343 } );
344}
345
346
347=head2 ContextObject
348
349Returns context object for this collection of custom fields,
350but only if it's defined.
351
352=cut
353
354sub ContextObject {
355 my $self = shift;
356 return $self->{'context_object'};
357}
358
359
360=head2 SetContextObject
361
362Sets context object for this collection of custom fields.
363
364=cut
365
366sub SetContextObject {
367 my $self = shift;
368 return $self->{'context_object'} = shift;
369}
370
371
372sub _OCFAlias {
373 my $self = shift;
af59614d
MKG
374 return RT::ObjectCustomFields->new( $self->CurrentUser )
375 ->JoinTargetToThis( $self => @_ );
84fb5b46
MKG
376}
377
378
379=head2 Next
380
381Returns the next custom field that this user can see.
382
383=cut
384
385sub Next {
386 my $self = shift;
387
388 my $CF = $self->SUPER::Next();
389 return $CF unless $CF;
390
391 $CF->SetContextObject( $self->ContextObject );
392
393 return $self->Next unless $CF->CurrentUserHasRight('SeeCustomField');
394 return $CF;
395}
396
397=head2 NewItem
398
399Returns an empty new RT::CustomField item
400Overrides <RT::SearchBuilder/NewItem> to make sure </ContextObject>
401is inherited.
402
403=cut
404
405sub NewItem {
406 my $self = shift;
407 my $res = RT::CustomField->new($self->CurrentUser);
408 $res->SetContextObject($self->ContextObject);
409 return $res;
410}
411
412RT::Base->_ImportOverlays();
413
4141;