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.
Failed Conditions
Pull Request — master (#3)
by Pawel
03:18
created

NStackLoader::request()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 18
rs 9.9
1
<?php
2
3
namespace NStack\Translation;
4
5
use Illuminate\Translation\FileLoader;
6
use Illuminate\Filesystem\Filesystem;
7
use NStack\NStack;
8
use NStack\Clients\LocalizeClient;
9
use NStack\Models\Resource;
10
use Illuminate\Support\Collection;
11
use NStack\Exceptions\NotFoundException;
12
use Carbon\Carbon;
13
use NStack\Exceptions\MissingMasterKeyException;
14
15
/**
16
 * NStackLoader for translations
17
 *
18
 * @author Pawel Wilk <[email protected]>
19
 *
20
 */
21
class NStackLoader extends FileLoader
22
{
23
    /**
24
     * @var NStack
25
     */
26
    protected $nstack;
27
28
    /**
29
     * @var LocalizeClient|null
30
     */
31
    protected $client;
32
33
    /**
34
     * @var string
35
     */
36
    protected $platform;
37
38
    /**
39
     * @var int
40
     */
41
    protected $cacheTime;
42
43
    /**
44
     * To avoid spamming the service, only retry the service if retry is above this count or sec below.
45
     *
46
     * @var int
47
     */
48
    protected $maxNetworkRetries;
49
50
    /**
51
     * To avoid spamming the service, only retry the service if retry is above the count above or this sec.
52
     *
53
     * @var int
54
     */
55
    protected $retryNetworkAfterSec;
56
57
    /**
58
     * @var \Illuminate\Database\Eloquent\Collection
59
     */
60
    protected $failedCarbons;
61
62
    /**
63
     * Constructor
64
     *
65
     * @param Filesystem $files
66
     * @param string $path
67
     * @param NStack $nstack
68
     */
69
    public function __construct(Filesystem $files, $path, NStack $nstack) {
70
        parent::__construct($files, $path);
71
72
        $this->nstack = $nstack;
73
        $this->failedCarbons = new Collection();
74
75
        $this->platform = config('nstack.platform');
76
        $this->cacheTime = config('nstack.cacheTime', 600);
77
        $this->maxNetworkRetries = config('nstack.maxNetworkRetries', 3);
78
        $this->retryNetworkAfterSec = config('nstack.retryNetworkAfterSec', 10);
79
    }
80
81
    /**
82
     * {@inheritDoc}
83
     * @see \Illuminate\Translation\LoaderInterface::load()
84
     */
85
    public function load($locale, $group, $namespace = null)
86
    {
87
        if (!is_null($namespace) && ($namespace != '*')) {
88
            return $this->loadNamespaced($locale, $group, $namespace);
89
        }
90
91
        if ($resource = $this->findResource($locale)) {
92
            $data = $this->loadTranslations($resource);
93
94
            if (isset($data[$group])) {
95
                return $data[$group];
96
            }
97
        }
98
99
        return parent::load($locale, $group);
100
    }
101
102
    /**
103
     * Download and cache translations
104
     *
105
     * @param Resource $resource
106
     * @param bool $refresh
107
     *
108
     * @return array
109
     */
110
    protected function loadTranslations(Resource $resource, $refresh = true)
111
    {
112
        $cacheKey = sprintf('nstack.resource.%d', $resource->getId());
113
114
        if (($data = \Cache::get($cacheKey, false)) && !$refresh) {
0 ignored issues
show
Unused Code introduced by
The call to Illuminate\Cache\CacheManager::get() has too many arguments starting with false. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

114
        if (($data = \Cache::/** @scrutinizer ignore-call */ get($cacheKey, false)) && !$refresh) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
115
            return $data;
116
        }
117
118
        $response = $this->request(function () use ($resource) {
119
            return $this->getClient()->showResource($resource->getUrl());
120
        });
121
122
        if (empty($response['data'])) {
123
            return [];
124
        }
125
126
        \Cache::put($cacheKey, $response['data'], $this->cacheTime);
127
128
        return $response['data'];
129
    }
130
131
    protected function request(\Closure $closure)
132
    {
133
        try {
134
            return $closure();
135
        } catch (\GuzzleHttp\Exception\GuzzleException $e) {
136
            if ($e->getCode() == 403) {
137
                throw new \Exception('Invalid credentials');
138
            }
139
140
            $this->performFail();
141
        }
142
143
        if ($this->shouldTryAgain()) {
144
            sleep(1);
145
146
            return $this->request($closure);
147
        } else {
148
            throw new \Exception('Maximum amount retries reached');
149
        }
150
    }
151
152
    /**
153
     * Find resource corresponding to locale
154
     *
155
     * @param string $locale
156
     * @return \NStack\Models\Resource|boolean
157
     */
158
    protected function findResource($locale)
159
    {
160
        foreach ($this->getResources() as $resource) { /* @var $resource \NStack\Models\Resource */
161
            if (locale_filter_matches($resource->getLanguage()->getLocale(), $locale)) {
162
                return $resource;
163
            }
164
        }
165
166
        return false;
167
    }
168
169
    /**
170
     * Return nstack localize client
171
     *
172
     * @return \NStack\Clients\LocalizeClient
173
     */
174
    protected function getClient()
175
    {
176
        if (is_null($this->client)) {
177
            $this->client = new LocalizeClient($this->nstack->getConfig());
178
        }
179
180
        return $this->client;
181
    }
182
183
    /**
184
     * Get available resources for platform
185
     *
186
     * @return Resource[]
187
     */
188
    protected function getResources($force = false)
189
    {
190
        $cacheKey = 'nstack.availableLocales';
191
192
        if (($data = \Cache::get($cacheKey, false)) && !$force) {
0 ignored issues
show
Unused Code introduced by
The call to Illuminate\Cache\CacheManager::get() has too many arguments starting with false. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

192
        if (($data = \Cache::/** @scrutinizer ignore-call */ get($cacheKey, false)) && !$force) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
193
            return $data;
194
        }
195
196
        $response = $this->request(function () {
197
            return $this->getClient()->indexResources($this->platform);
198
        });
199
200
        if (empty($response)) {
201
            return [];
202
        }
203
204
        \Cache::put($cacheKey, $response, $this->cacheTime);
205
206
        return $response;
207
    }
208
209
    /**
210
     * shouldTryAgain.
211
     *
212
     * @author Casper Rasmussen <[email protected]>
213
     * @return bool
214
     */
215
    private function shouldTryAgain()
216
    {
217
        if ($this->failedCarbons->count() < $this->maxNetworkRetries) {
218
            return true;
219
        }
220
221
        /** @var Carbon $carbon */
222
        $carbon = $this->failedCarbons->first();
223
        if ($carbon->diffInSeconds(Carbon::now()) >= $this->retryNetworkAfterSec) {
224
            return true;
225
        }
226
227
        return false;
228
    }
229
230
    /**
231
     * performFail.
232
     *
233
     * @author Casper Rasmussen <[email protected]>
234
     * @return void
235
     */
236
    private function performFail()
237
    {
238
        $this->failedCarbons->prepend(new Carbon());
239
        if ($this->failedCarbons->count() > 3) {
240
            $this->failedCarbons->pop();
241
        }
242
    }
243
}
244