GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

NStackLoader::loadTranslations()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 9
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 19
ccs 0
cts 11
cp 0
crap 20
rs 9.9666
1
<?php
2
3
namespace NStack\Translation;
4
5
use Carbon\Carbon;
6
use Illuminate\Filesystem\Filesystem;
7
use Illuminate\Support\Collection;
8
use Illuminate\Translation\FileLoader;
9
use NStack\Clients\LocalizeClient;
10
use NStack\Models\Resource;
11
use NStack\NStack;
12
13
/**
14
 * NStackLoader for translations
15
 *
16
 * @author Pawel Wilk <[email protected]>
17
 */
18
class NStackLoader extends FileLoader
19
{
20
    /**
21
     * @var NStack
22
     */
23
    protected $nstack;
24
25
    /**
26
     * @var LocalizeClient|null
27
     */
28
    protected $client;
29
30
    /**
31
     * @var string
32
     */
33
    protected $platform;
34
35
    /**
36
     * @var int
37
     */
38
    protected $cacheTime;
39
40
    /**
41
     * To avoid spamming the service, only retry the service if retry is above this count or sec below.
42
     *
43
     * @var int
44
     */
45
    protected $maxNetworkRetries;
46
47
    /**
48
     * To avoid spamming the service, only retry the service if retry is above the count above or this sec.
49
     *
50
     * @var int
51
     */
52
    protected $retryNetworkAfterSec;
53
54
    /**
55
     * @var \Illuminate\Database\Eloquent\Collection
56
     */
57
    protected $failedCarbons;
58
59
    /**
60
     * Constructor
61
     *
62
     * @param Filesystem $files
63
     * @param string     $path
64
     * @param NStack     $nstack
65
     */
66 1
    public function __construct(Filesystem $files, $path, NStack $nstack)
67
    {
68 1
        parent::__construct($files, $path);
69
70 1
        $this->nstack = $nstack;
71 1
        $this->failedCarbons = new Collection();
72
73 1
        $this->platform = config('nstack.platform');
74
        $this->cacheTime = config('nstack.cacheTime', 600);
75
        $this->maxNetworkRetries = config('nstack.maxNetworkRetries', 3);
76
        $this->retryNetworkAfterSec = config('nstack.retryNetworkAfterSec', 10);
77
    }
78
79
    /**
80
     * {@inheritDoc}
81
     * @see \Illuminate\Translation\LoaderInterface::load()
82
     */
83
    public function load($locale, $group, $namespace = null)
84
    {
85
        if (!is_null($namespace) && ($namespace != '*')) {
86
            return $this->loadNamespaced($locale, $group, $namespace);
87
        }
88
89
        if ($resource = $this->findResource($locale)) {
90
            $data = $this->loadTranslations($resource);
91
92
            if (isset($data[$group])) {
93
                return $data[$group];
94
            }
95
        }
96
97
        return parent::load($locale, $group);
98
    }
99
100
    /**
101
     * Download and cache translations
102
     *
103
     * @param Resource $resource
104
     * @param bool     $refresh
105
     * @return array
106
     */
107
    protected function loadTranslations(Resource $resource, $refresh = true)
108
    {
109
        $cacheKey = sprintf('nstack.resource.%d', $resource->getId());
110
111
        if (($data = \Cache::get($cacheKey)) && !$refresh) {
112
            return $data;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $data returns the type Illuminate\Contracts\Cache\Repository which is incompatible with the documented return type array.
Loading history...
113
        }
114
115
        $response = $this->request(function () use ($resource) {
116
            return $this->getClient()->showResource($resource->getUrl());
117
        });
118
119
        if (empty($response['data'])) {
120
            return [];
121
        }
122
123
        \Cache::put($cacheKey, $response['data'], $this->cacheTime);
124
125
        return $response['data'];
126
    }
127
128
    protected function request(\Closure $closure)
129
    {
130
        try {
131
            return $closure();
132
        } catch (\GuzzleHttp\Exception\GuzzleException $e) {
133
            if ($e->getCode() == 403) {
134
                throw new \Exception('Invalid credentials');
135
            }
136
137
            $this->performFail();
138
        }
139
140
        if ($this->shouldTryAgain()) {
141
            sleep(1);
142
143
            return $this->request($closure);
144
        } else {
145
            throw new \Exception('Maximum amount retries reached');
146
        }
147
    }
148
149
    /**
150
     * Find resource corresponding to locale
151
     *
152
     * @param string $locale
153
     * @return \NStack\Models\Resource|boolean
154
     */
155
    protected function findResource($locale)
156
    {
157
        foreach ($this->getResources() as $resource) {
158
            /* @var $resource \NStack\Models\Resource */
159
            if (locale_filter_matches($resource->getLanguage()->getLocale(), $locale)) {
160
                return $resource;
161
            }
162
        }
163
164
        return false;
165
    }
166
167
    /**
168
     * Return nstack localize client
169
     *
170
     * @return \NStack\Clients\LocalizeClient
171
     */
172
    protected function getClient()
173
    {
174
        if (is_null($this->client)) {
175
            $this->client = new LocalizeClient($this->nstack->getConfig());
176
        }
177
178
        return $this->client;
179
    }
180
181
    /**
182
     * getResources
183
     *
184
     * @param bool $force
185
     * @return array
186
     * @throws \Exception
187
     * @author Casper Rasmussen <[email protected]>
188
     */
189
    protected function getResources($force = false): array
190
    {
191
        $cacheKey = 'nstack.availableLocales';
192
193
        if (($data = \Cache::get($cacheKey)) && !$force) {
194
195
            if (!is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) is always false.
Loading history...
196
                throw new \Exception('Cached data is not array');
197
            }
198
199
            return $data;
200
        }
201
202
        $response = $this->request(function () {
203
            return $this->getClient()->indexResources($this->platform);
204
        });
205
206
        if (empty($response)) {
207
            return [];
208
        }
209
210
        \Cache::put($cacheKey, $response, $this->cacheTime);
211
212
        return $response;
213
    }
214
215
    /**
216
     * shouldTryAgain.
217
     *
218
     * @return bool
219
     * @author Casper Rasmussen <[email protected]>
220
     */
221
    private function shouldTryAgain()
222
    {
223
        if ($this->failedCarbons->count() < $this->maxNetworkRetries) {
224
            return true;
225
        }
226
227
        /** @var Carbon $carbon */
228
        $carbon = $this->failedCarbons->first();
229
        if ($carbon->diffInSeconds(Carbon::now()) >= $this->retryNetworkAfterSec) {
230
            return true;
231
        }
232
233
        return false;
234
    }
235
236
    /**
237
     * performFail.
238
     *
239
     * @return void
240
     * @author Casper Rasmussen <[email protected]>
241
     */
242
    private function performFail()
243
    {
244
        $this->failedCarbons->prepend(new Carbon());
245
        if ($this->failedCarbons->count() > 3) {
246
            $this->failedCarbons->pop();
247
        }
248
    }
249
}
250