From 92d7f4b88ea7b20dec2d48c7ce9a2ee1ac78717e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Bj=C3=B6rkland?= Date: Fri, 17 Sep 2021 15:44:25 +0200 Subject: [PATCH 1/4] Added save-method to RelationFactory. Closes #2832 --- src/Factory/RelationFactory.php | 25 ++++- tests/php/Factory/RelationFactoryTest.php | 115 ++++++++++++++++++++++ 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 tests/php/Factory/RelationFactoryTest.php diff --git a/src/Factory/RelationFactory.php b/src/Factory/RelationFactory.php index 55b02c8b9..5a913f69a 100644 --- a/src/Factory/RelationFactory.php +++ b/src/Factory/RelationFactory.php @@ -7,18 +7,24 @@ use Bolt\Entity\Content; use Bolt\Entity\Relation; use Bolt\Repository\RelationRepository; +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\EntityManagerInterface; use Tightenco\Collect\Support\Collection; class RelationFactory { + /** @var EntityManagerInterface */ + private $em; + /** @var RelationRepository */ private $repository; /** @var Collection */ private $relations; - public function __construct(RelationRepository $repository) + public function __construct(RelationRepository $repository, EntityManagerInterface $em) { + $this->em = $em; $this->repository = $repository; $this->relations = collect([]); } @@ -51,4 +57,21 @@ private function getFromMemory(Content $from, Content $to): ?Relation || ($relation->getToContent() === $to && $relation->getToContent() === $from); })->last(null, null); } + + /** + * @param Relation|Relation[] $relation + */ + public function save($relation): void + { + if ($relation instanceof Relation) { + $this->em->persist($relation); + + } elseif (is_iterable($relation)) { + foreach ($relation as $r) { + $this->em->persist($r); + } + } + + $this->em->flush(); + } } diff --git a/tests/php/Factory/RelationFactoryTest.php b/tests/php/Factory/RelationFactoryTest.php new file mode 100644 index 000000000..c7aa12313 --- /dev/null +++ b/tests/php/Factory/RelationFactoryTest.php @@ -0,0 +1,115 @@ +getEm()->getRepository(Relation::class), $this->getEm()); + + /** + * @var Content $page + */ + $page = $this->getEm()->getRepository(Content::class)->findOneBy(['contentType' => 'pages']); + $nonRelatedEntry = $this->getNonRelatedEntryForPage($page); + + + + /** + * @var Relation $newRelation + */ + $newRelation = $relationFactory->create($nonRelatedEntry, $page); + + $relationFactory->save($newRelation); + + $this->assertNotNull($newRelation->getId(), 'If id is null, the relation has not been persisted.'); + + return [ + "page" => $page, + "entry" => $nonRelatedEntry, + "relation" => $newRelation + ]; + } + + + + /** + * @depends testSavePersistsTheRelation + */ + public function testPersistedRelationCascadesToContent(array $entities): void + { + /** @var Content $page */ + $page = $entities["page"]; + + /** @var Content $entry */ + $entry = $entities["entry"]; + + /** @var Relation $persistedRelation */ + $persistedRelation = $entities["relation"]; + + /** @var array $entryRelationIds */ + $entryRelationIds = $this->getContentRelatedIds($entry->getRelationsFromThisContent()); + + /** @var array $pageRelationIds */ + $pageRelationIds = $this->getContentRelatedIds($page->getRelationsToThisContent()); + + $this->assertTrue(in_array($persistedRelation->getId(), $pageRelationIds), "It seems like relation has not persisted for contentType pages"); + $this->assertTrue(in_array($persistedRelation->getId(), $entryRelationIds), "It seems like relation has not persisted for contentType entries"); + + } + + /** + * Returns a Content entity with contentType 'Entry' that does not have a + * relation with the argument. + * + * @return Content $nonRelatedEntry + */ + private function getNonRelatedEntryForPage(Content $page): ?Content + { + $relations = $page->getRelationsToThisContent(); + $relatedIds = []; + foreach ($relations as $relative) { + $relatedIds[] = $relative->getId(); + } + + $entries = $this->getEm()->getRepository(Content::class)->findBy(['contentType' => 'entries']); + $entryIds = array_map(function ($entry) { + return $entry->getId(); + }, $entries); + $nonRelatedEntries = array_filter($entryIds, fn ($id) => !in_array($id, $relatedIds)); + + reset($nonRelatedEntries); + + $randomNonRelatedEntryIndex = random_int(0, count($nonRelatedEntries) - 1); + $randomNonRelatedEntryId = $nonRelatedEntries[$randomNonRelatedEntryIndex]; + + /** + * @var Content $nonRelatedEntry + */ + $nonRelatedEntry = $this->getEm()->getRepository(Content::class)->findOneBy(['id' => $randomNonRelatedEntryId]); + + return $nonRelatedEntry; + } + + private function getContentRelatedIds(Collection $contentRelations): array + { + $relatedIds = []; + foreach ($contentRelations as $relation) { + $relatedIds[] = $relation->getId(); + } + + return $relatedIds; + } + +} From f247fecaaa13bc008aa7f137e923dd7eee8c590f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Bj=C3=B6rkland?= Date: Fri, 17 Sep 2021 16:37:13 +0200 Subject: [PATCH 2/4] Analyzed and corrected through ECS and PHPStan. --- src/Factory/RelationFactory.php | 4 +- tests/php/Factory/RelationFactoryTest.php | 118 ++++++++++++++-------- 2 files changed, 75 insertions(+), 47 deletions(-) diff --git a/src/Factory/RelationFactory.php b/src/Factory/RelationFactory.php index 5a913f69a..595f92145 100644 --- a/src/Factory/RelationFactory.php +++ b/src/Factory/RelationFactory.php @@ -7,14 +7,13 @@ use Bolt\Entity\Content; use Bolt\Entity\Relation; use Bolt\Repository\RelationRepository; -use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManagerInterface; use Tightenco\Collect\Support\Collection; class RelationFactory { /** @var EntityManagerInterface */ - private $em; + private $em; /** @var RelationRepository */ private $repository; @@ -65,7 +64,6 @@ public function save($relation): void { if ($relation instanceof Relation) { $this->em->persist($relation); - } elseif (is_iterable($relation)) { foreach ($relation as $r) { $this->em->persist($r); diff --git a/tests/php/Factory/RelationFactoryTest.php b/tests/php/Factory/RelationFactoryTest.php index c7aa12313..673122a07 100644 --- a/tests/php/Factory/RelationFactoryTest.php +++ b/tests/php/Factory/RelationFactoryTest.php @@ -1,34 +1,34 @@ -getEm()->getRepository(Relation::class); + /** @var RelationFactory $relationFactory */ - $relationFactory = new RelationFactory($this->getEm()->getRepository(Relation::class), $this->getEm()); + $relationFactory = new RelationFactory($relationRepository, $this->getEm()); - /** - * @var Content $page - */ + /** @var Content $page */ $page = $this->getEm()->getRepository(Content::class)->findOneBy(['contentType' => 'pages']); - $nonRelatedEntry = $this->getNonRelatedEntryForPage($page); - + /** @var Content|null $nonRelatedEntry */ + $nonRelatedEntry = $this->getNonRelatedEntryForPage($page); - /** - * @var Relation $newRelation - */ + /** @var Relation $newRelation */ $newRelation = $relationFactory->create($nonRelatedEntry, $page); $relationFactory->save($newRelation); @@ -36,46 +36,85 @@ public function testSavePersistsTheRelation(): array $this->assertNotNull($newRelation->getId(), 'If id is null, the relation has not been persisted.'); return [ - "page" => $page, - "entry" => $nonRelatedEntry, - "relation" => $newRelation + 'page' => $page, + 'entry' => $nonRelatedEntry, + 'relation' => $newRelation, ]; } - - /** * @depends testSavePersistsTheRelation */ public function testPersistedRelationCascadesToContent(array $entities): void - { + { /** @var Content $page */ - $page = $entities["page"]; + $page = $entities['page']; /** @var Content $entry */ - $entry = $entities["entry"]; + $entry = $entities['entry']; /** @var Relation $persistedRelation */ - $persistedRelation = $entities["relation"]; + $persistedRelation = $entities['relation']; - /** @var array $entryRelationIds */ + /** @var array $entryRelationIds */ $entryRelationIds = $this->getContentRelatedIds($entry->getRelationsFromThisContent()); - - /** @var array $pageRelationIds */ + + /** @var array $pageRelationIds */ $pageRelationIds = $this->getContentRelatedIds($page->getRelationsToThisContent()); - - $this->assertTrue(in_array($persistedRelation->getId(), $pageRelationIds), "It seems like relation has not persisted for contentType pages"); - $this->assertTrue(in_array($persistedRelation->getId(), $entryRelationIds), "It seems like relation has not persisted for contentType entries"); + $this->assertTrue(in_array($persistedRelation->getId(), $pageRelationIds, true), 'It seems like relation has not persisted for contentType pages'); + $this->assertTrue(in_array($persistedRelation->getId(), $entryRelationIds, true), 'It seems like relation has not persisted for contentType entries'); + } + + public function testSaveMultipleRelations(): void + { + /** @var RelationRepository */ + $relationRepository = $this->getEm()->getRepository(Relation::class); + + /** @var RelationFactory $relationFactory */ + $relationFactory = new RelationFactory($relationRepository, $this->getEm()); + + /** @var ContentRepository $contentRepository */ + $contentRepository = $this->getEm()->getRepository(Content::class); + + /** @var Content $page */ + $page = $this->getEm()->getRepository(Content::class)->findOneBy(['contentType' => 'pages']); + + /** @var array $nonRelatedEntryIds */ + $nonRelatedEntryIds = $this->getNonRelatedEntryIds($page); + + $entries = []; + $relations = []; + + $limit = count($nonRelatedEntryIds) > 5 ? 5 : count($nonRelatedEntryIds); + for ($i = 0; $i < $limit; $i++) { + /** @var Content|null $entry */ + $entry = $contentRepository->findOneById($nonRelatedEntryIds[$i]); + $entries[] = $entry; + $relations[] = $relationFactory->create($entry, $page); + } + + $relationFactory->save($relations); + $relationIds = array_map(fn ($relation) => $relation->getId(), $relations); + + $this->assertFalse(in_array(null, $relationIds, true), 'Some of the relations has not been persisted.'); } /** - * Returns a Content entity with contentType 'Entry' that does not have a + * Returns a Content entity with contentType 'Entry' that does not have a * relation with the argument. - * - * @return Content $nonRelatedEntry */ private function getNonRelatedEntryForPage(Content $page): ?Content + { + $nonRelatedEntries = $this->getNonRelatedEntryIds($page); + + $randomNonRelatedEntryIndex = random_int(0, count($nonRelatedEntries) - 1); + $randomNonRelatedEntryId = $nonRelatedEntries[$randomNonRelatedEntryIndex]; + + return $this->getEm()->getRepository(Content::class)->findOneBy(['id' => $randomNonRelatedEntryId]); + } + + private function getNonRelatedEntryIds(Content $page): array { $relations = $page->getRelationsToThisContent(); $relatedIds = []; @@ -84,25 +123,17 @@ private function getNonRelatedEntryForPage(Content $page): ?Content } $entries = $this->getEm()->getRepository(Content::class)->findBy(['contentType' => 'entries']); - $entryIds = array_map(function ($entry) { + $entryIds = array_map(function ($entry) { return $entry->getId(); }, $entries); - $nonRelatedEntries = array_filter($entryIds, fn ($id) => !in_array($id, $relatedIds)); + $nonRelatedEntries = array_filter($entryIds, fn ($id) => ! in_array($id, $relatedIds, true)); reset($nonRelatedEntries); - $randomNonRelatedEntryIndex = random_int(0, count($nonRelatedEntries) - 1); - $randomNonRelatedEntryId = $nonRelatedEntries[$randomNonRelatedEntryIndex]; - - /** - * @var Content $nonRelatedEntry - */ - $nonRelatedEntry = $this->getEm()->getRepository(Content::class)->findOneBy(['id' => $randomNonRelatedEntryId]); - - return $nonRelatedEntry; + return $nonRelatedEntries; } - private function getContentRelatedIds(Collection $contentRelations): array + private function getContentRelatedIds(Collection $contentRelations): array { $relatedIds = []; foreach ($contentRelations as $relation) { @@ -111,5 +142,4 @@ private function getContentRelatedIds(Collection $contentRelations): array return $relatedIds; } - } From c1d9447e43a3bb1f4b127ca1e4c470e904d6b0fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Bj=C3=B6rkland?= Date: Sun, 19 Sep 2021 10:27:21 +0200 Subject: [PATCH 3/4] Changed arrow function to anonymous function. --- tests/php/Factory/RelationFactoryTest.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/php/Factory/RelationFactoryTest.php b/tests/php/Factory/RelationFactoryTest.php index 673122a07..9348d5250 100644 --- a/tests/php/Factory/RelationFactoryTest.php +++ b/tests/php/Factory/RelationFactoryTest.php @@ -95,7 +95,9 @@ public function testSaveMultipleRelations(): void } $relationFactory->save($relations); - $relationIds = array_map(fn ($relation) => $relation->getId(), $relations); + $relationIds = array_map(function ($relation) { + return $relation->getId(); + }, $relations); $this->assertFalse(in_array(null, $relationIds, true), 'Some of the relations has not been persisted.'); } @@ -126,7 +128,9 @@ private function getNonRelatedEntryIds(Content $page): array $entryIds = array_map(function ($entry) { return $entry->getId(); }, $entries); - $nonRelatedEntries = array_filter($entryIds, fn ($id) => ! in_array($id, $relatedIds, true)); + $nonRelatedEntries = array_filter($entryIds, function ($id) use ($relatedIds) { + return ! in_array($id, $relatedIds, true); + }); reset($nonRelatedEntries); From 133ccd3ed29e87991e611ed51e9b7417f9ee7c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Bj=C3=B6rkland?= Date: Tue, 21 Sep 2021 13:50:34 +0200 Subject: [PATCH 4/4] Fixed array key resetting after filter. --- tests/php/Factory/RelationFactoryTest.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/php/Factory/RelationFactoryTest.php b/tests/php/Factory/RelationFactoryTest.php index 9348d5250..ac60dbda8 100644 --- a/tests/php/Factory/RelationFactoryTest.php +++ b/tests/php/Factory/RelationFactoryTest.php @@ -87,11 +87,15 @@ public function testSaveMultipleRelations(): void $relations = []; $limit = count($nonRelatedEntryIds) > 5 ? 5 : count($nonRelatedEntryIds); - for ($i = 0; $i < $limit; $i++) { + foreach ($nonRelatedEntryIds as $id) { /** @var Content|null $entry */ - $entry = $contentRepository->findOneById($nonRelatedEntryIds[$i]); + $entry = $contentRepository->findOneById($id); $entries[] = $entry; $relations[] = $relationFactory->create($entry, $page); + + if (count($relations) >= $limit) { + break; + } } $relationFactory->save($relations); @@ -132,9 +136,7 @@ private function getNonRelatedEntryIds(Content $page): array return ! in_array($id, $relatedIds, true); }); - reset($nonRelatedEntries); - - return $nonRelatedEntries; + return array_values($nonRelatedEntries); } private function getContentRelatedIds(Collection $contentRelations): array