Browse Source

[sluggable] fixed a bug where slug was treated as maching and was only shorter

gediminasm 14 years ago
parent
commit
44c381ee8c

+ 23 - 4
lib/Gedmo/Sluggable/SluggableListener.php

@@ -3,8 +3,6 @@
 namespace Gedmo\Sluggable;
 
 use Doctrine\Common\EventArgs;
-use Doctrine\Common\Persistence\ObjectManager;
-use Doctrine\Common\Persistence\Mapping\ClassMetadata;
 use Gedmo\Mapping\MappedEventSubscriber;
 use Gedmo\Sluggable\Mapping\Event\SluggableAdapter;
 
@@ -232,7 +230,7 @@ class SluggableListener extends MappedEventSubscriber
      * @param string $preferedSlug
      * @return string - unique slug
      */
-    private function makeUniqueSlug(SluggableAdapter $ea, $object, $preferedSlug)
+    private function makeUniqueSlug(SluggableAdapter $ea, $object, $preferedSlug, $recursing = false)
     {
         $om = $ea->getObjectManager();
         $meta = $om->getClassMetadata(get_class($object));
@@ -242,6 +240,10 @@ class SluggableListener extends MappedEventSubscriber
         $result = $ea->getSimilarSlugs($object, $meta, $config, $preferedSlug);
         // add similar persisted slugs into account
         $result += $this->getSimilarPersistedSlugs($meta->name, $preferedSlug);
+        // leave only right slugs
+        if (!$recursing) {
+            $this->filterSimilarSlugs($result, $config, $preferedSlug);
+        }
 
         if ($result) {
             $generatedSlug = $preferedSlug;
@@ -263,7 +265,7 @@ class SluggableListener extends MappedEventSubscriber
                     $mapping['length'] - (strlen($i) + strlen($config['separator']))
                 );
                 $this->exponent = strlen($i) - 1;
-                $generatedSlug = $this->makeUniqueSlug($ea, $object, $generatedSlug);
+                $generatedSlug = $this->makeUniqueSlug($ea, $object, $generatedSlug, true);
             }
             $preferedSlug = $generatedSlug;
         }
@@ -292,4 +294,21 @@ class SluggableListener extends MappedEventSubscriber
         }
         return $result;
     }
+
+    /**
+     * Filters $slugs which are matched as prefix but are
+     * simply shorter slugs
+     *
+     * @param array $slugs
+     * @param array $config
+     * @param string $prefered
+     */
+    private function filterSimilarSlugs(array &$slugs, array &$config, $prefered)
+    {
+        foreach ($slugs as $key => $similar) {
+            if (!preg_match("@{$prefered}($|{$config['separator']}[\d]+$)@smi", $similar['slug'])) {
+                unset($slugs[$key]);
+            }
+        }
+    }
 }

+ 17 - 0
tests/Gedmo/Sluggable/SluggableDocumentTest.php

@@ -61,6 +61,23 @@ class SluggableDocumentTest extends BaseTestCaseMongoODM
         }
     }
 
+    public function testGithubIssue57()
+    {
+        // slug matched by prefix
+        $article = new Article;
+        $article->setTitle('my');
+        $article->setCode('slug');
+        $this->dm->persist($article);
+
+        $article2 = new Article;
+        $article2->setTitle('my');
+        $article2->setCode('s');
+        $this->dm->persist($article2);
+
+        $this->dm->flush();
+        $this->assertEquals('my-s', $article2->getSlug());
+    }
+
     private function populate()
     {
         $art0 = new Article();

+ 19 - 1
tests/Gedmo/Sluggable/SluggableTest.php

@@ -72,7 +72,7 @@ class SluggableTest extends BaseTestCaseORM
             $this->em->clear();
 
             $shorten = $article->getSlug();
-            $this->assertEquals(strlen($shorten), 64);
+            $this->assertEquals(64, strlen($shorten));
             $expected = 'the-title-the-title-the-title-the-title-the-title-the-title-the-';
             $expected = substr($expected, 0, 64 - (strlen($i+1) + 1)) . '-' . ($i+1);
             $this->assertEquals($shorten, $expected);
@@ -112,6 +112,7 @@ class SluggableTest extends BaseTestCaseORM
 
     public function testGithubIssue45()
     {
+        // persist new records with same slug
         $article = new Article;
         $article->setTitle('test');
         $article->setCode('code');
@@ -127,6 +128,23 @@ class SluggableTest extends BaseTestCaseORM
         $this->assertEquals('test-code-1', $article2->getSlug());
     }
 
+    public function testGithubIssue57()
+    {
+        // slug matched by prefix
+        $article = new Article;
+        $article->setTitle('my');
+        $article->setCode('slug');
+        $this->em->persist($article);
+
+        $article2 = new Article;
+        $article2->setTitle('my');
+        $article2->setCode('s');
+        $this->em->persist($article2);
+
+        $this->em->flush();
+        $this->assertEquals('my-s', $article2->getSlug());
+    }
+
     protected function getUsedEntityFixtures()
     {
         return array(