|
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 Illuminate\Foundation\Application as LaravelApplication; |
|
15
|
|
|
use Laravel\Lumen\Application as LumenApplication; |
|
16
|
|
|
|
|
17
|
|
|
use Illuminate\Support\ServiceProvider; |
|
18
|
|
|
|
|
19
|
|
|
use bandwidthThrottle\tokenBucket\Rate; |
|
20
|
|
|
use bandwidthThrottle\tokenBucket\TokenBucket; |
|
21
|
|
|
use bandwidthThrottle\tokenBucket\BlockingConsumer; |
|
22
|
|
|
use bandwidthThrottle\tokenBucket\storage\FileStorage; |
|
23
|
|
|
|
|
24
|
|
|
use Projectmentor\Quota\Factories\RateFactory; |
|
25
|
|
|
use Projectmentor\Quota\Factories\FileStorageFactory; |
|
26
|
|
|
use Projectmentor\Quota\Factories\TokenBucketFactory; |
|
27
|
|
|
use Projectmentor\Quota\Factories\BlockingConsumerFactory; |
|
28
|
|
|
|
|
29
|
|
|
use Projectmentor\Quota\Stubs\RateData; |
|
30
|
|
|
use Projectmentor\Quota\Stubs\FileStorageData; |
|
31
|
|
|
use Projectmentor\Quota\Stubs\TokenBucketData; |
|
32
|
|
|
use Projectmentor\Quota\Stubs\BlockingConsumerData; |
|
33
|
|
|
|
|
34
|
|
|
use Projectmentor\Quota\Console\Commands\ResetQuotaLog; |
|
35
|
|
|
use Projectmentor\Quota\Console\Commands\TruncateQuotaLog; |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* This is the Quota service provider. |
|
39
|
|
|
* |
|
40
|
|
|
* "There is no need to bind classes into the container |
|
41
|
|
|
* if they do not depend on any interfaces" |
|
42
|
|
|
* - @See https://laravel.com/docs/5.2/container#binding |
|
43
|
|
|
* |
|
44
|
|
|
* Hence the base classes we are exposing from the library |
|
45
|
|
|
* Are not going to be registered here. |
|
46
|
|
|
* |
|
47
|
|
|
* We will register our factory classes and the Quota class |
|
48
|
|
|
* which will be used both as a `manager` and as a concrete |
|
49
|
|
|
* instance by leveraging call_user_func_array(). In this |
|
50
|
|
|
* manner we will be able to access Quota as a singleton, |
|
51
|
|
|
* via a Facade, and it will maintain an array of rate-limiters |
|
52
|
|
|
* which we can retrieve when needed. |
|
53
|
|
|
* @See Projectmentor\Quota\Quota.php |
|
54
|
|
|
* |
|
55
|
|
|
* |
|
56
|
|
|
* @author David Faith <[email protected]> |
|
57
|
|
|
*/ |
|
58
|
|
|
class QuotaServiceProvider extends ServiceProvider |
|
59
|
|
|
{ |
|
60
|
|
|
/** |
|
61
|
|
|
* Indicates if loading of the provider is deferred. |
|
62
|
|
|
* |
|
63
|
|
|
* NOTE: Since we are also configuring at boot time |
|
64
|
|
|
* we can not defer. |
|
65
|
|
|
* |
|
66
|
|
|
* @var bool |
|
67
|
|
|
*/ |
|
68
|
|
|
protected $defer = false; |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* Perform post-registration booting of services. |
|
72
|
|
|
* |
|
73
|
|
|
* @return void |
|
74
|
|
|
*/ |
|
75
|
37 |
|
public function boot() |
|
76
|
|
|
{ |
|
77
|
|
|
//dump(__CLASS__.'::'.__FUNCTION__); |
|
|
|
|
|
|
78
|
37 |
|
$this->setupConfig(); |
|
79
|
|
|
|
|
80
|
|
|
//$this->loadMigrationsFrom(__DIR__.'/../database/migrations'); |
|
|
|
|
|
|
81
|
|
|
|
|
82
|
37 |
|
if ($this->app->runningInConsole()) { |
|
83
|
37 |
|
$this->commands([ |
|
84
|
37 |
|
ResetQuotaLog::class, |
|
85
|
37 |
|
TruncateQuotaLog::class, |
|
86
|
37 |
|
]); |
|
87
|
37 |
|
} |
|
88
|
37 |
|
} |
|
89
|
|
|
|
|
90
|
|
|
/** |
|
91
|
|
|
* Register a database migration path. |
|
92
|
|
|
* |
|
93
|
|
|
* NOTE: This function is already part of 5.4 |
|
94
|
|
|
* it is backported here for 5.2 |
|
95
|
|
|
* |
|
96
|
|
|
* @param array|string $paths |
|
97
|
|
|
* @return void |
|
98
|
|
|
*/ |
|
99
|
|
|
//protected function loadMigrationsFrom($paths) |
|
|
|
|
|
|
100
|
|
|
//{ |
|
101
|
|
|
// dump(__CLASS__.'::'.__FUNCTION__); |
|
|
|
|
|
|
102
|
|
|
|
|
103
|
|
|
// $this->app->afterResolving('migrator', function ($migrator) use ($paths) { |
|
|
|
|
|
|
104
|
|
|
// foreach ((array) $paths as $path) { |
|
|
|
|
|
|
105
|
|
|
// dump($path); |
|
|
|
|
|
|
106
|
|
|
// $migrator->path($path); |
|
|
|
|
|
|
107
|
|
|
// } |
|
108
|
|
|
// }); |
|
109
|
|
|
//} |
|
110
|
|
|
|
|
111
|
|
|
/** |
|
112
|
|
|
* Setup the config |
|
113
|
|
|
* |
|
114
|
|
|
* @return void |
|
115
|
|
|
*/ |
|
116
|
37 |
|
protected function setupConfig() |
|
117
|
|
|
{ |
|
118
|
37 |
|
$source = realpath(__DIR__.'/../config/quota.php'); |
|
119
|
|
|
|
|
120
|
37 |
|
if ($this->app instanceof LaravelApplication && |
|
121
|
37 |
|
$this->app->runningInConsole()) { |
|
122
|
37 |
|
$this->publishes([$source => config_path('quota.php')]); |
|
123
|
37 |
|
} elseif ($this->app instanceof LumenApplication) { |
|
|
|
|
|
|
124
|
|
|
$this->app->configure('quota'); |
|
125
|
1 |
|
} |
|
126
|
|
|
|
|
127
|
37 |
|
$this->mergeConfigFrom($source, 'quota'); |
|
128
|
37 |
|
} |
|
129
|
|
|
|
|
130
|
|
|
/** |
|
131
|
|
|
* Register any package services. |
|
132
|
|
|
* |
|
133
|
|
|
* @return void |
|
134
|
|
|
*/ |
|
135
|
37 |
|
public function register() |
|
136
|
|
|
{ |
|
137
|
37 |
|
$this->bindInterfaces(); |
|
138
|
37 |
|
$this->registerFactories(); |
|
139
|
37 |
|
$this->registerClasses(); |
|
140
|
37 |
|
} |
|
141
|
|
|
|
|
142
|
|
|
/** |
|
143
|
|
|
* Bind interfaces to implementations. |
|
144
|
|
|
* @return void |
|
145
|
|
|
*/ |
|
146
|
37 |
|
public function bindInterfaces() |
|
147
|
|
|
{ |
|
148
|
37 |
|
$this->app->when(RateFactory::class) |
|
149
|
37 |
|
->needs('Projectmentor\Quota\Contracts\PayloadInterface') |
|
150
|
37 |
|
->give(RateData::class); |
|
151
|
|
|
|
|
152
|
37 |
|
$this->app->when(FileStorageFactory::class) |
|
153
|
37 |
|
->needs('Projectmentor\Quota\Contracts\PayloadInterface') |
|
154
|
37 |
|
->give(FileStorageData::class); |
|
155
|
|
|
|
|
156
|
37 |
|
$this->app->when(TokenBucketFactory::class) |
|
157
|
37 |
|
->needs('Projectmentor\Quota\Contracts\PayloadInterface') |
|
158
|
37 |
|
->give(TokenBucketData::class); |
|
159
|
|
|
|
|
160
|
37 |
|
$this->app->when(BlockingConsumerFactory::class) |
|
161
|
37 |
|
->needs('Projectmentor\Quota\Contracts\PayloadInterface') |
|
162
|
37 |
|
->give(BlockingConsumerData::class); |
|
163
|
37 |
|
} |
|
164
|
|
|
|
|
165
|
|
|
/** |
|
166
|
|
|
* Register the factory classes. |
|
167
|
|
|
* @return void |
|
168
|
|
|
*/ |
|
169
|
37 |
|
protected function registerFactories() |
|
170
|
|
|
{ |
|
171
|
|
|
$this->app->singleton('quota.factory.rate', function ($app) { |
|
|
|
|
|
|
172
|
1 |
|
return new RateFactory; |
|
173
|
37 |
|
}); |
|
174
|
|
|
|
|
175
|
|
|
$this->app->singleton('quota.factory.storage.file', function ($app) { |
|
|
|
|
|
|
176
|
1 |
|
return new FileStorageFactory; |
|
177
|
37 |
|
}); |
|
178
|
|
|
|
|
179
|
|
|
$this->app->singleton('quota.factory.tokenbucket', function ($app) { |
|
|
|
|
|
|
180
|
1 |
|
return new TokenBucketFactory; |
|
181
|
37 |
|
}); |
|
182
|
|
|
|
|
183
|
|
|
$this->app->singleton('quota.factory.blockingconsumer', function ($app) { |
|
|
|
|
|
|
184
|
1 |
|
return new BlockingConsumerFactory; |
|
185
|
37 |
|
}); |
|
186
|
|
|
|
|
187
|
37 |
|
$this->app->alias('quota.factory.rate', RateFactory::class); |
|
188
|
37 |
|
$this->app->alias('quota.factory.rate', FactoryInterface::class); |
|
189
|
|
|
|
|
190
|
37 |
|
$this->app->alias('quota.factory.storage.file', FileStorageFactory::class); |
|
191
|
37 |
|
$this->app->alias('quota.factory.storage.file', FactoryInterface::class); |
|
192
|
|
|
|
|
193
|
37 |
|
$this->app->alias('quota.factory.tokenbucket', TokenBucketFactory::class); |
|
194
|
37 |
|
$this->app->alias('quota.factory.tokenbucket', FactoryInterface::class); |
|
195
|
|
|
|
|
196
|
37 |
|
$this->app->alias('quota.factory.blockingconsumer', BlockingConsumerFactory::class); |
|
197
|
37 |
|
$this->app->alias('quota.factory.blockingconsumer', FactoryInterface::class); |
|
198
|
37 |
|
} |
|
199
|
|
|
|
|
200
|
|
|
/** |
|
201
|
|
|
* Register application classes. |
|
202
|
|
|
* |
|
203
|
|
|
* TODO: REFACTOR Binding with parameters is not |
|
204
|
|
|
* Best practice. |
|
205
|
|
|
* @See https://github.com/laravel/internals/issues/391 |
|
206
|
|
|
* |
|
207
|
|
|
* @return void |
|
208
|
|
|
*/ |
|
209
|
37 |
|
protected function registerClasses() |
|
210
|
|
|
{ |
|
211
|
|
|
$this->app->bind('quota.storage.file', function ($app, $params) { |
|
212
|
2 |
|
return new FileStorage($params['path']); |
|
213
|
37 |
|
}); |
|
214
|
|
|
|
|
215
|
|
|
$this->app->bind('quota.rate', function ($app, $params) { |
|
216
|
2 |
|
return new Rate($params['limit'], $params['period']); |
|
217
|
37 |
|
}); |
|
218
|
|
|
|
|
219
|
|
|
$this->app->bind('quota.bucket', function ($app, $params) { |
|
220
|
2 |
|
return new TokenBucket($params['capacity'], $params['rate'], $params['storage']); |
|
221
|
37 |
|
}); |
|
222
|
|
|
|
|
223
|
37 |
|
$this->app->bind('quota.blocker', function ($app, $params) { |
|
224
|
2 |
|
return new BlockingConsumer($params['bucket']); |
|
225
|
37 |
|
}); |
|
226
|
|
|
|
|
227
|
37 |
|
$this->app->alias('quota.storage.file', FileStorage::class); |
|
228
|
37 |
|
$this->app->alias('quota.storage.file', StorageInterface::class); |
|
229
|
|
|
|
|
230
|
37 |
|
$this->app->alias('quota.rate', Rate::class); |
|
231
|
|
|
|
|
232
|
37 |
|
$this->app->alias('quota.bucket', Tokenbucket::class); |
|
233
|
|
|
|
|
234
|
37 |
|
$this->app->alias('quota.blocker', BlockingConsumer::class); |
|
235
|
37 |
|
} |
|
236
|
|
|
|
|
237
|
|
|
/** |
|
238
|
|
|
* Get the services provided by this provider. |
|
239
|
|
|
* |
|
240
|
|
|
* @return string[] |
|
241
|
|
|
*/ |
|
242
|
1 |
|
public function provides() |
|
243
|
|
|
{ |
|
244
|
|
|
return [ |
|
245
|
1 |
|
'quota.factory.rate', |
|
246
|
1 |
|
'quota.factory.storage.file', |
|
247
|
1 |
|
'quota.factory.tokenbucket', |
|
248
|
1 |
|
'quota.factory.blockingconsumer', |
|
249
|
1 |
|
'quota.storage.file', |
|
250
|
1 |
|
'quota.rate', |
|
251
|
1 |
|
'quota.bucket', |
|
252
|
|
|
'quota.blocker' |
|
253
|
1 |
|
]; |
|
254
|
|
|
} |
|
255
|
|
|
} |
|
|
|
|
|
|
256
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.