Failed Conditions
Pull Request — experimental/3.1 (#2521)
by Kiyotaka
34:19
created

EccubePluginServiceProvider   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 355
Duplicated Lines 45.92 %

Coupling/Cohesion

Components 0
Dependencies 13

Test Coverage

Coverage 72.46%

Importance

Changes 0
Metric Value
dl 163
loc 355
ccs 121
cts 167
cp 0.7246
rs 8.3396
c 0
b 0
f 0
wmc 44
lcom 0
cbo 13

4 Methods

Rating   Name   Duplication   Size   Complexity  
B register() 0 48 5
A boot() 0 5 1
D initPluginEventDispatcher() 151 196 20
D loadPlugin() 12 94 18

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EccubePluginServiceProvider often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EccubePluginServiceProvider, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
4
namespace Eccube\ServiceProvider;
5
6
use Eccube\Common\Constant;
7
use Eccube\Entity\Plugin;
8
use Eccube\Plugin\ConfigManager as PluginConfigManager;
9
use Eccube\Service\PluginService;
10
use Pimple\Container;
11
use Pimple\ServiceProviderInterface;
12
use Silex\Api\BootableProviderInterface;
13
use Silex\Application;
14
use Symfony\Component\EventDispatcher\EventDispatcher;
15
use Symfony\Component\Finder\Finder;
16
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
17
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
18
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
19
use Symfony\Component\HttpKernel\KernelEvents;
20
21
22
class EccubePluginServiceProvider implements ServiceProviderInterface, BootableProviderInterface
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
23
{
24
    /**
25
     * {@inheritDoc}
26
     */
27 1069
    public function register(Container $app)
28
    {
29
        // EventDispatcher
30
        $app['eccube.event.dispatcher'] = function () {
31 345
            return new EventDispatcher();
32
        };
33
34
        // プラグインディレクトリを探索.
35 1069
        $pluginConfigs = PluginConfigManager::getPluginConfigAll($app['debug']);
36
37 1069
        $enabledPlugins = $app['orm.em']->getRepository('Eccube\Entity\Plugin')->findAllEnabled();
38
39
        $app['eccube.routers.plugin'] = function ($app) use ($enabledPlugins) {
40
            $pluginDirs = array_map(function($plugin) use ($app) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
41
                return $app['config']['root_dir'].'/app/Plugin/'.$plugin->getCode();
42 1069
            }, $enabledPlugins);
43
44 1069
            $routers = [];
45
46 1069
            if ((empty($pluginDirs)) === false) {
47
                $dirs = Finder::create()
48
                    ->in($pluginDirs)
49
                    ->name('Controller')
50
                    ->directories();
51
52
                foreach ($dirs as $dir) {
53
                    $realPath = $dir->getRealPath();
54
                    $pluginCode = basename(dirname($realPath));
55
                    $routers[] = $app['eccube.router']($realPath, 'Plugin'.$pluginCode);
56
                }
57
            }
58
59 1069
            return $routers;
60
        };
61
62 1069
        foreach ($pluginConfigs as $code => $pluginConfig) {
63 1069
            $config = $pluginConfig['config'];
64
65 1069
            if (isset($config['const'])) {
66
                $app->extend('config', function ($eccubeConfig) use ($config) {
67
                    $eccubeConfig[$config['code']] = array(
68
                        'const' => $config['const'],
69
                    );
70
                    return $eccubeConfig;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
71 1069
                });
72
            }
73
        }
74
    }
75
76
    /**
77
     * {@inheritDoc}
78
     */
79 1069
    public function boot(Application $app)
80
    {
81 1069
        $this->initPluginEventDispatcher($app);
82 1069
        $this->loadPlugin($app);
83
    }
84
85 1069
    public function initPluginEventDispatcher(Application $app)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
86
    {
87
        // hook point
88
        $app->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
89 314
            if (!$event->isMasterRequest()) {
90 58
                return;
91
            }
92 314
            $hookpoint = 'eccube.event.app.before';
93 314
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
94 1069
        }, Application::EARLY_EVENT);
95
96 View Code Duplication
        $app->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
97 314
            if (!$event->isMasterRequest()) {
98 58
                return;
99
            }
100 313
            $route = $event->getRequest()->attributes->get('_route');
101 313
            $hookpoint = "eccube.event.controller.$route.before";
102 313
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
103 1069
        });
104
105 View Code Duplication
        $app->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
106 295
            if (!$event->isMasterRequest()) {
107 58
                return;
108
            }
109 295
            $route = $event->getRequest()->attributes->get('_route');
110 295
            $hookpoint = "eccube.event.controller.$route.after";
