summaryrefslogtreecommitdiff
path: root/rt/lib/RT/CustomField_Overlay.pm
diff options
context:
space:
mode:
Diffstat (limited to 'rt/lib/RT/CustomField_Overlay.pm')
-rw-r--r--rt/lib/RT/CustomField_Overlay.pm232
1 files changed, 213 insertions, 19 deletions
diff --git a/rt/lib/RT/CustomField_Overlay.pm b/rt/lib/RT/CustomField_Overlay.pm
index 07a953c..5a4535e 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
# <jesse@bestpractical.com>
#
# (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'},
@@ -278,7 +292,7 @@ sub LoadByName {
my $CFs = RT::CustomFields->new($self->CurrentUser);
- $CFs->Limit( FIELD => 'Name', VALUE => $args{'Name'} );
+ $CFs->Limit( FIELD => 'Name', VALUE => $args{'Name'}, CASESENSITIVE => 0);
# Don't limit to queue if queue is 0. Trying to do so breaks
# RT::Group type CFs.
if (defined $args{'Queue'}) {
@@ -356,11 +370,8 @@ 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'));
@@ -370,13 +381,9 @@ sub AddValue {
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));
}
@@ -566,6 +573,22 @@ sub Types {
# }}}
+# {{{ IsSelectionType
+
+=head2 IsSelectionType
+
+Retuns a boolean value indicating whether the C<Values> method makes sense
+to this Custom Field.
+
+=cut
+
+sub IsSelectionType {
+ my $self = shift;
+ $self->Type =~ /(?:Select|Combobox)/;
+}
+
+# }}}
+
=head2 FriendlyType [TYPE, MAX_VALUES]
@@ -638,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<Pattern> 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
@@ -809,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
@@ -952,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);
@@ -1002,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
@@ -1038,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();
@@ -1101,6 +1224,77 @@ sub _ForObjectType {
}
-# }}}
+=head2 IncludeContentForValue [VALUE] (and SetIncludeContentForValue)
+
+Gets or sets the C<IncludeContentForValue> 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<LinkValueTo> 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<NAME>, 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;