CustomFields.pm 9.58 KB
Newer Older
1
# BEGIN BPS TAGGED BLOCK {{{
Jesse Vincent's avatar
Jesse Vincent committed
2
#
3
# COPYRIGHT:
Jesse Vincent's avatar
Jesse Vincent committed
4
#
5
# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
Kevin Falcone's avatar
Kevin Falcone committed
6
#                                          <sales@bestpractical.com>
Jesse Vincent's avatar
Jesse Vincent committed
7
#
8
# (Except where explicitly superseded by other copyright notices)
Jesse Vincent's avatar
Jesse Vincent committed
9
10
#
#
11
# LICENSE:
Jesse Vincent's avatar
Jesse Vincent committed
12
#
13
14
15
# This work is made available to you under the terms of Version 2 of
# the GNU General Public License. A copy of that license should have
# been provided with this software, but in any event can be snarfed
16
# from www.gnu.org.
Jesse Vincent's avatar
Jesse Vincent committed
17
#
18
19
20
21
# This work is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
Jesse Vincent's avatar
Jesse Vincent committed
22
#
23
24
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
Jesse Vincent's avatar
Jesse Vincent committed
25
26
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 or visit their web page on the internet at
Ruslan Zakirov's avatar
Ruslan Zakirov committed
27
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
Jesse Vincent's avatar
Jesse Vincent committed
28
29
#
#
30
# CONTRIBUTION SUBMISSION POLICY:
Jesse Vincent's avatar
Jesse Vincent committed
31
#
32
33
34
35
36
# (The following paragraph is not intended to limit the rights granted
# to you to modify and distribute this software under the terms of
# the GNU General Public License and is only of importance to you if
# you choose to contribute your changes and enhancements to the
# community by submitting them to Best Practical Solutions, LLC.)
Jesse Vincent's avatar
Jesse Vincent committed
37
#
38
39
40
41
42
43
44
45
# By intentionally submitting any modifications, corrections or
# derivatives to this work, or any other work intended for use with
# Request Tracker, to Best Practical Solutions, LLC, you confirm that
# you are the copyright holder for those contributions and you grant
# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
# royalty-free, perpetual, license to use, copy, create derivative
# works based on those contributions, and sublicense and distribute
# those contributions and any derivatives thereof.
Jesse Vincent's avatar
Jesse Vincent committed
46
#
47
# END BPS TAGGED BLOCK }}}
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
=head1 NAME

  RT::CustomFields - a collection of RT CustomField objects

=head1 SYNOPSIS

  use RT::CustomFields;

=head1 DESCRIPTION

=head1 METHODS



=cut

65
66
67

package RT::CustomFields;

68
use strict;
69
use warnings;
70

71
72
use base 'RT::SearchBuilder';

73
use DBIx::SearchBuilder::Unique;
74

75
76
77
78
use RT::CustomField;

sub Table { 'CustomFields'}

79
80
sub _Init {
    my $self = shift;
81
82
83
84
85
86
87
88
89
90
91
92
93

  # By default, order by SortOrder
  $self->OrderByCols(
	 { ALIAS => 'main',
	   FIELD => 'SortOrder',
	   ORDER => 'ASC' },
	 { ALIAS => 'main',
	   FIELD => 'Name',
	   ORDER => 'ASC' },
	 { ALIAS => 'main',
	   FIELD => 'id',
	   ORDER => 'ASC' },
     );
94
95
    $self->{'with_disabled_column'} = 1;

96
    return ( $self->SUPER::_Init(@_) );
97
}
98

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
=head2 LimitToGrouping

Limits this collection object to custom fields which appear under a
specified grouping by calling L</Limit> for each CF name as appropriate.

Requires an L<RT::Record> object or class name as the first argument and
accepts a grouping name as the second.  If the grouping name is false
(usually via the empty string), limits to custom fields which appear in no
grouping.

I<Caveat:> While the record object or class name is used to find the
available groupings, no automatic limit is placed on the lookup type of
the custom fields.  It's highly suggested you limit the collection by
queue or another lookup type first.  This is already done for you if
you're creating the collection via the L</CustomFields> method on an
L<RT::Record> object.

