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 (#5)
by Casper
02:08
created

src/Translation/NStackLoader.php (2 issues)

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 Carbon\Carbon;
12
13
/**
14
 * NStackLoader for translations
15
 *
16
 * @author Pawel Wilk <[email protected]>
17
 *
18
 */
19
class NStackLoader extends FileLoader
20
{
21
    /**
22
     * @var NStack
23
     */
24
    protected $nstack;
25
26
    /**
27
     * @var LocalizeClient|null
28
     */
29
    protected $client;
30
31
    /**
32
     * @var string
33
     */
34
    protected $platform;
35
36
    /**
37
     * @var int
38
     */
39
    protected $cacheTime;
40
41
    /**
42
     * To avoid spamming the service, only retry the service if retry is above this count or sec below.
43
     *
44
     * @var int
45
     */
46
    protected $maxNetworkRetries;
47
48
    /**
49
     * To avoid spamming the service, only retry the service if retry is above the count above or this sec.
50
     *
51
     * @var int
52
     */
53
    protected $retryNetworkAfterSec;
54
55
    /**
56
     * @var \Illuminate\Database\Eloquent\Collection
57
     */
58
    protected $failedCarbons;
59
60
    /**
61
     * Constructor
62
     *
63
     * @param Filesystem $files
64
     * @param string $path
65
     * @param NStack $nstack
66
     */
67
    public function __construct(Filesystem $files, $path, NStack $nstack) {
68
        parent::__construct($files, $path);
69
70
        $this->nstack = $nstack;
71
        $this->failedCarbons = new Collection();
72
73
        $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
     *
106
     * @return array
107
     */
108
    protected function loadTranslations(Resource $resource, $refresh = true)
109
    {
110
        $cacheKey = sprintf('nstack.resource.%d', $resource->getId());
111
112
        if (($data = \Cache::get($cacheKey)) && !$refresh) {
113
            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...
114
        }
115
116
        $response = $this->request(function () use ($resource) {
117
            return $this->getClient()->showResource($resource->getUrl());
118
        });
119
120
        if (empty($response['data'])) {
121
            return [];
122
        }
123
124
        \Cache::put($cacheKey, $response['data'], $this->cacheTime);
125
126
        return $response['data'];
127
    }
128
129
    protected function request(\Closure $closure)
130
    {
131
        try {
132
            return $closure();
133
        } catch (\GuzzleHttp\Exception\GuzzleException $e) {
134
            if ($e->getCode() == 403) {
135
                throw new \Exception('Invalid credentials');
136
            }
137
138
            $this->performFail();
139
        }
140
141
        if ($this->shouldTryAgain()) {
142
            sleep(1);
143
144
            return $this->request($closure);
145
        } else {
146
            throw new \Exception('Maximum amount retries reached');
147
        }
148
    }
149
150
    /**
151
     * Find resource corresponding to locale
152
     *
153
     * @param string $locale
154
     * @return \NStack\Models\Resource|boolean
155
     */
156
    protected function findResource($locale)
157
    {
158
        foreach ($this->getResources() as $resource) { /* @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
     * Get available resources for platform
183
     *
184
     * @return Resource[]
185
     */
186
    protected function getResources($force = false)
187
    {
188
        $cacheKey = 'nstack.availableLocales';
189
190
        if (($data = \Cache::get($cacheKey)) && !$force) {
191
            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 NStack\Models\Resource[].
Loading history...
192
        }
193
194
        $response = $this->request(function () {
195
            return $this->getClient()->indexResources($this->platform);
196
        });
197
198
        if (empty($response)) {
199
            return [];
200
        }
201
202
        \Cache::put($cacheKey, $response, $this->cacheTime);
203
204
        return $response;
205
    }
206
207
    /**
208
     * shouldTryAgain.
209
     *
210
     * @author Casper Rasmussen <[email protected]>
211
     * @return bool
212
     */
213
    private function shouldTryAgain()
214
    {
215
        if ($this->failedCarbons->count() < $this->maxNetworkRetries) {
216
            return true;
217
        }
218
219
        /** @var Carbon $carbon */
220
        $carbon = $this->failedCarbons->first();
221
        if ($carbon->diffInSeconds(Carbon::now()) >= $this->retryNetworkAfterSec) {
222
            return true;
223
        }
224
225
        return false;
226
    }
227
228
    /**
229
     * performFail.
230
     *
231
     * @author Casper Rasmussen <[email protected]>
232
     * @return void
233
     */
234
    private function performFail()
235
    {
236
        $this->failedCarbons->prepend(new Carbon());
237
        if ($this->failedCarbons->count() > 3) {
238
            $this->failedCarbons->pop();
239
        }
240
    }
241
}
242