# BEGIN LICENSE BLOCK # # Copyright (c) 1996-2003 Jesse Vincent # # (Except where explictly superceded by other copyright notices) # # 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 # from www.gnu.org. # # 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. # # Unless otherwise specified, all modifications, corrections or # extensions to this work which alter its source code become the # property of Best Practical Solutions, LLC when submitted for # inclusion in the work. # # # END LICENSE BLOCK use strict; no warnings qw(redefine); use vars qw(@TYPES %TYPES); use RT::CustomFieldValues; use RT::TicketCustomFieldValues; # Enumerate all valid types for this custom field @TYPES = ( 'SelectSingle', # loc 'SelectMultiple', # loc 'FreeformSingle', # loc 'FreeformMultiple', # loc ); # Populate a hash of types of easier validation for (@TYPES) { $TYPES{$_} = 1}; =head1 NAME RT::CustomField_Overlay =head1 DESCRIPTION =head1 'CORE' METHODS =cut =head2 Create PARAMHASH Create takes a hash of values and creates a row in the database: varchar(200) 'Name'. varchar(200) 'Type'. int(11) 'Queue'. varchar(255) 'Description'. int(11) 'SortOrder'. smallint(6) 'Disabled'. =cut sub Create { my $self = shift; my %args = ( Name => '', Type => '', Queue => '0', Description => '', SortOrder => '0', Disabled => '0', @_); if ( ! $args{'Queue'} ) { unless ( $self->CurrentUser->HasRight( Object => $RT::System, Right => 'AdminCustomFields') ) { return ( 0, $self->loc('Permission Denied') ); } } else { my $queue = RT::Queue->new($self->CurrentUser); $queue->Load($args{'Queue'}); unless ($queue->Id) { return (0, $self->loc("Queue not found")); } unless ( $queue->CurrentUserHasRight('AdminCustomFields') ) { return ( 0, $self->loc('Permission Denied') ); } } $self->SUPER::Create( Name => $args{'Name'}, Type => $args{'Type'}, Queue => $args{'Queue'}, Description => $args{'Description'}, SortOrder => $args{'SortOrder'}, Disabled => $args{'Disabled'}, ); } # {{{ sub LoadByNameAndQueue =head2 LoadByNameAndQueue (Queue => QUEUEID, Name => NAME) Loads the Custom field named NAME for Queue QUEUE. If QUEUE is 0, loads a global custom field =cut # Compatibility for API change after 3.0 beta 1 *LoadNameAndQueue = \&LoadByNameAndQueue; sub LoadByNameAndQueue { my $self = shift; my %args = ( Queue => undef, Name => undef, @_, ); if ($args{'Queue'} =~ /\D/) { my $QueueObj = RT::Queue->new($self->CurrentUser); $QueueObj->Load($args{'Queue'}); $args{'Queue'} = $QueueObj->Id; } return ( $self->LoadByCols( Name => $args{'Name'}, Queue => $args{'Queue'} ) ); } # }}} # {{{ Dealing with custom field values =begin testing use_ok(RT::CustomField); ok(my $cf = RT::CustomField->new($RT::SystemUser)); ok(my ($id, $msg)= $cf->Create( Name => 'TestingCF', Queue => '0', SortOrder => '1', Description => 'A Testing custom field', Type=> 'SelectSingle'), 'Created a global CustomField'); ok($id != 0, 'Global custom field correctly created'); ok ($cf->SingleValue); ok($cf->Type eq 'SelectSingle'); ok($cf->SetType('SelectMultiple')); ok($cf->Type eq 'SelectMultiple'); ok(!$cf->SingleValue ); ok(my ($bogus_val, $bogus_msg) = $cf->SetType('BogusType') , "Trying to set a custom field's type to a bogus type"); ok($bogus_val == 0, "Unable to set a custom field's type to a bogus type"); ok(my $bad_cf = RT::CustomField->new($RT::SystemUser)); ok(my ($bad_id, $bad_msg)= $cf->Create( Name => 'TestingCF-bad', Queue => '0', SortOrder => '1', Description => 'A Testing custom field with a bogus Type', Type=> 'SelectSingleton'), 'Created a global CustomField with a bogus type'); ok($bad_id == 0, 'Global custom field correctly decided to not create a cf with a bogus type '); =end testing =cut # {{{ AddValue =head2 AddValue HASH Create a new value for this CustomField. Takes a paramhash containing the elements Name, Description and SortOrder =begin testing ok(my $cf = RT::CustomField->new($RT::SystemUser)); $cf->Load(1); ok($cf->Id == 1); ok(my ($val,$msg) = $cf->AddValue(Name => 'foo' , Description => 'TestCFValue', SortOrder => '6')); ok($val != 0); ok (my ($delval, $delmsg) = $cf->DeleteValue($val)); ok ($delval != 0); =end testing =cut sub AddValue { my $self = shift; my %args = ( Name => undef, Description => undef, SortOrder => undef, @_ ); unless ($self->CurrentUserHasRight('AdminCustomFields')) { return (0, $self->loc('Permission Denied')); } unless ($args{'Name'}) { return(0, $self->loc("Can't add a custom field value without a name")); } my $newval = RT::CustomFieldValue->new($self->CurrentUser); return($newval->Create( CustomField => $self->Id, Name =>$args{'Name'}, Description => ($args{'Description'} || ''), SortOrder => ($args{'SortOrder'} || '0') )); } # }}} # {{{ DeleteValue =head2 DeleteValue ID Deletes a value from this custom field by id. Does not remove this value for any article which has had it selected =cut sub DeleteValue { my $self = shift; my $id = shift; unless ($self->CurrentUserHasRight('AdminCustomFields')) { return (0, $self->loc('Permission Denied')); } my $val_to_del = RT::CustomFieldValue->new($self->CurrentUser); $val_to_del->Load($id); unless ($val_to_del->Id) { return (0, $self->loc("Couldn't find that value")); } unless ($val_to_del->CustomField == $self->Id) { return (0, $self->loc("That is not a value for this custom field")); } my $retval = $val_to_del->Delete(); if ($retval) { return ($retval, $self->loc("Custom field value deleted")); } else { return(0, $self->loc("Custom field value could not be deleted")); } } # }}} # {{{ Values =head2 Values FIELD Return a CustomFieldeValues object of all acceptable values for this Custom Field. =cut sub Values { my $self = shift; my $cf_values = RT::CustomFieldValues->new($self->CurrentUser); if ( $self->__Value('Queue') == 0 || $self->CurrentUserHasRight( 'SeeQueue') ) { $cf_values->LimitToCustomField($self->Id); } return ($cf_values); } # }}} # }}} # {{{ Ticket related routines # {{{ ValuesForTicket =head2 ValuesForTicket TICKET Returns a RT::TicketCustomFieldValues object of this Field's values for TICKET. TICKET is a ticket id. =cut sub ValuesForTicket { my $self = shift; my $ticket_id = shift; my $values = new RT::TicketCustomFieldValues($self->CurrentUser); $values->LimitToCustomField($self->Id); $values->LimitToTicket($ticket_id); return ($values); } # }}} # {{{ AddValueForTicket =head2 AddValueForTicket HASH Adds a custom field value for a ticket. Takes a param hash of Ticket and Content =cut sub AddValueForTicket { my $self = shift; my %args = ( Ticket => undef, Content => undef, @_ ); my $newval = RT::TicketCustomFieldValue->new($self->CurrentUser); my $val = $newval->Create(Ticket => $args{'Ticket'}, Content => $args{'Content'}, CustomField => $self->Id); return($val); } # }}} # {{{ DeleteValueForTicket =head2 DeleteValueForTicket HASH Adds a custom field value for a ticket. Takes a param hash of Ticket and Content =cut sub DeleteValueForTicket { my $self = shift; my %args = ( Ticket => undef, Content => undef, @_ ); my $oldval = RT::TicketCustomFieldValue->new($self->CurrentUser); $oldval->LoadByTicketContentAndCustomField (Ticket => $args{'Ticket'}, Content => $args{'Content'}, CustomField => $self->Id ); # check ot make sure we found it unless ($oldval->Id) { return(0, $self->loc("Custom field value [_1] could not be found for custom field [_2]", $args{'Content'}, $self->Name)); } # delete it my $ret = $oldval->Delete(); unless ($ret) { return(0, $self->loc("Custom field value could not be found")); } return(1, $self->loc("Custom field value deleted")); } # }}} # }}} =head2 ValidateQueue Queue Make sure that the queue specified is a valid queue name =cut sub ValidateQueue { my $self = shift; my $id = shift; if ($id eq '0') { # 0 means "Global" null would _not_ be ok. return (1); } my $q = RT::Queue->new($RT::SystemUser); $q->Load($id); unless ($q->id) { return undef; } return (1); } # {{{ Types =head2 Types Retuns an array of the types of CustomField that are supported =cut sub Types { return (@TYPES); } # }}} =head2 FriendlyType [TYPE] Returns a localized human-readable version of the custom field type. If a custom field type is specified as the parameter, the friendly type for that type will be returned =cut sub FriendlyType { my $self = shift; my $type = shift || $self->Type; if ( $type eq 'SelectSingle' ) { return ( $self->loc('Select one value') ); } elsif ( $type eq 'SelectMultiple' ) { return ( $self->loc('Select multiple values') ); } elsif ( $type eq 'FreeformSingle' ) { return ( $self->loc('Enter one value') ); } elsif ( $type eq 'FreeformMultiple' ) { return ( $self->loc('Enter multiple values') ); } else { return ( $self->loc( $self->Type ) ); } } =head2 ValidateType TYPE Takes a single string. returns true if that string is a value type of custom field =begin testing ok(my $cf = RT::CustomField->new($RT::SystemUser)); ok($cf->ValidateType('SelectSingle')); ok($cf->ValidateType('SelectMultiple')); ok(!$cf->ValidateType('SelectFooMultiple')); =end testing =cut sub ValidateType { my $self = shift; my $type = shift; if( $TYPES{$type}) { return(1); } else { return undef; } } # {{{ SingleValue =head2 SingleValue Returns true if this CustomField only accepts a single value. Returns false if it accepts multiple values =cut sub SingleValue { my $self = shift; if ($self->Type =~ /Single$/) { return 1; } else { return undef; } } # }}} # {{{ sub CurrentUserHasRight =head2 CurrentUserHasRight RIGHT Helper function to call the custom field's queue's CurrentUserHasRight with the passed in args. =cut sub CurrentUserHasRight { my $self = shift; my $right = shift; # if there's no queue, we want to know about a global right if ( ( !defined $self->__Value('Queue') ) || ( $self->__Value('Queue') == 0 ) ) { return $self->CurrentUser->HasRight( Object => $RT::System, Right => $right); } else { return ( $self->QueueObj->CurrentUserHasRight($right) ); } } # }}} # {{{ sub _Set sub _Set { my $self = shift; unless ( $self->CurrentUserHasRight('AdminCustomFields') ) { return ( 0, $self->loc('Permission Denied') ); } return ( $self->SUPER::_Set(@_) ); } # }}} # {{{ sub _Value =head2 _Value Takes the name of a table column. Returns its value as a string, if the user passes an ACL check =cut sub _Value { my $self = shift; my $field = shift; # We need to expose the queue so that we can do things like ACL checks if ( $field eq 'Queue') { return ( $self->SUPER::_Value($field) ); } #Anybody can see global custom fields, otherwise we need to do the rights check unless ( $self->__Value('Queue') == 0 || $self->CurrentUserHasRight( 'SeeQueue') ) { return (undef); } return ( $self->__Value($field) ); } # }}} # {{{ sub SetDisabled =head2 SetDisabled Takes a boolean. 1 will cause this custom field to no longer be avaialble for tickets. 0 will re-enable this queue =cut # }}} 1;