MovieTranslationsProcessor   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 76.35%

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 9
dl 0
loc 140
ccs 42
cts 55
cp 0.7635
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
B process() 0 37 6
A loadTranslationsFromTMDB() 0 14 3
A addTranslations() 0 17 3
A getSubscribedTopics() 0 4 1
A isAllTranslationsSaved() 0 11 3
1
<?php
2
3
namespace App\Movies\EventListener;
4
5
use App\Movies\DTO\MovieTranslationDTO;
6
use App\Movies\Entity\Movie;
7
use App\Movies\Entity\MovieTranslations;
8
use App\Movies\Exception\TmdbMovieNotFoundException;
9
use App\Movies\Exception\TmdbRequestLimitException;
10
use App\Movies\Repository\MovieRepository;
11
use App\Movies\Service\TmdbSearchService;
12
use App\Service\LocaleService;
13
use Doctrine\ORM\EntityManagerInterface;
14
use Enqueue\Client\ProducerInterface;
15
use Enqueue\Client\TopicSubscriberInterface;
16
use Interop\Queue\Context;
17
use Interop\Queue\Message as QMessage;
18
use Interop\Queue\Processor;
19
20
class MovieTranslationsProcessor implements Processor, TopicSubscriberInterface
21
{
22
    const LOAD_TRANSLATIONS = 'LoadMoviesTranslationsFromTMDB';
23
24
    private $em;
25
    private $searchService;
26
    private $movieRepository;
27
    private $locales;
28
    private $localesCount;
29
    private $producer;
30
31 3
    public function __construct(EntityManagerInterface $em, ProducerInterface $producer, MovieRepository $movieRepository, TmdbSearchService $searchService, LocaleService $localeService)
32
    {
33 3
        $this->em = $em;
34 3
        $this->movieRepository = $movieRepository;
35 3
        $this->searchService = $searchService;
36 3
        $this->locales = $localeService->getLocales();
37 3
        $this->localesCount = \count($this->locales);
38 3
        $this->producer = $producer;
39 3
    }
40
41
    /**
42
     * @param QMessage $message
43
     * @param Context  $session
44
     *
45
     * @throws \Doctrine\ORM\ORMException
46
     * @throws \ErrorException
47
     *
48
     * @return object|string
49
     */
50 3
    public function process(QMessage $message, Context $session)
51
    {
52 3
        $movieId = $message->getBody();
53 3
        $movieId = json_decode($movieId, true);
54
55 3
        if ($this->em->isOpen() === false) {
56
            throw new \ErrorException('em is closed');
57
        }
58
59 3
        if (null === $movie = $this->movieRepository->find($movieId)) {
60
            return self::REJECT;
61
        }
62
63 3
        if ($this->isAllTranslationsSaved($movie) === true) {
64
            return self::ACK;
65
        }
66
67
        try {
68 3
            $translationsDTOs = $this->loadTranslationsFromTMDB($movie->getTmdb()->getId());
69
        } catch (TmdbRequestLimitException $requestLimitException) {
70
            sleep(5);
71
72
            return self::REQUEUE;
73
        } catch (TmdbMovieNotFoundException $notFoundException) {
74
            return self::REJECT;
75
        }
76
77 3
        $this->addTranslations($translationsDTOs, $movie);
78
79 1
        $this->em->flush();
80 1
        $this->em->clear();
81
82 1
        $message = $session = $movie = $movieId = null;
83 1
        unset($message, $session, $movie, $movieId);
84
85 1
        return self::ACK;
86
    }
87
88
    /**
89
     * @param int $tmdbId
90
     *
91
     * @throws TmdbMovieNotFoundException
92
     * @throws TmdbRequestLimitException
93
     *
94
     * @return \Iterator
95
     */
96 3
    private function loadTranslationsFromTMDB(int $tmdbId): \Iterator
97
    {
98 3
        $translationsResponse = $this->searchService->findMovieTranslationsById($tmdbId);
99 1
        $translations = $translationsResponse['translations'];
100
101 1
        foreach ($translations as $translation) {
102 1
            if (\in_array($translation['iso_639_1'], $this->locales, true) === false) {
103
                continue;
104
            }
105 1
            $data = $translation['data'];
106
107 1
            yield new MovieTranslationDTO($translation['iso_639_1'], $data['title'] ?? '', $data['overview'] ?? null, null);
108
        }
109 1
    }
110
111
    /**
112
     * @param \Iterator $moviesTranslationsDTOs
113
     * @param Movie     $movie
114
     *
115
     * @throws \Doctrine\ORM\ORMException
116
     * @throws \ErrorException
117
     */
118 3
    private function addTranslations(\Iterator $moviesTranslationsDTOs, Movie $movie): void
119
    {
120
        /** @var $movieReference Movie */
121 3
        $movieReference = $this->em->getReference(Movie::class, $movie->getId());
122
123 3
        foreach ($moviesTranslationsDTOs as $translationDTO) {
124 1
            if ($movie->getTranslation($translationDTO->getLocale(), false) !== null) {
125
                // If we already have translation for this locale just go to next iteration
126
                continue;
127
            }
128
129 1
            $movieTranslation = new MovieTranslations($movieReference, $translationDTO);
130 1
            $movie->addTranslation($movieTranslation);
131
132 1
            $this->em->persist($movieTranslation);
133
        }
134 1
    }
135
136
    /**
137
     * @param Movie $movie
138
     *
139
     * @throws \ErrorException
140
     *
141
     * @return bool
142
     */
143 3
    private function isAllTranslationsSaved(Movie $movie): bool
144
    {
145 3
        $existingTranslations = [];
146 3
        foreach ($this->locales as $locale) {
147 3
            if ($movie->getTranslation($locale, false) !== null) {
148
                $existingTranslations[] = $locale;
149
            }
150
        }
151
152 3
        return \count(array_diff($this->locales, $existingTranslations)) <= 2;
153
    }
154
155
    public static function getSubscribedTopics()
156
    {
157
        return [self::LOAD_TRANSLATIONS];
158
    }
159
}
160