Completed
Pull Request — master (#382)
by Elan
01:20
created

ServiceContainer::storageDriverPdo()   B

Complexity

Conditions 5
Paths 1

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 42
rs 8.9368
c 0
b 0
f 0
cc 5
nc 1
nop 1
1
<?php
2
3
namespace XHGui;
4
5
use MongoClient;
6
use MongoCollection;
7
use MongoDB;
8
use MongoDB\Driver\Manager;
9
use PDO;
10
use Pimple\Container;
11
use RuntimeException;
12
use Slim\Middleware\SessionCookie;
13
use Slim\Slim as App;
14
use Slim\Views\Twig;
15
use XHGui\Db\PdoRepository;
16
use XHGui\Middleware\RenderMiddleware;
17
use XHGui\Saver\NormalizingSaver;
18
use XHGui\Searcher\MongoSearcher;
19
use XHGui\Searcher\PdoSearcher;
20
use XHGui\Twig\TwigExtension;
21
22
class ServiceContainer extends Container
23
{
24
    /** @var self */
25
    protected static $_instance;
26
27
    /**
28
     * @return self
29
     */
30
    public static function instance()
31
    {
32
        if (empty(static::$_instance)) {
33
            static::$_instance = new self();
34
        }
35
36
        return static::$_instance;
37
    }
38
39
    public function __construct()
40
    {
41
        parent::__construct();
42
        $this->_slimApp();
0 ignored issues
show
Unused Code introduced by
The call to the method XHGui\ServiceContainer::_slimApp() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
43
        $this->_services();
0 ignored issues
show
Unused Code introduced by
The call to the method XHGui\ServiceContainer::_services() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
44
        $this->storageDriverPdo($this);
0 ignored issues
show
Unused Code introduced by
The call to the method XHGui\ServiceContainer::storageDriverPdo() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
45
        $this->storageDriverMongoDb($this);
0 ignored issues
show
Unused Code introduced by
The call to the method XHGui\ServiceContainer::storageDriverMongoDb() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
46
        $this->_controllers();
47
    }
48
49
    // Create the Slim app.
50
    protected function _slimApp()
51
    {
52
        $this['view'] = static function ($c) {
53
            $cacheDir = $c['config']['cache'] ?? XHGUI_ROOT_DIR . '/cache';
54
55
            // Configure Twig view for slim
56
            $view = new Twig();
57
58
            $view->twigTemplateDirs = [dirname(__DIR__) . '/templates'];
59
            $view->parserOptions = [
60
                'charset' => 'utf-8',
61
                'cache' => $cacheDir,
62
                'auto_reload' => true,
63
                'strict_variables' => false,
64
                'autoescape' => true,
65
            ];
66
67
            return $view;
68
        };
69
70
        $this['app'] = static function ($c) {
71
            if ($c['config']['timezone']) {
72
                date_default_timezone_set($c['config']['timezone']);
73
            }
74
75
            $app = new App($c['config']);
76
77
            // Enable cookie based sessions
78
            $app->add(new SessionCookie([
79
                'httponly' => true,
80
            ]));
81
82
            // Add renderer.
83
            $app->add(new RenderMiddleware());
84
85
            $view = $c['view'];
86
            $view->parserExtensions = [
87
                new TwigExtension($app),
88
            ];
89
            $app->view($view);
90
91
            return $app;
92
        };
93
    }
94
95
    /**
96
     * Add common service objects to the container.
97
     */
98
    protected function _services()
99
    {
100
        $this['config'] = Config::all();
101
102
        $this['searcher'] = static function ($c) {
103
            $saver = $c['config']['save.handler'];
104
105
            return $c["searcher.$saver"];
106
        };
107
108
        $this['saver'] = static function ($c) {
109
            $saver = $c['config']['save.handler'];
110
111
            return new NormalizingSaver($c["saver.$saver"]);
112
        };
113
    }
114
115
    private function storageDriverPdo(Container $app) {
116
        $app['pdo'] = static function ($app) {
117
            if (!class_exists(PDO::class)) {
118
                throw new RuntimeException('Required extension ext-pdo is missing');
119
            }
120
121
            $driver = explode(':', $app['config']['pdo']['dsn'], 2)[0];
122
123
            // check the PDO driver is available
124
            if (!in_array($driver, PDO::getAvailableDrivers(), true)) {
125
                $drivers = implode(',', PDO::getAvailableDrivers()) ?: '(none)';
126
                throw new RuntimeException("Required PDO driver $driver is missing, Available drivers: $drivers");
127
            }
128
129
            $options = [
130
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
131
            ];
132
133
            if ($driver === 'mysql') {
134
                $options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET SQL_MODE=ANSI_QUOTES;';
135
            }
136
137
            return new PDO(
138
                $app['config']['pdo']['dsn'],
139
                $app['config']['pdo']['user'],
140
                $app['config']['pdo']['pass'],
141
                $options
142
            );
143
        };
144
145
        $app[PdoRepository::class] = static function ($app) {
146
            return new PdoRepository($app['pdo'], $app['config']['pdo']['table']);
147
        };
148
149
        $app['searcher.pdo'] = static function ($app) {
150
            return new PdoSearcher($app[PdoRepository::class]);
151
        };
152
153
        $app['saver.pdo'] = static function ($app) {
154
            return new Saver\PdoSaver($app[PdoRepository::class]);
155
        };
156
    }
157
158
    private function storageDriverMongoDb(Container $app)
159
    {
160
        // NOTE: db.host, db.options, db.driverOptions, db.db are @deprecated and will be removed in the future
161
        $app['mongodb.database'] = static function ($app) {
162
            $config = $app['config'];
163
164
            return $config['db.db'] ?? $mongodb['database'] ?? 'xhgui';
165
        };
166
167
        $app[MongoDB::class] = static function ($app) {
168
            $database = $app['mongodb.database'];
169
            /** @var MongoClient $client */
170
            $client = $app[MongoClient::class];
171
            $mongoDB = $client->selectDb($database);
172
            $mongoDB->results->findOne();
173
174
            return $mongoDB;
175
        };
176
177
        $app[MongoClient::class] = static function ($app) {
178
            if (!class_exists(Manager::class)) {
179
                throw new RuntimeException('Required extension ext-mongodb missing');
180
            }
181
182
            $config = $app['config'];
183
            $mongodb = $config['mongodb'] ?? [];
184
            $options = $config['db.options'] ?? $mongodb['options'] ?? [];
185
            $driverOptions = $config['db.driverOptions'] ?? $mongodb['driverOptions'] ?? [];
186
            $server = $config['db.host'] ?? sprintf('mongodb://%s:%s', $mongodb['hostname'], $mongodb['port']);
187
188
            return new MongoClient($server, $options, $driverOptions);
189
        };
190
191
        $app['searcher.mongodb'] = static function ($app) {
192
            return new MongoSearcher($app[MongoDB::class]);
193
        };
194
195
        $app['saver.mongodb'] = static function ($app) {
196
            /** @var MongoDB $mongoDB */
197
            $mongoDB = $app[MongoDB::class];
198
            /** @var MongoCollection $collection */
199
            $collection = $mongoDB->results;
0 ignored issues
show
Bug introduced by
The property results does not seem to exist in MongoDB.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
200
201
            return new Saver\MongoSaver($collection);
202
        };
203
    }
204
205
    /**
206
     * Add controllers to the DI container.
207
     */
208
    protected function _controllers()
209
    {
210
        $this['watchController'] = $this->factory(static function ($c) {
211
            return new Controller\WatchController($c['app'], $c['searcher']);
212
        });
213
214
        $this['runController'] = $this->factory(static function ($c) {
215
            return new Controller\RunController($c['app'], $c['searcher']);
216
        });
217
218
        $this['customController'] = $this->factory(static function ($c) {
219
            return new Controller\CustomController($c['app'], $c['searcher']);
220
        });
221
222
        $this['waterfallController'] = $this->factory(static function ($c) {
223
            return new Controller\WaterfallController($c['app'], $c['searcher']);
224
        });
225
226
        $this['importController'] = $this->factory(static function ($c) {
227
            return new Controller\ImportController($c['app'], $c['saver'], $c['config']['upload.token']);
228
        });
229
230
        $this['metricsController'] = $this->factory(static function ($c) {
231
            return new Controller\MetricsController($c['app'], $c['searcher']);
232
        });
233
    }
234
}
235