From 6ce25d8aa296166370b3466fa62f360180aa5739 Mon Sep 17 00:00:00 2001 From: Grafikart Date: Tue, 14 Feb 2017 13:27:02 +0100 Subject: [PATCH 1/4] Added TagRepository --- src/AppBundle/Entity/Tag.php | 50 ++++++++++++++++++- src/AppBundle/Repository/TagRepository.php | 56 ++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 src/AppBundle/Repository/TagRepository.php diff --git a/src/AppBundle/Entity/Tag.php b/src/AppBundle/Entity/Tag.php index 69bbe93a3..22e528d9b 100644 --- a/src/AppBundle/Entity/Tag.php +++ b/src/AppBundle/Entity/Tag.php @@ -5,7 +5,7 @@ use Doctrine\ORM\Mapping as ORM; /** - * @ORM\Entity() + * @ORM\Entity(repositoryClass="AppBundle\Repository\TagRepository") * @ORM\Table(name="symfony_demo_tag") * * Defines the properties of the Tag entity to represent the post tags. @@ -25,6 +25,13 @@ class Tag implements \JsonSerializable */ private $id; + /** + * @var array + * + * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Post", mappedBy="tags") + */ + private $posts; + /** * @var string * @@ -66,4 +73,45 @@ public function __toString() { return $this->name; } + /** + * Constructor + */ + public function __construct() + { + $this->posts = new \Doctrine\Common\Collections\ArrayCollection(); + } + + /** + * Add post + * + * @param \AppBundle\Entity\Post $post + * + * @return Tag + */ + public function addPost(\AppBundle\Entity\Post $post) + { + $this->posts[] = $post; + + return $this; + } + + /** + * Remove post + * + * @param \AppBundle\Entity\Post $post + */ + public function removePost(\AppBundle\Entity\Post $post) + { + $this->posts->removeElement($post); + } + + /** + * Get posts + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getPosts() + { + return $this->posts; + } } diff --git a/src/AppBundle/Repository/TagRepository.php b/src/AppBundle/Repository/TagRepository.php new file mode 100644 index 000000000..51d36e39c --- /dev/null +++ b/src/AppBundle/Repository/TagRepository.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace AppBundle\Repository; + +use AppBundle\Entity\Tag; +use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Query; +use Pagerfanta\Adapter\DoctrineORMAdapter; +use Pagerfanta\Pagerfanta; + +/** + * This custom Doctrine repository contains some methods which are useful when + * querying for blog post information. + * + * See http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes + * + * @author Ryan Weaver + * @author Javier Eguiluz + * @author Yonel Ceruto + */ +class TagRepository extends EntityRepository +{ + /** + * @param int $page + * + * @return Pagerfanta + */ + public function cleanUnusedTags() + { + $unused_tags = $this->getEntityManager() + ->createQuery(' + SELECT t.id + FROM AppBundle:Tag t + LEFT JOIN t.posts p + WHERE p.id IS NULL + ')->getResult(); + if (!empty($unused_tags)) { + $tag_ids = array_map(function ($tag) { + return $tag['id']; + }, $unused_tags); + $this->getEntityManager() + ->createQuery('DELETE FROM AppBundle:Tag t WHERE t.id IN (:tags)') + ->setParameter('tags', $tag_ids) + ->execute(); + } + } +} From 34e955855de02126b42c2cf2cb2af4f7f1fbfc55 Mon Sep 17 00:00:00 2001 From: Grafikart Date: Tue, 14 Feb 2017 14:09:30 +0100 Subject: [PATCH 2/4] Clean up unused Tags --- src/AppBundle/Controller/Admin/BlogController.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/AppBundle/Controller/Admin/BlogController.php b/src/AppBundle/Controller/Admin/BlogController.php index 903a69c76..3bbb19a8b 100644 --- a/src/AppBundle/Controller/Admin/BlogController.php +++ b/src/AppBundle/Controller/Admin/BlogController.php @@ -12,6 +12,7 @@ namespace AppBundle\Controller\Admin; use AppBundle\Entity\Post; +use AppBundle\Entity\Tag; use AppBundle\Form\PostType; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; @@ -147,6 +148,7 @@ public function editAction(Post $post, Request $request) if ($form->isSubmitted() && $form->isValid()) { $post->setSlug($this->get('slugger')->slugify($post->getTitle())); $entityManager->flush(); + $this->getDoctrine()->getRepository(Tag::class)->cleanUnusedTags(); $this->addFlash('success', 'post.updated_successfully'); @@ -184,6 +186,7 @@ public function deleteAction(Request $request, Post $post) $entityManager->remove($post); $entityManager->flush(); + $this->getDoctrine()->getRepository(Tag::class)->cleanUnusedTags(); $this->addFlash('success', 'post.deleted_successfully'); From 04c32a152dbf44c7b5f26397be4090ccf4c113fb Mon Sep 17 00:00:00 2001 From: Grafikart Date: Tue, 14 Feb 2017 13:27:02 +0100 Subject: [PATCH 3/4] Cleaned TagRepositoy --- .../Controller/Admin/BlogController.php | 23 ++++----- src/AppBundle/Entity/Tag.php | 48 ------------------- src/AppBundle/Repository/TagRepository.php | 42 ++++++---------- 3 files changed, 27 insertions(+), 86 deletions(-) diff --git a/src/AppBundle/Controller/Admin/BlogController.php b/src/AppBundle/Controller/Admin/BlogController.php index 3bbb19a8b..5146b4153 100644 --- a/src/AppBundle/Controller/Admin/BlogController.php +++ b/src/AppBundle/Controller/Admin/BlogController.php @@ -147,8 +147,10 @@ public function editAction(Post $post, Request $request) if ($form->isSubmitted() && $form->isValid()) { $post->setSlug($this->get('slugger')->slugify($post->getTitle())); - $entityManager->flush(); - $this->getDoctrine()->getRepository(Tag::class)->cleanUnusedTags(); + $entityManager->transactional(function ($entityManager) { + $entityManager->flush(); + $this->getDoctrine()->getRepository(Tag::class)->cleanUnusedTags(); + }); $this->addFlash('success', 'post.updated_successfully'); @@ -178,15 +180,14 @@ public function deleteAction(Request $request, Post $post) } $entityManager = $this->getDoctrine()->getManager(); - - // Delete the tags associated with this blog post. This is done automatically - // by Doctrine, except for SQLite (the database used in this application) - // because foreign key support is not enabled by default in SQLite - $post->getTags()->clear(); - - $entityManager->remove($post); - $entityManager->flush(); - $this->getDoctrine()->getRepository(Tag::class)->cleanUnusedTags(); + $entityManager->transactional(function ($entityManager) use ($post) { + // Delete the tags associated with this blog post. This is done automatically + // by Doctrine, except for SQLite (the database used in this application) + // because foreign key support is not enabled by default in SQLite + $post->getTags()->clear(); + $entityManager->remove($post); + $this->getDoctrine()->getRepository(Tag::class)->cleanUnusedTags(); + }); $this->addFlash('success', 'post.deleted_successfully'); diff --git a/src/AppBundle/Entity/Tag.php b/src/AppBundle/Entity/Tag.php index 22e528d9b..fbe14ca4c 100644 --- a/src/AppBundle/Entity/Tag.php +++ b/src/AppBundle/Entity/Tag.php @@ -25,13 +25,6 @@ class Tag implements \JsonSerializable */ private $id; - /** - * @var array - * - * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Post", mappedBy="tags") - */ - private $posts; - /** * @var string * @@ -73,45 +66,4 @@ public function __toString() { return $this->name; } - /** - * Constructor - */ - public function __construct() - { - $this->posts = new \Doctrine\Common\Collections\ArrayCollection(); - } - - /** - * Add post - * - * @param \AppBundle\Entity\Post $post - * - * @return Tag - */ - public function addPost(\AppBundle\Entity\Post $post) - { - $this->posts[] = $post; - - return $this; - } - - /** - * Remove post - * - * @param \AppBundle\Entity\Post $post - */ - public function removePost(\AppBundle\Entity\Post $post) - { - $this->posts->removeElement($post); - } - - /** - * Get posts - * - * @return \Doctrine\Common\Collections\Collection - */ - public function getPosts() - { - return $this->posts; - } } diff --git a/src/AppBundle/Repository/TagRepository.php b/src/AppBundle/Repository/TagRepository.php index 51d36e39c..5baa360c6 100644 --- a/src/AppBundle/Repository/TagRepository.php +++ b/src/AppBundle/Repository/TagRepository.php @@ -11,46 +11,34 @@ namespace AppBundle\Repository; +use AppBundle\Entity\Post; use AppBundle\Entity\Tag; use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\Query; -use Pagerfanta\Adapter\DoctrineORMAdapter; -use Pagerfanta\Pagerfanta; +use Doctrine\ORM\Query\ResultSetMapping; /** * This custom Doctrine repository contains some methods which are useful when - * querying for blog post information. + * querying tags and * * See http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes * - * @author Ryan Weaver - * @author Javier Eguiluz - * @author Yonel Ceruto */ class TagRepository extends EntityRepository { /** - * @param int $page - * - * @return Pagerfanta + * Remove unused Tag from the Database */ public function cleanUnusedTags() { - $unused_tags = $this->getEntityManager() - ->createQuery(' - SELECT t.id - FROM AppBundle:Tag t - LEFT JOIN t.posts p - WHERE p.id IS NULL - ')->getResult(); - if (!empty($unused_tags)) { - $tag_ids = array_map(function ($tag) { - return $tag['id']; - }, $unused_tags); - $this->getEntityManager() - ->createQuery('DELETE FROM AppBundle:Tag t WHERE t.id IN (:tags)') - ->setParameter('tags', $tag_ids) - ->execute(); - } + $joinTable = $this->getEntityManager()->getClassMetadata(Post::class)->getAssociationMapping('tags')['joinTable']['name']; + $tagTable = $this->getClassMetadata()->getTableName(); + $unused_tags = $this->getEntityManager()->createNativeQuery(" + DELETE FROM `$tagTable` WHERE id IN + ( + SELECT t.id FROM `$tagTable` t + LEFT JOIN `$joinTable` j ON j.tag_id = t.id + WHERE j.tag_id IS NULL + ) + ", new ResultSetMapping())->execute(); } -} +} \ No newline at end of file From 33b3a706fd2d2f4ccdad854ec05416ec75be7a46 Mon Sep 17 00:00:00 2001 From: Grafikart Date: Tue, 14 Feb 2017 17:53:31 +0100 Subject: [PATCH 4/4] Fixed typo --- src/AppBundle/Repository/TagRepository.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/AppBundle/Repository/TagRepository.php b/src/AppBundle/Repository/TagRepository.php index 5baa360c6..419744403 100644 --- a/src/AppBundle/Repository/TagRepository.php +++ b/src/AppBundle/Repository/TagRepository.php @@ -17,16 +17,14 @@ use Doctrine\ORM\Query\ResultSetMapping; /** - * This custom Doctrine repository contains some methods which are useful when - * querying tags and + * This custom Doctrine repository contains some methods to about tags. * * See http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes - * */ class TagRepository extends EntityRepository { /** - * Remove unused Tag from the Database + * Remove unused Tag from the Database. */ public function cleanUnusedTags() { @@ -41,4 +39,4 @@ public function cleanUnusedTags() ) ", new ResultSetMapping())->execute(); } -} \ No newline at end of file +}