Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Broadcasting;
4
 
5
use Ably\AblyRest;
6
use Closure;
7
use GuzzleHttp\Client as GuzzleClient;
8
use Illuminate\Broadcasting\Broadcasters\AblyBroadcaster;
9
use Illuminate\Broadcasting\Broadcasters\LogBroadcaster;
10
use Illuminate\Broadcasting\Broadcasters\NullBroadcaster;
11
use Illuminate\Broadcasting\Broadcasters\PusherBroadcaster;
12
use Illuminate\Broadcasting\Broadcasters\RedisBroadcaster;
13
use Illuminate\Bus\UniqueLock;
14
use Illuminate\Contracts\Broadcasting\Factory as FactoryContract;
15
use Illuminate\Contracts\Broadcasting\ShouldBeUnique;
16
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
17
use Illuminate\Contracts\Bus\Dispatcher as BusDispatcherContract;
18
use Illuminate\Contracts\Cache\Repository as Cache;
19
use Illuminate\Contracts\Foundation\CachesRoutes;
20
use InvalidArgumentException;
21
use Psr\Log\LoggerInterface;
22
use Pusher\Pusher;
23
 
24
/**
25
 * @mixin \Illuminate\Contracts\Broadcasting\Broadcaster
26
 */
27
class BroadcastManager implements FactoryContract
28
{
29
    /**
30
     * The application instance.
31
     *
32
     * @var \Illuminate\Contracts\Container\Container
33
     */
34
    protected $app;
35
 
36
    /**
37
     * The array of resolved broadcast drivers.
38
     *
39
     * @var array
40
     */
41
    protected $drivers = [];
42
 
43
    /**
44
     * The registered custom driver creators.
45
     *
46
     * @var array
47
     */
48
    protected $customCreators = [];
49
 
50
    /**
51
     * Create a new manager instance.
52
     *
53
     * @param  \Illuminate\Contracts\Container\Container  $app
54
     * @return void
55
     */
56
    public function __construct($app)
57
    {
58
        $this->app = $app;
59
    }
60
 
61
    /**
62
     * Register the routes for handling broadcast channel authentication and sockets.
63
     *
64
     * @param  array|null  $attributes
65
     * @return void
66
     */
67
    public function routes(array $attributes = null)
68
    {
69
        if ($this->app instanceof CachesRoutes && $this->app->routesAreCached()) {
70
            return;
71
        }
72
 
73
        $attributes = $attributes ?: ['middleware' => ['web']];
74
 
75
        $this->app['router']->group($attributes, function ($router) {
76
            $router->match(
77
                ['get', 'post'], '/broadcasting/auth',
78
                '\\'.BroadcastController::class.'@authenticate'
79
            )->withoutMiddleware([\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class]);
80
        });
81
    }
82
 
83
    /**
84
     * Register the routes for handling broadcast user authentication.
85
     *
86
     * @param  array|null  $attributes
87
     * @return void
88
     */
89
    public function userRoutes(array $attributes = null)
90
    {
91
        if ($this->app instanceof CachesRoutes && $this->app->routesAreCached()) {
92
            return;
93
        }
94
 
95
        $attributes = $attributes ?: ['middleware' => ['web']];
96
 
97
        $this->app['router']->group($attributes, function ($router) {
98
            $router->match(
99
                ['get', 'post'], '/broadcasting/user-auth',
100
                '\\'.BroadcastController::class.'@authenticateUser'
101
            )->withoutMiddleware([\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class]);
102
        });
103
    }
104
 
105
    /**
106
     * Register the routes for handling broadcast authentication and sockets.
107
     *
108
     * Alias of "routes" method.
109
     *
110
     * @param  array|null  $attributes
111
     * @return void
112
     */
113
    public function channelRoutes(array $attributes = null)
114
    {
115
        return $this->routes($attributes);
116
    }
117
 
118
    /**
119
     * Get the socket ID for the given request.
120
     *
121
     * @param  \Illuminate\Http\Request|null  $request
122
     * @return string|null
123
     */
124
    public function socket($request = null)
125
    {
126
        if (! $request && ! $this->app->bound('request')) {
127
            return;
128
        }
129
 
130
        $request = $request ?: $this->app['request'];
131
 
132
        return $request->header('X-Socket-ID');
133
    }
134
 
135
    /**
136
     * Begin broadcasting an event.
137
     *
138
     * @param  mixed|null  $event
139
     * @return \Illuminate\Broadcasting\PendingBroadcast
140
     */
141
    public function event($event = null)
142
    {
143
        return new PendingBroadcast($this->app->make('events'), $event);
144
    }
145
 
146
    /**
147
     * Queue the given event for broadcast.
148
     *
149
     * @param  mixed  $event
150
     * @return void
151
     */
152
    public function queue($event)
153
    {
154
        if ($event instanceof ShouldBroadcastNow ||
155
            (is_object($event) &&
156
             method_exists($event, 'shouldBroadcastNow') &&
157
             $event->shouldBroadcastNow())) {
158
            return $this->app->make(BusDispatcherContract::class)->dispatchNow(new BroadcastEvent(clone $event));
159
        }
160
 
161
        $queue = null;
162
 
163
        if (method_exists($event, 'broadcastQueue')) {
164
            $queue = $event->broadcastQueue();
165
        } elseif (isset($event->broadcastQueue)) {
166
            $queue = $event->broadcastQueue;
167
        } elseif (isset($event->queue)) {
168
            $queue = $event->queue;
169
        }
170
 
171
        $broadcastEvent = new BroadcastEvent(clone $event);
172
 
173
        if ($event instanceof ShouldBeUnique) {
174
            $broadcastEvent = new UniqueBroadcastEvent(clone $event);
175
 
176
            if ($this->mustBeUniqueAndCannotAcquireLock($broadcastEvent)) {
177
                return;
178
            }
179
        }
180
 
181
        $this->app->make('queue')
182
            ->connection($event->connection ?? null)
183
            ->pushOn($queue, $broadcastEvent);
184
    }
185
 
186
    /**
187
     * Determine if the broadcastable event must be unique and determine if we can acquire the necessary lock.
188
     *
189
     * @param  mixed  $event
190
     * @return bool
191
     */
192
    protected function mustBeUniqueAndCannotAcquireLock($event)
193
    {
194
        return ! (new UniqueLock(
195
            method_exists($event, 'uniqueVia')
196
                ? $event->uniqueVia()
197
                : $this->app->make(Cache::class)
198
        ))->acquire($event);
199
    }
200
 
201
    /**
202
     * Get a driver instance.
203
     *
204
     * @param  string|null  $driver
205
     * @return mixed
206
     */
207
    public function connection($driver = null)
208
    {
209
        return $this->driver($driver);
210
    }
211
 
212
    /**
213
     * Get a driver instance.
214
     *
215
     * @param  string|null  $name
216
     * @return mixed
217
     */
218
    public function driver($name = null)
219
    {
220
        $name = $name ?: $this->getDefaultDriver();
221
 
222
        return $this->drivers[$name] = $this->get($name);
223
    }
224
 
225
    /**
226
     * Attempt to get the connection from the local cache.
227
     *
228
     * @param  string  $name
229
     * @return \Illuminate\Contracts\Broadcasting\Broadcaster
230
     */
231
    protected function get($name)
232
    {
233
        return $this->drivers[$name] ?? $this->resolve($name);
234
    }
235
 
236
    /**
237
     * Resolve the given broadcaster.
238
     *
239
     * @param  string  $name
240
     * @return \Illuminate\Contracts\Broadcasting\Broadcaster
241
     *
242
     * @throws \InvalidArgumentException
243
     */
244
    protected function resolve($name)
245
    {
246
        $config = $this->getConfig($name);
247
 
248
        if (is_null($config)) {
249
            throw new InvalidArgumentException("Broadcast connection [{$name}] is not defined.");
250
        }
251
 
252
        if (isset($this->customCreators[$config['driver']])) {
253
            return $this->callCustomCreator($config);
254
        }
255
 
256
        $driverMethod = 'create'.ucfirst($config['driver']).'Driver';
257
 
258
        if (! method_exists($this, $driverMethod)) {
259
            throw new InvalidArgumentException("Driver [{$config['driver']}] is not supported.");
260
        }
261
 
262
        return $this->{$driverMethod}($config);
263
    }
264
 
265
    /**
266
     * Call a custom driver creator.
267
     *
268
     * @param  array  $config
269
     * @return mixed
270
     */
271
    protected function callCustomCreator(array $config)
272
    {
273
        return $this->customCreators[$config['driver']]($this->app, $config);
274
    }
275
 
276
    /**
277
     * Create an instance of the driver.
278
     *
279
     * @param  array  $config
280
     * @return \Illuminate\Contracts\Broadcasting\Broadcaster
281
     */
282
    protected function createPusherDriver(array $config)
283
    {
284
        return new PusherBroadcaster($this->pusher($config));
285
    }
286
 
287
    /**
288
     * Get a Pusher instance for the given configuration.
289
     *
290
     * @param  array  $config
291
     * @return \Pusher\Pusher
292
     */
293
    public function pusher(array $config)
294
    {
295
        $pusher = new Pusher(
296
            $config['key'],
297
            $config['secret'],
298
            $config['app_id'],
299
            $config['options'] ?? [],
300
            isset($config['client_options']) && ! empty($config['client_options'])
301
                    ? new GuzzleClient($config['client_options'])
302
                    : null,
303
        );
304
 
305
        if ($config['log'] ?? false) {
306
            $pusher->setLogger($this->app->make(LoggerInterface::class));
307
        }
308
 
309
        return $pusher;
310
    }
311
 
312
    /**
313
     * Create an instance of the driver.
314
     *
315
     * @param  array  $config
316
     * @return \Illuminate\Contracts\Broadcasting\Broadcaster
317
     */
318
    protected function createAblyDriver(array $config)
319
    {
320
        return new AblyBroadcaster($this->ably($config));
321
    }
322
 
323
    /**
324
     * Get an Ably instance for the given configuration.
325
     *
326
     * @param  array  $config
327
     * @return \Ably\AblyRest
328
     */
329
    public function ably(array $config)
330
    {
331
        return new AblyRest($config);
332
    }
333
 
334
    /**
335
     * Create an instance of the driver.
336
     *
337
     * @param  array  $config
338
     * @return \Illuminate\Contracts\Broadcasting\Broadcaster
339
     */
340
    protected function createRedisDriver(array $config)
341
    {
342
        return new RedisBroadcaster(
343
            $this->app->make('redis'), $config['connection'] ?? null,
344
            $this->app['config']->get('database.redis.options.prefix', '')
345
        );
346
    }
347
 
348
    /**
349
     * Create an instance of the driver.
350
     *
351
     * @param  array  $config
352
     * @return \Illuminate\Contracts\Broadcasting\Broadcaster
353
     */
354
    protected function createLogDriver(array $config)
355
    {
356
        return new LogBroadcaster(
357
            $this->app->make(LoggerInterface::class)
358
        );
359
    }
360
 
361
    /**
362
     * Create an instance of the driver.
363
     *
364
     * @param  array  $config
365
     * @return \Illuminate\Contracts\Broadcasting\Broadcaster
366
     */
367
    protected function createNullDriver(array $config)
368
    {
369
        return new NullBroadcaster;
370
    }
371
 
372
    /**
373
     * Get the connection configuration.
374
     *
375
     * @param  string  $name
376
     * @return array
377
     */
378
    protected function getConfig($name)
379
    {
380
        if (! is_null($name) && $name !== 'null') {
381
            return $this->app['config']["broadcasting.connections.{$name}"];
382
        }
383
 
384
        return ['driver' => 'null'];
385
    }
386
 
387
    /**
388
     * Get the default driver name.
389
     *
390
     * @return string
391
     */
392
    public function getDefaultDriver()
393
    {
394
        return $this->app['config']['broadcasting.default'];
395
    }
396
 
397
    /**
398
     * Set the default driver name.
399
     *
400
     * @param  string  $name
401
     * @return void
402
     */
403
    public function setDefaultDriver($name)
404
    {
405
        $this->app['config']['broadcasting.default'] = $name;
406
    }
407
 
408
    /**
409
     * Disconnect the given disk and remove from local cache.
410
     *
411
     * @param  string|null  $name
412
     * @return void
413
     */
414
    public function purge($name = null)
415
    {
416
        $name ??= $this->getDefaultDriver();
417
 
418
        unset($this->drivers[$name]);
419
    }
420
 
421
    /**
422
     * Register a custom driver creator Closure.
423
     *
424
     * @param  string  $driver
425
     * @param  \Closure  $callback
426
     * @return $this
427
     */
428
    public function extend($driver, Closure $callback)
429
    {
430
        $this->customCreators[$driver] = $callback;
431
 
432
        return $this;
433
    }
434
 
435
    /**
436
     * Get the application instance used by the manager.
437
     *
438
     * @return \Illuminate\Contracts\Foundation\Application
439
     */
440
    public function getApplication()
441
    {
442
        return $this->app;
443
    }
444
 
445
    /**
446
     * Set the application instance used by the manager.
447
     *
448
     * @param  \Illuminate\Contracts\Foundation\Application  $app
449
     * @return $this
450
     */
451
    public function setApplication($app)
452
    {
453
        $this->app = $app;
454
 
455
        return $this;
456
    }
457
 
458
    /**
459
     * Forget all of the resolved driver instances.
460
     *
461
     * @return $this
462
     */
463
    public function forgetDrivers()
464
    {
465
        $this->drivers = [];
466
 
467
        return $this;
468
    }
469
 
470
    /**
471
     * Dynamically call the default driver instance.
472
     *
473
     * @param  string  $method
474
     * @param  array  $parameters
475
     * @return mixed
476
     */
477
    public function __call($method, $parameters)
478
    {
479
        return $this->driver()->$method(...$parameters);
480
    }
481
}