Completed
Push — 2.x ( c1417c...43f5a4 )
by Cy
08:56
created

RedisSentinelServiceProvider::isLumenApplication()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Monospice\LaravelRedisSentinel;
4
5
use Illuminate\Cache\CacheManager;
6
use Illuminate\Cache\RedisStore;
7
use Illuminate\Queue\QueueManager;
8
use Illuminate\Queue\Connectors\RedisConnector;
9
use Illuminate\Session\CacheBasedSessionHandler;
10
use Illuminate\Session\SessionManager;
11
use Illuminate\Support\Arr;
12
use Illuminate\Support\ServiceProvider;
13
use Monospice\LaravelRedisSentinel\Configuration\Loader as ConfigurationLoader;
14
use Monospice\LaravelRedisSentinel\RedisSentinelManager;
15
use Monospice\LaravelRedisSentinel\Manager;
16
17
/**
18
 * Registers the "redis-sentinel" driver as an available driver for Laravel's
19
 * cache, session, and queue services and loads the appropriate configuration.
20
 *
21
 * @category Package
22
 * @package  Monospice\LaravelRedisSentinel
23
 * @author   Cy Rossignol <[email protected]>
24
 * @license  See LICENSE file
25
 * @link     https://github.com/monospice/laravel-redis-sentinel-drivers
26
 */
27
class RedisSentinelServiceProvider extends ServiceProvider
28
{
29
    /**
30
     * Loads the package's configuration and provides configuration values.
31
     *
32
     * @var ConfigurationLoader
33
     */
34
    protected $config;
35
36
    /**
37
     * Boot the service by registering extensions with Laravel's cache, queue,
38
     * and session managers for the "redis-sentinel" driver.
39
     *
40
     * @return void
41
     */
42
    public function boot()
43
    {
44
        $this->addRedisSentinelCacheDriver($this->app->make('cache'));
45
        $this->addRedisSentinelQueueConnector($this->app->make('queue'));
46
47
        // Since version 5.2, Lumen does not include support for sessions by
48
        // default, so we'll only register the session handler if enabled:
49
        if ($this->config->supportsSessions) {
50
            $this->addRedisSentinelSessionHandler($this->app->make('session'));
51
        }
52
53
        // If we want Laravel's Redis API to use Sentinel, we'll remove the
54
        // "redis" service from the deferred services in the container:
55
        if ($this->config->shouldOverrideLaravelRedisApi()) {
56
            $this->removeDeferredRedisServices();
57
        }
58
    }
59
60
    /**
61
     * Bind the "redis-sentinel" database driver to the application service
62
     * container.
63
     *
64
     * @return void
65
     */
66
    public function register()
67
    {
68
        $this->config = ConfigurationLoader::load($this->app);
69
70
        $this->app->singleton('redis-sentinel', function ($app) {
71
            $class = $this->getVersionedRedisSentinelManagerClass();
72
            $config = $app->make('config')->get('database.redis-sentinel', [ ]);
73
            $driver = Arr::pull($config, 'client', 'predis');
74
75
            return new RedisSentinelManager(new $class($driver, $config));
76
        });
77
78
        // If we want Laravel's Redis API to use Sentinel, we'll return an
79
        // instance of the RedisSentinelManager when requesting the "redis"
80
        // service:
81
        if ($this->config->shouldOverrideLaravelRedisApi()) {
82
            $this->registerOverrides();
83
        }
84
    }
85
86
    /**
87
     * Replace the standard Laravel Redis service with the Redis Sentinel
88
     * database driver so all Redis operations use Sentinel connections.
89
     *
90
     * @return void
91
     */
92
    protected function registerOverrides()
93
    {
94
        $this->app->singleton('redis', function ($app) {
95
            return $app->make('redis-sentinel');
96
        });
97
98
        $this->app->bind('redis.connection', function ($app) {
99
            return $app->make('redis-sentinel')->connection();
100
        });
101
    }
102
103
    /**
104
     * Remove the standard Laravel Redis service from the bound deferred
105
     * services so they don't overwrite Redis Sentinel registrations.
106
     *
107
     * @return void
0 ignored issues
show
Documentation introduced by
Should the return type not be false|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
108
     */
109
    protected function removeDeferredRedisServices()
110
    {
111
        if ($this->config->isLumen) {
112
            return false;
113
        }
114
115
        $deferredServices = $this->app->getDeferredServices();
116
117
        unset($deferredServices['redis']);
118
        unset($deferredServices['redis.connection']);
119
120
        $this->app->setDeferredServices($deferredServices);
121
    }
122
123
    /**
124
     * Add "redis-sentinel" as an available driver option to the Laravel cache
125
     * manager.
126
     *
127
     * @param CacheManager $cache The Laravel cache manager
128
     *
129
     * @return void
130
     */
131
    protected function addRedisSentinelCacheDriver(CacheManager $cache)
132
    {
133
        $cache->extend('redis-sentinel', function ($app, $conf) use ($cache) {
134
            $redis = $app->make('redis-sentinel')->getVersionedManager();
135
            $prefix = $app->make('config')->get('cache.prefix');
136
            $connection = Arr::get($conf, 'connection', 'default');
137
            $store = new RedisStore($redis, $prefix, $connection);
138
139
            return $cache->repository($store);
140
        });
141
    }
142
143
    /**
144
     * Add "redis-sentinel" as an available driver option to the Laravel
145
     * session manager.
146
     *
147
     * @param SessionManager $session The Laravel session manager
148
     *
149
     * @return void
150
     */
151
    protected function addRedisSentinelSessionHandler(SessionManager $session)
152
    {
153
        $session->extend('redis-sentinel', function ($app) {
154
            $config = $app->make('config');
155
            $cacheDriver = clone $app->make('cache')->driver('redis-sentinel');
156
            $minutes = $config->get('session.lifetime');
157
            $connection = $config->get('session.connection');
158
159
            $cacheDriver->getStore()->setConnection($connection);
160
161
            return new CacheBasedSessionHandler($cacheDriver, $minutes);
162
        });
163
    }
164
165
    /**
166
     * Add "redis-sentinel" as an available queue connection driver option to
167
     * the Laravel queue manager.
168
     *
169
     * @param QueueManager $queue The Laravel queue manager
170
     *
171
     * @return void
172
     */
173
    protected function addRedisSentinelQueueConnector(QueueManager $queue)
174
    {
175
        $queue->extend('redis-sentinel', function () {
176
            $redis = $this->app->make('redis-sentinel')->getVersionedManager();
177
178
            return new RedisConnector($redis);
179
        });
180
    }
181
182
    /**
183
     * Get the fully-qualified class name of the RedisSentinelManager class
184
     * for the current version of Laravel or Lumen.
185
     *
186
     * @return string The class name of the appropriate RedisSentinelManager
187
     * with its namespace
188
     */
189
    protected function getVersionedRedisSentinelManagerClass()
190
    {
191
        if ($this->config->isLumen) {
192
            $appVersion = substr($this->app->version(), 7, 3); // ex. "5.4"
193
            $frameworkVersion = '5.4';
194
        } else {
195
            $appVersion = \Illuminate\Foundation\Application::VERSION;
196
            $frameworkVersion = '5.4.20';
197
        }
198
199
        if (version_compare($appVersion, $frameworkVersion, 'lt')) {
200
            return Manager\Laravel540RedisSentinelManager::class;
201
        }
202
203
        return Manager\Laravel5420RedisSentinelManager::class;
204
    }
205
}
206