3 # Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
5 # (Except where explictly superceded by other copyright notices)
7 # This work is made available to you under the terms of Version 2 of
8 # the GNU General Public License. A copy of that license should have
9 # been provided with this software, but in any event can be snarfed
12 # This work is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # General Public License for more details.
17 # Unless otherwise specified, all modifications, corrections or
18 # extensions to this work which alter its source code become the
19 # property of Best Practical Solutions, LLC when submitted for
20 # inclusion in the work.
25 no warnings qw(redefine);
27 use vars qw(@TYPES %TYPES);
29 use RT::CustomFieldValues;
30 use RT::TicketCustomFieldValues;
32 # Enumerate all valid types for this custom field
35 'SelectMultiple', # loc
36 'FreeformSingle', # loc
37 'FreeformMultiple', # loc
40 # Populate a hash of types of easier validation
41 for (@TYPES) { $TYPES{$_} = 1};
48 RT::CustomField_Overlay
58 =head2 Create PARAMHASH
60 Create takes a hash of values and creates a row in the database:
65 varchar(255) 'Description'.
67 smallint(6) 'Disabled'.
88 if ( ! $args{'Queue'} ) {
89 unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'AdminCustomFields') ) {
90 return ( 0, $self->loc('Permission Denied') );
94 my $queue = RT::Queue->new($self->CurrentUser);
95 $queue->Load($args{'Queue'});
97 return (0, $self->loc("Queue not found"));
99 unless ( $queue->CurrentUserHasRight('AdminCustomFields') ) {
100 return ( 0, $self->loc('Permission Denied') );
103 $self->SUPER::Create(
104 Name => $args{'Name'},
105 Type => $args{'Type'},
106 Queue => $args{'Queue'},
107 Description => $args{'Description'},
108 SortOrder => $args{'SortOrder'},
109 Disabled => $args{'Disabled'},
115 # {{{ sub LoadByNameAndQueue
117 =head2 LoadByNameAndQueue (Queue => QUEUEID, Name => NAME)
119 Loads the Custom field named NAME for Queue QUEUE. If QUEUE is 0,
120 loads a global custom field
124 # Compatibility for API change after 3.0 beta 1
125 *LoadNameAndQueue = \&LoadByNameAndQueue;
127 sub LoadByNameAndQueue {
135 if ($args{'Queue'} =~ /\D/) {
136 my $QueueObj = RT::Queue->new($self->CurrentUser);
137 $QueueObj->Load($args{'Queue'});
138 $args{'Queue'} = $QueueObj->Id;
141 return ( $self->LoadByCols( Name => $args{'Name'}, Queue => $args{'Queue'} ) );
147 # {{{ Dealing with custom field values
150 use_ok(RT::CustomField);
151 ok(my $cf = RT::CustomField->new($RT::SystemUser));
152 ok(my ($id, $msg)= $cf->Create( Name => 'TestingCF',
155 Description => 'A Testing custom field',
156 Type=> 'SelectSingle'), 'Created a global CustomField');
157 ok($id != 0, 'Global custom field correctly created');
158 ok ($cf->SingleValue);
159 ok($cf->Type eq 'SelectSingle');
161 ok($cf->SetType('SelectMultiple'));
162 ok($cf->Type eq 'SelectMultiple');
163 ok(!$cf->SingleValue );
164 ok(my ($bogus_val, $bogus_msg) = $cf->SetType('BogusType') , "Trying to set a custom field's type to a bogus type");
165 ok($bogus_val == 0, "Unable to set a custom field's type to a bogus type");
167 ok(my $bad_cf = RT::CustomField->new($RT::SystemUser));
168 ok(my ($bad_id, $bad_msg)= $cf->Create( Name => 'TestingCF-bad',
171 Description => 'A Testing custom field with a bogus Type',
172 Type=> 'SelectSingleton'), 'Created a global CustomField with a bogus type');
173 ok($bad_id == 0, 'Global custom field correctly decided to not create a cf with a bogus type ');
183 Create a new value for this CustomField. Takes a paramhash containing the elements Name, Description and SortOrder
187 ok(my $cf = RT::CustomField->new($RT::SystemUser));
190 ok(my ($val,$msg) = $cf->AddValue(Name => 'foo' , Description => 'TestCFValue', SortOrder => '6'));
192 ok (my ($delval, $delmsg) = $cf->DeleteValue($val));
201 my %args = ( Name => undef,
202 Description => undef,
206 unless ($self->CurrentUserHasRight('AdminCustomFields')) {
207 return (0, $self->loc('Permission Denied'));
210 unless ($args{'Name'}) {
211 return(0, $self->loc("Can't add a custom field value without a name"));
213 my $newval = RT::CustomFieldValue->new($self->CurrentUser);
214 return($newval->Create(
215 CustomField => $self->Id,
216 Name =>$args{'Name'},
217 Description => ($args{'Description'} || ''),
218 SortOrder => ($args{'SortOrder'} || '0')
227 =head2 DeleteValue ID
229 Deletes a value from this custom field by id.
231 Does not remove this value for any article which has had it selected
238 unless ($self->CurrentUserHasRight('AdminCustomFields')) {
239 return (0, $self->loc('Permission Denied'));
242 my $val_to_del = RT::CustomFieldValue->new($self->CurrentUser);
243 $val_to_del->Load($id);
244 unless ($val_to_del->Id) {
245 return (0, $self->loc("Couldn't find that value"));
247 unless ($val_to_del->CustomField == $self->Id) {
248 return (0, $self->loc("That is not a value for this custom field"));
251 my $retval = $val_to_del->Delete();
253 return ($retval, $self->loc("Custom field value deleted"));
255 return(0, $self->loc("Custom field value could not be deleted"));
265 Return a CustomFieldeValues object of all acceptable values for this Custom Field.
273 my $cf_values = RT::CustomFieldValues->new($self->CurrentUser);
274 if ( $self->__Value('Queue') == 0 || $self->CurrentUserHasRight( 'SeeQueue') ) {
275 $cf_values->LimitToCustomField($self->Id);
284 # {{{ Ticket related routines
286 # {{{ ValuesForTicket
288 =head2 ValuesForTicket TICKET
290 Returns a RT::TicketCustomFieldValues object of this Field's values for TICKET.
291 TICKET is a ticket id.
296 sub ValuesForTicket {
298 my $ticket_id = shift;
300 my $values = new RT::TicketCustomFieldValues($self->CurrentUser);
301 $values->LimitToCustomField($self->Id);
302 $values->LimitToTicket($ticket_id);
309 # {{{ AddValueForTicket
311 =head2 AddValueForTicket HASH
313 Adds a custom field value for a ticket. Takes a param hash of Ticket and Content
317 sub AddValueForTicket {
319 my %args = ( Ticket => undef,
323 my $newval = RT::TicketCustomFieldValue->new($self->CurrentUser);
324 my $val = $newval->Create(Ticket => $args{'Ticket'},
325 Content => $args{'Content'},
326 CustomField => $self->Id);
335 # {{{ DeleteValueForTicket
337 =head2 DeleteValueForTicket HASH
339 Adds a custom field value for a ticket. Takes a param hash of Ticket and Content
343 sub DeleteValueForTicket {
345 my %args = ( Ticket => undef,
349 my $oldval = RT::TicketCustomFieldValue->new($self->CurrentUser);
350 $oldval->LoadByTicketContentAndCustomField (Ticket => $args{'Ticket'},
351 Content => $args{'Content'},
352 CustomField => $self->Id );
353 # check ot make sure we found it
354 unless ($oldval->Id) {
355 return(0, $self->loc("Custom field value [_1] could not be found for custom field [_2]", $args{'Content'}, $self->Name));
359 my $ret = $oldval->Delete();
361 return(0, $self->loc("Custom field value could not be found"));
363 return(1, $self->loc("Custom field value deleted"));
371 =head2 ValidateQueue Queue
373 Make sure that the queue specified is a valid queue name
381 if ($id eq '0') { # 0 means "Global" null would _not_ be ok.
385 my $q = RT::Queue->new($RT::SystemUser);
400 Retuns an array of the types of CustomField that are supported
411 =head2 FriendlyType [TYPE]
413 Returns a localized human-readable version of the custom field type.
414 If a custom field type is specified as the parameter, the friendly type for that type will be returned
421 my $type = shift || $self->Type;
423 if ( $type eq 'SelectSingle' ) {
424 return ( $self->loc('Select one value') );
426 elsif ( $type eq 'SelectMultiple' ) {
427 return ( $self->loc('Select multiple values') );
429 elsif ( $type eq 'FreeformSingle' ) {
430 return ( $self->loc('Enter one value') );
432 elsif ( $type eq 'FreeformMultiple' ) {
433 return ( $self->loc('Enter multiple values') );
436 return ( $self->loc( $self->Type ) );
441 =head2 ValidateType TYPE
443 Takes a single string. returns true if that string is a value
448 ok(my $cf = RT::CustomField->new($RT::SystemUser));
449 ok($cf->ValidateType('SelectSingle'));
450 ok($cf->ValidateType('SelectMultiple'));
451 ok(!$cf->ValidateType('SelectFooMultiple'));
473 Returns true if this CustomField only accepts a single value.
474 Returns false if it accepts multiple values
480 if ($self->Type =~ /Single$/) {
490 # {{{ sub CurrentUserHasRight
492 =head2 CurrentUserHasRight RIGHT
494 Helper function to call the custom field's queue's CurrentUserHasRight with the passed in args.
498 sub CurrentUserHasRight {
501 # if there's no queue, we want to know about a global right
502 if ( ( !defined $self->__Value('Queue') ) || ( $self->__Value('Queue') == 0 ) ) {
503 return $self->CurrentUser->HasRight( Object => $RT::System, Right => $right);
505 return ( $self->QueueObj->CurrentUserHasRight($right) );
516 unless ( $self->CurrentUserHasRight('AdminCustomFields') ) {
517 return ( 0, $self->loc('Permission Denied') );
519 return ( $self->SUPER::_Set(@_) );
529 Takes the name of a table column.
530 Returns its value as a string, if the user passes an ACL check
539 # We need to expose the queue so that we can do things like ACL checks
540 if ( $field eq 'Queue') {
541 return ( $self->SUPER::_Value($field) );
545 #Anybody can see global custom fields, otherwise we need to do the rights check
546 unless ( $self->__Value('Queue') == 0 || $self->CurrentUserHasRight( 'SeeQueue') ) {
549 return ( $self->__Value($field) );
554 # {{{ sub SetDisabled
559 1 will cause this custom field to no longer be avaialble for tickets.
560 0 will re-enable this queue