Skip to content

Commit ecf41a6

Browse files
authored
[Translatable] Fix mixing attributes and annotations (#2322)
1 parent 056bf3e commit ecf41a6

File tree

7 files changed

+174
-5
lines changed

7 files changed

+174
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ a release.
2020

2121
## [Unreleased]
2222
### Fixed
23+
- Translatable: Using ORM/ODM attribute mapping and translatable annotations.
2324
- Tree: Missing support for `tree-path-hash` fields in XML mapping.
2425
- Tree: Check for affected rows at `ClosureTreeRepository::cleanUpClosure()` and `Closure::updateNode()`.
2526
- `Gedmo\Mapping\Driver\Xml::_loadMappingFile()` behavior in scenarios where `libxml_disable_entity_loader(true)` was previously
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
namespace Gedmo\Mapping\Driver;
4+
5+
use Doctrine\Common\Annotations\Reader;
6+
use Gedmo\Mapping\Annotation\Annotation;
7+
use ReflectionClass;
8+
use ReflectionMethod;
9+
10+
/**
11+
* @author Gediminas Morkevicius <[email protected]>
12+
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
13+
*
14+
* @internal
15+
*/
16+
final class AttributeAnnotationReader implements Reader
17+
{
18+
/**
19+
* @var Reader
20+
*/
21+
private $annotationReader;
22+
23+
/**
24+
* @var AttributeReader
25+
*/
26+
private $attributeReader;
27+
28+
public function __construct(AttributeReader $attributeReader, Reader $annotationReader)
29+
{
30+
$this->attributeReader = $attributeReader;
31+
$this->annotationReader = $annotationReader;
32+
}
33+
34+
/**
35+
* @return Annotation[]
36+
*/
37+
public function getClassAnnotations(ReflectionClass $class): array
38+
{
39+
$annotations = $this->attributeReader->getClassAnnotations($class);
40+
41+
if ([] !== $annotations) {
42+
return $annotations;
43+
}
44+
45+
return $this->annotationReader->getClassAnnotations($class);
46+
}
47+
48+
public function getClassAnnotation(ReflectionClass $class, $annotationName): ?Annotation
49+
{
50+
$annotation = $this->attributeReader->getClassAnnotation($class, $annotationName);
51+
52+
if (null !== $annotation) {
53+
return $annotation;
54+
}
55+
56+
return $this->annotationReader->getClassAnnotation($class, $annotationName);
57+
}
58+
59+
/**
60+
* @return Annotation[]
61+
*/
62+
public function getPropertyAnnotations(\ReflectionProperty $property): array
63+
{
64+
$propertyAnnotations = $this->attributeReader->getPropertyAnnotations($property);
65+
66+
if ([] !== $propertyAnnotations) {
67+
return $propertyAnnotations;
68+
}
69+
70+
return $this->annotationReader->getPropertyAnnotations($property);
71+
}
72+
73+
public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName): ?Annotation
74+
{
75+
$annotation = $this->attributeReader->getPropertyAnnotation($property, $annotationName);
76+
77+
if (null !== $annotation) {
78+
return $annotation;
79+
}
80+
81+
return $this->annotationReader->getPropertyAnnotation($property, $annotationName);
82+
}
83+
84+
public function getMethodAnnotations(ReflectionMethod $method)
85+
{
86+
throw new \BadMethodCallException('Not implemented');
87+
}
88+
89+
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
90+
{
91+
throw new \BadMethodCallException('Not implemented');
92+
}
93+
}

