ItemChangesListener   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 254
Duplicated Lines 13.39 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 35
c 2
b 0
f 0
lcom 1
cbo 5
dl 34
loc 254
ccs 0
cts 137
cp 0
rs 9

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 21 2
A postRemove() 17 17 4
A prePersist() 0 7 3
A postPersist() 17 17 4
A preUpdate() 0 7 3
A addSource() 0 10 3
B postUpdate() 0 26 5
B getId() 0 24 5
B findIdForItem() 0 19 5
A renderEntry() 0 7 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * AnimeDb package
4
 *
5
 * @package   AnimeDb
6
 * @author    Peter Gribanov <[email protected]>
7
 * @copyright Copyright (c) 2011, Peter Gribanov
8
 * @license   http://opensource.org/licenses/GPL-3.0 GPL v3
9
 */
10
11
namespace AnimeDb\Bundle\MyAnimeListSyncBundle\Event\Listener;
12
13
use AnimeDb\Bundle\CatalogBundle\Entity\Name;
14
use AnimeDb\Bundle\MyAnimeListSyncBundle\Service\Client;
15
use Doctrine\ORM\EntityManagerInterface;
16
use AnimeDb\Bundle\MyAnimeListSyncBundle\Repository\ItemRepository;
17
use Doctrine\ORM\Event\LifecycleEventArgs;
18
use Symfony\Component\Templating\EngineInterface;
19
use AnimeDb\Bundle\CatalogBundle\Entity\Item as ItemCatalog;
20
use AnimeDb\Bundle\CatalogBundle\Entity\Source;
21
use AnimeDb\Bundle\AppBundle\Entity\Notice;
22
use AnimeDb\Bundle\MyAnimeListSyncBundle\Entity\Item as ItemMal;
23
24
/**
25
 * @package AnimeDb\Bundle\MyAnimeListSyncBundle\Event\Listener
26
 * @author  Peter Gribanov <[email protected]>
27
 */
