Passed
Push — master ( 4cb925...613187 )
by Marek
10:16
created

ExternalLibraryJiraService::getResponseContent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
c 0
b 0
f 0
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace AppBuilder\Application\Module\Jira;
6
7
use AppBuilder\Application\Module\HttpClient\ExternalLibraryHttpClient;
8
use AppBuilder\Application\Module\Jira\Exception\InvalidJiraStatusException;
9
use AppBuilder\Application\Module\Jira\Exception\NullResultReturned;
10
use AppBuilder\Application\Module\Jira\ValueObject\JiraTicketStatus;
11
use AppBuilder\Application\Utils\Mapper\Factory\JiraMapperFactory;
12
use AppBuilder\Event\Application\CredentialsValidatedEvent;
13
use AppBuilder\Event\Application\CredentialsValidatedEventAware;
14
use AppBuilder\Event\Application\JiraTicketMappedEvent;
15
use Exception;
16
use GuzzleHttp\Psr7\Response;
17
use Psr\Log\LoggerInterface;
18
use RuntimeException;
19
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
20
21
class ExternalLibraryJiraService implements JiraService, CredentialsValidatedEventAware
22
{
23
    /** @var ExternalLibraryHttpClient */
24
    private $httpClient;
25
26
    /** @var LoggerInterface */
27
    private $logger;
28
29
    /** @var EventDispatcherInterface */
30
    private $dispatcher;
31
32
    /** @var QueryRepository */
33
    private $queryRepository;
34
35 4
    public function __construct(
36
        ExternalLibraryHttpClient $httpClient,
37
        LoggerInterface $logger,
38
        EventDispatcherInterface $dispatcher,
39
        QueryRepository $queryRepository
40
    ) {
41 4
        $this->httpClient      = $httpClient;
42 4
        $this->logger          = $logger;
43 4
        $this->dispatcher      = $dispatcher;
44 4
        $this->queryRepository = $queryRepository;
45 4
    }
46
47
    /**
48
     * Service connects to JIRA with specified credentials when event occurs.
49
     * If connected successfully, fetches all tickets from JIRA.
50
     */
51
    public function onCredentialsValidated(CredentialsValidatedEvent $event = null) : void
52
    {
53
        try {
54
            $this->fetchAllTickets();
55
        } catch (Exception $exception) {
56
            $this->logger->warning($exception->getMessage(), [$exception]);
57
        }
58
    }
59
60
    /**
61
     * Fetches tickets with passed status and passes them to flattenArray method.
62
     *
63
     * @throws NullResultReturned
64
     * @throws RuntimeException
65
     */
66 2
    public function fetchTicketsByStatus(string $status) : void
67
    {
68 2
        $tickets = null;
69
        try {
70
            $response = $this
71 2
                ->httpClient->request(
72 2
                    ExternalLibraryHttpClient::GET,
73
                    $this
74 2
                        ->createUrl($this
75 2
                            ->queryRepository
76 2
                            ->fetchTicketsByStatus(JiraTicketStatus::createFromString($status)->status()))
77
                );
78
79 1
            $tickets = $this->getResponseContent($response);
80 1
        } catch (InvalidJiraStatusException $exception) {
81 1
            $this->logger->warning('Error: ' . $exception->getMessage(), [$exception]);
82
        }
83
84 2
        if (null === $tickets) {
85 1
            throw new NullResultReturned('Error. Fetching method returned null');
86
        }
87
88 1
        $this->flattenArray($tickets);
89 1
    }
90
91
    /**
92
     * Fetches all tickets and passes them to flattenArray method.
93
     *
94
     * @throws NullResultReturned
95
     * @throws RuntimeException
96
     */
97 2
    public function fetchAllTickets() : void
98
    {
99
        $response = $this
100 2
            ->httpClient->request(
101 2
                ExternalLibraryHttpClient::GET,
102
                $this
103 2
                    ->createUrl($this
104 2
                        ->queryRepository
105 2
                        ->fetchAllTickets())
106
            );
107
108 2
        $tickets = $this->getResponseContent($response);
109
110 2
        if (null === $tickets) {
111 1
            throw new NullResultReturned('Error. Jira fetching method returned null');
112
        }
113
114 1
        $this->flattenArray($tickets);
115 1
    }
116
117
    /**
118
     * Gets content from response and decodes it into array.
119
     *
120
     * @throws RuntimeException
121
     */
122 3
    private function getResponseContent(Response $response) : ?array
123
    {
124 3
        $content = $response->getBody()->getContents();
125
126 3
        $this->logger->info('Tickets fetched.');
127
128 3
        return json_decode($content, true);
129
    }
130
131
    /**
132
     * Reconstructs array structure.
133
     */
134 2
    private function flattenArray(array $tickets) : void
135
    {
136 2
        $ticketsArray = [];
137 2
        foreach ($tickets['issues'] as $issue) {
138 2
            $ticketsArray[$issue['key']] = $issue;
139
        }
140
141 2
        $this->mapToJiraTicket($ticketsArray);
142 2
    }
143
144
    /**
145
     * Combines jira rest api url with jql.
146
     */
147 3
    private function createUrl(string $jql) : string
148
    {
149 3
        return $this->httpClient->applicationParams()->jiraHost()
150 3
            . '/rest/api/2/search?jql='
151 3
            . $jql
152 3
            . '&maxResults='
153 3
            . $this->httpClient->applicationParams()->jiraSearchMaxResults();
154
    }
155
156
    /**
157
     * Maps and filters array with full Jira ticket into desired array format.
158
     */
159 2
    private function mapToJiraTicket(array $tickets) : void
160
    {
161 2
        $mappedTickets = [];
162 2
        $ticketMappers = [];
163 2
        foreach ($tickets as $key => $value) {
164 2
            $ticketMappers[$key] = JiraMapperFactory::create();
165 2
            foreach ($ticketMappers[$key] as $mapper) {
166 2
                $mappedTickets[$key][$mapper->outputKey()] = $mapper->map($value);
167
            }
168
        }
169 2
        $this->logger->info('Tickets mapped.');
170 2
        foreach ($mappedTickets as $mappedTicket) {
171 2
            $this->dispatchJiraTicketMappedEvent($mappedTicket);
172
        }
173 2
    }
174
175
    /**
176
     * Dispatches JiraTicketMappedEvent.
177
     */
178 2
    private function dispatchJiraTicketMappedEvent(array $ticket) : void
179
    {
180 2
        $this->dispatcher->dispatch(
181 2
            JiraTicketMappedEvent::NAME,
182 2
            new JiraTicketMappedEvent($ticket)
183
        );
184 2
    }
185
}
186