TagManager::saveRelation()   C
last analyzed

Complexity

Conditions 7
Paths 14

Size

Total Lines 42
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
c 3
b 1
f 1
dl 0
loc 42
rs 6.7272
cc 7
eloc 20
nc 14
nop 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Rafidion Michael
5
 * Date: 10/12/2014
6
 * Time: 13:16
7
 */
8
9
namespace Mykees\TagBundle\Manager;
10
11
12
use Mykees\TagBundle\Util\Urlizer;
13
use Doctrine\Common\Collections\ArrayCollection;
14
use Doctrine\Common\Persistence\ManagerRegistry;
15
use Mykees\TagBundle\Interfaces\Taggable;
16
use Mykees\TagBundle\Traits\ManagerArrayTrait;
17
use Mykees\TagBundle\Traits\ManagerObjectTrait;
18
use Mykees\TagBundle\Entity\Tag;
19
use Mykees\TagBundle\Entity\TagRelation;
20
21
class TagManager {
22
23
    public $em;
24
    public $tag;
25
    public $tagRelation;
26
27
    use ManagerArrayTrait, ManagerObjectTrait;
28
29
    public function __construct( ManagerRegistry $managerRegistry, $tag=null, $tagRelation=null )
30
    {
31
        $this->em = $managerRegistry->getManager();
32
        $this->tag = $tag ?: 'Mykees\TagBundle\Entity\Tag';
33
        $this->tagRelation = $tagRelation ?: 'Mykees\TagBundle\Entity\TagRelation';
34
    }
35
36
37
38
    public function findTagRelation( $model )
39
    {
40
        if(is_array($model))
41
        {
42
            $this->getTagRelationArray($model);
43
        }else{
44
            $this->getTagRelation($model);
45
        }
46
    }
47
48
    /**
49
     * Remove relation between Tag and a model given
50
     * @param Taggable $model
51
     * @param bool $onlyDeleteRelation
52
     */
53
    public function deleteTagRelation( Taggable $model, $onlyDeleteRelation = false )
54
    {
55
        if($onlyDeleteRelation)
56
        {
57
            $model->setRemove(true);
58
        }
59
        $tagRelationList = $this->em->createQueryBuilder()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\Common\Persistence\ObjectManager as the method createQueryBuilder() does only exist in the following implementations of said interface: Doctrine\ORM\Decorator\EntityManagerDecorator, Doctrine\ORM\EntityManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
60
            ->select('t')
61
            ->from($this->tagRelation, 't')
62
            ->where('t.model = :type')
63
            ->setParameter('type', $model->getModel())
64
            ->andWhere('t.modelId = :id')
65
            ->setParameter('id', $model->getModelId())
66
            ->getQuery()
67
            ->getResult();
68
69
        foreach($tagRelationList as $relation)
70
        {
71
            $this->em->remove($relation);
72
            $this->useless($relation->getTag()->getId());
73
        }
74
        $this->em->flush();
75
    }
76
77
    /**
78
     * Remove tag
79
     * @param $tag_id
80
     */
81
    public function delete( $tag_id )
82
    {
83
        $tag = $this->em->createQueryBuilder()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\Common\Persistence\ObjectManager as the method createQueryBuilder() does only exist in the following implementations of said interface: Doctrine\ORM\Decorator\EntityManagerDecorator, Doctrine\ORM\EntityManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
84
            ->select('t')
85
            ->from($this->tag, 't')
86
            ->where('t.id = :id')
87
            ->setParameter('id', $tag_id)
88
            ->getQuery()
89
            ->getOneOrNullResult();
90
        $this->em->remove($tag);
91
        $this->em->flush();
92
    }
93
94
    public function deleteByName($name)
95
    {
96
97
        if(is_array($name))
98
        {
99
            $names = $this->findByName($name);
100
            foreach($names as $n)
101
            {
102
                $this->em->remove($n);
103
            }
104
            $this->em->flush();
105
        }else{
106
            $tag = $this->em->createQueryBuilder()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\Common\Persistence\ObjectManager as the method createQueryBuilder() does only exist in the following implementations of said interface: Doctrine\ORM\Decorator\EntityManagerDecorator, Doctrine\ORM\EntityManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
107
                ->select('t')
108
                ->from($this->tag, 't')
109
                ->where('t.name = :name')
110
                ->setParameter('name', $name)
111
                ->getQuery()
112
                ->getOneOrNullResult();
113
            $this->em->remove($tag);
114
            $this->em->flush();
115
        }
116
    }
117
118
    /**
119
     * Save Tag Relation and add create and save tags if don't exist
120
     * @param Taggable $model
121
     */
122
    public function saveRelation( Taggable $model )
123
    {
124
        if(!$model->getRemove())
125
        {
126
            if($model->getTags()->count() > 0)
127
            {
128
                $addedTags = $model->getTags();
129
                $model_id = $model->getModelId();
130
                $model_name = $model->getModel();
131
                $addNewTags = $addedTags;
132
133
                $tagsRelationExisted = $this->findRelationByTagName($model->getTags(),$model);
134
135
                //Remove existed Tag from collection
136
                foreach($tagsRelationExisted as $tagExisted)
137
                {
138
                    if($addedTags->exists(function($index, Tag $addedTag) use ($tagExisted)
139
                    {
140
                        return $addedTag->getName() === $tagExisted->getName();
141
                    })){
142
                        $addNewTags->removeElement($tagExisted);
143
                    }
144
                }
145
146
                //Save
147
                foreach($addNewTags as $tag)
148
                {
149
                    $relation = new TagRelation();
150
                    $relation->setModel($model_name);
151
                    $relation->setModelId($model_id);
152
                    $relation->setTag($tag);
153
                    $this->em->persist($relation);
154
                }
155
156
                if (count($addNewTags) > 0)
157
                {
158
                    $this->em->flush();
159
                }
160
            }
161
        }
162
163
    }
164
165
    /**
166
     * Return Tag by a name
167
     * @param array $names
168
     */
169
    public function findByName( $names )
170
    {
171
        $q = $this->em->createQueryBuilder()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\Common\Persistence\ObjectManager as the method createQueryBuilder() does only exist in the following implementations of said interface: Doctrine\ORM\Decorator\EntityManagerDecorator, Doctrine\ORM\EntityManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
172
            ->select('t')
173
            ->from($this->tag,'t')
174
175
        ;
176
        if(is_array($names))
177
        {
178
            $q->where($this->em->createQueryBuilder()->expr()->in('t.name', $names));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\Common\Persistence\ObjectManager as the method createQueryBuilder() does only exist in the following implementations of said interface: Doctrine\ORM\Decorator\EntityManagerDecorator, Doctrine\ORM\EntityManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
179
        }else{
180
            $q->where('t.name = :name')->setParameter('name', $names);
181
        }
182
183
        return $q->getQuery()->getResult();
184
    }
185
186
    /**
187
     * Return ids of model type linked with a tag
188
     * @param $slug
189
     * @param null $modelType
190
     * @return array
191
     */
192
    public function findReferer( $slug, $modelType=null )
193
    {
194
        $modelRefererIds = [];
195
196
        $q = $this->em->createQueryBuilder()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\Common\Persistence\ObjectManager as the method createQueryBuilder() does only exist in the following implementations of said interface: Doctrine\ORM\Decorator\EntityManagerDecorator, Doctrine\ORM\EntityManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
197
            ->select('tr')
198
            ->from($this->tagRelation,'tr')
199
            ->innerJoin('tr.tag','t')
200
            ->addSelect('t')
201
            ->where('t.slug = :slug')
202
            ->setParameter('slug',$slug)
203
        ;
204
205
        $query = $this->addModelTypeConstraint($q,$modelType);
206
        $result = $query->getQuery()->getResult();
207
208
        foreach($result as $tr)
209
        {
210
            array_push($modelRefererIds,$tr->getModelId());
211
        }
212
213
        return $modelRefererIds;
214
    }
215
216
    /**
217
     * Delete tag unused
218
     * @param $tag_id
219
     */
220
    public function useless($tag_id)
221
    {
222
        $count = $this->em->getRepository('MykeesTagBundle:TagRelation')->findCount($tag_id);
223
        if($count < 2)
224
        {
225
            $this->delete($tag_id);
226
        }
227
    }
228
229
    public function create( $name )
230
    {
231
        $tag = new Tag();
232
        $tag->setName($name);
233
        $tag->setSlug(Urlizer::urlize($name));
234
        $this->em->persist($tag);
235
        $this->em->flush();
236
237
        return $tag;
238
    }
239
240
    public function countTags()
241
    {
242
        return $this->em->getRepository('MykeesTagBundle:Tag')->findCount();
243
    }
244
245
    public function manageTags( $names )
246
    {
247
        foreach($names as $k=>$name)
248
        {
249
            $name = trim($name);
250
            if(!empty($name))
251
            {
252
                $q = $this->queryTag();
253
                $query = $this->addNameConstraint($q,$name);
254
                $tagExist = $query->getQuery()->getOneOrNullResult();
255
256
                if(!empty($tagExist))
257
                {
258
                    $names[$k] = $tagExist;
259
                }else{
260
                    $tag = $this->create($name);
261
                    $names[$k] = $tag;
262
                }
263
            }else{
264
                unset($names[$k]);
265
            }
266
        }
267
268
        return $names;
269
    }
270
}
271