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

ServiceContainer::storageDriverMongoDb()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 46
rs 9.1781
c 0
b 0
f 0
cc 2
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
    {
117
        $app['pdo'] = static function ($app) {
118
            if (!class_exists(PDO::class)) {
119
                throw new RuntimeException('Required extension ext-pdo is missing');
120
            }
121
122
            $driver = explode(':', $app['config']['pdo']['dsn'], 2)[0];
123
124
            // check the PDO driver is available
125
            if (!in_array($driver, PDO::getAvailableDrivers(), true)) {
126
                $drivers = implode(',', PDO::getAvailableDrivers()) ?: '(none)';
127
                throw new RuntimeException("Required PDO driver $driver is missing, Available drivers: $drivers");
128
            }
129
130
            $options = [
131
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
132
            ];
133
134
            if ($driver === 'mysql') {
135
                $options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET SQL_MODE=ANSI_QUOTES;';
136
            }
137
138
            return new PDO(
139
                $app['config']['pdo']['dsn'],
140
                $app['config']['pdo']['user'],
141
                $app['config']['pdo']['pass'],
142
                $options
143
            );
144
        };
145
146
        $app[PdoRepository::class] = static function ($app) {
147
            return new PdoRepository($app['pdo'], $app['config']['pdo']['table']);
148
        };
149
150
        $app['searcher.pdo'] = static function ($app) {
151
            return new PdoSearcher($app[PdoRepository::class]);
152
        };
153
154
        $app['saver.pdo'] = static function ($app) {
155
            return new Saver\PdoSaver($app[PdoRepository::class]);
156
        };
157
    }
158
159
    private function storageDriverMongoDb(Container $app)
160
    {
161
        // NOTE: db.host, db.options, db.driverOptions, db.db are @deprecated and will be removed in the future
162
        $app['mongodb.database'] = static function ($app) {
163
            $config = $app['config'];
164
165
            return $config['db.db'] ?? $mongodb['database'] ?? 'xhgui';
166
        };
167
168
        $app[MongoDB::class] = static function ($app) {
169
            $database = $app['mongodb.database'];
170
            /** @var MongoClient $client */
171
            $client = $app[MongoClient::class];
172
            $mongoDB = $client->selectDb($database);
173
            $mongoDB->results->findOne();
174
175
            return $mongoDB;
176
        };
177
178
        $app[MongoClient::class] = static function ($app) {
179
            if (!class_exists(Manager::class)) {
180
                throw new RuntimeException('Required extension ext-mongodb missing');
181
            }
182
183
            $config = $app['config'];
184
            $mongodb = $config['mongodb'] ?? [];
185
            $options = $config['db.options'] ?? $mongodb['options'] ?? [];
186
            $driverOptions = $config['db.driverOptions'] ?? $mongodb['driverOptions'] ?? [];
187
            $server = $config['db.host'] ?? sprintf('mongodb://%s:%s', $mongodb['hostname'], $mongodb['port']);
188
189
            return new MongoClient($server, $options, $driverOptions);
190
        };
191
192
        $app['searcher.mongodb'] = static function ($app) {
193
            return new MongoSearcher($app[MongoDB::class]);
194
        };
195
196
        $app['saver.mongodb'] = static function ($app) {
197
            /** @var MongoDB $mongoDB */
198
            $mongoDB = $app[MongoDB::class];
199
            /** @var MongoCollection $collection */
200
            $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...
201
202
            return new Saver\MongoSaver($collection);
203
        };
204
    }
205
206
    /**
207
     * Add controllers to the DI container.
208
     */
209
    protected function _controllers()
210
    {
211
        $this['watchController'] = $this->factory(static function ($c) {
212
            return new Controller\WatchController($c['app'], $c['searcher']);
213
        });
214
215
        $this['runController'] = $this->factory(static function ($c) {
216
            return new Controller\RunController($c['app'], $c['searcher']);
217
        });
218
219
        $this['customController'] = $this->factory(static function ($c) {
220
            return new Controller\CustomController($c['app'], $c['searcher']);
221
        });
222
223
        $this['waterfallController'] = $this->factory(static function ($c) {
224
            return new Controller\WaterfallController($c['app'], $c['searcher']);
225
        });
226
227
        $this['importController'] = $this->factory(static function ($c) {
228
            return new Controller\ImportController($c['app'], $c['saver'], $c['config']['upload.token']);
229
        });
230
231
        $this['metricsController'] = $this->factory(static function ($c) {
232
            return new Controller\MetricsController($c['app'], $c['searcher']);
233
        });
234
    }
235
}
236