From 89aee9b8b2710c692977a9972d60525f98251e36 Mon Sep 17 00:00:00 2001 From: dchaudhari7177 <111210939+dchaudhari7177@users.noreply.github.com> Date: Wed, 9 Sep 2026 12:18:48 +0530 Subject: [PATCH] Do not assert a namespace separator when reporting a missing mapping file SymfonyFileLocator::findMappingFile() ends by computing the class's short name for the exception message: $pos = strrpos($className, '\'); assert(is_int($pos)); A class in the root namespace has no separator, so strrpos() returns false and the assertion fails. With zend.assertions enabled the caller gets an AssertionError instead of the MappingException the method is trying to throw: $locator = new SymfonyFileLocator([]); $locator->findMappingFile(DateTime::class); The realistic route in is AbstractQuery::setParameter() with a DateTime value and no explicit type. $pos exists only to render the message, so there is nothing to assert. A class with no separator is its own short name, which is a perfectly good thing to put in the message. --- src/Mapping/Driver/SymfonyFileLocator.php | 9 +++++---- tests/Mapping/SymfonyFileLocatorTest.php | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Mapping/Driver/SymfonyFileLocator.php b/src/Mapping/Driver/SymfonyFileLocator.php index ff662d78..44626192 100644 --- a/src/Mapping/Driver/SymfonyFileLocator.php +++ b/src/Mapping/Driver/SymfonyFileLocator.php @@ -12,10 +12,8 @@ use function array_keys; use function array_merge; -use function assert; use function is_dir; use function is_file; -use function is_int; use function realpath; use function sprintf; use function str_replace; @@ -244,11 +242,14 @@ public function findMappingFile(string $className) } $pos = strrpos($className, '\\'); - assert(is_int($pos)); throw MappingException::mappingFileNotFound( $className, - substr($className, $pos + 1) . $this->fileExtension + // A class in the root namespace has no separator, and then its + // short name is the whole name: DateTime is DateTime, which is a + // perfectly good thing to name in the message rather than a + // reason to fail an assertion. + ($pos === false ? $className : substr($className, $pos + 1)) . $this->fileExtension ); } diff --git a/tests/Mapping/SymfonyFileLocatorTest.php b/tests/Mapping/SymfonyFileLocatorTest.php index b04484ca..9b02e32f 100644 --- a/tests/Mapping/SymfonyFileLocatorTest.php +++ b/tests/Mapping/SymfonyFileLocatorTest.php @@ -189,6 +189,22 @@ public function testFindMappingFileNotFound(): void $locator->findMappingFile('Foo\\stdClass2'); } + public function testFindMappingFileNotFoundForClassInRootNamespace(): void + { + $path = __DIR__ . '/_files'; + $prefix = 'Foo'; + + $locator = new SymfonyFileLocator([$path => $prefix], '.yml'); + + // A class with no namespace separator used to fail the assertion that + // computed the short name for this message, so with zend.assertions + // on this threw AssertionError instead of MappingException. Reported + // from \DateTime reaching here through AbstractQuery::setParameter(). + $this->expectException(MappingException::class); + $this->expectExceptionMessage("No mapping file found named 'DateTime.yml' for class 'DateTime'."); + $locator->findMappingFile('DateTime'); + } + public function testFindMappingFileLeastSpecificNamespaceFirst(): void { // Low -> High