Skip to content

Commit

Permalink
feature #1511 [make:entity] helper message with two classes having th…
Browse files Browse the repository at this point in the history
…e same name under different namespaces
  • Loading branch information
jeromegxj authored Apr 17, 2024
1 parent 481d6c6 commit be24be4
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/Maker/MakeEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,12 @@ private function askRelationType(ConsoleStyle $io, string $entityClass, string $

$originalEntityShort = Str::getShortClassName($entityClass);
$targetEntityShort = Str::getShortClassName($targetEntityClass);
if ($originalEntityShort === $targetEntityShort) {
[$originalDiscriminator, $targetDiscriminator] = Str::getHumanDiscriminatorBetweenTwoClasses($entityClass, $targetEntityClass);
$originalEntityShort = trim($originalDiscriminator.'\\'.$originalEntityShort, '\\');
$targetEntityShort = trim($targetDiscriminator.'\\'.$targetEntityShort, '\\');
}

$rows = [];
$rows[] = [
EntityRelation::MANY_TO_ONE,
Expand Down
32 changes: 32 additions & 0 deletions src/Str.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,38 @@ public static function getShortClassName(string $fullClassName): string
return substr($fullClassName, strrpos($fullClassName, '\\') + 1);
}

/**
* @return array{0: string, 1: string}
*/
public static function getHumanDiscriminatorBetweenTwoClasses(string $className, string $classNameOther): array
{
$namespace = self::getNamespace($className);
$namespaceOther = self::getNamespace($classNameOther);
if (empty($namespace) || empty($namespaceOther)) {
return [$namespace, $namespaceOther];
}

$namespaceParts = explode('\\', $namespace);
$namespacePartsOther = explode('\\', $namespaceOther);

$min = min(\count($namespaceParts), \count($namespacePartsOther));
for ($i = 0; $i < $min; ++$i) {
$part = $namespaceParts[$i];
$partOther = $namespacePartsOther[$i];
if ($part !== $partOther) {
break;
}

$namespaceParts[$i] = null;
$namespacePartsOther[$i] = null;
}

return [
implode('\\', array_filter($namespaceParts)),
implode('\\', array_filter($namespacePartsOther)),
];
}

public static function getNamespace(string $fullClassName): string
{
return substr($fullClassName, 0, strrpos($fullClassName, '\\'));
Expand Down
39 changes: 39 additions & 0 deletions tests/Maker/MakeEntityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,45 @@ public function getTestDetails(): \Generator
}),
];

yield 'it_adds_many_to_many_between_same_entity_name_different_namespace' => [$this->createMakeEntityTest()
->run(function (MakerTestRunner $runner) {
$this->copyEntity($runner, 'User-basic.php');
$this->copyEntity($runner, 'Friend/User-sub-namespace.php');

$output = $runner->runMaker([
// entity class name
'User',
// field name
'friends',
// add a relationship field
'relation',
// the target entity
'Friend\\User',
// relation type
'ManyToMany',
// inverse side?
'y',
// field name on opposite side - use default 'courses'
'',
// finish adding fields
'',
]);

$this->assertStringContainsString('src/Entity/User.php', $output);
$this->assertStringContainsString('src/Entity/Friend/User.php', $output);
$this->assertStringContainsString('ManyToOne Each User relates to (has) one Friend\User.', $output);
$this->assertStringContainsString('Each Friend\User can relate to (can have) many User objects.', $output);
$this->assertStringContainsString('OneToMany Each User can relate to (can have) many Friend\User objects.', $output);
$this->assertStringContainsString('Each Friend\User relates to (has) one User.', $output);
$this->assertStringContainsString('ManyToMany Each User can relate to (can have) many Friend\User objects.', $output);
$this->assertStringContainsString('Each Friend\User can also relate to (can also have) many User objects.', $output);
$this->assertStringContainsString('OneToOne Each User relates to (has) exactly one Friend\User.', $output);
$this->assertStringContainsString('Each Friend\User also relates to (has) exactly one User.', $output);

// $this->runCustomTest($runner, 'it_adds_many_to_many_between_same_entity_name_different_namespace.php');
}),
];

yield 'it_adds_one_to_one_simple' => [$this->createMakeEntityTest()
->run(function (MakerTestRunner $runner) {
$this->copyEntity($runner, 'User-basic.php');
Expand Down
18 changes: 18 additions & 0 deletions tests/StrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,24 @@ public function getShortClassNameCaseTests()
yield ['Foo', 'Foo'];
}

/**
* @dataProvider getHumanDiscriminatorBetweenTwoClassesTests
*/
public function testHumanDiscriminatorBetweenTwoClasses(string $className, string $classNameOther, array $expected)
{
$this->assertSame($expected, Str::getHumanDiscriminatorBetweenTwoClasses($className, $classNameOther));
}

public function getHumanDiscriminatorBetweenTwoClassesTests()
{
yield ['\\User', 'App\\Entity\\User', ['', 'App\\Entity']];
yield ['App\\Entity\\User', 'App\\Entity\\Friend\\User', ['', 'Friend']];
yield ['App\\Entity\\User', 'Custom\\Entity\\User', ['App\\Entity', 'Custom\\Entity']];
yield ['App\\Entity\\User', 'App\\Bundle\\Entity\\User', ['Entity', 'Bundle\\Entity']];
yield ['App\\Entity\\User', 'App\\Bundle\\User', ['Entity', 'Bundle']];
yield ['App\\Entity\\User', 'Custom\\Bundle\\Friend\\Entity\\User', ['App\\Entity', 'Custom\\Bundle\\Friend\\Entity']];
}

/**
* @dataProvider asHumanWordsTests
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace App\Entity\Friend;

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;

#[ORM\Column(length: 255, nullable: true)]
private ?string $firstName = null;

#[ORM\Column(nullable: true)]
private ?\DateTimeInterface $createdAt = null;

public function getId()
{
return $this->id;
}

public function getFirstName()
{
return $this->firstName;
}

public function setFirstName(?string $firstName)
{
$this->firstName = $firstName;
}

public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}

public function setCreatedAt(?\DateTimeInterface $createdAt)
{
$this->createdAt = $createdAt;
}
}

0 comments on commit be24be4

Please sign in to comment.