[Rt-commit] rt branch, 5.0/articles-unique-only-within-own-class, created. rt-5.0.1-1-g5dcbf9879d

Steve Burr steve at bestpractical.com
Fri Apr 23 16:42:56 EDT 2021


The branch, 5.0/articles-unique-only-within-own-class has been created
        at  5dcbf9879d2c8aa27d62fee3133f5ea609479220 (commit)

- Log -----------------------------------------------------------------
commit 5dcbf9879d2c8aa27d62fee3133f5ea609479220
Author: Steven Burr <steve at bestpractical.com>
Date:   Fri Apr 23 16:27:39 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 396c77918f..4b90bd0284 100644
--- a/lib/RT/Article.pm
+++ b/lib/RT/Article.pm
@@ -63,7 +63,6 @@ use RT::CustomFields;
 use RT::URI::fsck_com_article;
 use RT::Transactions;
 
-
 sub Table {'Articles'}
 
 # This object takes custom fields
@@ -111,12 +110,14 @@ sub Create {
         return ( 0, $self->loc('Invalid Class') );
     }
 
+    $self->{->'_creating_class'} = $class->id;
+
     unless ( $class->CurrentUserHasRight('CreateArticle') ) {
         return ( 0, $self->loc("Permission Denied") );
     }
 
     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(
@@ -231,7 +232,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 permitted.
 
@@ -241,16 +244,28 @@ Empty names are permitted.
 sub ValidateName {
     my $self = shift;
     my $name = shift;
+    my $class = shift || ($self->ClassObj && $self->ClassObj->id) || $self->{'_creating_class'};
 
     if ( !$name ) {
         return (1);
     }
 
-    my $temp = RT::Article->new($RT::SystemUser);
-    $temp->LoadByCols( Name => $name );
-    if ( $temp->id && 
-         (!$self->id || ($temp->id != $self->id ))) {
-        return (undef);
+    if ( $class ) {
+        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 );
+        while ( my $article = $articles->Next ) {
+            if ( $article->id && ( !$self->id || ($article->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);

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


More information about the rt-commit mailing list