[Rt-commit] rt branch, 5.0/articles-unique-only-within-own-class2, created. rt-5.0.1-334-g2c818ce3cb

Steve Burr steve at bestpractical.com
Thu May 20 11:48:21 EDT 2021


The branch, 5.0/articles-unique-only-within-own-class2 has been created
        at  2c818ce3cbe33df2b09ee5287347257523b47681 (commit)

- Log -----------------------------------------------------------------
commit cd2550e0f8e02c51d5ae8e947033f5ec9f68a042
Author: Steven Burr <steve at bestpractical.com>
Date:   Thu May 20 11:47:22 2021 -0400

    Allow articles with same name in different classes
    
    Article names must be globally unique across RT. This change allows
    articles of the same name to exist as long as they belong to
    different article classes.
    
    Note that the RT::Article::ValidateName() method is changed to allow
    a ClassId to be passed as a second parameter, thereby altering the
    behavior of the uniqueness check. If the RT::Article::Create()
    method was called, it will always use the scoped uniqueness logic. If
    the object was populated another way e.g. Load() then the caller is
    responsible for supplying the second argument herself if that is the
    desired behavior.

diff --git a/lib/RT/Article.pm b/lib/RT/Article.pm
index dc24c9ba70..400e5234b6 100644
--- a/lib/RT/Article.pm
+++ b/lib/RT/Article.pm
@@ -117,8 +117,11 @@ sub Create {
 
     return ( undef, $self->loc('Name is required') ) unless $args{Name};
 
+    # only here for ValidateName, on create, being called in the context of DBIx::SB
+    $self->{'_creating_class'} = $class->id;
+
     return ( undef, $self->loc('Name in use') )
-      unless $self->ValidateName( $args{'Name'} );
+      unless $self->ValidateName( $args{'Name'}, $class->id );
 
     $RT::Handle->BeginTransaction();
     my ( $id, $msg ) = $self->SUPER::Create(
@@ -233,7 +236,9 @@ sub Create {
 
 =head2 ValidateName NAME
 
-Takes a string name. Returns true if that name isn't in use by another article
+Takes a string name and a class object. Returns true if that name isn't in use by another article of that class.
+
+If no class is supplied, returns true if that name isn't used by any other article at all.
 
 Empty names are not permitted.
 
@@ -243,16 +248,27 @@ Empty names are not permitted.
 sub ValidateName {
     my $self = shift;
     my $name = shift;
+    my $class_id = shift || ($self->ClassObj && $self->ClassObj->id) || $self->{'_creating_class'};
 
     if ( !$name ) {
         return (0);
     }
 
-    my $temp = RT::Article->new($RT::SystemUser);
-    $temp->LoadByCols( Name => $name );
-    if ( $temp->id && 
-         (!$self->id || ($temp->id != $self->id ))) {
-        return (undef);
+    if ( $class_id ) {
+        my $articles = RT::Articles->new($RT::SystemUser);
+        $articles->Limit( FIELD => 'Name', OPERATOR => '=', VALUE => $name );  # cannot use LimitName() as it hardcodes 'LIKE'
+        $articles->Limit( FIELD => 'Class', OPERATOR => '=', VALUE => $class_id );
+        while ( my $article = $articles->Next ) {
+            if ( $article->id && ( !$self->id || ($article->id != $self->id )) ) {
+                return (undef);
+            }
+        }
+    } else {
+        my $temp = RT::Article->new($RT::SystemUser);
+        $temp->LoadByCols( Name => $name );
+        if ( $temp->id && ( !$self->id || ($temp->id != $self->id )) ) {
+            return (undef);
+        }
     }
 
     return (1);

commit 2c818ce3cbe33df2b09ee5287347257523b47681
Author: Steven Burr <steve at bestpractical.com>
Date:   Thu May 20 11:47:59 2021 -0400

    Add tests for per-class article uniqueness

diff --git a/t/articles/article.t b/t/articles/article.t
index 4af62be303..2076766798 100644
--- a/t/articles/article.t
+++ b/t/articles/article.t
@@ -2,7 +2,7 @@
 use strict;
 use warnings;
 
-use RT::Test tests => 67;
+use RT::Test tests => 72;
 
 use_ok 'RT::Articles';
 use_ok 'RT::Classes';
@@ -82,6 +82,30 @@ ok ($val, "Article Deleted: $msg");
 $a2->Load($id);
 ok ($a2->Disabled, "the article is disabled");
 
+
+
+my $class1 = RT::Class->new($RT::SystemUser);
+($id, $msg) = $class1->Create(Name => "ScopedClassTest1-$$");
+ok ($id, $msg);
+
+my $class2 = RT::Class->new($RT::SystemUser);
+($id, $msg) = $class2->Create(Name => "ScopedClassTest2-$$");
+ok ($id, $msg);
+
+my $a4 = RT::Article->new($RT::SystemUser);
+($id, $msg) = $a4->Create(Class => $class1->id, Name => "ScopedClassTest$$" );
+ok ($id, $msg);
+
+my $a5 = RT::Article->new($RT::SystemUser);
+($id, $msg) = $a5->Create(Class => $class1->id, Name => "ScopedClassTest$$" );
+ok (!$id, $msg);
+
+my $a6 = RT::Article->new($RT::SystemUser);
+($id, $msg) = $a4->Create(Class => $class2->id, Name => "ScopedClassTest$$" );
+ok ($id, $msg);
+
+
+
 # NOT OK
 #$RT::Handle->SimpleQuery("DELETE FROM Links");
 

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


More information about the rt-commit mailing list