Completed
Push — master ( 9684f5...5d31f9 )
by Sander
36:56 queued 12:48
created

src/Kunstmaan/TaggingBundle/Entity/TagManager.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Kunstmaan\TaggingBundle\Entity;
4
5
use Doctrine\ORM\Query\Expr;
6
use Doctrine\ORM\Query\ResultSetMappingBuilder;
7
use DoctrineExtensions\Taggable\Taggable as BaseTaggable;
8
use DoctrineExtensions\Taggable\TagManager as BaseTagManager;
9
use Kunstmaan\NodeBundle\Entity\AbstractPage;
10
11
class TagManager extends BaseTagManager
12
{
13
    const TAGGING_HYDRATOR = 'taggingHydrator';
14
15
    /**
16
     * @param BaseTaggable $resource
17
     */
18
    public function loadTagging(BaseTaggable $resource)
19
    {
20
        if ($resource instanceof LazyLoadingTaggableInterface) {
21
            $resource->setTagLoader(function (Taggable $taggable) {
22
                parent::loadTagging($taggable);
23
            });
24
25
            return;
26
        }
27
28
        parent::loadTagging($resource);
29
    }
30
31
    /**
32
     * @param BaseTaggable $resource
33
     */
34
    public function saveTagging(BaseTaggable $resource)
35
    {
36
        $tags = clone $resource->getTags();
37
        parent::saveTagging($resource);
38
        if (count($tags) !== count($resource->getTags())) {
39
            // parent::saveTagging uses getTags by reference and removes elements, so it ends up empty :-/
40
            // this causes all tags to be deleted when an entity is persisted more than once in a request
41
            // Restore:
42
            $this->replaceTags($tags->toArray(), $resource);
43
        }
44
    }
45
46
    /**
47
     * Gets all tags for the given taggable resource
48
     *
49
     * @param BaseTaggable $resource Taggable resource
50
     *
51
     * @return array
52
     */
53
    public function getTagging(BaseTaggable $resource)
54
    {
55
        $em = $this->em;
56
57
        $config = $em->getConfiguration();
58
        if (is_null($config->getCustomHydrationMode(self::TAGGING_HYDRATOR))) {
59
            $config->addCustomHydrationMode(self::TAGGING_HYDRATOR, 'Doctrine\ORM\Internal\Hydration\ObjectHydrator');
60
        }
61
62
        return $em
63
            ->createQueryBuilder()
64
65
            ->select('t')
66
            ->from($this->tagClass, 't')
67
68
            ->innerJoin('t.tagging', 't2', Expr\Join::WITH, 't2.resourceId = :id AND t2.resourceType = :type')
69
            ->setParameter('id', $resource->getTaggableId())
70
            ->setParameter('type', $resource->getTaggableType())
71
72
            ->getQuery()
73
            ->getResult(self::TAGGING_HYDRATOR);
74
    }
75
76
    /**
77
     * @param $id
78
     *
79
     * @return mixed|null
80
     *
81
     * @throws \Doctrine\ORM\NonUniqueResultException
82
     */
83
    public function findById($id)
84
    {
85
        if (!isset($id) || is_null($id)) {
86
            return null;
87
        }
88
        $builder = $this->em->createQueryBuilder();
89
90
        $tag = $builder
91
            ->select('t')
92
            ->from($this->tagClass, 't')
93
94
            ->where($builder->expr()->eq('t.id', $id))
95
96
            ->getQuery()
97
            ->getOneOrNullResult();
98
99
        return $tag;
100
    }
101
102
    /**
103
     * @return array
0 ignored issues
show
Consider making the return type a bit more specific; maybe use object[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
104
     */
105
    public function findAll()
106
    {
107
        $tagsRepo = $this->em->getRepository('KunstmaanTaggingBundle:Tag');
108
109
        return $tagsRepo->findAll();
110
    }
111
112
    /**
113
     * @param Taggable $item
114
     * @param $class
115
     * @param $locale
116
     * @param int $nbOfItems
117
     *
118
     * @return array|null
119
     */
120
    public function findRelatedItems(Taggable $item, $class, $locale, $nbOfItems = 1)
121
    {
122
        $instance = new $class();
123
        if (!($instance instanceof Taggable)) {
124
            return null;
125
        }
126
127
        $em = $this->em;
128
        $rsm = new ResultSetMappingBuilder($em);
129
        $rsm->addRootEntityFromClassMetadata($class, 'i');
130
131
        $meta = $em->getClassMetadata($class);
132
        $tableName = $meta->getTableName();
133
134
        $escapedClass = str_replace('\\', '\\\\', $class);
135
136
        $query = <<<EOD
137
            SELECT i.*, COUNT(i.id) as number
138
            FROM {$tableName} i
139
            LEFT JOIN kuma_taggings t
140
            ON t.resource_id = i.id
141
            AND t.resource_type = '{$instance->getTaggableType()}'
142
            WHERE t.tag_id IN (
143
                SELECT tg.tag_id
144
                FROM kuma_taggings tg
145
                WHERE tg.resource_id = {$item->getId()}
146
                AND tg.resource_type = '{$item->getTaggableType()}'
147
            )
148
            AND i.id <> {$item->getId()}
149
EOD;
150
151
        if ($item instanceof AbstractPage) {
152
            $query .= <<< EOD
153
                AND i.id IN (
154
                    SELECT nodeversion.refId
155
                    FROM kuma_nodes as node
156
                    INNER JOIN kuma_node_translations as nodetranslation
157
                    ON node.id = nodetranslation.node
158
                    AND nodetranslation.lang = '{$locale}'
159
                    INNER JOIN kuma_node_versions as nodeversion
160
                    ON nodetranslation.publicNodeVersion = nodeversion.id
161
                    AND nodeversion.refEntityname = '{$escapedClass}'
162
                    AND node.deleted = 0
163
                    AND nodetranslation.online = 1
164
                )
165
EOD;
166
        }
167
168
        $query .= <<<EOD
169
            GROUP BY
170
                i.id
171
            HAVING
172
                number > 0
173
            ORDER BY
174
                number DESC
175
            LIMIT {$nbOfItems};
176
EOD;
177
178
        $items = $em->createNativeQuery($query, $rsm)->getResult();
179
180
        return $items;
181
    }
182
}
183