=cut

118
sub LimitToGrouping {
119
    my $self = shift;
120
    my $obj = shift;
121
    my $grouping = shift;
122

123
    my $config = RT->Config->Get('CustomFieldGroupings');
124
       $config = {} unless ref($config) eq 'HASH';
125
       $config = $config->{ref($obj) || $obj} || {};
126

127
128
    if ( $grouping ) {
        my $list = $config->{$grouping};
129
        unless ( $list and ref($list) eq 'ARRAY' and @$list ) {
130
131
132
133
134
135
            return $self->Limit( FIELD => 'id', VALUE => 0, ENTRYAGGREGATOR => 'AND' );
        }
        foreach ( @$list ) {
            $self->Limit( FIELD => 'Name', VALUE => $_ );
        }
    } else {
136
        my @list = map {@$_} grep defined && ref($_) eq 'ARRAY',
137
            values %{ $config };
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

        return unless @list;
        foreach ( @list ) {
            $self->Limit(
                FIELD => 'Name',
                OPERATOR => '!=',
                VALUE => $_,
                ENTRYAGGREGATOR => 'AND',
            );
        }

    }
    return;
}

153

154
=head2 LimitToLookupType
155

156
157
158
159
160
Takes LookupType and limits collection.

=cut

sub LimitToLookupType  {
161
    my $self = shift;
162
    my $lookup = shift;
Jesse Vincent's avatar
Jesse Vincent committed
163

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
    $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" );
    $self->Limit( FIELD => 'LookupType', ENDSWITH => "$lookup" );
}


=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" );
    $self->Limit( FIELD => 'LookupType', STARTSWITH => "$lookup" );
196
197
198
}


199
200
201
=head2 LimitToGlobalOrObjectId

Takes list of object IDs and limits collection to custom
202
fields that are added to these objects or globally.
203
204

=cut
Jesse Vincent's avatar
Jesse Vincent committed
205

206
207
208
209
210
211
212
213
214
215
216
217
sub LimitToGlobalOrObjectId {
    my $self = shift;
    my $global_only = 1;


    foreach my $id (@_) {
	$self->Limit( ALIAS           => $self->_OCFAlias,
		    FIELD           => 'ObjectId',
		    OPERATOR        => '=',
		    VALUE           => $id || 0,
		    ENTRYAGGREGATOR => 'OR' );
	$global_only = 0 if $id;
Jesse Vincent's avatar
Jesse Vincent committed
218
    }
219
220
221
222
223
224

    $self->Limit( ALIAS           => $self->_OCFAlias,
                 FIELD           => 'ObjectId',
                 OPERATOR        => '=',
                 VALUE           => 0,
                 ENTRYAGGREGATOR => 'OR' ) unless $global_only;
225
226
}

227
=head2 LimitToNotAdded
228
229
230
231
232
233
234

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

235
sub LimitToNotAdded {
236
    my $self = shift;
237
    return RT::ObjectCustomFields->new( $self->CurrentUser )
238
        ->LimitTargetToNotAdded( $self => @_ );
239
}
240

241
=head2 LimitToAdded
242
243
244
245
246
247

Limits collection to custom fields to listed objects or any corespondingly. Use
zero to mean global.

=cut

248
sub LimitToAdded {
249
    my $self = shift;
250
    return RT::ObjectCustomFields->new( $self->CurrentUser )
251
        ->LimitTargetToAdded( $self => @_ );
252
253
}

Kevin Riggle's avatar
Kevin Riggle committed
254
=head2 LimitToGlobalOrQueue QUEUEID
255

256
257
Limits the set of custom fields found to global custom fields or those
tied to the queue C<QUEUEID>, similar to L</LimitToGlobalOrObjectId>.
258

259
Note that this will cause the collection to only return ticket CFs.
260
261
262

=cut

