DoctrineExtensions icon indicating copy to clipboard operation
DoctrineExtensions copied to clipboard

RelativeSlugHandler with urilize set to true

Open alcohol opened this issue 2 months ago • 2 comments

See https://github.com/doctrine-extensions/DoctrineExtensions/pull/2985#issuecomment-3365518379 also.

It seems a missing test scenario caused a bug to sneak in.

Environment

Package

show

$ composer show --latest gedmo/doctrine-extensions
name     : gedmo/doctrine-extensions
descrip. : Doctrine behavioral extensions
keywords : Blameable, behaviors, doctrine, extensions, gedmo, loggable, nestedset, odm, orm, sluggable, sortable, timestampable, translatable, tree, uploadable
versions : * v3.21.0
released : 2025-09-22, last week
latest   : v3.21.0 released 2025-09-22, last week
type     : library
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage : http://gediminasm.org/
source   : [git] https://github.com/doctrine-extensions/DoctrineExtensions.git eb53dfcb2b592327b76ac5226fbb003d32aea37e
dist     : [zip] https://api.github.com/repos/doctrine-extensions/DoctrineExtensions/zipball/eb53dfcb2b592327b76ac5226fbb003d32aea37e eb53dfcb2b592327b76ac5226fbb003d32aea37e
path     : /workdir/vendor/gedmo/doctrine-extensions
names    : gedmo/doctrine-extensions

Doctrine packages

show

$ composer show --latest 'doctrine/*'
Direct dependencies required in composer.json:
doctrine/doctrine-bundle            2.16.2 2.16.2 Symfony DoctrineBundle
doctrine/doctrine-fixtures-bundle   4.1.0  4.1.0  Symfony DoctrineFixturesBundle
doctrine/doctrine-migrations-bundle 3.4.2  3.4.2  Symfony DoctrineMigrationsBundle
doctrine/orm                        3.5.2  3.5.2  Object-Relational-Mapper for PHP

Transitive dependencies not required in composer.json:
doctrine/collections                2.3.0  2.3.0  PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.
doctrine/data-fixtures              2.1.0  2.1.0  Data Fixtures for all Doctrine Object Managers
doctrine/dbal                       4.3.3  4.3.3  Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.
doctrine/deprecations               1.1.5  1.1.5  A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.
doctrine/event-manager              2.0.1  2.0.1  The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.
doctrine/inflector                  2.1.0  2.1.0  PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.
doctrine/instantiator               2.0.0  2.0.0  A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer                      3.0.1  3.0.1  PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
doctrine/migrations                 3.9.4  3.9.4  PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.
doctrine/persistence                4.1.0  4.1.0  The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.
doctrine/sql-formatter              1.5.2  1.5.2  a PHP SQL highlighting library

PHP version

$ php -v
PHP 8.4.12 (cli) (built: Aug 28 2025 18:19:24) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.4.12, Copyright (c) Zend Technologies
    with Zend OPcache v8.4.12, Copyright (c), by Zend Technologies

Subject

When using the RelativeSlugHandler with the option urilize set to true, it no longer applies the same transformation as before version v3.21.0.

Minimal repository with the bug

Steps to reproduce

Upgrade from an older version to v3.21.0.

Expected results

Apply the transformation as always.

Actual results

Transformation is not (fully) apply to the relative field.

alcohol avatar Oct 03 '25 13:10 alcohol

I threw some tests together quickly to hit that uncovered code path (basically just cloned the existing fixtures for relative slug handlers and added the urilize option) in https://github.com/doctrine-extensions/DoctrineExtensions/compare/main...mbabker:DoctrineExtensions:urilized-relative-slug-handler and the tests all pass without any src/ changes. As soon as I apply the changes you noted you needed, I got test failures.

EDIT: Draft PR with this branch at https://github.com/doctrine-extensions/DoctrineExtensions/pull/2991 just to ensure it worked across the whole dependency matrix, and Codecov does show it being hit now so that's a plus

diff --git a/src/Sluggable/Handler/RelativeSlugHandler.php b/src/Sluggable/Handler/RelativeSlugHandler.php
index 2fdac40b..344da781 100644
--- a/src/Sluggable/Handler/RelativeSlugHandler.php
+++ b/src/Sluggable/Handler/RelativeSlugHandler.php
@@ -126,6 +126,10 @@ class RelativeSlugHandler implements SlugHandlerInterface
                     $this->originalTransliterator,
                     [$slug, $separator, $object]
                 );
+                $slug = call_user_func_array(
+                    $this->sluggable->getUrlizer(),
+                    [$slug, $separator, $object]
+                );
             }
 
             $result = $slug.$this->usedOptions['separator'].$result;
There were 2 failures:

1) Gedmo\Tests\Sluggable\Handlers\BothSlugHandlerTest::testSlugGeneration
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'web/developer/php/herzult'
+'web-developer-php/herzult'

/tests/Gedmo/Sluggable/Handlers/BothSlugHandlerTest.php:58

2) Gedmo\Tests\Sluggable\Handlers\BothSlugHandlerTest::testSlugUpdates
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'web/developer/upd-gedi'
+'web-developer/upd-gedi'

/tests/Gedmo/Sluggable/Handlers/BothSlugHandlerTest.php:101

mbabker avatar Oct 03 '25 14:10 mbabker

Yeah I think I missed a perhaps crucial part of our setup; we are referencing a field that does not contain a slugged value, but the actual original value. This is because the slug of the referenced entity is not allowed to change - but the same does not hold true for the relative entity. Another reason we do that I just saw is because the slug of the "parent" entity is also composed using the RelativeleSlugHandler, but we only want the value of the entity itself, not the full relative slug.

I can see how this would break tests where RelativeleSlugHandler is basically used multiple times with already sluggified values (then the separator gets urilized).

alcohol avatar Oct 03 '25 14:10 alcohol