111 295
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
112 1069
        });
113
114
        $app->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
115 295
            if (!$event->isMasterRequest()) {
116 58
                return;
117
            }
118 295
            $hookpoint = 'eccube.event.app.after';
119 295
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
120 1069
        }, Application::LATE_EVENT);
121
122
        $app->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($app) {
123 295
            $route = $event->getRequest()->attributes->get('_route');
124 295
            $hookpoint = "eccube.event.controller.$route.finish";
125 295
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
126 1069
        });
127
128
        $app->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
129 295
            if (!$event->isMasterRequest()) {
130 58
                return;
131
            }
132 295
            $route = $event->getRequest()->attributes->get('_route');
133 295
            $app['eccube.event.dispatcher']->dispatch('eccube.event.render.'.$route.'.before', $event);
134 1069
        });
135
136
        // Request Event
137 View Code Duplication
        $app->on(\Symfony\Component\HttpKernel\KernelEvents::REQUEST, function (\Symfony\Component\HttpKernel\Event\GetResponseEvent $event) use ($app) {
138
139 314
            if (!$event->isMasterRequest()) {
140 58
                return;
141
            }
142
143 314
            $route = $event->getRequest()->attributes->get('_route');
144
145 314
            if (is_null($route)) {
146
                return;
147
            }
148
149 314
            $app['monolog']->debug('KernelEvents::REQUEST '.$route);
150
151
            // 全体
152 314
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.request', $event);
153
154 314
            if (strpos($route, 'admin') === 0) {
155
                // 管理画面
156 218
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.request', $event);
157
            } else {
158
                // フロント画面
159 96
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.request', $event);
160
            }
161
162
            // ルーティング単位
163 314
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.request", $event);
164
165 1069
        }, 30); // Routing(32)が解決し, 認証判定(8)が実行される前のタイミング.
166
167
        // Controller Event
168 View Code Duplication
        $app->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
169
170 304
            if (!$event->isMasterRequest()) {
171 58
                return;
172
            }
173
174 303
            $route = $event->getRequest()->attributes->get('_route');
175
176 303
            if (is_null($route)) {
177
                return;
178
            }
179
180 303
            $app['monolog']->debug('KernelEvents::CONTROLLER '.$route);
181
182
            // 全体
183 303
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.controller', $event);
184
185 303
            if (strpos($route, 'admin') === 0) {
186
                // 管理画面
187 209
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.controller', $event);
188
            } else {
189
                // フロント画面
190 94
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.controller', $event);
191
            }
192
            // ルーティング単位
193 303
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.controller", $event);
194 1069
        });
195
196
        // Response Event
197 View Code Duplication
        $app->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
198 295
            if (!$event->isMasterRequest()) {
199 58
                return;
200
            }
201
202 295
            $route = $event->getRequest()->attributes->get('_route');
203
204 295
            if (is_null($route)) {
205
                return;
206
            }
207
208 295
            $app['monolog']->debug('KernelEvents::RESPONSE '.$route);
209
210
            // ルーティング単位
211 295
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.response", $event);
212
213 295
            if (strpos($route, 'admin') === 0) {
214
                // 管理画面
215 208
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.response', $event);
216
            } else {
217
                // フロント画面
218 87
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.response', $event);
219
            }
220
221
            // 全体
222 295
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.response', $event);
223 1069
        });
224
225
        // Exception Event
226 View Code Duplication
        $app->on(\Symfony\Component\HttpKernel\KernelEvents::EXCEPTION, function (\Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event) use ($app) {
227
228 23
            if (!$event->isMasterRequest()) {
229
                return;
230
            }
231
232 23
            $route = $event->getRequest()->attributes->get('_route');
233
234 23
            if (is_null($route)) {
235
                return;
236
            }
237
238 23
            $app['monolog']->debug('KernelEvents::EXCEPTION '.$route);
239
240
            // ルーティング単位
241 23
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.exception", $event);
242
243 23
            if (strpos($route, 'admin') === 0) {
244
                // 管理画面
245 10
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.exception', $event);
246
            } else {
247
                // フロント画面
248 13
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.exception', $event);
249
            }
250
251
            // 全体
252 23
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.exception', $event);
253 1069
        });
254
255
        // Terminate Event
