Failed Conditions
Push — master ( 6b68f9...e59aad )
by Guilherme
21:04 queued 12:27
created

SystemsRegistryService::fetchInfo()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 20
nc 4
nop 2
dl 0
loc 30
ccs 0
cts 18
cp 0
crap 20
rs 8.5806
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of the login-cidadao project or it's bundles.
4
 *
5
 * (c) Guilherme Donato <guilhermednt on github>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace PROCERGS\LoginCidadao\AccountingBundle\Service;
12
13
use GuzzleHttp\ClientInterface as HttpClientInterface;
14
use GuzzleHttp\Exception\ClientException;
15
use LoginCidadao\OAuthBundle\Model\ClientInterface;
16
use PROCERGS\Generic\Traits\OptionalLoggerAwareTrait;
17
use PROCERGS\LoginCidadao\AccountingBundle\Entity\ProcergsLink;
18
use PROCERGS\LoginCidadao\AccountingBundle\Entity\ProcergsLinkRepository;
19
use Psr\Log\LoggerAwareInterface;
20
21
class SystemsRegistryService implements LoggerAwareInterface
22
{
23
    use OptionalLoggerAwareTrait;
24
25
    /** @var HttpClientInterface */
26
    private $client;
27
28
    /** @var string */
29
    private $apiUri;
30
31
    /** @var array */
32
    private $headers;
33
34
    /** @var array */
35
    private $cache = [];
36
37
    /**
38
     * SystemsRegistryService constructor.
39
     * @param HttpClientInterface $client
40
     * @param array $options
41
     */
42
    public function __construct(HttpClientInterface $client, array $options)
43
    {
44
        $this->client = $client;
45
        $this->apiUri = $options['apiUri'];
46
        $this->headers = [
47
            'organizacao' => $options['organization'],
48
            'matricula' => $options['registration_number'],
49
            'senha' => $options['password'],
50
        ];
51
    }
52
53
    public function getSystemInitials(ClientInterface $client, \DateTime $activeAfter = null)
54
    {
55
        $this->log('info', "Fetching PROCERGS's system initials for client_id: {$client->getPublicId()}");
56
        $queries = $this->getQueries($client);
57
58
        $identifiedSystems = [];
59
        $systems = [];
60
        foreach ($queries as $query) {
61
            foreach (array_column($this->fetchInfo($query, $activeAfter), 'sistema') as $system) {
62
                if (array_key_exists($system, $systems)) {
63
                    $systems[$system] += 1;
64
                } else {
65
                    $systems[$system] = 1;
66
                }
67
            }
68
        }
69
        if (count($systems) <= 0) {
70
            return [];
71
        }
72
        asort($systems);
73
        $max = max($systems);
74
        foreach ($systems as $key => $value) {
75
            if ($value === $max) {
76
                $identifiedSystems[] = $key;
77
            }
78
        }
79
80
        return $identifiedSystems;
81
    }
82
83
    public function getSystemOwners(ClientInterface $client, \DateTime $activeAfter = null)
84
    {
85
        $queries = $this->getQueries($client);
86
87
        $identifiedOwners = [];
88
        $owners = [];
89
        foreach ($queries as $query) {
90
            foreach (array_column($this->fetchInfo($query, $activeAfter), 'clienteDono') as $owner) {
91
                if (array_key_exists($owner, $owners)) {
92
                    $owners[$owner] += 1;
93
                } else {
94
                    $owners[$owner] = 1;
95
                }
96
            }
97
        }
98
        if (count($owners) <= 0) {
99
            return [];
100
        }
101
        asort($owners);
102
        $max = max($owners);
103
        foreach ($owners as $key => $value) {
104
            if ($value === $max) {
105
                $identifiedOwners[] = $key;
106
            }
107
        }
108
109
        return $identifiedOwners;
110
    }
111
112
    /**
113
     * @param $query
114
     * @param \DateTime $activeAfter systems deactivated after this date will be included in the report.
115
     * @return mixed
116
     */
117
    private function fetchInfo($query, \DateTime $activeAfter = null)
118
    {
119
        $this->log('info', "Searching for '{$query}'");
120
        $hashKey = hash('sha256', $query);
121
        if (false === array_key_exists($hashKey, $this->cache)) {
122
            $requestUrl = str_replace('{host}', $query, $this->apiUri);
123
124
            $response = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $response is dead and can be removed.
Loading history...
125
            try {
126
                $response = $this->client->get($requestUrl, ['headers' => $this->headers]);
127
            } catch (ClientException $e) {
128
                if ($e->getResponse()->getStatusCode() === 404) {
129
                    $response = $e->getResponse();
130
                } else {
131
                    $this->log('info',
132
                        "An exception occurred when trying to fetch PROCERGS's system initials for '{$query}'",
133
                        ['exception' => $e]
134
                    );
135
                    throw $e;
136
                }
137
            }
138
139
            $systems = $this->filterInactive($response->json(), $activeAfter);
140
141
            $this->cache[$hashKey] = $systems;
142
        } else {
143
            $this->log('info', "Returning cached result for '{$query}'");
144
        }
145
146
        return $this->cache[$hashKey];
147
    }
148
149
    /**
150
     * @param ClientInterface[] $clients OIDC Clients mapped by ID
151
     * @param ProcergsLinkRepository $repo
152
     * @return ProcergsLink[]
153
     */
154
    public function fetchLinked(array $clients, ProcergsLinkRepository $repo)
155
    {
156
        $result = [];
157
        $linked = $repo->findBy(['client' => $clients]);
158
        foreach ($linked as $link) {
159
            if ($link instanceof ProcergsLink && $link->getSystemType() !== null) {
160
                $result[$link->getClient()->getId()] = $link;
161
            }
162
        }
163
164
        return $result;
165
    }
166
167
    private function getQueries(ClientInterface $client)
168
    {
169
        $urls = array_filter($client->getRedirectUris());
170
        if ($client->getSiteUrl()) {
171
            $urls[] = $client->getSiteUrl();
172
        }
173
174
        return array_unique($urls);
175
    }
176
177
    private function filterInactive($response, \DateTime $activeAfter = null)
178
    {
179
        if ($activeAfter === null) {
180
            return $response;
181
        }
182
183
        $systems = $this->removeDecommissionedByDate($response, $activeAfter);
184
        $systems = $this->removeDecommissionedBySituation($systems);
185
186
        return $systems;
187
    }
188
189
    private function removeDecommissionedByDate($systems, \DateTime $activeAfter = null)
190
    {
191
        return array_filter($systems, function ($system) use ($activeAfter) {
192
            if (!isset($system['decommissionedOn'])) {
193
                return true;
194
            }
195
196
            $decommissionedOn = \DateTime::createFromFormat('Y-m-d', $system['decommissionedOn']);
197
            if ($decommissionedOn < $activeAfter) {
198
                $this->log('info',
199
                    "Ignoring system {$system['sistema']}: decommissioned on {$decommissionedOn->format('Y-m-d')}");
200
201
                return false;
202
            }
203
204
            return true;
205
        });
206
    }
207
208
    private function removeDecommissionedBySituation($systems)
209
    {
210
        return array_filter($systems, function ($system) {
211
            if (!isset($system['situacao'])) {
212
                return true;
213
            }
214
215
            return $system['situacao'] === 'Implantado';
216
        });
217
    }
218
}
219