diff --git a/CHANGELOG.md b/CHANGELOG.md index b8509e42a7..660e8b82a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ a release. ### Added - Tree: `setSibling()` and `getSibling()` methods in the `Node` interface through the BC `@method` annotation - Tree: Support array of fields and directions in the `$sortByField` and `$direction` parameters at `AbstractTreeRepository::recover()` +- Loggable: Support for composite identifiers. ### Changed - Named arguments have precedence over the values passed in the `$data` array in annotation classes at `Gedmo\Mapping\Annotation\` @@ -34,6 +35,8 @@ a release. ### Deprecated - Tree: Not implementing `Node` interface in classes that are used as nodes +- Implementing the `Gedmo\Tool\WrapperInterface::getIdentifier()` method without the second argument (`$flatten`) is deprecated and will + be required in version 4.0. ## [3.11.1] - 2023-02-20 ### Fixed diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 07777390e0..998834fc50 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -65,6 +65,11 @@ parameters: count: 4 path: src/Loggable/LoggableListener.php + - + message: "#^Method Gedmo\\\\Tool\\\\WrapperInterface\\\\:\\:getIdentifier\\(\\) invoked with 2 parameters, 0-1 required\\.#" + count: 2 + path: src/Loggable/LoggableListener.php + - message: "#^Access to an undefined property Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\:\\:\\$associationMappings\\.$#" count: 1 @@ -355,11 +360,26 @@ parameters: count: 1 path: src/Timestampable/Mapping/Driver/Yaml.php + - + message: "#^PHPDoc tag \\@param references unknown parameter\\: \\$flatten$#" + count: 1 + path: src/Tool/WrapperInterface.php + - message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\ObjectManager\\:\\:getUnitOfWork\\(\\)\\.$#" count: 1 path: src/Tool/Wrapper/EntityWrapper.php + - + message: "#^Method Gedmo\\\\Tool\\\\Wrapper\\\\EntityWrapper\\:\\:getIdentifier\\(\\) has parameter \\$flatten with no type specified\\.$#" + count: 1 + path: src/Tool/Wrapper/EntityWrapper.php + + - + message: "#^Parameter \\#2 \\$em of class Gedmo\\\\Tool\\\\Wrapper\\\\EntityWrapper constructor expects Doctrine\\\\ORM\\\\EntityManagerInterface, Doctrine\\\\Persistence\\\\ObjectManager given\\.$#" + count: 1 + path: src/Tool/Wrapper/EntityWrapper.php + - message: "#^Access to an undefined property ProxyManager\\\\Proxy\\\\GhostObjectInterface\\:\\:\\$identifier\\.$#" count: 1 @@ -370,6 +390,11 @@ parameters: count: 2 path: src/Tool/Wrapper/MongoDocumentWrapper.php + - + message: "#^Method Gedmo\\\\Tool\\\\Wrapper\\\\MongoDocumentWrapper\\:\\:getIdentifier\\(\\) has parameter \\$flatten with no type specified\\.$#" + count: 1 + path: src/Tool/Wrapper/MongoDocumentWrapper.php + - message: "#^Access to offset 'association' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\FieldMapping\\.$#" count: 2 diff --git a/src/Loggable/Document/Repository/LogEntryRepository.php b/src/Loggable/Document/Repository/LogEntryRepository.php index c29308f66f..af1291978f 100644 --- a/src/Loggable/Document/Repository/LogEntryRepository.php +++ b/src/Loggable/Document/Repository/LogEntryRepository.php @@ -106,10 +106,11 @@ public function revert($document, $version = 1) throw new UnexpectedValueException('Count not find any log entries under version: '.$version); } - $data = []; + $data = [[]]; while ($log = array_shift($logs)) { - $data = array_merge($data, $log->getData()); + $data[] = $log->getData(); } + $data = array_merge(...$data); $this->fillDocument($document, $data); } diff --git a/src/Loggable/Entity/Repository/LogEntryRepository.php b/src/Loggable/Entity/Repository/LogEntryRepository.php index 7dae26e7b5..489f80191a 100644 --- a/src/Loggable/Entity/Repository/LogEntryRepository.php +++ b/src/Loggable/Entity/Repository/LogEntryRepository.php @@ -77,7 +77,7 @@ public function getLogEntriesQuery($entity) $dql .= ' AND log.objectClass = :objectClass'; $dql .= ' ORDER BY log.version DESC'; - $objectId = (string) $wrapped->getIdentifier(); + $objectId = (string) $wrapped->getIdentifier(false, true); $q = $this->_em->createQuery($dql); $q->setParameters(compact('objectId', 'objectClass')); @@ -111,7 +111,7 @@ public function revert($entity, $version = 1) $dql .= ' AND log.version <= :version'; $dql .= ' ORDER BY log.version ASC'; - $objectId = (string) $wrapped->getIdentifier(); + $objectId = (string) $wrapped->getIdentifier(false, true); $q = $this->_em->createQuery($dql); $q->setParameters(compact('objectId', 'objectClass', 'version')); $logs = $q->getResult(); diff --git a/src/Loggable/LoggableListener.php b/src/Loggable/LoggableListener.php index 45a840cc01..38683db08a 100644 --- a/src/Loggable/LoggableListener.php +++ b/src/Loggable/LoggableListener.php @@ -10,9 +10,11 @@ namespace Gedmo\Loggable; use Doctrine\Common\EventArgs; +use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\Persistence\Event\LoadClassMetadataEventArgs; use Doctrine\Persistence\ObjectManager; use Gedmo\Exception\InvalidArgumentException; +use Gedmo\Loggable\Entity\LogEntry; use Gedmo\Loggable\Mapping\Event\LoggableAdapter; use Gedmo\Mapping\MappedEventSubscriber; use Gedmo\Tool\Wrapper\AbstractWrapper; @@ -150,7 +152,7 @@ public function postPersist(EventArgs $args) $logEntry = $this->pendingLogEntryInserts[$oid]; $logEntryMeta = $om->getClassMetadata(get_class($logEntry)); - $id = $wrapped->getIdentifier(); + $id = $wrapped->getIdentifier(false, true); $logEntryMeta->getReflectionProperty('objectId')->setValue($logEntry, $id); $uow->scheduleExtraUpdate($logEntry, [ 'objectId' => [null, $id], @@ -320,10 +322,10 @@ protected function createLogEntry($action, $object, LoggableAdapter $ea) // check for the availability of the primary key $uow = $om->getUnitOfWork(); - if (LogEntryInterface::ACTION_CREATE === $action && $ea->isPostInsertGenerator($meta)) { + if (LogEntryInterface::ACTION_CREATE === $action && ($ea->isPostInsertGenerator($meta) || ($meta instanceof ClassMetadata && $meta->isIdentifierComposite))) { $this->pendingLogEntryInserts[spl_object_id($object)] = $logEntry; } else { - $logEntry->setObjectId($wrapped->getIdentifier()); + $logEntry->setObjectId($wrapped->getIdentifier(false, true)); } $newValues = []; if (LogEntryInterface::ACTION_REMOVE !== $action && isset($config['versioned'])) { diff --git a/src/Loggable/Mapping/Driver/Annotation.php b/src/Loggable/Mapping/Driver/Annotation.php index 8fa4234f3d..6fd718fa03 100644 --- a/src/Loggable/Mapping/Driver/Annotation.php +++ b/src/Loggable/Mapping/Driver/Annotation.php @@ -9,6 +9,7 @@ namespace Gedmo\Loggable\Mapping\Driver; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as ClassMetadataODM; use Doctrine\Persistence\Mapping\ClassMetadata; use Gedmo\Exception\InvalidMappingException; use Gedmo\Mapping\Annotation\Loggable; @@ -40,7 +41,7 @@ class Annotation extends AbstractAnnotationDriver public function validateFullMetadata(ClassMetadata $meta, array $config) { - if ($config && is_array($meta->getIdentifier()) && count($meta->getIdentifier()) > 1) { + if ($config && $meta instanceof ClassMetadataODM && is_array($meta->getIdentifier()) && count($meta->getIdentifier()) > 1) { throw new InvalidMappingException("Loggable does not support composite identifiers in class - {$meta->getName()}"); } if (isset($config['versioned']) && !isset($config['loggable'])) { @@ -87,7 +88,7 @@ public function readExtendedMetadata($meta, array &$config) } if (!$meta->isMappedSuperclass && $config) { - if (is_array($meta->getIdentifier()) && count($meta->getIdentifier()) > 1) { + if ($meta instanceof ClassMetadataODM && is_array($meta->getIdentifier()) && count($meta->getIdentifier()) > 1) { throw new InvalidMappingException("Loggable does not support composite identifiers in class - {$meta->getName()}"); } if ($this->isClassAnnotationInValid($meta, $config)) { diff --git a/src/Loggable/Mapping/Driver/Xml.php b/src/Loggable/Mapping/Driver/Xml.php index d2f054006b..82a33dcdb0 100644 --- a/src/Loggable/Mapping/Driver/Xml.php +++ b/src/Loggable/Mapping/Driver/Xml.php @@ -9,6 +9,7 @@ namespace Gedmo\Loggable\Mapping\Driver; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as ClassMetadataODM; use Doctrine\Persistence\Mapping\ClassMetadata; use Gedmo\Exception\InvalidMappingException; use Gedmo\Mapping\Driver\Xml as BaseXml; @@ -37,7 +38,7 @@ public function readExtendedMetadata($meta, array &$config) $xml = $xml->children(self::GEDMO_NAMESPACE_URI); - if ('entity' === $xmlDoctrine->getName() || 'document' === $xmlDoctrine->getName() || 'mapped-superclass' === $xmlDoctrine->getName()) { + if (in_array($xmlDoctrine->getName(), ['mapped-superclass', 'entity', 'document'], true)) { if (isset($xml->loggable)) { /** * @var \SimpleXMLElement; @@ -74,7 +75,7 @@ public function readExtendedMetadata($meta, array &$config) } if (!$meta->isMappedSuperclass && $config) { - if (is_array($meta->getIdentifier()) && count($meta->getIdentifier()) > 1) { + if ($meta instanceof ClassMetadataODM && is_array($meta->getIdentifier()) && count($meta->getIdentifier()) > 1) { throw new InvalidMappingException("Loggable does not support composite identifiers in class - {$meta->getName()}"); } if (isset($config['versioned']) && !isset($config['loggable'])) { diff --git a/src/Loggable/Mapping/Driver/Yaml.php b/src/Loggable/Mapping/Driver/Yaml.php index 3ddbfb12f6..5481473d51 100644 --- a/src/Loggable/Mapping/Driver/Yaml.php +++ b/src/Loggable/Mapping/Driver/Yaml.php @@ -9,6 +9,7 @@ namespace Gedmo\Loggable\Mapping\Driver; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Gedmo\Exception\InvalidMappingException; use Gedmo\Mapping\Driver; use Gedmo\Mapping\Driver\File; @@ -26,7 +27,7 @@ * * @internal */ -class Yaml extends File implements Driver +class Yaml extends File { /** * File extension @@ -124,11 +125,11 @@ public function readExtendedMetadata($meta, array &$config) } if (!$meta->isMappedSuperclass && $config) { - if (is_array($meta->getIdentifier()) && count($meta->getIdentifier()) > 1) { + if ($meta instanceof ClassMetadata && is_array($meta->getIdentifier()) && count($meta->getIdentifier()) > 1) { throw new InvalidMappingException("Loggable does not support composite identifiers in class - {$meta->getName()}"); } if (isset($config['versioned']) && !isset($config['loggable'])) { - throw new InvalidMappingException("Class must be annoted with Loggable annotation in order to track versioned fields in class - {$meta->getName()}"); + throw new InvalidMappingException("Class must be annotated with Loggable annotation in order to track versioned fields in class - {$meta->getName()}"); } } } diff --git a/src/Loggable/Mapping/Event/Adapter/ORM.php b/src/Loggable/Mapping/Event/Adapter/ORM.php index 75ee997622..b30fe9c8ba 100644 --- a/src/Loggable/Mapping/Event/Adapter/ORM.php +++ b/src/Loggable/Mapping/Event/Adapter/ORM.php @@ -13,6 +13,7 @@ use Gedmo\Loggable\Entity\LogEntry; use Gedmo\Loggable\Mapping\Event\LoggableAdapter; use Gedmo\Mapping\Event\Adapter\ORM as BaseAdapterORM; +use Gedmo\Tool\Wrapper\EntityWrapper; /** * Doctrine event adapter for ORM adapted @@ -39,8 +40,8 @@ public function getNewVersion($meta, $object) { $em = $this->getObjectManager(); $objectMeta = $em->getClassMetadata(get_class($object)); - $identifierField = $this->getSingleIdentifierFieldName($objectMeta); - $objectId = (string) $objectMeta->getReflectionProperty($identifierField)->getValue($object); + $wrapper = new EntityWrapper($object, $em); + $objectId = $wrapper->getIdentifier(false, true); $dql = "SELECT MAX(log.version) FROM {$meta->getName()} log"; $dql .= ' WHERE log.objectId = :objectId'; diff --git a/src/References/Mapping/Driver/Xml.php b/src/References/Mapping/Driver/Xml.php index 4ac26889ae..9a7b0c774d 100644 --- a/src/References/Mapping/Driver/Xml.php +++ b/src/References/Mapping/Driver/Xml.php @@ -51,7 +51,7 @@ public function readExtendedMetadata($meta, array &$config) $xml = $xml->children(self::GEDMO_NAMESPACE_URI); - if ('entity' === $xmlDoctrine->getName() || 'document' === $xmlDoctrine->getName() || 'mapped-superclass' === $xmlDoctrine->getName()) { + if (in_array($xmlDoctrine->getName(), ['mapped-superclass', 'entity', 'document'], true)) { if (isset($xml->reference)) { /** * @var \SimpleXMLElement diff --git a/src/Tool/Wrapper/EntityWrapper.php b/src/Tool/Wrapper/EntityWrapper.php index 3eb8dac8da..fd557c0d5f 100644 --- a/src/Tool/Wrapper/EntityWrapper.php +++ b/src/Tool/Wrapper/EntityWrapper.php @@ -9,6 +9,7 @@ namespace Gedmo\Tool\Wrapper; +use Doctrine\Common\Util\ClassUtils; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Proxy\Proxy; @@ -77,34 +78,33 @@ public function getRootObjectName() return $this->meta->rootEntityName; } - public function getIdentifier($single = true) + public function getIdentifier($single = true, $flatten = false) { + $flatten = 1 < \func_num_args() && true === func_get_arg(1); if (null === $this->identifier) { - if ($this->object instanceof Proxy) { - $uow = $this->om->getUnitOfWork(); - if ($uow->isInIdentityMap($this->object)) { - $this->identifier = $uow->getEntityIdentifier($this->object); - } else { - $this->initialize(); - } + $uow = $this->om->getUnitOfWork(); + $this->identifier = $uow->isInIdentityMap($this->object) + ? $uow->getEntityIdentifier($this->object) + : $this->meta->getIdentifierValues($this->object); + if (is_array($this->identifier) && empty($this->identifier)) { + $this->identifier = null; + } + } + if (is_array($this->identifier)) { + if ($single) { + return reset($this->identifier); } - if (null === $this->identifier) { - $this->identifier = []; - $incomplete = false; - foreach ($this->meta->identifier as $name) { - $this->identifier[$name] = $this->getPropertyValue($name); - if (null === $this->identifier[$name]) { - $incomplete = true; + if ($flatten) { + $id = $this->identifier; + foreach ($id as $i => $value) { + if (is_object($value) && $this->om->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) { + $id[$i] = (new self($value, $this->om))->getIdentifier(false, true); } } - if ($incomplete) { - $this->identifier = null; - } + + return implode(' ', $id); } } - if ($single && is_array($this->identifier)) { - return reset($this->identifier); - } return $this->identifier; } diff --git a/src/Tool/Wrapper/MongoDocumentWrapper.php b/src/Tool/Wrapper/MongoDocumentWrapper.php index eaea024c62..6ff2d9a6e7 100644 --- a/src/Tool/Wrapper/MongoDocumentWrapper.php +++ b/src/Tool/Wrapper/MongoDocumentWrapper.php @@ -76,7 +76,7 @@ public function hasValidIdentifier() return (bool) $this->getIdentifier(); } - public function getIdentifier($single = true) + public function getIdentifier($single = true, $flatten = false) { if (!$this->identifier) { if ($this->object instanceof GhostObjectInterface) { diff --git a/src/Tool/WrapperInterface.php b/src/Tool/WrapperInterface.php index f99f7d05e7..15004a51a7 100644 --- a/src/Tool/WrapperInterface.php +++ b/src/Tool/WrapperInterface.php @@ -75,10 +75,13 @@ public function getMetadata(); * Get the object identifier, single or composite. * * @param bool $single + * @param bool $flatten * * @return array|mixed Array if a composite value, otherwise a single scalar + * + * @todo Uncomment the second parameter for 4.0 */ - public function getIdentifier($single = true); + public function getIdentifier($single = true/* , $flatten = false */); /** * Get the root object class name. diff --git a/src/Uploadable/Mapping/Driver/Xml.php b/src/Uploadable/Mapping/Driver/Xml.php index d6d9796096..c480335550 100644 --- a/src/Uploadable/Mapping/Driver/Xml.php +++ b/src/Uploadable/Mapping/Driver/Xml.php @@ -35,7 +35,7 @@ public function readExtendedMetadata($meta, array &$config) $xmlDoctrine = $xml; $xml = $xml->children(self::GEDMO_NAMESPACE_URI); - if ('entity' === $xmlDoctrine->getName() || 'mapped-superclass' === $xmlDoctrine->getName()) { + if (in_array($xmlDoctrine->getName(), ['mapped-superclass', 'entity'], true)) { if (isset($xml->uploadable)) { $xmlUploadable = $xml->uploadable; $config['uploadable'] = true; diff --git a/tests/Gedmo/Loggable/Fixture/Entity/Composite.php b/tests/Gedmo/Loggable/Fixture/Entity/Composite.php new file mode 100644 index 0000000000..fa3bf79f50 --- /dev/null +++ b/tests/Gedmo/Loggable/Fixture/Entity/Composite.php @@ -0,0 +1,79 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Loggable\Fixture\Entity; + +use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Mapping as ORM; +use Gedmo\Mapping\Annotation as Gedmo; + +/** + * @ORM\Entity + * @Gedmo\Loggable + */ +#[ORM\Entity] +#[Gedmo\Loggable] +class Composite +{ + /** + * @var int + * + * @ORM\Id + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\Column(name: 'one', type: Types::INTEGER)] + private $one; + + /** + * @var int + * + * @ORM\Id + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\Column(name: 'two', type: Types::INTEGER)] + private $two; + + /** + * @var string + * + * @ORM\Column(length=8) + * @Gedmo\Versioned + */ + #[ORM\Column(name: 'title', type: Types::STRING, length: 8)] + #[Gedmo\Versioned] + private $title; + + public function __construct(int $one, int $two) + { + $this->one = $one; + $this->two = $two; + } + + public function getOne(): int + { + return $this->one; + } + + public function getTwo(): int + { + return $this->two; + } + + public function setTitle(string $title): void + { + $this->title = $title; + } + + public function getTitle(): string + { + return $this->title; + } +} diff --git a/tests/Gedmo/Loggable/Fixture/Entity/CompositeRelation.php b/tests/Gedmo/Loggable/Fixture/Entity/CompositeRelation.php new file mode 100644 index 0000000000..31947a44b0 --- /dev/null +++ b/tests/Gedmo/Loggable/Fixture/Entity/CompositeRelation.php @@ -0,0 +1,79 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Loggable\Fixture\Entity; + +use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Mapping as ORM; +use Gedmo\Mapping\Annotation as Gedmo; + +/** + * @ORM\Entity + * @Gedmo\Loggable + */ +#[ORM\Entity] +#[Gedmo\Loggable] +class CompositeRelation +{ + /** + * @var Article + * + * @ORM\Id + * @ORM\ManyToOne(targetEntity="Article") + */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: Article::class)] + private $articleOne; + + /** + * @var Article + * + * @ORM\Id + * @ORM\ManyToOne(targetEntity="Article") + */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: Article::class)] + private $articleTwo; + + /** + * @var string + * + * @ORM\Column(length=8) + * @Gedmo\Versioned + */ + #[ORM\Column(name: 'title', type: Types::STRING, length: 8)] + #[Gedmo\Versioned] + private $title; + + public function __construct(Article $articleOne, Article $articleTwo) + { + $this->articleOne = $articleOne; + $this->articleTwo = $articleTwo; + } + + public function getArticleOne(): Article + { + return $this->articleOne; + } + + public function getArticleTwo(): Article + { + return $this->articleTwo; + } + + public function setTitle(string $title): void + { + $this->title = $title; + } + + public function getTitle(): string + { + return $this->title; + } +} diff --git a/tests/Gedmo/Loggable/LoggableEntityTest.php b/tests/Gedmo/Loggable/LoggableEntityTest.php index a935b1d383..2de1abe090 100644 --- a/tests/Gedmo/Loggable/LoggableEntityTest.php +++ b/tests/Gedmo/Loggable/LoggableEntityTest.php @@ -16,6 +16,8 @@ use Gedmo\Tests\Loggable\Fixture\Entity\Address; use Gedmo\Tests\Loggable\Fixture\Entity\Article; use Gedmo\Tests\Loggable\Fixture\Entity\Comment; +use Gedmo\Tests\Loggable\Fixture\Entity\Composite; +use Gedmo\Tests\Loggable\Fixture\Entity\CompositeRelation; use Gedmo\Tests\Loggable\Fixture\Entity\Geo; use Gedmo\Tests\Loggable\Fixture\Entity\GeoLocation; use Gedmo\Tests\Loggable\Fixture\Entity\RelatedArticle; @@ -30,6 +32,8 @@ abstract class LoggableEntityTest extends BaseTestCaseORM { public const ARTICLE = Article::class; public const COMMENT = Comment::class; + public const COMPOSITE = Composite::class; + public const COMPOSITE_RELATION = CompositeRelation::class; public const RELATED_ARTICLE = RelatedArticle::class; public const COMMENT_LOG = \Gedmo\Tests\Loggable\Fixture\Entity\Log\Comment::class; @@ -143,6 +147,110 @@ public function testLogEmbedded(): void static::assertCount(5, $logEntries[3]->getData()); } + public function testComposite(): void + { + $logRepo = $this->em->getRepository(LogEntry::class); + $compositeRepo = $this->em->getRepository(self::COMPOSITE); + static::assertCount(0, $logRepo->findAll()); + + $compositeIds = [1, 2]; + + $cmp = new Composite(...$compositeIds); + $cmp->setTitle('Title2'); + + $this->em->persist($cmp); + $this->em->flush(); + + $cmpId = sprintf('%s %s', ...$compositeIds); + + $log = $logRepo->findOneBy(['objectId' => $cmpId]); + + static::assertNotNull($log); + static::assertSame('create', $log->getAction()); + static::assertSame(get_class($cmp), $log->getObjectClass()); + static::assertSame('jules', $log->getUsername()); + static::assertSame(1, $log->getVersion()); + $data = $log->getData(); + static::assertCount(1, $data); + static::assertArrayHasKey('title', $data); + static::assertSame($data['title'], 'Title2'); + + // test update + $composite = $compositeRepo->findOneBy(['title' => 'Title2']); + + $composite->setTitle('New'); + $this->em->persist($composite); + $this->em->flush(); + $this->em->clear(); + + $log = $logRepo->findOneBy(['version' => 2, 'objectId' => $cmpId]); + static::assertSame('update', $log->getAction()); + + // test delete + $composite = $compositeRepo->findOneBy(['title' => 'New']); + $this->em->remove($composite); + $this->em->flush(); + $this->em->clear(); + + $log = $logRepo->findOneBy(['version' => 3, 'objectId' => $cmpId]); + static::assertSame('remove', $log->getAction()); + static::assertNull($log->getData()); + } + + public function testCompositeRelation(): void + { + $logRepo = $this->em->getRepository(LogEntry::class); + $compositeRepo = $this->em->getRepository(self::COMPOSITE_RELATION); + static::assertCount(0, $logRepo->findAll()); + + $art0 = new Article(); + $art0->setTitle('Title0'); + $art1 = new Article(); + $art1->setTitle('Title1'); + $cmp0 = new CompositeRelation($art0, $art1); + $cmp0->setTitle('Title2'); + + $this->em->persist($art0); + $this->em->persist($art1); + $this->em->persist($cmp0); + $this->em->flush(); + + $cmpId = sprintf('%s %s', $art0->getId(), $art1->getId()); + + $log = $logRepo->findOneBy(['objectId' => $cmpId]); + + static::assertNotNull($log); + static::assertSame('create', $log->getAction()); + static::assertSame(get_class($cmp0), $log->getObjectClass()); + static::assertSame('jules', $log->getUsername()); + static::assertSame(1, $log->getVersion()); + $data = $log->getData(); + static::assertCount(1, $data); + static::assertArrayHasKey('title', $data); + static::assertSame($data['title'], 'Title2'); + + // test update + $composite = $compositeRepo->findOneBy(['title' => 'Title2']); + + $composite->setTitle('New'); + $this->em->persist($composite); + $this->em->flush(); + $this->em->clear(); + + $log = $logRepo->findOneBy(['version' => 2, 'objectId' => $cmpId]); + static::assertSame('update', $log->getAction()); + + // test delete + $composite = $compositeRepo->findOneBy(['title' => 'New']); + $this->em->remove($composite); + $this->em->flush(); + $this->em->clear(); + + $log = $logRepo->findOneBy(['version' => 3, 'objectId' => $cmpId]); + static::assertSame('remove', $log->getAction()); + static::assertNull($log->getData()); + } + protected function getUsedEntityFixtures(): array { return [ @@ -150,6 +258,8 @@ protected function getUsedEntityFixtures(): array self::COMMENT, self::COMMENT_LOG, self::RELATED_ARTICLE, + self::COMPOSITE, + self::COMPOSITE_RELATION, LogEntry::class, Address::class, Geo::class, diff --git a/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.LoggableComposite.dcm.xml b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.LoggableComposite.dcm.xml new file mode 100644 index 0000000000..1eee13f615 --- /dev/null +++ b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.LoggableComposite.dcm.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.LoggableCompositeRelation.dcm.xml b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.LoggableCompositeRelation.dcm.xml new file mode 100644 index 0000000000..4a35271e9f --- /dev/null +++ b/tests/Gedmo/Mapping/Driver/Xml/Gedmo.Tests.Mapping.Fixture.Xml.LoggableCompositeRelation.dcm.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.Loggable.dcm.yml b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.Loggable.dcm.yml new file mode 100644 index 0000000000..8f21c2ff24 --- /dev/null +++ b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.Loggable.dcm.yml @@ -0,0 +1,17 @@ +--- +Gedmo\Tests\Mapping\Fixture\Yaml\Loggable: + type: entity + table: loggable + gedmo: + loggable: + logEntryClass: Gedmo\Loggable\Entity\LogEntry + id: + id: + type: integer + generator: + strategy: AUTO + fields: + title: + type: string + gedmo: + - versioned diff --git a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.LoggableComposite.dcm.yml b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.LoggableComposite.dcm.yml new file mode 100644 index 0000000000..30d55862cf --- /dev/null +++ b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.LoggableComposite.dcm.yml @@ -0,0 +1,17 @@ +--- +Gedmo\Tests\Mapping\Fixture\Yaml\LoggableComposite: + type: entity + table: loggable_with_composite + gedmo: + loggable: + logEntryClass: Gedmo\Loggable\Entity\LogEntry + id: + one: + type: integer + two: + type: integer + fields: + title: + type: string + gedmo: + - versioned diff --git a/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.LoggableCompositeRelation.dcm.yml b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.LoggableCompositeRelation.dcm.yml new file mode 100644 index 0000000000..c63163f0f3 --- /dev/null +++ b/tests/Gedmo/Mapping/Driver/Yaml/Gedmo.Tests.Mapping.Fixture.Yaml.LoggableCompositeRelation.dcm.yml @@ -0,0 +1,20 @@ +--- +Gedmo\Tests\Mapping\Fixture\Yaml\LoggableCompositeRelation: + type: entity + table: loggable_with_composite_relation + gedmo: + loggable: + logEntryClass: Gedmo\Loggable\Entity\LogEntry + id: + one: + associationKey: true + two: + type: integer + fields: + title: + type: string + gedmo: + - versioned + manyToOne: + one: + targetEntity: Loggable diff --git a/tests/Gedmo/Mapping/Fixture/Loggable.php b/tests/Gedmo/Mapping/Fixture/Loggable.php new file mode 100644 index 0000000000..6f474089e3 --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/Loggable.php @@ -0,0 +1,52 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture; + +use Doctrine\ORM\Mapping as ORM; +use Gedmo\Mapping\Annotation as Gedmo; + +/** + * @ORM\Entity + * @Gedmo\Loggable + */ +class Loggable +{ + /** + * @var int + * + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + private $id; + + /** + * @var string + * + * @ORM\Column(name="title", type="string", length=64) + * @Gedmo\Versioned + */ + private $title; + + public function getId(): int + { + return $this->id; + } + + public function setTitle(string $title): void + { + $this->title = $title; + } + + public function getTitle(): string + { + return $this->title; + } +} diff --git a/tests/Gedmo/Mapping/Fixture/LoggableComposite.php b/tests/Gedmo/Mapping/Fixture/LoggableComposite.php new file mode 100644 index 0000000000..9a8666b561 --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/LoggableComposite.php @@ -0,0 +1,64 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture; + +use Doctrine\ORM\Mapping as ORM; +use Gedmo\Mapping\Annotation as Gedmo; + +/** + * @ORM\Entity + * @Gedmo\Loggable + */ +class LoggableComposite +{ + /** + * @var int + * + * @ORM\Id + * @ORM\Column(type="integer") + */ + private $one; + + /** + * @var int + * + * @ORM\Id + * @ORM\Column(type="integer") + */ + private $two; + + /** + * @var string + * + * @ORM\Column(name="title", type="string", length=64) + * @Gedmo\Versioned + */ + private $title; + + public function getOne(): int + { + return $this->one; + } + + public function getTwo(): int + { + return $this->two; + } + + public function setTitle(string $title): void + { + $this->title = $title; + } + + public function getTitle(): string + { + return $this->title; + } +} diff --git a/tests/Gedmo/Mapping/Fixture/LoggableCompositeRelation.php b/tests/Gedmo/Mapping/Fixture/LoggableCompositeRelation.php new file mode 100644 index 0000000000..e4a1e9d21a --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/LoggableCompositeRelation.php @@ -0,0 +1,64 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture; + +use Doctrine\ORM\Mapping as ORM; +use Gedmo\Mapping\Annotation as Gedmo; + +/** + * @ORM\Entity + * @Gedmo\Loggable + */ +class LoggableCompositeRelation +{ + /** + * @var Loggable + * + * @ORM\Id + * @ORM\ManyToOne(targetEntity="Loggable") + */ + private $one; + + /** + * @var int + * + * @ORM\Id + * @ORM\Column(type="integer") + */ + private $two; + + /** + * @var string + * + * @ORM\Column(name="title", type="string", length=64) + * @Gedmo\Versioned + */ + private $title; + + public function getOne(): Loggable + { + return $this->one; + } + + public function getTwo(): int + { + return $this->two; + } + + public function setTitle(string $title): void + { + $this->title = $title; + } + + public function getTitle(): string + { + return $this->title; + } +} diff --git a/tests/Gedmo/Mapping/Fixture/Xml/LoggableComposite.php b/tests/Gedmo/Mapping/Fixture/Xml/LoggableComposite.php new file mode 100644 index 0000000000..59ca1eadfd --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/Xml/LoggableComposite.php @@ -0,0 +1,28 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture\Xml; + +class LoggableComposite +{ + /** + * @var int + */ + private $one; + + /** + * @var int + */ + private $two; + + /** + * @var string + */ + private $title; +} diff --git a/tests/Gedmo/Mapping/Fixture/Xml/LoggableCompositeRelation.php b/tests/Gedmo/Mapping/Fixture/Xml/LoggableCompositeRelation.php new file mode 100644 index 0000000000..0db9ba164f --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/Xml/LoggableCompositeRelation.php @@ -0,0 +1,28 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture\Xml; + +class LoggableCompositeRelation +{ + /** + * @var Loggable + */ + private $one; + + /** + * @var int + */ + private $two; + + /** + * @var string + */ + private $title; +} diff --git a/tests/Gedmo/Mapping/Fixture/Yaml/Loggable.php b/tests/Gedmo/Mapping/Fixture/Yaml/Loggable.php new file mode 100644 index 0000000000..7c4dcb506f --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/Yaml/Loggable.php @@ -0,0 +1,23 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture\Yaml; + +class Loggable +{ + /** + * @var int + */ + private $id; + + /** + * @var string + */ + private $title; +} diff --git a/tests/Gedmo/Mapping/Fixture/Yaml/LoggableComposite.php b/tests/Gedmo/Mapping/Fixture/Yaml/LoggableComposite.php new file mode 100644 index 0000000000..81036f0126 --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/Yaml/LoggableComposite.php @@ -0,0 +1,28 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture\Yaml; + +class LoggableComposite +{ + /** + * @var int + */ + private $one; + + /** + * @var int + */ + private $two; + + /** + * @var string + */ + private $title; +} diff --git a/tests/Gedmo/Mapping/Fixture/Yaml/LoggableCompositeRelation.php b/tests/Gedmo/Mapping/Fixture/Yaml/LoggableCompositeRelation.php new file mode 100644 index 0000000000..713708663d --- /dev/null +++ b/tests/Gedmo/Mapping/Fixture/Yaml/LoggableCompositeRelation.php @@ -0,0 +1,28 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Mapping\Fixture\Yaml; + +class LoggableCompositeRelation +{ + /** + * @var Loggable + */ + private $one; + + /** + * @var int + */ + private $two; + + /** + * @var string + */ + private $title; +} diff --git a/tests/Gedmo/Mapping/LoggableORMMappingTest.php b/tests/Gedmo/Mapping/LoggableORMMappingTest.php index b9f71b5fe4..f3944dc1d9 100644 --- a/tests/Gedmo/Mapping/LoggableORMMappingTest.php +++ b/tests/Gedmo/Mapping/LoggableORMMappingTest.php @@ -11,14 +11,18 @@ namespace Gedmo\Tests\Mapping; +use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\EventManager; use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Mapping\Driver\AnnotationDriver; use Doctrine\ORM\Mapping\Driver\YamlDriver; use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; use Gedmo\Loggable\Entity\LogEntry; use Gedmo\Loggable\LoggableListener; use Gedmo\Mapping\ExtensionMetadataFactory; use Gedmo\Tests\Mapping\Fixture\Yaml\Category; +use Gedmo\Tests\Mapping\Fixture\Yaml\LoggableComposite; +use Gedmo\Tests\Mapping\Fixture\Yaml\LoggableCompositeRelation; /** * These are mapping tests for tree extension @@ -28,6 +32,8 @@ final class LoggableORMMappingTest extends ORMMappingTestCase { public const YAML_CATEGORY = Category::class; + public const COMPOSITE = LoggableComposite::class; + public const COMPOSITE_RELATION = LoggableCompositeRelation::class; /** * @var EntityManager @@ -39,12 +45,17 @@ protected function setUp(): void parent::setUp(); $config = $this->getBasicConfiguration(); - $chainDriverImpl = new MappingDriverChain(); - $chainDriverImpl->addDriver( - new YamlDriver([__DIR__.'/Driver/Yaml']), - 'Gedmo\Tests\Mapping\Fixture\Yaml' - ); - $config->setMetadataDriverImpl($chainDriverImpl); + + $reader = new AnnotationReader(); + $annotationDriver = new AnnotationDriver($reader); + + $yamlDriver = new YamlDriver(__DIR__.'/Driver/Yaml'); + + $chain = new MappingDriverChain(); + $chain->addDriver($yamlDriver, 'Gedmo\Tests\Mapping\Fixture\Yaml'); + $chain->addDriver($annotationDriver, 'Gedmo\Tests\Mapping\Fixture'); + + $config->setMetadataDriverImpl($chain); $conn = [ 'driver' => 'pdo_sqlite', @@ -69,4 +80,32 @@ public function testLoggableMapping(): void static::assertArrayHasKey('logEntryClass', $config); static::assertSame(LogEntry::class, $config['logEntryClass']); } + + public function testLoggableCompositeMapping(): void + { + $meta = $this->em->getClassMetadata(self::COMPOSITE); + + static::assertIsArray($meta->identifier); + static::assertCount(2, $meta->identifier); + + $cacheId = ExtensionMetadataFactory::getCacheId(self::COMPOSITE, 'Gedmo\Loggable'); + $config = $this->cache->getItem($cacheId)->get(); + + static::assertArrayHasKey('loggable', $config); + static::assertTrue($config['loggable']); + } + + public function testLoggableCompositeRelationMapping(): void + { + $meta = $this->em->getClassMetadata(self::COMPOSITE_RELATION); + + static::assertIsArray($meta->identifier); + static::assertCount(2, $meta->identifier); + + $cacheId = ExtensionMetadataFactory::getCacheId(self::COMPOSITE_RELATION, 'Gedmo\Loggable'); + $config = $this->cache->getItem($cacheId)->get(); + + static::assertArrayHasKey('loggable', $config); + static::assertTrue($config['loggable']); + } } diff --git a/tests/Gedmo/Mapping/Xml/LoggableMappingTest.php b/tests/Gedmo/Mapping/Xml/LoggableMappingTest.php index b966da3321..31fc92ea56 100644 --- a/tests/Gedmo/Mapping/Xml/LoggableMappingTest.php +++ b/tests/Gedmo/Mapping/Xml/LoggableMappingTest.php @@ -21,6 +21,8 @@ use Gedmo\Loggable\LoggableListener; use Gedmo\Tests\Mapping\Fixture\Xml\Embedded; use Gedmo\Tests\Mapping\Fixture\Xml\Loggable; +use Gedmo\Tests\Mapping\Fixture\Xml\LoggableComposite; +use Gedmo\Tests\Mapping\Fixture\Xml\LoggableCompositeRelation; use Gedmo\Tests\Mapping\Fixture\Xml\LoggableWithEmbedded; use Gedmo\Tests\Mapping\Fixture\Xml\Status; use Gedmo\Tests\Tool\BaseTestCaseOM; @@ -86,6 +88,36 @@ public function testLoggableMetadata(): void static::assertContains('status', $config['versioned']); } + public function testLoggableCompositeMetadata(): void + { + $meta = $this->em->getClassMetadata(LoggableComposite::class); + $config = $this->loggable->getConfiguration($this->em, $meta->name); + + static::assertArrayHasKey('logEntryClass', $config); + static::assertSame(LogEntry::class, $config['logEntryClass']); + static::assertArrayHasKey('loggable', $config); + static::assertTrue($config['loggable']); + + static::assertArrayHasKey('versioned', $config); + static::assertCount(1, $config['versioned']); + static::assertContains('title', $config['versioned']); + } + + public function testLoggableCompositeRelationMetadata(): void + { + $meta = $this->em->getClassMetadata(LoggableCompositeRelation::class); + $config = $this->loggable->getConfiguration($this->em, $meta->name); + + static::assertArrayHasKey('logEntryClass', $config); + static::assertSame(LogEntry::class, $config['logEntryClass']); + static::assertArrayHasKey('loggable', $config); + static::assertTrue($config['loggable']); + + static::assertArrayHasKey('versioned', $config); + static::assertCount(1, $config['versioned']); + static::assertContains('title', $config['versioned']); + } + public function testLoggableMetadataWithEmbedded(): void { $meta = $this->em->getClassMetadata(LoggableWithEmbedded::class); diff --git a/tests/Gedmo/Mapping/Yaml/LoggableMappingTest.php b/tests/Gedmo/Mapping/Yaml/LoggableMappingTest.php index 27a75e48ef..d8f18de016 100644 --- a/tests/Gedmo/Mapping/Yaml/LoggableMappingTest.php +++ b/tests/Gedmo/Mapping/Yaml/LoggableMappingTest.php @@ -20,6 +20,8 @@ use Gedmo\Loggable\Entity\LogEntry; use Gedmo\Loggable\LoggableListener; use Gedmo\Tests\Mapping\Fixture\Yaml\Embedded; +use Gedmo\Tests\Mapping\Fixture\Yaml\LoggableComposite; +use Gedmo\Tests\Mapping\Fixture\Yaml\LoggableCompositeRelation; use Gedmo\Tests\Mapping\Fixture\Yaml\LoggableWithEmbedded; use Gedmo\Tests\Tool\BaseTestCaseOM; @@ -66,6 +68,36 @@ protected function setUp(): void ], $chain); } + public function testLoggableCompositeMetadata(): void + { + $meta = $this->em->getClassMetadata(LoggableComposite::class); + $config = $this->loggable->getConfiguration($this->em, $meta->name); + + static::assertArrayHasKey('logEntryClass', $config); + static::assertSame(LogEntry::class, $config['logEntryClass']); + static::assertArrayHasKey('loggable', $config); + static::assertTrue($config['loggable']); + + static::assertArrayHasKey('versioned', $config); + static::assertCount(1, $config['versioned']); + static::assertContains('title', $config['versioned']); + } + + public function testLoggableCompositeRelationMetadata(): void + { + $meta = $this->em->getClassMetadata(LoggableCompositeRelation::class); + $config = $this->loggable->getConfiguration($this->em, $meta->name); + + static::assertArrayHasKey('logEntryClass', $config); + static::assertSame(LogEntry::class, $config['logEntryClass']); + static::assertArrayHasKey('loggable', $config); + static::assertTrue($config['loggable']); + + static::assertArrayHasKey('versioned', $config); + static::assertCount(1, $config['versioned']); + static::assertContains('title', $config['versioned']); + } + public function testLoggableMetadataWithEmbedded(): void { $meta = $this->em->getClassMetadata(LoggableWithEmbedded::class); diff --git a/tests/Gedmo/Wrapper/EntityWrapperTest.php b/tests/Gedmo/Wrapper/EntityWrapperTest.php index 4a344b0089..4b20a2cbc8 100644 --- a/tests/Gedmo/Wrapper/EntityWrapperTest.php +++ b/tests/Gedmo/Wrapper/EntityWrapperTest.php @@ -15,6 +15,8 @@ use Doctrine\ORM\Proxy\Proxy; use Gedmo\Tests\Tool\BaseTestCaseORM; use Gedmo\Tests\Wrapper\Fixture\Entity\Article; +use Gedmo\Tests\Wrapper\Fixture\Entity\Composite; +use Gedmo\Tests\Wrapper\Fixture\Entity\CompositeRelation; use Gedmo\Tool\Wrapper\EntityWrapper; /** @@ -25,6 +27,8 @@ final class EntityWrapperTest extends BaseTestCaseORM { public const ARTICLE = Article::class; + public const COMPOSITE = Composite::class; + public const COMPOSITE_RELATION = CompositeRelation::class; protected function setUp(): void { @@ -63,6 +67,47 @@ public function testProxy(): void static::assertSame('test', $wrapped->getPropertyValue('title')); } + public function testComposite(): void + { + $test = $this->em->getReference(self::COMPOSITE, ['one' => 1, 'two' => 2]); + static::assertInstanceOf(self::COMPOSITE, $test); + $wrapped = new EntityWrapper($test, $this->em); + + $id = $wrapped->getIdentifier(false); + static::assertIsArray($id); + static::assertCount(2, $id); + static::assertArrayHasKey('one', $id); + static::assertArrayHasKey('two', $id); + static::assertSame(1, $id['one']); + static::assertSame(2, $id['two']); + + $id = $wrapped->getIdentifier(false, true); + static::assertIsString($id); + static::assertSame('1 2', $id); + + static::assertSame('test', $wrapped->getPropertyValue('title')); + } + + public function testCompositeRelation(): void + { + $art1 = $this->em->getReference(self::ARTICLE, ['id' => 1]); + $test = $this->em->getReference(self::COMPOSITE_RELATION, ['article' => $art1->getId(), 'status' => 2]); + static::assertInstanceOf(self::COMPOSITE_RELATION, $test); + $wrapped = new EntityWrapper($test, $this->em); + + $id = $wrapped->getIdentifier(false); + static::assertIsArray($id); + static::assertCount(2, $id); + static::assertArrayHasKey('article', $id); + static::assertArrayHasKey('status', $id); + + $id = $wrapped->getIdentifier(false, true); + static::assertIsString($id); + static::assertSame('1 2', $id); + + static::assertSame('test', $wrapped->getPropertyValue('title')); + } + public function testDetachedEntity(): void { $test = $this->em->find(self::ARTICLE, ['id' => 1]); @@ -83,6 +128,28 @@ public function testDetachedProxy(): void static::assertSame('test', $wrapped->getPropertyValue('title')); } + public function testDetachedCompositeRelation(): void + { + $test = $this->em->getReference(self::COMPOSITE_RELATION, ['article' => 1, 'status' => 2]); + $this->em->clear(); + $wrapped = new EntityWrapper($test, $this->em); + + static::assertSame('1 2', $wrapped->getIdentifier(false, true)); + static::assertSame('test', $wrapped->getPropertyValue('title')); + } + + public function testCompositeRelationProxy(): void + { + $this->em->clear(); + $art1 = $this->em->getReference(self::ARTICLE, ['id' => 1]); + $test = $this->em->getReference(self::COMPOSITE_RELATION, ['article' => $art1->getId(), 'status' => 2]); + static::assertInstanceOf(Proxy::class, $test); + $wrapped = new EntityWrapper($test, $this->em); + + static::assertSame('1 2', $wrapped->getIdentifier(false, true)); + static::assertSame('test', $wrapped->getPropertyValue('title')); + } + public function testSomeFunctions(): void { $test = new Article(); @@ -98,14 +165,22 @@ protected function getUsedEntityFixtures(): array { return [ self::ARTICLE, + self::COMPOSITE, + self::COMPOSITE_RELATION, ]; } private function populate(): void { - $test = new Article(); - $test->setTitle('test'); - $this->em->persist($test); + $article = new Article(); + $article->setTitle('test'); + $this->em->persist($article); + $composite = new Composite(1, 2); + $composite->setTitle('test'); + $this->em->persist($composite); + $compositeRelation = new CompositeRelation($article, 2); + $compositeRelation->setTitle('test'); + $this->em->persist($compositeRelation); $this->em->flush(); } } diff --git a/tests/Gedmo/Wrapper/Fixture/Entity/Composite.php b/tests/Gedmo/Wrapper/Fixture/Entity/Composite.php new file mode 100644 index 0000000000..af22193e9d --- /dev/null +++ b/tests/Gedmo/Wrapper/Fixture/Entity/Composite.php @@ -0,0 +1,74 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Wrapper\Fixture\Entity; + +use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Mapping as ORM; + +/** + * @ORM\Entity + */ +#[ORM\Entity] +class Composite +{ + /** + * @var int + * + * @ORM\Id + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] + private $one; + + /** + * @var int + * + * @ORM\Id + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] + private $two; + + /** + * @var string + * + * @ORM\Column(length=128) + */ + #[ORM\Column(length: 128)] + private $title; + + public function __construct(int $one, int $two) + { + $this->one = $one; + $this->two = $two; + } + + public function getOne(): int + { + return $this->one; + } + + public function getTwo(): int + { + return $this->two; + } + + public function setTitle(string $title): void + { + $this->title = $title; + } + + public function getTitle(): string + { + return $this->title; + } +} diff --git a/tests/Gedmo/Wrapper/Fixture/Entity/CompositeRelation.php b/tests/Gedmo/Wrapper/Fixture/Entity/CompositeRelation.php new file mode 100644 index 0000000000..c8d53d6e16 --- /dev/null +++ b/tests/Gedmo/Wrapper/Fixture/Entity/CompositeRelation.php @@ -0,0 +1,74 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tests\Wrapper\Fixture\Entity; + +use Doctrine\DBAL\Types\Types; +use Doctrine\ORM\Mapping as ORM; + +/** + * @ORM\Entity + */ +#[ORM\Entity] +class CompositeRelation +{ + /** + * @var Article + * + * @ORM\Id + * @ORM\ManyToOne(targetEntity="Gedmo\Tests\Wrapper\Fixture\Entity\Article") + */ + #[ORM\Id] + #[ORM\ManyToOne(targetEntity: Article::class)] + private $article; + + /** + * @var int + * + * @ORM\Id + * @ORM\Column(type="integer") + */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] + private $status; + + /** + * @var string + * + * @ORM\Column(length=128) + */ + #[ORM\Column(length: 128)] + private $title; + + public function __construct(Article $articleOne, int $status) + { + $this->article = $articleOne; + $this->status = $status; + } + + public function getArticle(): Article + { + return $this->article; + } + + public function getStatus(): int + { + return $this->status; + } + + public function setTitle(string $title): void + { + $this->title = $title; + } + + public function getTitle(): string + { + return $this->title; + } +}