256 1069 View Code Duplication
        $app->on(\Symfony\Component\HttpKernel\KernelEvents::TERMINATE, function (\Symfony\Component\HttpKernel\Event\PostResponseEvent $event) use ($app) {
257
258 295
            $route = $event->getRequest()->attributes->get('_route');
259
260 295
            if (is_null($route)) {
261
                return;
262
            }
263
264 295
            $app['monolog']->debug('KernelEvents::TERMINATE '.$route);
265
266
            // ルーティング単位
267 295
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.terminate", $event);
268
269 295
            if (strpos($route, 'admin') === 0) {
270
                // 管理画面
271 208
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.terminate', $event);
272
            } else {
273
                // フロント画面
274 87
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.terminate', $event);
275
            }
276
277
            // 全体
278 295
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.terminate', $event);
279 1069
        });
280
    }
281
282 1069
    public function loadPlugin(Application $app)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
283
    {
284
        // ハンドラ優先順位をdbから持ってきてハッシュテーブルを作成
285 1069
        $priorities = array();
286 1069
        $pluginConfigs = PluginConfigManager::getPluginConfigAll($app['debug']);
287
288 1069
        $handlers = $app['orm.em']
289 1069
            ->getRepository('Eccube\Entity\PluginEventHandler')
290 1069
            ->getHandlers();
291
292 1069
        foreach ($handlers as $handler) {
293
            if ($handler->getPlugin()->getEnable()) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
294
295
                $priority = $handler->getPriority();
296
            } else {
297
                // Pluginがdisable、削除済みの場合、EventHandlerのPriorityを全て0とみなす
298
                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED;
299
            }
300
            $priorities[$handler->getPlugin()->getClassName()][$handler->getEvent()][$handler->getHandler()] = $priority;
301
        }
302
303
        // プラグインをロードする.
304
        // config.yml/event.ymlの定義に沿ってインスタンスの生成を行い, イベント設定を行う.
305 1069
        foreach ($pluginConfigs as $code => $pluginConfig) {
306
            // 正しい形式の pluginConfig のみ読み込む
307 1069
            $path = PluginConfigManager::getPluginRealDir().'/'.$code;
308
            try {
309 1069
                $app[PluginService::class]->checkPluginArchiveContent($path, $pluginConfig['config']);
310
            } catch (\Eccube\Exception\PluginException $e) {
311
                $app['monolog']->warning("Configuration file config.yml for plugin {$code} not found or is invalid. Skipping loading.", array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
312
                    'path' => $path,
313
                    'original-message' => $e->getMessage()
314
                ));
315
                continue;
316
            }
317 1069
            $config = $pluginConfig['config'];
318
319 1069
            $plugin = $app['orm.em']
320 1069
                ->getRepository('Eccube\Entity\Plugin')
321 1069
                ->findOneBy(array('code' => $config['code']));
322
323
            // const
324 1069
            if ($plugin && $plugin->getEnable() == Constant::DISABLED) {
325
                // プラグインが無効化されていれば読み込まない
326
                continue;
327
            }
328
329
            // Type: Event
330 1069
            if (isset($config['event'])) {
331
                $class = '\\Plugin\\'.$config['code'].'\\'.$config['event'];
332
                $eventExists = true;
333
334 View Code Duplication
                if (!class_exists($class)) {
335
                    $app['monolog']->warning("Event class for plugin {$code} not exists.", array(
336
                        'class' => $class,
337
                    ));
338
                    $eventExists = false;
339
                }
340
341
                if ($eventExists && isset($config['event'])) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
342
343
                    $subscriber = new $class($app);
344
345
                    foreach ($pluginConfig['event'] as $event => $handlers) {
346
                        foreach ($handlers as $handler) {
347
                            if (!isset($priorities[$config['event']][$event][$handler[0]])) { // ハンドラテーブルに登録されていない(ソースにしか記述されていない)ハンドラは一番後ろにする
348
                                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_LATEST;
349
                            } else {
350
                                $priority = $priorities[$config['event']][$event][$handler[0]];
351
                            }
352
                            // 優先度が0のプラグインは登録しない
353
                            if (\Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED != $priority) {
354
                                $app['eccube.event.dispatcher']->addListener($event, array($subscriber, $handler[0]), $priority);
355
                            }
356
                        }
357
                    }
358
                }
359
            }
360
361
            // Type: ServiceProvider
362 1069
            if (isset($config['service'])) {
363 1069
                foreach ($config['service'] as $service) {
364 1069
                    $class = '\\Plugin\\'.$config['code'].'\\ServiceProvider\\'.$service;
365 1069 View Code Duplication
                    if (!class_exists($class)) {
366
                        $app['monolog']->warning("Service provider class for plugin {$code} not exists.", array(
367
                            'class' => $class,
368
                        ));
369
                        continue;
370
                    }
371 1069
                    $app->register(new $class($this));
372
                }
373
            }
374
        }
375
    }
376
}
377