From 2c06a4b37c85c9a66f0f9b3bf13750da7be74d00 Mon Sep 17 00:00:00 2001 From: Henrypenny Date: Mon, 10 Apr 2017 18:05:46 +1200 Subject: [PATCH] Make Tag entity configurable --- AdminList/TagAdminListConfigurator.php | 21 ++++++- Controller/TagAdminListController.php | 4 +- Entity/Tag.php | 3 +- Entity/TagManager.php | 82 +++++++++++++++++++++++-- Entity/Tagging.php | 4 -- EventListener/CloneListener.php | 9 +-- EventListener/TagRelationSubscriber.php | 77 +++++++++++++++++++++++ Repository/TagRepository.php | 17 ----- Resources/config/services.yml | 14 ++++- 9 files changed, 192 insertions(+), 39 deletions(-) create mode 100644 EventListener/TagRelationSubscriber.php diff --git a/AdminList/TagAdminListConfigurator.php b/AdminList/TagAdminListConfigurator.php index ef202fe..63a8d88 100644 --- a/AdminList/TagAdminListConfigurator.php +++ b/AdminList/TagAdminListConfigurator.php @@ -12,14 +12,16 @@ class TagAdminListConfigurator extends AbstractDoctrineORMAdminListConfigurator { + protected $repositoryName; + /** * @param EntityManager $em The entity manager * @param AclHelper $aclHelper The acl helper */ - public function __construct(EntityManager $em, AclHelper $aclHelper = null) + public function __construct(EntityManager $em, AclHelper $aclHelper = null, $repositoryName) { parent::__construct($em, $aclHelper); - $this->setAdminType(new TagAdminType()); + $this->repositoryName = $repositoryName; } /** @@ -60,4 +62,19 @@ public function getEntityName() return 'Tag'; } + /** + * Return default repository name. + * + * @return string + */ + public function getRepositoryName() + { + return $this->repositoryName; + } + + public function getAdminType($entity) + { + return parent::getAdminType($entity); // TODO: Change the autogenerated stub + } + } diff --git a/Controller/TagAdminListController.php b/Controller/TagAdminListController.php index e61e0f2..5e3e63e 100644 --- a/Controller/TagAdminListController.php +++ b/Controller/TagAdminListController.php @@ -23,7 +23,7 @@ class TagAdminListController extends AdminListController public function getAdminListConfigurator() { if (!isset($this->configurator)) { - $this->configurator = new TagAdminListConfigurator($this->getEntityManager()); + $this->configurator = new TagAdminListConfigurator($this->getEntityManager(), null, $this->getParameter('kuma_tagging.tag.repository')); } return $this->configurator; @@ -81,7 +81,7 @@ public function autocompleteAction(Request $request) { $search = $request->get('term'); $em = $this->getDoctrine()->getManager(); - $qb = $em->getRepository('KunstmaanTaggingBundle:Tag')->createQueryBuilder('n') + $qb = $em->getRepository($this->getParameter('kuma_tagging.tag.repository'))->createQueryBuilder('n') ->where('n.name LIKE :search') ->orderBy('n.name', 'ASC') ->setParameter('search', '%' . $search . '%'); diff --git a/Entity/Tag.php b/Entity/Tag.php index e1ff595..6e0e68f 100644 --- a/Entity/Tag.php +++ b/Entity/Tag.php @@ -6,7 +6,6 @@ use Doctrine\ORM\Mapping as ORM; use Gedmo\Mapping\Annotation as Gedmo; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; - use Kunstmaan\TaggingBundle\Form\TagAdminType; /** @@ -42,7 +41,7 @@ class Tag extends BaseTag protected $updatedAt; /** - * @ORM\OneToMany(targetEntity="Kunstmaan\TaggingBundle\Entity\Tagging", mappedBy="tag", fetch="LAZY") + * Mapping happens in TagRelationSubscriber */ protected $tagging; diff --git a/Entity/TagManager.php b/Entity/TagManager.php index 36e6366..d763cae 100644 --- a/Entity/TagManager.php +++ b/Entity/TagManager.php @@ -14,6 +14,13 @@ class TagManager extends BaseTagManager const TAGGING_HYDRATOR = 'taggingHydrator'; + public function copyTags($origin, $destination) + { + $tags = $this->getTagging($origin); + $this->replaceTags($tags, $destination); + $this->saveTagging($destination); + } + public function loadTagging(BaseTaggable $resource) { if ($resource instanceof LazyLoadingTaggableInterface) { @@ -41,6 +48,43 @@ public function saveTagging(BaseTaggable $resource) } + /** + * @param $tag + * @return array + */ + public function getResourcesByTag($tag, $entityName, $type) + { + $em = $this->em; + + $config = $em->getConfiguration(); + if (is_null($config->getCustomHydrationMode(TagManager::TAGGING_HYDRATOR))) { + $config->addCustomHydrationMode(TagManager::TAGGING_HYDRATOR, 'Doctrine\ORM\Internal\Hydration\ObjectHydrator'); + } + + if ($type) { + $joinCriteria = 't2.resourceType = :type and t2.resourceId = p.id'; + } + else { + $joinCriteria = 't2.resourceId = p.id'; + } + + $qb = $em + ->createQueryBuilder() + ->select('p') + ->from($entityName, 'p') + ->innerJoin($this->taggingClass, 't2', Expr\Join::WITH, $joinCriteria) + ->innerJoin('t2.tag', 't', Expr\Join::WITH, 't.name = :tag') + ->setParameter('tag', $tag); + + if($type) { + $qb->setParameter('type', $type); + } + + $query = $qb->getQuery(); + $pages = $query->getResult(TagManager::TAGGING_HYDRATOR); + + return $pages; + } /** * Gets all tags for the given taggable resource * @@ -56,20 +100,39 @@ public function getTagging(BaseTaggable $resource) $config->addCustomHydrationMode(self::TAGGING_HYDRATOR, 'Doctrine\ORM\Internal\Hydration\ObjectHydrator'); } - return $em + $qb = $em ->createQueryBuilder() - ->select('t') ->from($this->tagClass, 't') - ->innerJoin('t.tagging', 't2', Expr\Join::WITH, 't2.resourceId = :id AND t2.resourceType = :type') ->setParameter('id', $resource->getTaggableId()) - ->setParameter('type', $resource->getTaggableType()) + ->setParameter('type', $resource->getTaggableType()); - ->getQuery() + $query = $qb + ->getQuery(); + $result = $query ->getResult(self::TAGGING_HYDRATOR); + + return $result; } + public function getTagsByResourceType($type) + { + + $qb = $this->em->createQueryBuilder() + ->select('t.name, COUNT(t2) as cnt') + ->from($this->tagClass, 't') + ->leftJoin('t.tagging', 't2', Expr\Join::WITH, 't2.resourceType = \'' . $type . '\'') + ->groupBy('t') + ->orderBy('cnt', 'desc') + ->having('cnt > 0'); + + $query = $qb->getQuery(); + $results = $query->execute(); + return $results; + } + + public function findById($id) { @@ -92,11 +155,18 @@ public function findById($id) public function findAll() { - $tagsRepo = $this->em->getRepository('KunstmaanTaggingBundle:Tag'); + $tagsRepo = $this->em->getRepository($this->tagClass); return $tagsRepo->findAll(); } + public function findByName($name) + { + $tagsRepo = $this->em->getRepository($this->tagClass); + + return $tagsRepo->findOneBy(['name' => $name]); + } + public function findRelatedItems(Taggable $item, $class, $locale, $nbOfItems=1) { $instance = new $class(); diff --git a/Entity/Tagging.php b/Entity/Tagging.php index c23894a..920eb52 100644 --- a/Entity/Tagging.php +++ b/Entity/Tagging.php @@ -21,10 +21,6 @@ class Tagging extends BaseTagging */ protected $id; - /** - * @ORM\ManyToOne(targetEntity="Kunstmaan\TaggingBundle\Entity\Tag", inversedBy="tagging") - * @ORM\JoinColumn(name="tag_id", referencedColumnName="id", onDelete="CASCADE") - */ protected $tag; /** diff --git a/EventListener/CloneListener.php b/EventListener/CloneListener.php index b13fadb..5b627a4 100644 --- a/EventListener/CloneListener.php +++ b/EventListener/CloneListener.php @@ -5,6 +5,7 @@ use Doctrine\ORM\EntityManager; use DoctrineExtensions\Taggable\Taggable; use Kunstmaan\AdminBundle\Event\DeepCloneAndSaveEvent; +use Kunstmaan\TaggingBundle\Entity\TagManager; /** * This listener will make sure the tags are copied as well @@ -12,11 +13,11 @@ class CloneListener { - protected $em; + protected $tagManager; - public function __construct(EntityManager $em) + public function __construct(TagManager $tagManager) { - $this->em = $em; + $this->tagManager = $tagManager; } /** @@ -28,7 +29,7 @@ public function postDeepCloneAndSave(DeepCloneAndSaveEvent $event) if ($originalEntity instanceof Taggable) { $targetEntity = $event->getClonedEntity(); - $this->em->getRepository('KunstmaanTaggingBundle:Tag')->copyTags($originalEntity, $targetEntity); + $this->tagManager->copyTags($originalEntity, $targetEntity); } } diff --git a/EventListener/TagRelationSubscriber.php b/EventListener/TagRelationSubscriber.php new file mode 100644 index 0000000..a5235d3 --- /dev/null +++ b/EventListener/TagRelationSubscriber.php @@ -0,0 +1,77 @@ +tagClass = $tagClass; + $this->taggingClass = $taggingClass; + } + + /** + * {@inheritDoc} + */ + public function getSubscribedEvents() + { + return array( + Events::loadClassMetadata, + ); + } + + /** + * @param LoadClassMetadataEventArgs $eventArgs + */ + public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) + { + // the $metadata is the whole mapping info for this class + $metadata = $eventArgs->getClassMetadata(); + + if ($metadata->getName() == $this->taggingClass) { + + $metadata->mapManyToOne(array( + 'targetEntity' => $this->tagClass, + 'fieldName' => 'tag', + 'cascade' => [], + 'inversedBy' => 'tagging', + 'JoinColumn' => array( + 'name' => 'tag_id', + 'unique' => false, + 'nullable' => true, + 'referencedColumnName' => 'id', + 'columnDefinition' => null, + 'onDelete' => 'CASCADE' + ), + 'fetch' => 2, + 'type' => 2, + + )); + + } + else if ($metadata->getName() == $this->tagClass) { + + $metadata->mapOneToMany(array( + 'targetEntity' => $this->taggingClass, + 'fieldName' => 'tagging', + 'mappedBy' => 'tag', + 'fetch' => "LAZY", + )); + + } + } +} \ No newline at end of file diff --git a/Repository/TagRepository.php b/Repository/TagRepository.php index 6684ec1..ab97752 100644 --- a/Repository/TagRepository.php +++ b/Repository/TagRepository.php @@ -9,21 +9,4 @@ class TagRepository extends EntityRepository { - - protected $tagManager; - - public function __construct($em, ClassMetadata $class) - { - parent::__construct($em, $class); - $this->tagManager = new TagManager($em, 'Kunstmaan\TaggingBundle\Entity\Tag', 'Kunstmaan\TaggingBundle\Entity\Tagging'); - } - - public function copyTags($origin, $destination) - { - $tagManager = $this->tagManager; - $tags = $tagManager->getTagging($origin); - $tagManager->replaceTags($tags, $destination); - $tagManager->saveTagging($destination); - } - } diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 3a01281..c4c0acc 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -1,9 +1,13 @@ parameters: + kuma_tagging.tag.class: 'Kunstmaan\TaggingBundle\Entity\Tag' + kuma_tagging.tag.repository: 'KunstmaanTaggingBundle:Tag' + kuma_tagging.tagging.class: 'Kunstmaan\TaggingBundle\Entity\Tagging' + kuma_tagging.event_listener.tag_relation_subscriber.class: 'Kunstmaan\TaggingBundle\EventListener\TagRelationSubscriber' services: kuma_tagging.tag_manager: class: Kunstmaan\TaggingBundle\Entity\TagManager - arguments: ['@doctrine.orm.entity_manager', 'Kunstmaan\TaggingBundle\Entity\Tag', 'Kunstmaan\TaggingBundle\Entity\Tagging'] + arguments: ['@doctrine.orm.entity_manager', '%kuma_tagging.tag.class%', '%kuma_tagging.tagging.class%'] kuma_tagging.listener: class: Kunstmaan\TaggingBundle\EventListener\TagsListener @@ -16,7 +20,7 @@ services: kuma_tagging.clone.listener: class: Kunstmaan\TaggingBundle\EventListener\CloneListener - arguments: ['@doctrine.orm.entity_manager'] + arguments: ['@kuma_tagging.tag_manager'] tags: - { name: kernel.event_listener, event: kunstmaan_admin.postDeepCloneAndSave, method: postDeepCloneAndSave } @@ -36,3 +40,9 @@ services: arguments: ['@kuma_tagging.tag_manager'] tags: - { name: form.type } + + kuma_tagging.event_listener.tag_relation_subscriber: + class: '%kuma_tagging.event_listener.tag_relation_subscriber.class%' + arguments: ['%kuma_tagging.tag.class%', '%kuma_tagging.tagging.class%'] + tags: + - { name: doctrine.event_subscriber } \ No newline at end of file