28
class ItemChangesListener
29
{
30
    /**
31
     * @var EngineInterface
32
     */
33
    protected $templating;
34
35
    /**
36
     * @var Client
37
     */
38
    protected $client;
39
40
    /**
41
     * @var string
42
     */
43
    protected $host = '';
44
    /**
45
     * Sync the delete operation
46
     *
47
     * @var bool
48
     */
49
    protected $sync_remove = true;
50
51
    /**
52
     * Sync the insert operation
53
     *
54
     * @var bool
55
     */
56
    protected $sync_insert = true;
57
58
    /**
59
     * Sync the update operation
60
     *
61
     * @var bool
62
     */
63
    protected $sync_update = true;
64
65
    /**
66
     * @param EngineInterface $templating
67
     * @param Client $client
68
     * @param string $host
69
     * @param string $user_name
70
     * @param bool $sync_remove
71
     * @param bool $sync_insert
72
     * @param bool $sync_update
73
     */
74
    public function __construct(
75
        EngineInterface $templating,
76
        Client $client,
77
        $host,
78
        $user_name,
79
        $sync_remove,
80
        $sync_insert,
81
        $sync_update
82
    ) {
83
        $this->host = $host;
84
        $this->client = $client;
85
        $this->templating = $templating;
86
87
        if ($user_name) {
88
            $this->sync_remove = $sync_remove;
89
            $this->sync_insert = $sync_insert;
90
            $this->sync_update = $sync_update;
91
        } else {
92
            $this->sync_remove = $this->sync_insert = $this->sync_update = false;
93
        }
94
    }
95
96
    /**
97
     * @param LifecycleEventArgs $args
98
     */
99 View Code Duplication
    public function postRemove(LifecycleEventArgs $args)
100
    {
101
        $entity = $args->getEntity();
102
        if ($entity instanceof ItemCatalog && $this->sync_remove) {
103
            if ($id = $this->getId($entity, $args->getEntityManager())) {
104
                $this->client->sendAction(Client::ACTION_UPDATE, $id, $this->renderEntry($entity));
105
            } else {
106
                $notice = new Notice();
107
                $notice->setMessage($this->templating->render(
108
                    'AnimeDbMyAnimeListSyncBundle:Notice:failed_delete.html.twig',
109
                    ['item' => $entity]
110
                ));
111
                $args->getEntityManager()->persist($notice);
112
                $args->getEntityManager()->flush();
113
            }
114
        }
115
    }
116
117
    /**
118
     * Pre persist add item source if not exists
119
     *
120
     * @param LifecycleEventArgs $args
121
     */
122
    public function prePersist(LifecycleEventArgs $args)
123
    {
124
        $entity = $args->getEntity();
125
        if ($entity instanceof ItemCatalog && $this->sync_insert) {
126
            $this->addSource($entity, $args->getEntityManager());
127
        }
128
    }
129
130
    /**
131
     * @param LifecycleEventArgs $args
132
     */
133 View Code Duplication
    public function postPersist(LifecycleEventArgs $args)
134
    {
135
        $entity = $args->getEntity();
136
        if ($entity instanceof ItemCatalog && $this->sync_insert) {
137
            if ($id = $this->getId($entity, $args->getEntityManager())) {
138
                $this->client->sendAction(Client::ACTION_ADD, $id, $this->renderEntry($entity));
139
            } else {
140
                $notice = new Notice();
141
                $notice->setMessage($this->templating->render(
142
                    'AnimeDbMyAnimeListSyncBundle:Notice:failed_insert.html.twig',
143
                    ['item' => $entity]
144
                ));
145
                $args->getEntityManager()->persist($notice);
146
                $args->getEntityManager()->flush();
147
            }
148
        }
149
    }
150
151
    /**
152
     * Pre update add item source if not exists
153
     *
154
     * @param LifecycleEventArgs $args
155
     */
156
    public function preUpdate(LifecycleEventArgs $args)
157
    {
158
        $entity = $args->getEntity();
159
        if ($entity instanceof ItemCatalog && $this->sync_update) {
160
            $this->addSource($entity, $args->getEntityManager());
161
        }
162
    }
163
164
    /**
165
     * @param ItemCatalog $entity
166
     * @param EntityManagerInterface $em
167
     */
168
    protected function addSource(ItemCatalog $entity, EntityManagerInterface $em)
169
    {
170
        if (!$this->getId($entity, $em) && ($id = $this->findIdForItem($entity))) {
171
            $source = (new Source())->setUrl($this->host.'anime/'.$id.'/');
172
            $entity->addSource($source);
173
174
            $em->persist($source);
175
            $em->flush();
176
        }
177
    }
178
179
    /**
180
     * @param LifecycleEventArgs $args
181
     */
182
    public function postUpdate(LifecycleEventArgs $args)
183
    {
184
        $entity = $args->getEntity();
185
        if ($entity instanceof ItemCatalog && $this->sync_update) {
186
            /* @var $rep ItemRepository */
187
            $rep = $args->getEntityManager()->getRepository('AnimeDbMyAnimeListSyncBundle:Item');
188
            /* @var $mal_item ItemCatalog */
189
            $mal_item = $rep->findByCatalogItem($entity);
190
191
            if ($mal_item instanceof ItemMal) {
192
                $this->client->sendAction(Client::ACTION_UPDATE, $mal_item->getId(), $this->renderEntry($entity));
193
194
            } elseif ($id = $this->getId($entity, $args->getEntityManager())) {
195
                $this->client->sendAction(Client::ACTION_ADD, $id, $this->renderEntry($entity));
196
197
            } else {
198
                $notice = new Notice();
199
                $notice->setMessage($this->templating->render(
200
                    'AnimeDbMyAnimeListSyncBundle:Notice:failed_update.html.twig',
201
                    ['item' => $entity]
202
                ));
203
                $args->getEntityManager()->persist($notice);
204
                $args->getEntityManager()->flush();
205
            }
206
        }
207
    }
208
209
    /**
210
     * Get MyAnimeList id for item
211
     *
212
     * @param ItemCatalog $entity
213
     * @param EntityManagerInterface $em
214
     *
215
     * @return int
216
     */
217
    protected function getId(ItemCatalog $entity, EntityManagerInterface $em)
218
    {
219
        // search in sources
220
        /* @var $source Source */
221
        foreach ($entity->getSources() as $source) {
222
            if (strpos($source->getUrl(), $this->host) === 0) {
223
                if (preg_match('#/(\d+)/#', $source->getUrl(), $mat)) {
224
                    return $mat[1];
225
                }
226
                break;
227
            }
228
        }
229
230
        /* @var $rep ItemRepository */
231
        $rep = $em->getRepository('AnimeDbMyAnimeListSyncBundle:Item');
232
        // get MyAnimeList item link
233
        $mal_item = $rep->findByCatalogItem($entity);
234
235
        if ($mal_item instanceof ItemMal) {
236
            return $mal_item->getId();
237
        }
238
239
        return 0;
240
    }
241
242
    /**
243
     * Try to find the MyAnimeList id for the item
244
     *
245
     * @param ItemCatalog $item
246
     *
247
     * @return int|null
248
     */
249
    protected function findIdForItem(ItemCatalog $item)
250
    {
251
        // find name for search
252
        $query = '';
253
        if (preg_match('/[a-z]+/i', $item->getName())) {
254
            $query = $item->getName();
255
        } else {
256
            /* @var $name Name */
257
            foreach ($item->getNames() as $name) {
258
                if (preg_match('/[a-z]+/i', $name->getName())) {
259
                    $query = $name->getName();
260
                    break;
261
                }
262
            }
263
        }
264
265
        // try search
266
        return $query ? $this->client->search($query) : null;
267
    }
268
269
    /**
270
     * @param ItemCatalog $entity
271
     *
272
     * @return string
273
     */
274
    protected function renderEntry(ItemCatalog $entity)
275
    {
276
        return $this->templating->render(
277
            'AnimeDbMyAnimeListSyncBundle::entry.xml.twig',
278
            ['item' => $entity]
279
        );
280
    }
281
}
282