[Rt-commit] rt branch, 4.4/unique-custom-fields, created. rt-4.4.0-229-g080f81f

Shawn Moore shawn at bestpractical.com
Fri May 20 16:32:56 EDT 2016


The branch, 4.4/unique-custom-fields has been created
        at  080f81f5850b67f850d9a8062b97adbed0715e3e (commit)

- Log -----------------------------------------------------------------
commit a31e8a937baa7a336c718911f9450e40e2c3d077
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri May 20 20:06:31 2016 +0000

    Add UniqueValues column to Custom Fields
    
        It's not enforced yet, but it has an Admin UI checkbox

diff --git a/etc/schema.Oracle b/etc/schema.Oracle
index 16ae12b..9a75f4b 100644
--- a/etc/schema.Oracle
+++ b/etc/schema.Oracle
@@ -357,6 +357,7 @@ CREATE TABLE CustomFields (
         SortOrder       NUMBER(11,0) DEFAULT 0 NOT NULL,
         LookupType      VARCHAR2(255),
         EntryHint       VARCHAR2(255) NULL,
+        UniqueValues    NUMBER(11,0) DEFAULT 0 NOT NULL,
         Creator         NUMBER(11,0) DEFAULT 0 NOT NULL,
         Created         DATE,
         LastUpdatedBy   NUMBER(11,0) DEFAULT 0 NOT NULL,
diff --git a/etc/schema.Pg b/etc/schema.Pg
index b23dbf0..1c4f5a8 100644
--- a/etc/schema.Pg
+++ b/etc/schema.Pg
@@ -541,6 +541,7 @@ CREATE TABLE CustomFields (
   EntryHint varchar(255) NULL,
   Description varchar(255) NULL  ,
   SortOrder integer NOT NULL DEFAULT 0  ,
+  UniqueValues integer NOT NULL DEFAULT 0 ,
 
   Creator integer NOT NULL DEFAULT 0  ,
   Created TIMESTAMP NULL  ,
diff --git a/etc/schema.SQLite b/etc/schema.SQLite
index acf3b3f..4080598 100644
--- a/etc/schema.SQLite
+++ b/etc/schema.SQLite
@@ -387,6 +387,7 @@ CREATE TABLE CustomFields (
   SortOrder integer NOT NULL DEFAULT 0  ,
   LookupType varchar(255) collate NOCASE NOT NULL,
   EntryHint varchar(255) NULL,
+  UniqueValues int2 NOT NULL DEFAULT 0,
 
   Creator integer NOT NULL DEFAULT 0  ,
   Created DATETIME NULL  ,
diff --git a/etc/schema.mysql b/etc/schema.mysql
index 9b239ad..f03862d 100644
--- a/etc/schema.mysql
+++ b/etc/schema.mysql
@@ -359,6 +359,7 @@ CREATE TABLE CustomFields (
   SortOrder integer NOT NULL DEFAULT 0  ,
   LookupType varchar(255) CHARACTER SET ascii NOT NULL,
   EntryHint varchar(255) NULL,
+  UniqueValues int2 NOT NULL DEFAULT 0 ,
 
   Creator integer NOT NULL DEFAULT 0  ,
   Created DATETIME NULL  ,
diff --git a/etc/upgrade/4.4.2/schema.Oracle b/etc/upgrade/4.4.2/schema.Oracle
new file mode 100644
index 0000000..b7ce195
--- /dev/null
+++ b/etc/upgrade/4.4.2/schema.Oracle
@@ -0,0 +1 @@
+ALTER TABLE CustomFields ADD UniqueValues NUMBER(11,0) DEFAULT 0 NOT NULL;
diff --git a/etc/upgrade/4.4.2/schema.Pg b/etc/upgrade/4.4.2/schema.Pg
new file mode 100644
index 0000000..6da8b60
--- /dev/null
+++ b/etc/upgrade/4.4.2/schema.Pg
@@ -0,0 +1 @@
+ALTER TABLE CustomFields ADD COLUMN UniqueValues integer NOT NULL DEFAULT 0;
diff --git a/etc/upgrade/4.4.2/schema.SQLite b/etc/upgrade/4.4.2/schema.SQLite
new file mode 100644
index 0000000..33540e7
--- /dev/null
+++ b/etc/upgrade/4.4.2/schema.SQLite
@@ -0,0 +1 @@
+ALTER TABLE CustomFields ADD COLUMN UniqueValues int2 NOT NULL DEFAULT 0;
diff --git a/etc/upgrade/4.4.2/schema.mysql b/etc/upgrade/4.4.2/schema.mysql
new file mode 100644
index 0000000..33540e7
--- /dev/null
+++ b/etc/upgrade/4.4.2/schema.mysql
@@ -0,0 +1 @@
+ALTER TABLE CustomFields ADD COLUMN UniqueValues int2 NOT NULL DEFAULT 0;
diff --git a/lib/RT/CustomField.pm b/lib/RT/CustomField.pm
index ee56a25..328fcc5 100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@ -246,16 +246,17 @@ C<RT::Ticket->CustomFieldLookupType> or C<RT::Transaction->CustomFieldLookupType
 sub Create {
     my $self = shift;
     my %args = (
-        Name        => '',
-        Type        => '',
-        MaxValues   => 0,
-        Pattern     => '',
-        Description => '',
-        Disabled    => 0,
-        LookupType  => '',
-        LinkValueTo => '',
+        Name         => '',
+        Type         => '',
+        MaxValues    => 0,
+        Pattern      => '',
+        Description  => '',
+        Disabled     => 0,
+        LookupType   => '',
+        LinkValueTo  => '',
         IncludeContentForValue => '',
-        EntryHint   => undef,
+        EntryHint    => undef,
+        UniqueValues => 0,
         @_,
     );
 
@@ -328,16 +329,17 @@ sub Create {
     $args{'Disabled'} ||= 0;
 
     (my $rv, $msg) = $self->SUPER::Create(
-        Name        => $args{'Name'},
-        Type        => $args{'Type'},
-        RenderType  => $args{'RenderType'},
-        MaxValues   => $args{'MaxValues'},
-        Pattern     => $args{'Pattern'},
-        BasedOn     => $args{'BasedOn'},
-        ValuesClass => $args{'ValuesClass'},
-        Description => $args{'Description'},
-        Disabled    => $args{'Disabled'},
-        LookupType  => $args{'LookupType'},
+        Name         => $args{'Name'},
+        Type         => $args{'Type'},
+        RenderType   => $args{'RenderType'},
+        MaxValues    => $args{'MaxValues'},
+        Pattern      => $args{'Pattern'},
+        BasedOn      => $args{'BasedOn'},
+        ValuesClass  => $args{'ValuesClass'},
+        Description  => $args{'Description'},
+        Disabled     => $args{'Disabled'},
+        LookupType   => $args{'LookupType'},
+        UniqueValues => $args{'UniqueValues'},
     );
 
     if ($rv) {
@@ -2448,6 +2450,8 @@ sub _CoreAccessible {
         {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varchar(255)', default => ''},
         EntryHint =>
         {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0, is_numeric => 0,  type => 'varchar(255)', default => undef },
+        UniqueValues =>
+        {read => 1, write => 1, sql_type => 5, length => 6,  is_blob => 0,  is_numeric => 1,  type => 'smallint(6)', default => '0'},
         Creator => 
         {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         Created => 
diff --git a/share/html/Admin/CustomFields/Modify.html b/share/html/Admin/CustomFields/Modify.html
index f9a7324..4c357ee 100644
--- a/share/html/Admin/CustomFields/Modify.html
+++ b/share/html/Admin/CustomFields/Modify.html
@@ -163,6 +163,12 @@ jQuery( function() {
 </td></tr>
 % }
 
+<tr><td class="label"> </td><td>
+<input type="hidden" class="hidden" name="SetUniqueValues" value="1" />
+<input type="checkbox" class="checkbox" id="UniqueValues" name="UniqueValues" value="1" <% $UniqueValuesChecked |n %> />
+<label for="UniqueValues"><&|/l&>Values must be unique</&></label>
+</td></tr>
+
 % $m->callback(CallbackName => 'BeforeEnabled', CustomField => $CustomFieldObj, CFvalidations => \@CFvalidations);
 
 <tr><td class="label"> </td><td>
@@ -211,6 +217,7 @@ else {
             BasedOn       => $BasedOn,
             Disabled      => ($Enabled ? 0 : 1),
             EntryHint     => $EntryHint,
+            UniqueValues  => $UniqueValues,
         );
         if (!$val) {
             push @results, loc("Could not create CustomField: [_1]", $msg);
@@ -233,7 +240,11 @@ if ( $ARGS{'Update'} && $id ne 'new' ) {
     #we're asking about enabled on the web page but really care about disabled.
     $ARGS{'Disabled'} = $Enabled? 0 : 1;
 
-    my @attribs = qw(Disabled Pattern Name TypeComposite LookupType Description LinkValueTo IncludeContentForValue EntryHint);
+    # make sure the unchecked checkbox still causes an update
+    $ARGS{UniqueValues} ||= 0 if $SetUniqueValues;
+
+    my @attribs = qw(Disabled Pattern Name TypeComposite LookupType Description LinkValueTo IncludeContentForValue EntryHint UniqueValues);
+
     push @results, UpdateRecordObject(
         AttributesRef => \@attribs,
         Object        => $CustomFieldObj,
@@ -354,6 +365,9 @@ MaybeRedirectForResults(
 my $EnabledChecked = qq[checked="checked"];
 $EnabledChecked = '' if $CustomFieldObj->Disabled;
 
+my $UniqueValuesChecked = qq[checked="checked"];
+$UniqueValuesChecked = '' if !$CustomFieldObj->UniqueValues;
+
 my @CFvalidations = (
     '(?#Mandatory).',
     '(?#Digits)^[\d.]+$',
@@ -374,6 +388,8 @@ $Pattern => undef
 $Name => undef
 $SetEnabled => undef
 $Enabled => 0
+$SetUniqueValues => undef
+$UniqueValues => 0
 $ValuesClass => 'RT::CustomFieldValues'
 $RenderType => undef
 $LinkValueTo => undef

commit d6ec455a3f52d3f4eb72c757dcf8e4ca0028f0bd
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri May 20 20:14:30 2016 +0000

    Enforce CustomField UniqueValues

diff --git a/lib/RT/CustomField.pm b/lib/RT/CustomField.pm
index 328fcc5..1c0f715 100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@ -1683,6 +1683,22 @@ sub AddValueForObject {
         }
     }
 
+    if ($self->UniqueValues) {
+        my $existing = RT::ObjectCustomFieldValue->new(RT->SystemUser);
+        $existing->LoadByCols(
+            CustomField  => $self->Id,
+            Content      => $args{'Content'},
+            LargeContent => $args{'LargeContent'},
+            ContentType  => $args{'ContentType'},
+            Disabled     => 0,
+        );
+        if ($existing->Id) {
+            $RT::Logger->debug( "Non-unique custom field value for CF #" . $self->Id ." with object custom field value " . $existing->Id );
+            $RT::Handle->Rollback();
+            return ( 0, $self->loc('That is not a unique value') );
+        }
+    }
+
     my $newval = RT::ObjectCustomFieldValue->new( $self->CurrentUser );
     my ($val, $msg) = $newval->Create(
         ObjectType   => ref($obj),

commit 080f81f5850b67f850d9a8062b97adbed0715e3e
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri May 20 20:32:41 2016 +0000

    Basic tests for unique custom field values

diff --git a/t/customfields/unique_values.t b/t/customfields/unique_values.t
new file mode 100644
index 0000000..9751cea
--- /dev/null
+++ b/t/customfields/unique_values.t
@@ -0,0 +1,51 @@
+use warnings;
+use strict;
+
+use RT::Test tests => undef;
+
+
+my $alpha = RT::Test->create_ticket( Subject => 'test unique values alpha', Queue => 'General' );
+my $beta = RT::Test->create_ticket( Subject => 'test unique values beta', Queue => 'General' );
+my ( $ret, $msg );
+
+{
+    diag "testing freeform single cf";
+    my $unique_single = RT::Test->load_or_create_custom_field(
+        Name         => 'unique single',
+        Type         => 'FreeformSingle',
+        Queue        => 0,
+        UniqueValues => 1,
+    );
+    ok($unique_single->UniqueValues, 'unique values for this CF');
+
+    ( $ret, $msg ) =
+      $alpha->AddCustomFieldValue( Field => $unique_single, Value => 'foo' );
+    ok( $ret, $msg );
+    is( $alpha->FirstCustomFieldValue($unique_single), 'foo', 'value is foo' );
+
+    ( $ret, $msg ) =
+      $beta->AddCustomFieldValue( Field => $unique_single, Value => 'foo' );
+    ok( !$ret, "can't reuse the OCFV 'foo'");
+    like($msg, qr/That is not a unique value/);
+    is( $beta->FirstCustomFieldValue($unique_single), undef, 'no value since it was a duplicate' );
+
+    ( $ret, $msg ) =
+      $alpha->AddCustomFieldValue( Field => $unique_single, Value => 'bar' );
+    ok( $ret, $msg );
+
+    is( $alpha->FirstCustomFieldValue($unique_single), 'bar', 'value is now bar' );
+
+    ( $ret, $msg ) =
+      $beta->AddCustomFieldValue( Field => $unique_single, Value => 'foo' );
+    ok( $ret, "can reuse foo since alpha switched away");
+    is( $beta->FirstCustomFieldValue($unique_single), 'foo', 'now beta has foo' );
+
+    ( $ret, $msg ) =
+      $alpha->AddCustomFieldValue( Field => $unique_single, Value => 'foo' );
+    ok( !$ret, "alpha can't switch back to foo since beta uses it");
+
+    is( $alpha->FirstCustomFieldValue($unique_single), 'bar', 'value is still bar' );
+}
+
+done_testing;
+

-----------------------------------------------------------------------


More information about the rt-commit mailing list