Completed
Push — integration-tests ( ccbef3...cd7ccc )
by Cy
07:46 queued 03:20
created

HorizonServiceProvider::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 2
1
<?php
2
3
namespace Monospice\LaravelRedisSentinel\Horizon;
4
5
use Illuminate\Contracts\Config\Repository as ConfigRepository;
6
use Illuminate\Contracts\Container\Container;
7
use Illuminate\Contracts\Redis\Factory as RedisFactory;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\ServiceProvider;
10
use Laravel\Horizon\Connectors\RedisConnector as HorizonRedisConnector;
11
use Monospice\LaravelRedisSentinel\Configuration\Loader as ConfigurationLoader;
12
use Monospice\LaravelRedisSentinel\Horizon\HorizonServiceBindings;
13
use Monospice\LaravelRedisSentinel\RedisSentinelManager;
14
use RuntimeException;
15
16
/**
17
 * Configures the application to use Redis Sentinel connections for Laravel
18
 * Horizon.
19
 *
20
 * @category Package
21
 * @package  Monospice\LaravelRedisSentinel
22
 * @author   Cy Rossignol <[email protected]>
23
 * @license  See LICENSE file
24
 * @link     https://github.com/monospice/laravel-redis-sentinel-drivers
25
 */
26
class HorizonServiceProvider extends ServiceProvider
27
{
28
    /**
29
     * Loads the package's configuration and provides configuration values.
30
     *
31
     * @var ConfigurationLoader
32
     */
33
    protected $config;
34
35
    /**
36
     * Create a new service provider instance.
37
     *
38
     * @param Container           $app    The current Laravel/Lumen application
39
     * instance.
40
     * @param ConfigurationLoader $config Loads the package's configuration and
0 ignored issues
show
Documentation introduced by
Should the type for parameter $config not be null|ConfigurationLoader?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
41
     * provides configuration values.
42
     */
43
    public function __construct(
44
        Container $app,
45
        ConfigurationLoader $config = null
46
    ) {
47
        parent::__construct($app);
0 ignored issues
show
Compatibility introduced by
$app of type object<Illuminate\Contracts\Container\Container> is not a sub-type of object<Illuminate\Contra...Foundation\Application>. It seems like you assume a child interface of the interface Illuminate\Contracts\Container\Container to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
48
49
        if ($config === null) {
50
            $config = ConfigurationLoader::load($app);
0 ignored issues
show
Documentation introduced by
$app is of type object<Illuminate\Contracts\Container\Container>, 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...
51
        }
52
53
        $this->config = $config;
54
    }
55
56
    /**
57
     * Configure the package for use with Laravel Horizon.
58
     *
59
     * @return void
60
     */
61
    public function register()
62
    {
63 View Code Duplication
        $this->app->singleton('redis-sentinel', function ($app) {
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
64
            $this->createHorizonConnectionConfiguration();
65
66
            $class = $this->config->getVersionedRedisSentinelManagerClass();
67
            $config = $this->config->get('database.redis-sentinel', [ ]);
68
            $driver = Arr::pull($config, 'client', 'predis');
69
70
            return new RedisSentinelManager(new $class($driver, $config));
71
        });
72
73
        if ($this->shouldRebindHorizonRedisFactory()) {
74
            $this->rebindHorizonRedisFactory();
75
        }
76
77
        $this->addHorizonSentinelQueueConnector();
78
    }
79
80
    /**
81
     * Sets the Horizon Redis Sentinel connection configuration.
82
     *
83
     * @return void
84
     */
85
    protected function createHorizonConnectionConfiguration()
86
    {
87
        $horizonConfig = $this->getSelectedConnectionConfiguration();
88
        $options = Arr::get($horizonConfig, 'options', [ ]);
89
        $options['prefix'] = $this->config->get('horizon.prefix', 'horizon:');
90
91
        $horizonConfig['options'] = $options;
92
93
        $this->config->set('database.redis-sentinel.horizon', $horizonConfig);
94
    }
95
96
    /**
97
     * Copy the Redis Sentinel connection configuration to use for Horizon
98
     * connections from the connection specified by "horizon.use".
99
     *
100
     * @return array The configuration matching the connection name specified
101
     * by the "horizon.use" config directive.
102
     *
103
     * @throws RuntimeException If no Redis Sentinel connection matches the
104
     * name declared by "horizon.use".
105
     */
106
    protected function getSelectedConnectionConfiguration()
107
    {
108
        $use = $this->config->get('horizon.use', 'default');
109
        $connectionConfig = $this->config->get("database.redis-sentinel.$use");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $use instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
110
111
        if ($connectionConfig === null) {
112
            throw new RuntimeException(
113
                "The Redis Sentinel connection [$use] is not defined."
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $use instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
114
            );
115
        }
116
117
        return $connectionConfig;
118
    }
119
120
    /**
121
     * Determine whether the package needs to override the Redis service
122
     * injected into Horizon classes with the Sentinel service.
123
     *
124
     * @return bool True if configured as such and the package doesn't already
125
     * override the application's Redis API.
126
     */
127
    protected function shouldRebindHorizonRedisFactory()
128
    {
129
        // If we're already overriding Laravel's standard Redis API, we don't
130
        // need to rebind the "redis" service for Horizon.
131
        return ! $this->config->shouldOverrideLaravelRedisApi
132
            && $this->config->get('horizon.driver') === 'redis-sentinel';
133
    }
134
135
    /**
136
     * Add contextual bindings for Horizon's services that inject the package's
137
     * Redis Sentinel manager.
138
     *
139
     * @return void
140
     */
141
    protected function rebindHorizonRedisFactory()
142
    {
143
        // Although not all of the classes that Horizon registers need an
144
        // instance of the Redis service, we'll set up contextual bindings
145
        // for any declared so we don't need to update this package in the
146
        // future every time Horizon adds or removes one:
147
        foreach ((new HorizonServiceBindings()) as $serviceClass) {
148
            $this->app->when($serviceClass)
149
                ->needs(RedisFactory::class)
150
                ->give(function () {
151
                    return $this->app->make('redis-sentinel.manager');
152
                });
153
        }
154
    }
155
156
    /**
157
     * Add "redis-sentinel" as an available queue connection driver option to
158
     * the Laravel queue manager using Horizon's modified Redis connector.
159
     *
160
     * @return void
161
     */
162 View Code Duplication
    protected function addHorizonSentinelQueueConnector()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
    {
164
        $this->app->make('queue')->extend('redis-sentinel', function () {
165
            $redis = $this->app->make('redis-sentinel.manager');
166
167
            return new HorizonRedisConnector($redis);
168
        });
169
    }
170
}
171