From 3d9a427eb78b953da5ffef53ed70bdb433e8b446 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 5 Dec 2017 17:37:43 +0100 Subject: [PATCH 1/4] Revamped the data fixtures --- .../{FixturesTrait.php => AppFixtures.php} | 235 ++++++++++++------ src/DataFixtures/PostFixtures.php | 117 --------- src/DataFixtures/TagFixtures.php | 47 ---- src/DataFixtures/UserFixtures.php | 77 ------ src/Entity/Post.php | 11 +- var/data/blog.sqlite | Bin 241664 -> 274432 bytes 6 files changed, 170 insertions(+), 317 deletions(-) rename src/DataFixtures/{FixturesTrait.php => AppFixtures.php} (51%) delete mode 100644 src/DataFixtures/PostFixtures.php delete mode 100644 src/DataFixtures/TagFixtures.php delete mode 100644 src/DataFixtures/UserFixtures.php diff --git a/src/DataFixtures/FixturesTrait.php b/src/DataFixtures/AppFixtures.php similarity index 51% rename from src/DataFixtures/FixturesTrait.php rename to src/DataFixtures/AppFixtures.php index 334aed0dc..00de4cc5b 100644 --- a/src/DataFixtures/FixturesTrait.php +++ b/src/DataFixtures/AppFixtures.php @@ -11,49 +11,131 @@ namespace App\DataFixtures; -/** - * Helper class to create fixtures contents. - */ -trait FixturesTrait +use App\Entity\Comment; +use App\Entity\Post; +use App\Entity\Tag; +use App\Entity\User; +use App\Utils\Slugger; +use Doctrine\Bundle\FixturesBundle\Fixture; +use Doctrine\Common\Persistence\ObjectManager; +use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; + +class AppFixtures extends Fixture { - private function getPostContent(): string + private $passwordEncoder; + + public function __construct(UserPasswordEncoderInterface $passwordEncoder) { - return <<<'MARKDOWN' -Lorem ipsum dolor sit amet consectetur adipisicing elit, sed do eiusmod tempor -incididunt ut labore et **dolore magna aliqua**: Duis aute irure dolor in -reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. -Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia -deserunt mollit anim id est laborum. + $this->passwordEncoder = $passwordEncoder; + } - * Ut enim ad minim veniam - * Quis nostrud exercitation *ullamco laboris* - * Nisi ut aliquip ex ea commodo consequat + public function load(ObjectManager $manager) + { + $this->loadUsers($manager); + $this->loadTags($manager); + $this->loadPosts($manager); + } -Praesent id fermentum lorem. Ut est lorem, fringilla at accumsan nec, euismod at -nunc. Aenean mattis sollicitudin mattis. Nullam pulvinar vestibulum bibendum. -Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos -himenaeos. Fusce nulla purus, gravida ac interdum ut, blandit eget ex. Duis a -luctus dolor. + private function loadUsers(ObjectManager $manager) + { + foreach ($this->getUserData() as [$fullname, $username, $password, $email, $roles]) { + $user = new User(); + $user->setFullName($fullname); + $user->setUsername($username); + $user->setPassword($this->passwordEncoder->encodePassword($user, $password)); + $user->setEmail($email); + $user->setRoles($roles); + + $manager->persist($user); + $this->addReference($username, $user); + } -Integer auctor massa maximus nulla scelerisque accumsan. *Aliquam ac malesuada* -ex. Pellentesque tortor magna, vulputate eu vulputate ut, venenatis ac lectus. -Praesent ut lacinia sem. Mauris a lectus eget felis mollis feugiat. Quisque -efficitur, mi ut semper pulvinar, urna urna blandit massa, eget tincidunt augue -nulla vitae est. + $manager->flush(); + } -Ut posuere aliquet tincidunt. Aliquam erat volutpat. **Class aptent taciti** -sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi -arcu orci, gravida eget aliquam eu, suscipit et ante. Morbi vulputate metus vel -ipsum finibus, ut dapibus massa feugiat. Vestibulum vel lobortis libero. Sed -tincidunt tellus et viverra scelerisque. Pellentesque tincidunt cursus felis. -Sed in egestas erat. + private function loadTags(ObjectManager $manager) + { + foreach ($this->getTagData() as $index => $name) { + $tag = new Tag(); + $tag->setName($name); -Aliquam pulvinar interdum massa, vel ullamcorper ante consectetur eu. Vestibulum -lacinia ac enim vel placerat. Integer pulvinar magna nec dui malesuada, nec -congue nisl dictum. Donec mollis nisl tortor, at congue erat consequat a. Nam -tempus elit porta, blandit elit vel, viverra lorem. Sed sit amet tellus -tincidunt, faucibus nisl in, aliquet libero. -MARKDOWN; + $manager->persist($tag); + $this->addReference('tag-'.$name, $tag); + } + + $manager->flush(); + } + + private function loadPosts(ObjectManager $manager) + { + foreach ($this->getPostData() as [$title, $slug, $summary, $content, $publishedAt, $author, $tags]) { + $post = new Post(); + $post->setTitle($title); + $post->setSlug($slug); + $post->setSummary($summary); + $post->setContent($content); + $post->setPublishedAt($publishedAt); + $post->setAuthor($author); + $post->addTag(...$tags); + + foreach (range(1, 5) as $i) { + $comment = new Comment(); + $comment->setAuthor($this->getReference('john_user')); + $comment->setContent($this->getRandomText(random_int(255, 512))); + $comment->setPublishedAt(new \DateTime('now + '.($i).'seconds')); + + $post->addComment($comment); + } + + $manager->persist($post); + } + + $manager->flush(); + } + + private function getUserData(): array + { + return [ + // $userData = [$fullname, $username, $password, $email, $roles]; + ['Jane Doe', 'jane_admin', 'kitten', 'jane_admin@symfony.com', ['ROLE_ADMIN']], + ['Tom Doe', 'tom_admin', 'kitten', 'tom_admin@symfony.com', ['ROLE_ADMIN']], + ['John Doe', 'john_user', 'kitten', 'john_user@symfony.com', ['ROLE_USER']], + ]; + } + + private function getTagData(): array + { + return [ + 'lorem', + 'ipsum', + 'consectetur', + 'adipiscing', + 'incididunt', + 'labore', + 'voluptate', + 'dolore', + 'pariatur', + ]; + } + + private function getPostData() + { + $posts = []; + foreach ($this->getPhrases() as $i => $title) { + // $postData = [$title, $slug, $summary, $content, $publishedAt, $author, $tags, $comments]; + $posts[] = [ + $title, + Slugger::slugify($title), + $this->getRandomText(), + $this->getPostContent(), + new \DateTime('now - '.$i.'days'), + // Ensure that the first post is written by Jane Doe to simplify tests + $this->getReference(['jane_admin', 'tom_admin'][0 === $i ? 0 : random_int(0, 1)]), + $this->getRandomTags(), + ]; + } + + return $posts; } private function getPhrases(): array @@ -92,55 +174,64 @@ private function getPhrases(): array ]; } - private function getTagNames(): array - { - return [ - 'lorem', - 'ipsum', - 'consectetur', - 'adipiscing', - 'incididunt', - 'labore', - 'voluptate', - 'dolore', - 'pariatur', - ]; - } - - private function getRandomPostTitles(): array + private function getRandomText(int $maxLength = 255): string { $phrases = $this->getPhrases(); - - // this ensures that the first title is always 'Lorem Ipsum...' - $loremIpsumPhrase = array_shift($phrases); shuffle($phrases); - array_unshift($phrases, $loremIpsumPhrase); - return $phrases; + while (mb_strlen($text = implode('. ', $phrases).'.') > $maxLength) { + array_pop($phrases); + } + + return $text; } - private function getRandomPostSummary(int $maxLength = 255): string + private function getPostContent(): string { - $phrases = $this->getPhrases(); + return <<<'MARKDOWN' +Lorem ipsum dolor sit amet consectetur adipisicing elit, sed do eiusmod tempor +incididunt ut labore et **dolore magna aliqua**: Duis aute irure dolor in +reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. +Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia +deserunt mollit anim id est laborum. - $numPhrases = random_int(6, 12); - shuffle($phrases); - $phrases = array_slice($phrases, 0, $numPhrases - 1); + * Ut enim ad minim veniam + * Quis nostrud exercitation *ullamco laboris* + * Nisi ut aliquip ex ea commodo consequat - while (mb_strlen($summary = implode('. ', $phrases).'.') > $maxLength) { - array_pop($phrases); - } +Praesent id fermentum lorem. Ut est lorem, fringilla at accumsan nec, euismod at +nunc. Aenean mattis sollicitudin mattis. Nullam pulvinar vestibulum bibendum. +Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos +himenaeos. Fusce nulla purus, gravida ac interdum ut, blandit eget ex. Duis a +luctus dolor. + +Integer auctor massa maximus nulla scelerisque accumsan. *Aliquam ac malesuada* +ex. Pellentesque tortor magna, vulputate eu vulputate ut, venenatis ac lectus. +Praesent ut lacinia sem. Mauris a lectus eget felis mollis feugiat. Quisque +efficitur, mi ut semper pulvinar, urna urna blandit massa, eget tincidunt augue +nulla vitae est. - return $summary; +Ut posuere aliquet tincidunt. Aliquam erat volutpat. **Class aptent taciti** +sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi +arcu orci, gravida eget aliquam eu, suscipit et ante. Morbi vulputate metus vel +ipsum finibus, ut dapibus massa feugiat. Vestibulum vel lobortis libero. Sed +tincidunt tellus et viverra scelerisque. Pellentesque tincidunt cursus felis. +Sed in egestas erat. + +Aliquam pulvinar interdum massa, vel ullamcorper ante consectetur eu. Vestibulum +lacinia ac enim vel placerat. Integer pulvinar magna nec dui malesuada, nec +congue nisl dictum. Donec mollis nisl tortor, at congue erat consequat a. Nam +tempus elit porta, blandit elit vel, viverra lorem. Sed sit amet tellus +tincidunt, faucibus nisl in, aliquet libero. +MARKDOWN; } - private function getRandomCommentContent(): string + private function getRandomTags(): array { - $phrases = $this->getPhrases(); - - $numPhrases = random_int(2, 15); - shuffle($phrases); + $tagNames = $this->getTagData(); + shuffle($tagNames); + $selectedTags = array_slice($tagNames, 0, random_int(2, 4)); - return implode(' ', array_slice($phrases, 0, $numPhrases - 1)); + return array_map(function ($tagName) { return $this->getReference('tag-'.$tagName); }, $selectedTags); } } diff --git a/src/DataFixtures/PostFixtures.php b/src/DataFixtures/PostFixtures.php deleted file mode 100644 index ea5c8728c..000000000 --- a/src/DataFixtures/PostFixtures.php +++ /dev/null @@ -1,117 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace App\DataFixtures; - -use App\Entity\Comment; -use App\Entity\Post; -use App\Entity\User; -use App\Utils\Slugger; -use Doctrine\Common\DataFixtures\AbstractFixture; -use Doctrine\Common\DataFixtures\DependentFixtureInterface; -use Doctrine\Common\Persistence\ObjectManager; - -/** - * Defines the sample blog posts to load in the database before running the unit - * and functional tests. Execute this command to load the data. - * - * $ php bin/console doctrine:fixtures:load - * - * See https://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html - * - * @author Ryan Weaver - * @author Javier Eguiluz - * @author Yonel Ceruto - */ -class PostFixtures extends AbstractFixture implements DependentFixtureInterface -{ - use FixturesTrait; - - /** - * {@inheritdoc} - */ - public function load(ObjectManager $manager): void - { - foreach ($this->getRandomPostTitles() as $i => $title) { - $post = new Post(); - - $post->setTitle($title); - $post->setSummary($this->getRandomPostSummary()); - $post->setSlug(Slugger::slugify($post->getTitle())); - $post->setContent($this->getPostContent()); - $post->setPublishedAt(new \DateTime('now - '.$i.'days')); - - // Ensure that the first post is written by Jane Doe to simplify tests - // "References" are the way to share objects between fixtures defined - // in different files. This reference has been added in the UserFixtures - // file and it contains an instance of the User entity. - $post->setAuthor(0 === $i ? $this->getReference('jane-admin') : $this->getRandomUser()); - - // for aesthetic reasons, the first blog post always has 2 tags - foreach ($this->getRandomTags($i > 0 ? random_int(0, 3) : 2) as $tag) { - $post->addTag($tag); - } - - foreach (range(1, 5) as $j) { - $comment = new Comment(); - - $comment->setAuthor($this->getReference('john-user')); - $comment->setPublishedAt(new \DateTime('now + '.($i + $j).'seconds')); - $comment->setContent($this->getRandomCommentContent()); - - $post->addComment($comment); - - $manager->persist($comment); - } - - $manager->persist($post); - } - - $manager->flush(); - } - - /** - * Instead of defining the exact order in which the fixtures files must be loaded, - * this method defines which other fixtures this file depends on. Then, Doctrine - * will figure out the best order to fit all the dependencies. - */ - public function getDependencies(): array - { - return [ - TagFixtures::class, - UserFixtures::class, - ]; - } - - private function getRandomUser(): User - { - $admins = ['jane-admin', 'tom-admin']; - $index = array_rand($admins); - - return $this->getReference($admins[$index]); - } - - private function getRandomTags(int $numTags = 0): array - { - $tags = []; - - if (0 === $numTags) { - return $tags; - } - - $indexes = (array) array_rand($this->getTagNames(), $numTags); - foreach ($indexes as $index) { - $tags[] = $this->getReference('tag-'.$index); - } - - return $tags; - } -} diff --git a/src/DataFixtures/TagFixtures.php b/src/DataFixtures/TagFixtures.php deleted file mode 100644 index 9dccddb1d..000000000 --- a/src/DataFixtures/TagFixtures.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace App\DataFixtures; - -use App\Entity\Tag; -use Doctrine\Common\DataFixtures\AbstractFixture; -use Doctrine\Common\Persistence\ObjectManager; - -/** - * Defines the sample blog tags to load in the database before running the unit - * and functional tests. Execute this command to load the data. - * - * $ php bin/console doctrine:fixtures:load - * - * See https://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html - * - * @author Yonel Ceruto - */ -class TagFixtures extends AbstractFixture -{ - use FixturesTrait; - - /** - * {@inheritdoc} - */ - public function load(ObjectManager $manager): void - { - foreach ($this->getTagNames() as $index => $name) { - $tag = new Tag(); - $tag->setName($name); - - $manager->persist($tag); - $this->addReference('tag-'.$index, $tag); - } - - $manager->flush(); - } -} diff --git a/src/DataFixtures/UserFixtures.php b/src/DataFixtures/UserFixtures.php deleted file mode 100644 index d443a061f..000000000 --- a/src/DataFixtures/UserFixtures.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace App\DataFixtures; - -use App\Entity\User; -use Doctrine\Common\DataFixtures\AbstractFixture; -use Doctrine\Common\Persistence\ObjectManager; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; - -/** - * Defines the sample users to load in the database before running the unit and - * functional tests. Execute this command to load the data. - * - * $ php bin/console doctrine:fixtures:load - * - * See https://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html - * - * @author Ryan Weaver - * @author Javier Eguiluz - * @author Yonel Ceruto - */ -class UserFixtures extends AbstractFixture implements ContainerAwareInterface -{ - use ContainerAwareTrait; - - /** - * {@inheritdoc} - */ - public function load(ObjectManager $manager): void - { - $passwordEncoder = $this->container->get('security.password_encoder'); - - $janeAdmin = new User(); - $janeAdmin->setFullName('Jane Doe'); - $janeAdmin->setUsername('jane_admin'); - $janeAdmin->setEmail('jane_admin@symfony.com'); - $janeAdmin->setRoles(['ROLE_ADMIN']); - $encodedPassword = $passwordEncoder->encodePassword($janeAdmin, 'kitten'); - $janeAdmin->setPassword($encodedPassword); - $manager->persist($janeAdmin); - // In case if fixture objects have relations to other fixtures, adds a reference - // to that object by name and later reference it to form a relation. - // See https://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html#sharing-objects-between-fixtures - $this->addReference('jane-admin', $janeAdmin); - - $tomAdmin = new User(); - $tomAdmin->setFullName('Tom Doe'); - $tomAdmin->setUsername('tom_admin'); - $tomAdmin->setEmail('tom_admin@symfony.com'); - $tomAdmin->setRoles(['ROLE_ADMIN']); - $encodedPassword = $passwordEncoder->encodePassword($tomAdmin, 'kitten'); - $tomAdmin->setPassword($encodedPassword); - $manager->persist($tomAdmin); - $this->addReference('tom-admin', $tomAdmin); - - $johnUser = new User(); - $johnUser->setFullName('John Doe'); - $johnUser->setUsername('john_user'); - $johnUser->setEmail('john_user@symfony.com'); - $encodedPassword = $passwordEncoder->encodePassword($johnUser, 'kitten'); - $johnUser->setPassword($encodedPassword); - $manager->persist($johnUser); - $this->addReference('john-user', $johnUser); - - $manager->flush(); - } -} diff --git a/src/Entity/Post.php b/src/Entity/Post.php index 4689691be..8bf6853a1 100644 --- a/src/Entity/Post.php +++ b/src/Entity/Post.php @@ -104,7 +104,8 @@ class Post * @ORM\OneToMany( * targetEntity="Comment", * mappedBy="post", - * orphanRemoval=true + * orphanRemoval=true, + * cascade={"persist"} * ) * @ORM\OrderBy({"publishedAt": "DESC"}) */ @@ -211,10 +212,12 @@ public function setSummary(string $summary): void $this->summary = $summary; } - public function addTag(Tag $tag): void + public function addTag(Tag ...$tags): void { - if (!$this->tags->contains($tag)) { - $this->tags->add($tag); + foreach ($tags as $tag) { + if (!$this->tags->contains($tag)) { + $this->tags->add($tag); + } } } diff --git a/var/data/blog.sqlite b/var/data/blog.sqlite index 1bdf92e07118e797346c2618611a201bb2586e7c..1ff16420e4b8966b06a94318ee9f21c8182be98c 100644 GIT binary patch literal 274432 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%0DjCi&lx^^qweN|9>|9 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 delta 16271 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 From 7c3e8650852ee66ab56e75ec9bfe8a02b7baa460 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 10 Dec 2017 12:51:57 +0100 Subject: [PATCH 2/4] Don't use the fixtures trait in tests --- tests/Controller/Admin/BlogControllerTest.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/Controller/Admin/BlogControllerTest.php b/tests/Controller/Admin/BlogControllerTest.php index 7dee0bbae..c5f222543 100644 --- a/tests/Controller/Admin/BlogControllerTest.php +++ b/tests/Controller/Admin/BlogControllerTest.php @@ -11,7 +11,6 @@ namespace App\Tests\Controller\Admin; -use App\DataFixtures\FixturesTrait; use App\Entity\Post; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Component\HttpFoundation\Response; @@ -33,8 +32,6 @@ */ class BlogControllerTest extends WebTestCase { - use FixturesTrait; - /** * @dataProvider getUrlsForRegularUsers */ @@ -83,8 +80,8 @@ public function testAdminBackendHomePage() public function testAdminNewPost() { $postTitle = 'Blog Post Title '.mt_rand(); - $postSummary = $this->getRandomPostSummary(); - $postContent = $this->getPostContent(); + $postSummary = $this->generateRandomString(255); + $postContent = $this->generateRandomString(1024); $client = static::createClient([], [ 'PHP_AUTH_USER' => 'jane_admin', @@ -166,4 +163,11 @@ public function testAdminDeletePost() $post = $client->getContainer()->get('doctrine')->getRepository(Post::class)->find(1); $this->assertNull($post); } + + private function generateRandomString(int $length): string + { + $chars = ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + + return substr(str_shuffle(str_repeat($chars, ceil($length/strlen($chars)) )),1, $length); + } } From a3494346343bed4e0a2a3b2df239961da670401b Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 10 Dec 2017 12:53:52 +0100 Subject: [PATCH 3/4] CS fixes --- tests/Controller/Admin/BlogControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Controller/Admin/BlogControllerTest.php b/tests/Controller/Admin/BlogControllerTest.php index c5f222543..e3d9feeff 100644 --- a/tests/Controller/Admin/BlogControllerTest.php +++ b/tests/Controller/Admin/BlogControllerTest.php @@ -168,6 +168,6 @@ private function generateRandomString(int $length): string { $chars = ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - return substr(str_shuffle(str_repeat($chars, ceil($length/strlen($chars)) )),1, $length); + return substr(str_shuffle(str_repeat($chars, ceil($length/strlen($chars)))), 1, $length); } } From 83aaba49134222315d6684fe49c24a34261326a9 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 10 Dec 2017 13:08:59 +0100 Subject: [PATCH 4/4] Minor fixes --- tests/Controller/Admin/BlogControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Controller/Admin/BlogControllerTest.php b/tests/Controller/Admin/BlogControllerTest.php index e3d9feeff..23235d463 100644 --- a/tests/Controller/Admin/BlogControllerTest.php +++ b/tests/Controller/Admin/BlogControllerTest.php @@ -166,8 +166,8 @@ public function testAdminDeletePost() private function generateRandomString(int $length): string { - $chars = ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - return substr(str_shuffle(str_repeat($chars, ceil($length/strlen($chars)))), 1, $length); + return mb_substr(str_shuffle(str_repeat($chars, ceil($length / mb_strlen($chars)))), 1, $length); } }