263
sub LimitToGlobalOrQueue {
264
265
    my $self = shift;
    my $queue = shift;
Audrey Tang's avatar
Audrey Tang committed
266
267
    $self->LimitToGlobalOrObjectId( $queue );
    $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
268
269
270
271
272
}


=head2 LimitToQueue QUEUEID

273
274
275
Takes a numeric C<QUEUEID>, and limits the Custom Field collection to
those only applied directly to it; this limit is OR'd with other
L</LimitToQueue> and L</LimitToGlobal> limits.
276

277
Note that this will cause the collection to only return ticket CFs.
278
279
280
281
282

=cut

sub LimitToQueue  {
   my $self = shift;
283
284
285
286
287
288
289
290
   my $queue = shift;

   $self->Limit (ALIAS => $self->_OCFAlias,
                 ENTRYAGGREGATOR => 'OR',
                 FIELD => 'ObjectId',
                 VALUE => "$queue")
       if defined $queue;
   $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
291
292
293
294
295
}


=head2 LimitToGlobal

296
297
Limits the Custom Field collection to global ticket CFs; this limit is
OR'd with L</LimitToQueue> limits.
298

299
Note that this will cause the collection to only return ticket CFs.
300

301
=cut
302
303
304

sub LimitToGlobal  {
   my $self = shift;
305

306
307
308
  $self->Limit (ALIAS => $self->_OCFAlias,
                ENTRYAGGREGATOR => 'OR',
		FIELD => 'ObjectId',
309
		VALUE => 0);
Audrey Tang's avatar
Audrey Tang committed
310
  $self->LimitToLookupType( 'RT::Queue-RT::Ticket' );
311
312
}

Jesse Vincent's avatar
Jesse Vincent committed
313

314
=head2 ApplySortOrder
315

316
317
318
319
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.
320
321

=cut
322
323

sub ApplySortOrder {
324
    my $self = shift;
325
326
327
328
329
330
331
    my $order = shift || 'ASC';
    $self->OrderByCols( {
        ALIAS => $self->_OCFAlias,
        FIELD => 'SortOrder',
        ORDER => $order,
    } );
}
332
333


334
=head2 ContextObject
Jesse Vincent's avatar
Jesse Vincent committed
335

336
337
Returns context object for this collection of custom fields,
but only if it's defined.
Jesse Vincent's avatar
Jesse Vincent committed
338

339
=cut
340
341
342
343
344
345
346

sub ContextObject {
    my $self = shift;
    return $self->{'context_object'};
}


347
=head2 SetContextObject
348

349
Sets context object for this collection of custom fields.
350

Jesse Vincent's avatar
Jesse Vincent committed
351
352
=cut

353
sub SetContextObject {
354
    my $self = shift;
355
    return $self->{'context_object'} = shift;
356
357
}

358

359
sub _OCFAlias {
360
    my $self = shift;
361
362
    return RT::ObjectCustomFields->new( $self->CurrentUser )
        ->JoinTargetToThis( $self => @_ );
363
364
}

365
366
367
368
369
370

=head2 Next

Returns the next custom field that this user can see.

=cut
371

372
373
374
375
sub Next {
    my $self = shift;

    my $CF = $self->SUPER::Next();
376
    return $CF unless $CF;
Audrey Tang's avatar
Audrey Tang committed
377

378
    $CF->SetContextObject( $self->ContextObject );
Audrey Tang's avatar
Audrey Tang committed
379

380
381
    return $self->Next unless $CF->CurrentUserHasRight('SeeCustomField');
    return $CF;
382
}
Audrey Tang's avatar
Audrey Tang committed
383

384
=head2 NewItem
385

386
Returns an empty new RT::CustomField item
387
Overrides <RT::SearchBuilder/NewItem> to make sure </ContextObject>
388
is inherited.
389

390
=cut
391
392
393
394
395
396

sub NewItem {
    my $self = shift;
    my $res = RT::CustomField->new($self->CurrentUser);
    $res->SetContextObject($self->ContextObject);
    return $res;
397
}
398

399
400
RT::Base->_ImportOverlays();

401
1;