src/Mapping/Driver/AttributeReader.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
*/
1414
final class AttributeReader
1515
{
16-
/** @return array<Annotation> */
16+
/**
17+
* @return Annotation[]
18+
*/
1719
public function getClassAnnotations(ReflectionClass $class): array
1820
{
1921
return $this->convertToAttributeInstances($class->getAttributes());
@@ -24,7 +26,9 @@ public function getClassAnnotation(ReflectionClass $class, $annotationName): ?An
2426
return $this->getClassAnnotations($class)[$annotationName] ?? null;
2527
}
2628

27-
/** @return array<Annotation> */
29+
/**
30+
* @return Annotation[]
31+
*/
2832
public function getPropertyAnnotations(\ReflectionProperty $property): array
2933
{
3034
return $this->convertToAttributeInstances($property->getAttributes());
@@ -38,7 +42,7 @@ public function getPropertyAnnotation(\ReflectionProperty $property, $annotation
3842
/**
3943
* @param array<\ReflectionAttribute> $attributes
4044
*
41-
* @return array<Annotation>
45+
* @return Annotation[]
4246
*/
4347
private function convertToAttributeInstances(array $attributes): array
4448
{

src/Mapping/ExtensionMetadataFactory.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Doctrine\Persistence\Mapping\Driver\SymfonyFileLocator;
1111
use Doctrine\Persistence\ObjectManager;
1212
use Gedmo\Mapping\Driver\AnnotationDriverInterface;
13+
use Gedmo\Mapping\Driver\AttributeAnnotationReader;
1314
use Gedmo\Mapping\Driver\AttributeDriverInterface;
1415
use Gedmo\Mapping\Driver\AttributeReader;
1516
use Gedmo\Mapping\Driver\File as FileDriver;
@@ -186,7 +187,7 @@ protected function getDriver($omDriver)
186187
}
187188

188189
if ($driver instanceof AttributeDriverInterface) {
189-
$driver->setAnnotationReader(new AttributeReader());
190+
$driver->setAnnotationReader(new AttributeAnnotationReader(new AttributeReader(), $this->annotationReader));
190191
} elseif ($driver instanceof AnnotationDriverInterface) {
191192
$driver->setAnnotationReader($this->annotationReader);
192193
}

src/Translatable/Mapping/Driver/Attribute.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
/**
99
* This is an attribute mapping driver for Translatable
1010
* behavioral extension. Used for extraction of extended
11-
* metadata from Annotations specifically for Translatable
11+
* metadata from attributes specifically for Translatable
1212
* extension.
1313
*
1414
* @author Gediminas Morkevicius <[email protected]>

tests/Gedmo/Translatable/AttributeEntityTranslationTableTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Doctrine\Common\EventManager;
66
use Gedmo\Tests\Tool\BaseTestCaseORM;
7+
use Gedmo\Tests\Translatable\Fixture\Attribute\File;
78
use Gedmo\Tests\Translatable\Fixture\Attribute\Person;
89
use Gedmo\Tests\Translatable\Fixture\Attribute\PersonTranslation;
910
use Gedmo\Translatable\Entity\Repository\TranslationRepository;
@@ -24,6 +25,7 @@ final class AttributeEntityTranslationTableTest extends BaseTestCaseORM
2425
{
2526
public const PERSON = Person::class;
2627
public const TRANSLATION = PersonTranslation::class;
28+
public const FILE = File::class;
2729

2830
private $translatableListener;
2931

@@ -76,11 +78,37 @@ public function testFixtureGeneratedTranslations(): void
7678
$this->translatableListener->setTranslatableLocale('en_us');
7779
}
7880

81+
public function testFixtureWithAttributeMappingAndAnnotations(): void
82+
{
83+
$file = new File();
84+
$file->setTitle('title in en');
85+
86+
$this->em->persist($file);
87+
$this->em->flush();
88+
$this->em->clear();
89+
90+
$file = $this->em->find(self::FILE, $file->getId());
91+
92+
$file->locale = 'de';
93+
$file->setTitle('title in de');
94+
95+
$this->em->flush();
96+
$this->em->clear();
97+
98+
$file = $this->em->find(self::FILE, $file->getId());
99+
100+
static::assertEquals('title in en', $file->getTitle());
101+
$file->locale = 'de';
102+
$this->em->refresh($file);
103+
static::assertEquals('title in de', $file->getTitle());
104+
}
105+
79106
protected function getUsedEntityFixtures()
80107
{
81108
return [
82109
self::PERSON,
83110
self::TRANSLATION,
111+
self::FILE,
84112
];
85113
}
86114
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Gedmo\Tests\Translatable\Fixture\Attribute;
4+
5+
use Doctrine\DBAL\Types\Types;
6+
use Doctrine\ORM\Mapping as ORM;
7+
use Gedmo\Mapping\Annotation as Gedmo;
8+
9+
#[ORM\Entity]
10+
class File
11+
{
12+
#[ORM\Id]
13+
#[ORM\GeneratedValue]
14+
#[ORM\Column(type: Types::INTEGER)]
15+
private $id;
16+
17+
/**
18+
* @Gedmo\Translatable
19+
*/
20+
#[ORM\Column(name: 'title', type: Types::STRING, length: 128)]
21+
private $title;
22+
23+
/**
24+
* @Gedmo\Locale
25+
*/
26+
public $locale;
27+
28+
public function getId()
29+
{
30+
return $this->id;
31+
}
32+
33+
public function setTitle($title)
34+
{
35+
$this->title = $title;
36+
}
37+
38+
public function getTitle()
39+
{
40+
return $this->title;
41+
}
42+
}

0 commit comments

Comments
 (0)