X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=rt%2Flib%2FRT%2FCustomField_Overlay.pm;h=8f7c8bd555005211b14d2986732872b86ce06f23;hp=743c85cd7a4b274687a5d36248ec5e52c30aa370;hb=ef20b2b6b1feb47ad02b5ff7525f1a0fd11d0fa4;hpb=a513c0bef534d05f03c1242831b6f3be19b97dae diff --git a/rt/lib/RT/CustomField_Overlay.pm b/rt/lib/RT/CustomField_Overlay.pm index 743c85cd7..8f7c8bd55 100644 --- a/rt/lib/RT/CustomField_Overlay.pm +++ b/rt/lib/RT/CustomField_Overlay.pm @@ -2,7 +2,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC # # # (Except where explicitly superseded by other copyright notices) @@ -22,7 +22,9 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/copyleft/gpl.html. # # # CONTRIBUTION SUBMISSION POLICY: @@ -85,6 +87,11 @@ use RT::ObjectCustomFieldValues; 'Upload one file', # loc 'Upload up to [_1] files', # loc ], + Combobox => [ + 'Combobox: Select or enter multiple values', # loc + 'Combobox: Select or enter one value', # loc + 'Combobox: Select or enter up to [_1] values', # loc + ], ); @@ -194,8 +201,15 @@ sub Create { unless ( $queue->CurrentUserHasRight('AssignCustomFields') ) { return ( 0, $self->loc('Permission Denied') ); } - $args{'LookupType'} = 'RT::Queue-RT::Ticket'; + $args{'LookupType'} = 'RT::Queue-RT::Ticket'; + $args{'Queue'} = $queue->Id; + } + + my ($ok, $msg) = $self->_IsValidRegex($args{'Pattern'}); + if (!$ok) { + return (0, $self->loc("Invalid pattern: [_1]", $msg)); } + my $rv = $self->SUPER::Create( Name => $args{'Name'}, Type => $args{'Type'}, @@ -356,26 +370,20 @@ ok ($delval,"Deleting a cf value: $delmsg"); =cut sub AddValue { - my $self = shift; - my %args = ( Name => undef, - Description => undef, - SortOrder => undef, - @_ ); + my $self = shift; + my %args = @_; unless ($self->CurrentUserHasRight('AdminCustomField')) { return (0, $self->loc('Permission Denied')); } - unless ($args{'Name'}) { + # allow zero value + if ( !defined $args{'Name'} || $args{'Name'} eq '' ) { 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') - )); + + my $newval = RT::CustomFieldValue->new($self->CurrentUser); + return($newval->Create(%args, CustomField => $self->Id)); } @@ -565,6 +573,22 @@ sub Types { # }}} +# {{{ IsSelectionType + +=head2 IsSelectionType + +Retuns a boolean value indicating whether the C method makes sense +to this Custom Field. + +=cut + +sub IsSelectionType { + my $self = shift; + $self->Type =~ /(?:Select|Combobox)/; +} + +# }}} + =head2 FriendlyType [TYPE, MAX_VALUES] @@ -637,6 +661,51 @@ sub SetType { $self->SUPER::SetType($type); } +=head2 SetPattern STRING + +Takes a single string representing a regular expression. Performs basic +validation on that regex, and sets the C field for the CF if it +is valid. + +=cut + +sub SetPattern { + my $self = shift; + my $regex = shift; + + my ($ok, $msg) = $self->_IsValidRegex($regex); + if ($ok) { + return $self->SUPER::SetPattern($regex); + } + else { + return (0, $self->loc("Invalid pattern: [_1]", $msg)); + } +} + +=head2 _IsValidRegex(Str $regex) returns (Bool $success, Str $msg) + +Tests if the string contains an invalid regex. + +=cut + +sub _IsValidRegex { + my $self = shift; + my $regex = shift or return (1, 'valid'); + + local $^W; local $@; + $SIG{__DIE__} = sub { 1 }; + $SIG{__WARN__} = sub { 1 }; + + if (eval { qr/$regex/; 1 }) { + return (1, 'valid'); + } + + my $err = $@; + $err =~ s{[,;].*}{}; # strip debug info from error + chomp $err; + return (0, $err); +} + # {{{ SingleValue =head2 SingleValue @@ -808,7 +877,7 @@ Returns an array of all possible composite values for custom fields. sub TypeComposites { my $self = shift; - return grep !/Text-0/, map { ("$_-1", "$_-0") } $self->Types; + return grep !/(?:[Tt]ext|Combobox)-0/, map { ("$_-1", "$_-0") } $self->Types; } =head2 LookupTypes @@ -876,10 +945,10 @@ sub AddToObject { if ( $ObjectCF->Id ) { return ( 0, $self->loc("That is already the current value") ); } - my ( $id, $msg ) = + my ( $oid, $msg ) = $ObjectCF->Create( ObjectId => $id, CustomField => $self->Id ); - return ( $id, $msg ); + return ( $oid, $msg ); } @@ -911,9 +980,10 @@ sub RemoveFromObject { unless ( $ObjectCF->Id ) { return ( 0, $self->loc("This custom field does not apply to that object") ); } - my ( $id, $msg ) = $ObjectCF->Delete; + # XXX: Delete doesn't return anything + my ( $oid, $msg ) = $ObjectCF->Delete; - return ( $id, $msg ); + return ( $oid, $msg ); } # {{{ AddValueForObject @@ -950,6 +1020,10 @@ sub AddValueForObject { return ( 0, $self->loc('Permission Denied') ); } + unless ( $self->MatchPattern($args{Content}) ) { + return ( 0, $self->loc('Input must match [_1]', $self->FriendlyPattern) ); + } + $RT::Handle->BeginTransaction; my $current_values = $self->ValuesForObject($obj); @@ -1000,6 +1074,51 @@ sub AddValueForObject { # }}} +# {{{ MatchPattern + +=head2 MatchPattern STRING + +Tests the incoming string against the Pattern of this custom field object +and returns a boolean; returns true if the Pattern is empty. + +=cut + +sub MatchPattern { + my $self = shift; + my $regex = $self->Pattern; + + return 1 if !length($regex); + return ($_[0] =~ $regex); +} + + +# }}} + +# {{{ FriendlyPattern + +=head2 FriendlyPattern + +Prettify the pattern of this custom field, by taking the text in C<(?#text)> +and localizing it. + +=cut + +sub FriendlyPattern { + my $self = shift; + my $regex = $self->Pattern; + + return '' if !length($regex); + if ($regex =~ /\(\?#([^)]*)\)/) { + return '[' . $self->loc($1) . ']'; + } + else { + return $regex; + } +} + + +# }}} + # {{{ DeleteValueForObject =head2 DeleteValueForObject HASH @@ -1036,10 +1155,16 @@ sub DeleteValueForObject { } - # check ot make sure we found it + # check to 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)); } + + # for single-value fields, we need to validate that empty string is a valid value for it + if ( $self->SingleValue and not $self->MatchPattern( '' ) ) { + return ( 0, $self->loc('Input must match [_1]', $self->FriendlyPattern) ); + } + # delete it my $ret = $oldval->Delete(); @@ -1099,6 +1224,77 @@ sub _ForObjectType { } -# }}} +=head2 IncludeContentForValue [VALUE] (and SetIncludeContentForValue) + +Gets or sets the C for this custom field. RT +uses this field to automatically include content into the user's browser +as they display records with custom fields in RT. + +=cut + +sub SetIncludeContentForValue { + shift->IncludeContentForValue(@_); +} +sub IncludeContentForValue{ + my $self = shift; + $self->_URLTemplate('IncludeContentForValue', @_); +} + + + +=head2 LinkValueTo [VALUE] (and SetLinkValueTo) + +Gets or sets the C for this custom field. RT +uses this field to make custom field values into hyperlinks in the user's +browser as they display records with custom fields in RT. + +=cut + + +sub SetLinkValueTo { + shift->LinkValueTo(@_); +} + +sub LinkValueTo { + my $self = shift; + $self->_URLTemplate('LinkValueTo', @_); + +} + + +=head2 _URLTemplate NAME [VALUE] + +With one argument, returns the _URLTemplate named C, but only if +the current user has the right to see this custom field. + +With two arguments, attemptes to set the relevant template value. + +=cut + + + +sub _URLTemplate { + my $self = shift; + my $template_name = shift; + if (@_) { + + my $value = shift; + unless ( $self->CurrentUserHasRight('AdminCustomField') ) { + return ( 0, $self->loc('Permission Denied') ); + } + $self->SetAttribute( Name => $template_name, Content => $value ); + return ( 1, $self->loc('Updated') ); + } else { + unless ( $self->id && $self->CurrentUserHasRight('SeeCustomField') ) { + return (undef); + } + + my @attr = $self->Attributes->Named($template_name); + my $attr = shift @attr; + + if ($attr) { return $attr->Content } + + } +} 1;