Skip to content

Commit

Permalink
fix: Normalize class names #300 (#301)
Browse files Browse the repository at this point in the history
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
  • Loading branch information
Tofandel and greg0ire committed Jul 7, 2022
1 parent 25ec98a commit 51e12c3
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 1 deletion.
12 changes: 12 additions & 0 deletions psalm.phpstub
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
/**
* Workaround for psalm to return a class-string when used with a class string
* Can be removed when https://github.com/vimeo/psalm/pull/8219 is released
*
* @psalm-pure
*
* @return ($string is class-string ? ($characters is '\\' ? class-string : string) : string)
*
* @psalm-flow ($string) -> return
*/
function ltrim(string $string, string $characters = " \t\n\r\0\x0B") : string {}
3 changes: 3 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,7 @@
</errorLevel>
</ArgumentTypeCoercion>
</issueHandlers>
<stubs>
<file name="psalm.phpstub" />
</stubs>
</psalm>
23 changes: 22 additions & 1 deletion src/Persistence/Mapping/AbstractClassMetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use function array_unshift;
use function assert;
use function class_exists;
use function ltrim;
use function str_replace;
use function strpos;
use function strrpos;
Expand Down Expand Up @@ -153,6 +154,21 @@ abstract protected function initializeReflection(
*/
abstract protected function isEntity(ClassMetadata $class);

/**
* Removes the prepended backslash of a class string to conform with how php outputs class names
*
* @psalm-param class-string $className
*
* @psalm-return class-string
*/
private function normalizeClassName(string $className): string
{
/**
* @phpstan-ignore-next-line
*/
return ltrim($className, '\\');
}

/**
* {@inheritDoc}
*
Expand All @@ -161,6 +177,8 @@ abstract protected function isEntity(ClassMetadata $class);
*/
public function getMetadataFor(string $className)
{
$className = $this->normalizeClassName($className);

if (isset($this->loadedMetadata[$className])) {
return $this->loadedMetadata[$className];
}
Expand Down Expand Up @@ -232,6 +250,8 @@ public function getMetadataFor(string $className)
*/
public function hasMetadataFor(string $className)
{
$className = $this->normalizeClassName($className);

return isset($this->loadedMetadata[$className]);
}

Expand All @@ -240,13 +260,14 @@ public function hasMetadataFor(string $className)
*
* NOTE: This is only useful in very special cases, like when generating proxy classes.
*
* @psalm-param class-string $className
* @psalm-param CMTemplate $class
*
* @return void
*/
public function setMetadataFor(string $className, ClassMetadata $class)
{
$this->loadedMetadata[$className] = $class;
$this->loadedMetadata[$this->normalizeClassName($className)] = $class;
}

/**
Expand Down
20 changes: 20 additions & 0 deletions tests/Persistence/Mapping/AbstractClassMetadataFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,22 @@ public function testItThrowsWhenAttemptingToCheckTransientForShortAlias(): void
// @phpstan-ignore-next-line
$cmf->isTransient('App:Test');
}

public function testItGetsTheSameMetadataForBackslashedClassName(): void
{
$cmf = $this->getMockForAbstractClass(AbstractClassMetadataFactory::class);
$cmf
->method('newClassMetadataInstance')
->with(SomeOtherEntity::class)
->willReturn(
$this->createStub(ClassMetadata::class)
);

/**
* @psalm-suppress ArgumentTypeCoercion
*/
self::assertSame($cmf->getMetadataFor(SomeOtherEntity::class), $cmf->getMetadataFor('\\' . SomeOtherEntity::class));
}
}

class SomeGrandParentEntity
Expand All @@ -91,3 +107,7 @@ class SomeParentEntity extends SomeGrandParentEntity
final class SomeEntity extends SomeParentEntity
{
}

final class SomeOtherEntity
{
}

0 comments on commit 51e12c3

Please sign in to comment.