Completed
Push — 1.x ( 81f0ab...1d5f69 )
by Cy
01:55
created

bootComponentDrivers()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 17
rs 9.4285
cc 3
eloc 7
nc 4
nop 0
1
<?php
2
3
namespace Monospice\LaravelRedisSentinel;
4
5
use Illuminate\Broadcasting\Broadcasters\RedisBroadcaster;
6
use Illuminate\Cache\RedisStore;
7
use Illuminate\Queue\Connectors\RedisConnector;
8
use Illuminate\Session\CacheBasedSessionHandler;
9
use Illuminate\Support\Arr;
10
use Illuminate\Support\ServiceProvider;
11
use Monospice\LaravelRedisSentinel\Configuration\Loader as ConfigurationLoader;
12
use Monospice\LaravelRedisSentinel\RedisSentinelDatabase;
13
14
/**
15
 * Registers the "redis-sentinel" driver as an available driver for Laravel's
16
 * cache, session, and queue services and loads the appropriate configuration.
17
 *
18
 * @category Package
19
 * @package  Monospice\LaravelRedisSentinel
20
 * @author   Cy Rossignol <[email protected]>
21
 * @license  See LICENSE file
22
 * @link     https://github.com/monospice/laravel-redis-sentinel-drivers
23
 */
24
class RedisSentinelServiceProvider extends ServiceProvider
25
{
26
    /**
27
     * Loads the package's configuration and provides configuration values.
28
     *
29
     * @var ConfigurationLoader
30
     */
31
    protected $config;
32
33
    /**
34
     * Boot the service by registering extensions with Laravel's cache, queue,
35
     * and session managers for the "redis-sentinel" driver.
36
     *
37
     * @return void
38
     */
39
    public function boot()
40
    {
41
        $this->bootComponentDrivers();
42
43
        // If we want Laravel's Redis API to use Sentinel, we'll remove the
44
        // "redis" service from the deferred services in the container:
45
        if ($this->config->shouldOverrideLaravelRedisApi()) {
46
            $this->removeDeferredRedisServices();
47
        }
48
    }
49
50
    /**
51
     * Bind the "redis-sentinel" database driver to the application service
52
     * container.
53
     *
54
     * @return void
55
     */
56
    public function register()
57
    {
58
        $this->config = ConfigurationLoader::load($this->app);
0 ignored issues
show
Documentation introduced by
$this->app is of type object<Illuminate\Contra...Foundation\Application>, but the function expects a object<Illuminate\Founda...avel\Lumen\Application>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
59
60
        $this->app->singleton('redis-sentinel', function ($app) {
61
            $config = $app->make('config')->get('database.redis-sentinel', [ ]);
62
63
            return new RedisSentinelDatabase($config);
64
        });
65
66
        // If we want Laravel's Redis API to use Sentinel, we'll return an
67
        // instance of the RedisSentinelDatabase when requesting the "redis"
68
        // service:
69
        if ($this->config->shouldOverrideLaravelRedisApi()) {
70
            $this->registerOverrides();
71
        }
72
    }
73
74
    /**
75
     * Replace the standard Laravel Redis service with the Redis Sentinel
76
     * database driver so all Redis operations use Sentinel connections.
77
     *
78
     * @return void
79
     */
80
    protected function registerOverrides()
81
    {
82
        $this->app->singleton('redis', function ($app) {
83
            return $app->make('redis-sentinel');
84
        });
85
    }
86
87
    /**
88
     * Extend each of the Laravel services this package supports with the
89
     * corresponding 'redis-sentinel' driver.
90
     *
91
     * @return void
92
     */
93
    protected function bootComponentDrivers()
94
    {
95
        $this->addRedisSentinelCacheDriver();
96
        $this->addRedisSentinelQueueConnector();
97
98
        // The Laravel broadcasting API exists in version 5.1 and later, so we
99
        // will only register the broadcaster if available:
100
        if ($this->config->supportsBroadcasting) {
101
            $this->addRedisSentinelBroadcaster();
102
        }
103
104
        // Since version 5.2, Lumen does not include support for sessions by
105
        // default, so we'll only register the session handler if enabled:
106
        if ($this->config->supportsSessions) {
107
            $this->addRedisSentinelSessionHandler();
108
        }
109
    }
110
111
    /**
112
     * Remove the standard Laravel Redis service from the bound deferred
113
     * services so they don't overwrite Redis Sentinel registrations.
114
     *
115
     * @return void
116
     */
117
    protected function removeDeferredRedisServices()
118
    {
119
        if ($this->config->isLumen) {
120
            unset($this->app->availableBindings['redis']);
121
122
            return;
123
        }
124
125
        $deferredServices = $this->app->getDeferredServices();
126
127
        unset($deferredServices['redis']);
128
129
        $this->app->setDeferredServices($deferredServices);
130
    }
131
132
    /**
133
     * Add "redis-sentinel" as an available broadcaster option to the Laravel
134
     * event broadcasting manager.
135
     *
136
     * @return void
137
     */
138
    protected function addRedisSentinelBroadcaster()
139
    {
140
        $broadcast = 'Illuminate\Contracts\Broadcasting\Factory';
141
142
        // Lumen 5.2 and below don't provide a hook that initializes the
143
        // broadcast component when attempting to resolve the BroadcastManager:
144
        if ($this->config->isLumen
145
            && ! array_key_exists($broadcast, $this->app->availableBindings)
0 ignored issues
show
Bug introduced by
Accessing availableBindings on the interface Illuminate\Contracts\Foundation\Application suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
146
        ) {
147
            $provider = 'Illuminate\Broadcasting\BroadcastServiceProvider';
148
            $this->app->register($provider);
149
        }
150
151
        $this->app->make($broadcast)
152
            ->extend('redis-sentinel', function ($app, $conf) {
153
                $redis = $app->make('redis-sentinel');
154
                $connection = Arr::get($conf, 'connection', 'default');
155
156
                return new RedisBroadcaster($redis, $connection);
157
            });
158
    }
159
160
    /**
161
     * Add "redis-sentinel" as an available driver option to the Laravel cache
162
     * manager.
163
     *
164
     * @return void
165
     */
166
    protected function addRedisSentinelCacheDriver()
167
    {
168
        $cache = $this->app->make('cache');
169
170
        $cache->extend('redis-sentinel', function ($app, $conf) use ($cache) {
171
            $redis = $app->make('redis-sentinel');
172
            $prefix = $app->make('config')->get('cache.prefix');
173
            $connection = Arr::get($conf, 'connection', 'default');
174
            $store = new RedisStore($redis, $prefix, $connection);
175
176
            return $cache->repository($store);
177
        });
178
    }
179
180
    /**
181
     * Add "redis-sentinel" as an available driver option to the Laravel
182
     * session manager.
183
     *
184
     * @return void
185
     */
186
    protected function addRedisSentinelSessionHandler()
187
    {
188
        $this->app->make('session')->extend('redis-sentinel', function ($app) {
189
            $config = $app->make('config');
190
            $cacheDriver = clone $app->make('cache')->driver('redis-sentinel');
191
            $minutes = $config->get('session.lifetime');
192
            $connection = $config->get('session.connection');
193
194
            $cacheDriver->getStore()->setConnection($connection);
195
196
            return new CacheBasedSessionHandler($cacheDriver, $minutes);
197
        });
198
    }
199
200
    /**
201
     * Add "redis-sentinel" as an available queue connection driver option to
202
     * the Laravel queue manager.
203
     *
204
     * @return void
205
     */
206
    protected function addRedisSentinelQueueConnector()
207
    {
208
        $this->app->make('queue')->extend('redis-sentinel', function () {
209
            $redis = $this->app->make('redis-sentinel');
210
211
            return new RedisConnector($redis);
212
        });
213
    }
214
}
215