Completed
Pull Request — master (#4)
by
unknown
07:52
created

BandwidthQuota::getPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 2
cp 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * This file is part of laravel-quota
5
 *
6
 * (c) David Faith <[email protected]>
7
 *
8
 * Full copyright and license information is available
9
 * in the LICENSE file distributed with this source code.
10
 */
11
12
namespace Projectmentor\Quota;
13
14
use \bandwidthThrottle\tokenBucket\storage\FileStorage;
15
use \bandwidthThrottle\tokenBucket\Rate;
16
use \bandwidthThrottle\tokenBucket\TokenBucket;
17
use \bandwidthThrottle\tokenBucket\BlockingConsumer;
18
19
/**
20
 * This is the BandwidthQuota class.
21
 * It provides rate-of-flow quota restriction
22
 * e.g. limit api requests to 60/second.
23
 *
24
 * Currently only support FileStorage type
25
 * of persistance.
26
 */
27
28
class BandwidthQuota extends Quota
29
{
30
    /**
31
     * The driver shortcut name as known to the IoC.
32
     *
33
     * @var string
34
     */
35
    protected $driver;
36
37
    /**
38
     * The file path, if driver resolves to FileStorage
39
     *
40
     * @var string
41
     */
42
    protected $path;
43
44
    /**
45
     * The persistant storage for the bucket.
46
     *
47
     * @var mixed
48
     */
49
    protected $storage;
50
51
    /**
52
     * The rate
53
     *
54
     * @var \bandwidthThrottle\tokenBucket\Rate
55
     */
56
    protected $rate;
57
58
    /**
59
     * The bucket
60
     *
61
     * @var \bandwidthThrottle\tokenBucket\TokenBucket
62
     */
63
    protected $bucket;
64
65
    /**
66
     * The blocking consumer
67
     *
68
     * @var \bandwidthThrottle\tokenBucket\BlockingConsumer
69
     */
70
    protected $blocker;
71
72
    /**
73
     *  Construct instance.
74
     *
75
     *  NOTE: Laravel 5.4 breaking change:
76
     *      App::make(...) ~> App::makeWith(...)
77
     *
78
     *  TODO: REFACTOR Currently only supports FileStorage.
79
     *  Also, resolving from container with parameters is not
80
     *  best practice.
81
     *  @See https://github.com/laravel/internals/issues/391
82
     *
83
     *  @param string $connection
84
     *  @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
85
     */
86 2
    public function __construct($connection)
87
    {
88 2
        parent::__construct($connection);
89
90 2
        $this->driver = config($this->index . '.driver');
91
92
        //TODO: REFACTOR for multiple storage types.
93 2
        if ($this->driver != 'quota.storage.file') {
94
            throw new \Exception('Driver: ' . $this->driver . ' not supported.');
95
        }
96
97 2
        $this->path = config($this->index . '.path');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
98 2
        $this->storage = app($this->driver, ['path' =>  $this->path]);
99
        //END REFACTOR
100
101
        //Resolve rate via IoC container.
102 2
        $this->rate = app(
103 2
            'quota.rate',
104 2
            ['limit' => $this->limit, 'period' => $this->period]
105 2
        );
106
107
        //Resolve bucket via IoC container.
108 2
        $capacity = config($this->index . '.capacity');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
109 2
        $this->bucket = app('quota.bucket', [
110 2
            'capacity' => $capacity,
111 2
            'rate' => $this->rate,
112 2
            'storage' => $this->storage
113 2
        ]);
114
115
        //Bootstrap storage if not already initialized.
116 2
        $this->bucket->bootstrap($capacity);
117
118
        //Optionally enclose bucket within a blocking consumer.
119 2
        if (config($this->index . '.block') == true) {
120 2
            $this->blocker = app('quota.blocker', ['bucket' => $this->bucket]);
121 2
        }
122 2
    }
123
124
    /**
125
     * Enforce the quota.
126
     * Future public interface
127
     *
128
     * @return boolean true on success
129
     *
130
     * @throws ErrorException
131
     * Overquota exceeds bandwidth rate.
132
     *
133
     * @throws LengthException
134
     *  The token amount is larger than the bucket's capacity.
135
     *
136
     * @throws StorageException
137
     * The stored microtime could not be accessed.
138
     */
139
    public function enforce()
140
    {
141
        return $this->consume();
142
    }
143
144
    /**
145
     * Consume tokens.
146
     *
147
     * If  $this->bucket does not have sufficient tokens
148
     * and $this->block is true, then block until available.
149
     *
150
     * If this->bucket does not have sufficient tokens
151
     * and $this->block is false, the throw exception.
152
     *
153
     * If this->bucket has sufficent tokens, then:
154
     *
155
     *    If $this is logging to database then:
156
     *      If  hits exceed periodic limit then:
157
     *          increment misses in the database
158
     *          throw exception.
159
     *      Else
160
     *          increment hits in database
161
     *
162
     *    reduce the amount of tokens in the bucket
163
     *    return  true.
164
     *
165
     * @param int $tokens default  === 1
166
     * @return boolean true on success
167
     *
168
     * @throws ErrorException
169
     * Overquota exceeds bandwidth rate.
170
     *
171
     * @throws LengthException
172
     *  The token amount is larger than the bucket's capacity.
173
     *
174
     * @throws StorageException
175
     * The stored microtime could not be accessed.
176
     */
177
    public function consume($tokens = 1)
0 ignored issues
show
Coding Style introduced by
function consume() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
178
    {
179
        if (isset($this->bucket)) {
180
            if (! isset($this->blocker)) {
181
                $result = $this->bucket->consume($tokens, $seconds);
182
                if ($result === false) {
183
                    throw new \ErrorException(
184
                        __CLASS__ . '::' . __FUNCTION__ .
185
                        ' Overquota. Exceeded bandwidth. Wait ' . $seconds . ' seconds.'
186
                    );
187
                }
188
            } else {
189
                $result = $this->blocker->consume($tokens);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as $this->blocker->consume($tokens) (which targets bandwidthThrottle\tokenB...kingConsumer::consume()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
190
            }
191
        }
192
        return (isset($result)) ? $result : false;
193
    }
194
195
    /**
196
     * Clean up before removing storage for gc.
197
     * Releases $blocker, $bucket, $rate
198
     * Does not release $storage.
199
     * Does not unlink file storage file.
200
     *
201
     * @return void
202
     */
203 2
    public function release()
204
    {
205 2
        if (isset($this->blocker)) {
206 2
            unset($this->blocker);
207 2
        }
208
209 2
        if (isset($this->bucket)) {
210 2
            unset($this->bucket);
211 2
        }
212
213 2
        if (isset($this->rate)) {
214 2
            unset($this->rate);
215 2
        }
216 2
    }
217
218
    /**
219
     * Unlink the handle to storage then release storage.
220
     * e.g: if file storage, then unlink (delete) file on disk.
221
     *
222
     * @return void
223
     */
224 2
    public function remove()
225
    {
226 2
        if (isset($this->storage)) {
227 2
            $this->storage->remove();
228 2
            unset($this->storage);
229 2
        }
230 2
    }
231
232
    /**
233
     * Orderly clean up.
234
     *
235
     * @internal
236
     */
237 2
    public function __destruct()
238
    {
239 2
        $this->release();
240 2
        $this->remove();
241 2
    }
242
243
    /**
244
     * Get the driver IoC shortcut name
245
     *
246
     * @return string
247
     */
248
    public function getDriver()
249
    {
250
        return $this->driver;
251
    }
252
253
    /**
254
     * Get the path to FileStorage
255
     *
256
     * @return string
257
     */
258
    public function getPath()
259
    {
260
        return $this->path;
261
    }
262
263
    /**
264
     * Get the persistant storage backing instance.
265
     *
266
     * @return mixed
267
     */
268 1
    public function getStorage()
269
    {
270 1
        return $this->storage;
271
    }
272
273
    /**
274
     * Get the rate instance.
275
     *
276
     * @return \bandwidthThrottle\tokenBucket\Rate
277
     */
278 1
    public function getRate()
279
    {
280 1
        return $this->rate;
281
    }
282
283
    /**
284
     * Get the TokenBucket instance.
285
     *
286
     * @return \bandwidthThrottle\tokenBucket\TokenBucket
287
     */
288 1
    public function getBucket()
289
    {
290 1
        return $this->bucket;
291
    }
292
293
    /**
294
     * Get the (optional) BlockingConsumer instance.
295
     *
296
     * @return \bandwidthThrottle\tokenBucket\BlockingConsumer
297
     */
298 2
    public function getBlocker()
299
    {
300 2
        return $this->blocker;
301
    }
302
303
    /**
304
     * Set the driver IoC shortcut name.
305
     *
306
     * @param  string $driver
307
     * @return void
308
     */
309
    public function setDriver($driver)
310
    {
311
        $this->driver = $driver;
312
    }
313
314
    /**
315
     * Set the path for FileStorage
316
     *
317
     * @param string $path
318
     * @return void
319
     */
320
    public function setPath($path)
321
    {
322
        //TODO: validate path
323
        $this->path = $path;
324
    }
325
    /**
326
     * Set the persistant storage backing instance.
327
     *
328
     * @param  mixed $storage
329
     * @return void
330
     */
331
    public function setStorage($storage)
332
    {
333
        $this->storage = $storage;
334
    }
335
336
    /**
337
     * Set the rate instance.
338
     *
339
     * @param \bandwidthThrottle\tokenBucket\Rate $rate
340
     * @return void
341
     */
342
    public function setRate($rate)
343
    {
344
        //TODO: validate rate
345
        $this->rate = $rate;
346
    }
347
348
    /**
349
     * Set the TokenBucket instance.
350
     *
351
     * @param \bandwidthThrottle\tokenBucket\TokenBucket $bucket
352
     * @return void
353
     */
354
    public function setBucket($bucket)
355
    {
356
        $this->bucket = $bucket;
357
    }
358
359
    /**
360
     * Set the (optional) BlockingConsumer instance.
361
     *
362
     * @param \bandwidthThrottle\tokenBucket\BlockingConsumer $blocker
363
     * @return void
364
     */
365
    public function setBlocker($blocker)
366
    {
367
        $this->blocker = $blocker;
368
    }
369
}
0 ignored issues
show
Coding Style introduced by
As per coding style, files should not end with a newline character.

This check marks files that end in a newline character, i.e. an empy line.

Loading history...
370