1 # {{{ BEGIN BPS TAGGED BLOCK
5 # This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC
6 # <jesse@bestpractical.com>
8 # (Except where explicitly superseded by other copyright notices)
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
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
28 # CONTRIBUTION SUBMISSION POLICY:
30 # (The following paragraph is not intended to limit the rights granted
31 # to you to modify and distribute this software under the terms of
32 # the GNU General Public License and is only of importance to you if
33 # you choose to contribute your changes and enhancements to the
34 # community by submitting them to Best Practical Solutions, LLC.)
36 # By intentionally submitting any modifications, corrections or
37 # derivatives to this work, or any other work intended for use with
38 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
39 # you are the copyright holder for those contributions and you grant
40 # Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
41 # royalty-free, perpetual, license to use, copy, create derivative
42 # works based on those contributions, and sublicense and distribute
43 # those contributions and any derivatives thereof.
45 # }}} END BPS TAGGED BLOCK
47 no warnings qw(redefine);
49 use vars qw(@TYPES %TYPES);
51 use RT::CustomFieldValues;
52 use RT::TicketCustomFieldValues;
54 # Enumerate all valid types for this custom field
57 'SelectMultiple', # loc
58 'FreeformSingle', # loc
59 'FreeformMultiple', # loc
62 # Populate a hash of types of easier validation
63 for (@TYPES) { $TYPES{$_} = 1};
70 RT::CustomField_Overlay
80 =head2 Create PARAMHASH
82 Create takes a hash of values and creates a row in the database:
87 varchar(255) 'Description'.
89 smallint(6) 'Disabled'.
110 if ( ! $args{'Queue'} ) {
111 unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'AdminCustomFields') ) {
112 return ( 0, $self->loc('Permission Denied') );
116 my $queue = RT::Queue->new($self->CurrentUser);
117 $queue->Load($args{'Queue'});
118 unless ($queue->Id) {
119 return (0, $self->loc("Queue not found"));
121 unless ( $queue->CurrentUserHasRight('AdminCustomFields') ) {
122 return ( 0, $self->loc('Permission Denied') );
125 $self->SUPER::Create(
126 Name => $args{'Name'},
127 Type => $args{'Type'},
128 Queue => $args{'Queue'},
129 Description => $args{'Description'},
130 SortOrder => $args{'SortOrder'},
131 Disabled => $args{'Disabled'},
137 # {{{ sub LoadByNameAndQueue
139 =head2 LoadByNameAndQueue (Queue => QUEUEID, Name => NAME)
141 Loads the Custom field named NAME for Queue QUEUE. If QUEUE is 0,
142 loads a global custom field
146 # Compatibility for API change after 3.0 beta 1
147 *LoadNameAndQueue = \&LoadByNameAndQueue;
149 sub LoadByNameAndQueue {
157 if ($args{'Queue'} =~ /\D/) {
158 my $QueueObj = RT::Queue->new($self->CurrentUser);
159 $QueueObj->Load($args{'Queue'});
160 $args{'Queue'} = $QueueObj->Id;
163 return ( $self->LoadByCols( Name => $args{'Name'}, Queue => $args{'Queue'} ) );
169 # {{{ Dealing with custom field values
172 use_ok(RT::CustomField);
173 ok(my $cf = RT::CustomField->new($RT::SystemUser));
174 ok(my ($id, $msg)= $cf->Create( Name => 'TestingCF',
177 Description => 'A Testing custom field',
178 Type=> 'SelectSingle'), 'Created a global CustomField');
179 ok($id != 0, 'Global custom field correctly created');
180 ok ($cf->SingleValue);
181 ok($cf->Type eq 'SelectSingle');
183 ok($cf->SetType('SelectMultiple'));
184 ok($cf->Type eq 'SelectMultiple');
185 ok(!$cf->SingleValue );
186 ok(my ($bogus_val, $bogus_msg) = $cf->SetType('BogusType') , "Trying to set a custom field's type to a bogus type");
187 ok($bogus_val == 0, "Unable to set a custom field's type to a bogus type");
189 ok(my $bad_cf = RT::CustomField->new($RT::SystemUser));
190 ok(my ($bad_id, $bad_msg)= $cf->Create( Name => 'TestingCF-bad',
193 Description => 'A Testing custom field with a bogus Type',
194 Type=> 'SelectSingleton'), 'Created a global CustomField with a bogus type');
195 ok($bad_id == 0, 'Global custom field correctly decided to not create a cf with a bogus type ');
205 Create a new value for this CustomField. Takes a paramhash containing the elements Name, Description and SortOrder
209 ok(my $cf = RT::CustomField->new($RT::SystemUser));
212 ok(my ($val,$msg) = $cf->AddValue(Name => 'foo' , Description => 'TestCFValue', SortOrder => '6'));
214 ok (my ($delval, $delmsg) = $cf->DeleteValue($val));
223 my %args = ( Name => undef,
224 Description => undef,
228 unless ($self->CurrentUserHasRight('AdminCustomFields')) {
229 return (0, $self->loc('Permission Denied'));
232 unless ($args{'Name'}) {
233 return(0, $self->loc("Can't add a custom field value without a name"));
235 my $newval = RT::CustomFieldValue->new($self->CurrentUser);
236 return($newval->Create(
237 CustomField => $self->Id,
238 Name =>$args{'Name'},
239 Description => ($args{'Description'} || ''),
240 SortOrder => ($args{'SortOrder'} || '0')
249 =head2 DeleteValue ID
251 Deletes a value from this custom field by id.
253 Does not remove this value for any article which has had it selected
260 unless ($self->CurrentUserHasRight('AdminCustomFields')) {
261 return (0, $self->loc('Permission Denied'));
264 my $val_to_del = RT::CustomFieldValue->new($self->CurrentUser);
265 $val_to_del->Load($id);
266 unless ($val_to_del->Id) {
267 return (0, $self->loc("Couldn't find that value"));
269 unless ($val_to_del->CustomField == $self->Id) {
270 return (0, $self->loc("That is not a value for this custom field"));
273 my $retval = $val_to_del->Delete();
275 return ($retval, $self->loc("Custom field value deleted"));
277 return(0, $self->loc("Custom field value could not be deleted"));
287 Return a CustomFieldeValues object of all acceptable values for this Custom Field.
295 my $cf_values = RT::CustomFieldValues->new($self->CurrentUser);
296 if ( $self->__Value('Queue') == 0 || $self->CurrentUserHasRight( 'SeeQueue') ) {
297 $cf_values->LimitToCustomField($self->Id);
306 # {{{ Ticket related routines
308 # {{{ ValuesForTicket
310 =head2 ValuesForTicket TICKET
312 Returns a RT::TicketCustomFieldValues object of this Field's values for TICKET.
313 TICKET is a ticket id.
318 sub ValuesForTicket {
320 my $ticket_id = shift;
322 my $values = new RT::TicketCustomFieldValues($self->CurrentUser);
323 $values->LimitToCustomField($self->Id);
324 $values->LimitToTicket($ticket_id);
331 # {{{ AddValueForTicket
333 =head2 AddValueForTicket HASH
335 Adds a custom field value for a ticket. Takes a param hash of Ticket and Content
339 sub AddValueForTicket {
341 my %args = ( Ticket => undef,
345 my $newval = RT::TicketCustomFieldValue->new($self->CurrentUser);
346 my $val = $newval->Create(Ticket => $args{'Ticket'},
347 Content => $args{'Content'},
348 CustomField => $self->Id);
357 # {{{ DeleteValueForTicket
359 =head2 DeleteValueForTicket HASH
361 Adds a custom field value for a ticket. Takes a param hash of Ticket and Content
365 sub DeleteValueForTicket {
367 my %args = ( Ticket => undef,
371 my $oldval = RT::TicketCustomFieldValue->new($self->CurrentUser);
372 $oldval->LoadByTicketContentAndCustomField (Ticket => $args{'Ticket'},
373 Content => $args{'Content'},
374 CustomField => $self->Id );
375 # check ot make sure we found it
376 unless ($oldval->Id) {
377 return(0, $self->loc("Custom field value [_1] could not be found for custom field [_2]", $args{'Content'}, $self->Name));
381 my $ret = $oldval->Delete();
383 return(0, $self->loc("Custom field value could not be found"));
385 return(1, $self->loc("Custom field value deleted"));
393 =head2 ValidateQueue Queue
395 Make sure that the queue specified is a valid queue name
403 if ($id eq '0') { # 0 means "Global" null would _not_ be ok.
407 my $q = RT::Queue->new($RT::SystemUser);
422 Retuns an array of the types of CustomField that are supported
433 =head2 FriendlyType [TYPE]
435 Returns a localized human-readable version of the custom field type.
436 If a custom field type is specified as the parameter, the friendly type for that type will be returned
443 my $type = shift || $self->Type;
445 if ( $type eq 'SelectSingle' ) {
446 return ( $self->loc('Select one value') );
448 elsif ( $type eq 'SelectMultiple' ) {
449 return ( $self->loc('Select multiple values') );
451 elsif ( $type eq 'FreeformSingle' ) {
452 return ( $self->loc('Enter one value') );
454 elsif ( $type eq 'FreeformMultiple' ) {
455 return ( $self->loc('Enter multiple values') );
458 return ( $self->loc( $self->Type ) );
463 =head2 ValidateType TYPE
465 Takes a single string. returns true if that string is a value
470 ok(my $cf = RT::CustomField->new($RT::SystemUser));
471 ok($cf->ValidateType('SelectSingle'));
472 ok($cf->ValidateType('SelectMultiple'));
473 ok(!$cf->ValidateType('SelectFooMultiple'));
495 Returns true if this CustomField only accepts a single value.
496 Returns false if it accepts multiple values
502 if ($self->Type =~ /Single$/) {
512 # {{{ sub CurrentUserHasRight
514 =head2 CurrentUserHasRight RIGHT
516 Helper function to call the custom field's queue's CurrentUserHasRight with the passed in args.
520 sub CurrentUserHasRight {
523 # if there's no queue, we want to know about a global right
524 if ( ( !defined $self->__Value('Queue') ) || ( $self->__Value('Queue') == 0 ) ) {
525 return $self->CurrentUser->HasRight( Object => $RT::System, Right => $right);
527 return ( $self->QueueObj->CurrentUserHasRight($right) );
538 unless ( $self->CurrentUserHasRight('AdminCustomFields') ) {
539 return ( 0, $self->loc('Permission Denied') );
541 return ( $self->SUPER::_Set(@_) );
551 Takes the name of a table column.
552 Returns its value as a string, if the user passes an ACL check
561 # We need to expose the queue so that we can do things like ACL checks
562 if ( $field eq 'Queue') {
563 return ( $self->SUPER::_Value($field) );
567 #Anybody can see global custom fields, otherwise we need to do the rights check
568 unless ( $self->__Value('Queue') == 0 || $self->CurrentUserHasRight( 'SeeQueue') ) {
571 return ( $self->__Value($field) );
576 # {{{ sub SetDisabled
581 1 will cause this custom field to no longer be avaialble for tickets.
582 0 will re-enable this queue