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 classes like Application 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 Application, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 40 | class Application extends ApplicationTrait |
||
|
|
|||
| 41 | { |
||
| 42 | protected static $instance; |
||
| 43 | |||
| 44 | protected $initialized = false; |
||
| 45 | protected $initializedPlugin = false; |
||
| 46 | protected $testMode = false; |
||
| 47 | |||
| 48 | 998 | public static function getInstance(array $values = array()) |
|
| 56 | |||
| 57 | 933 | public static function clearInstance() |
|
| 61 | |||
| 62 | final public function __clone() |
||
| 66 | |||
| 67 | 946 | public function __construct(array $values = array()) |
|
| 81 | |||
| 82 | 946 | public function initConfig() |
|
| 164 | |||
| 165 | 946 | public function initLogger() |
|
| 172 | |||
| 173 | 936 | public function initialize() |
|
| 248 | |||
| 249 | 936 | public function initLocale() |
|
| 282 | |||
| 283 | 936 | public function initSession() |
|
| 298 | |||
| 299 | 936 | public function initRendering() |
|
| 300 | { |
||
| 301 | 936 | $this->register(new \Silex\Provider\TwigServiceProvider(), array( |
|
| 302 | 936 | 'twig.form.templates' => array('Form/form_layout.twig'), |
|
| 303 | )); |
||
| 304 | $this['twig'] = $this->share($this->extend('twig', function(\Twig_Environment $twig, \Silex\Application $app) { |
||
| 305 | 364 | $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app)); |
|
| 306 | 364 | $twig->addExtension(new \Twig_Extension_StringLoader()); |
|
| 307 | |||
| 308 | 364 | return $twig; |
|
| 309 | 936 | })); |
|
| 310 | |||
| 311 | $this->before(function(Request $request, \Silex\Application $app) { |
||
| 312 | // フロント or 管理画面ごとにtwigの探索パスを切り替える. |
||
| 313 | $app['twig'] = $app->share($app->extend('twig', function(\Twig_Environment $twig, \Silex\Application $app) { |
||
| 314 | 351 | $paths = array(); |
|
| 315 | |||
| 316 | // 互換性がないのでprofiler とproduction 時のcacheを分離する |
||
| 317 | |||
| 318 | 351 | $app['admin'] = false; |
|
| 319 | 351 | $app['front'] = false; |
|
| 320 | |||
| 321 | 351 | if (isset($app['profiler'])) { |
|
| 322 | $cacheBaseDir = __DIR__.'/../../app/cache/twig/profiler/'; |
||
| 323 | } else { |
||
| 324 | 351 | $cacheBaseDir = __DIR__.'/../../app/cache/twig/production/'; |
|
| 325 | } |
||
| 326 | 351 | $pathinfo = rawurldecode($app['request']->getPathInfo()); |
|
| 327 | 351 | if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) { |
|
| 328 | 187 | if (file_exists(__DIR__.'/../../app/template/admin')) { |
|
| 329 | 187 | $paths[] = __DIR__.'/../../app/template/admin'; |
|
| 330 | } |
||
| 331 | 187 | $paths[] = $app['config']['template_admin_realdir']; |
|
| 332 | 187 | $paths[] = __DIR__.'/../../app/Plugin'; |
|
| 333 | 187 | $cache = $cacheBaseDir.'admin'; |
|
| 334 | 187 | $app['admin'] = true; |
|
| 335 | } else { |
||
| 336 | 165 | if (file_exists($app['config']['template_realdir'])) { |
|
| 337 | 165 | $paths[] = $app['config']['template_realdir']; |
|
| 338 | } |
||
| 339 | 165 | $paths[] = $app['config']['template_default_realdir']; |
|
| 340 | 165 | $paths[] = __DIR__.'/../../app/Plugin'; |
|
| 341 | 165 | $cache = $cacheBaseDir.$app['config']['template_code']; |
|
| 342 | 165 | $app['front'] = true; |
|
| 343 | } |
||
| 344 | 351 | $twig->setCache($cache); |
|
| 345 | 351 | $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths)); |
|
| 346 | |||
| 347 | 351 | return $twig; |
|
| 348 | 353 | })); |
|
| 349 | |||
| 350 | // 管理画面のIP制限チェック. |
||
| 351 | 353 | $pathinfo = rawurldecode($app['request']->getPathInfo()); |
|
| 352 | 353 | if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) { |
|
| 353 | // IP制限チェック |
||
| 354 | 187 | $allowHost = $app['config']['admin_allow_host']; |
|
| 355 | 187 | if (count($allowHost) > 0) { |
|
| 356 | if (array_search($app['request']->getClientIp(), $allowHost) === false) { |
||
| 357 | throw new \Exception(); |
||
| 358 | } |
||
| 359 | } |
||
| 360 | } |
||
| 361 | 936 | }, self::EARLY_EVENT); |
|
| 362 | |||
| 363 | // twigのグローバル変数を定義. |
||
| 364 | 936 | $app = $this; |
|
| 365 | $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function(\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) { |
||
| 366 | // ショップ基本情報 |
||
| 367 | 351 | $BaseInfo = $app['eccube.repository.base_info']->get(); |
|
| 368 | 351 | $app['twig']->addGlobal('BaseInfo', $BaseInfo); |
|
| 369 | |||
| 370 | 351 | $pathinfo = rawurldecode($app['request']->getPathInfo()); |
|
| 371 | 351 | if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) { |
|
| 372 | // 管理画面 |
||
| 373 | // 管理画面メニュー |
||
| 374 | 187 | $menus = array('', '', ''); |
|
| 375 | 187 | $app['twig']->addGlobal('menus', $menus); |
|
| 376 | |||
| 377 | 187 | $Member = $app->user(); |
|
| 378 | 187 | if (is_object($Member)) { |
|
| 379 | // ログインしていれば管理者のロールを取得 |
||
| 380 | 181 | $AuthorityRoles = $app['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority())); |
|
| 381 | |||
| 382 | 181 | $roles = array(); |
|
| 383 | 181 | foreach ($AuthorityRoles as $AuthorityRole) { |
|
| 384 | // 管理画面でメニュー制御するため相対パス全てをセット |
||
| 385 | 181 | $roles[] = $app['request']->getBaseUrl().'/'.$app['config']['admin_route'].$AuthorityRole->getDenyUrl(); |
|
| 386 | } |
||
| 387 | |||
| 388 | 187 | $app['twig']->addGlobal('AuthorityRoles', $roles); |
|
| 389 | } |
||
| 390 | |||
| 391 | } else { |
||
| 392 | // フロント画面 |
||
| 393 | 165 | $request = $event->getRequest(); |
|
| 394 | 165 | $route = $request->attributes->get('_route'); |
|
| 395 | |||
| 396 | // ユーザ作成画面 |
||
| 397 | 165 | if ($route === trim($app['config']['user_data_route'])) { |
|
| 398 | 2 | $params = $request->attributes->get('_route_params'); |
|
| 399 | 2 | $route = $params['route']; |
|
| 400 | // プレビュー画面 |
||
| 401 | 163 | } elseif ($request->get('preview')) { |
|
| 402 | $route = 'preview'; |
||
| 403 | } |
||
| 404 | |||
| 405 | try { |
||
| 406 | 165 | $DeviceType = $app['eccube.repository.master.device_type'] |
|
| 407 | 165 | ->find(\Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC); |
|
| 408 | 165 | $PageLayout = $app['eccube.repository.page_layout']->getByUrl($DeviceType, $route); |
|
| 409 | 135 | } catch (\Doctrine\ORM\NoResultException $e) { |
|
| 410 | 135 | $PageLayout = $app['eccube.repository.page_layout']->newPageLayout($DeviceType); |
|
| 411 | } |
||
| 412 | |||
| 413 | 165 | $app['twig']->addGlobal('PageLayout', $PageLayout); |
|
| 414 | 165 | $app['twig']->addGlobal('title', $PageLayout->getName()); |
|
| 415 | } |
||
| 416 | 936 | }); |
|
| 417 | } |
||
| 418 | |||
| 419 | 936 | public function initMailer() |
|
| 448 | |||
| 449 | 936 | public function initDoctrine() |
|
| 507 | |||
| 508 | 936 | public function initSecurity() |
|
| 608 | |||
| 609 | 936 | public function initializePlugin() |
|
| 623 | |||
| 624 | 936 | public function initPluginEventDispatcher() |
|
| 625 | { |
||
| 626 | // EventDispatcher |
||
| 627 | $this['eccube.event.dispatcher'] = $this->share(function() { |
||
| 628 | 366 | return new EventDispatcher(); |
|
| 629 | 936 | }); |
|
| 630 | |||
| 631 | 936 | $app = $this; |
|
| 632 | |||
| 633 | // hook point |
||
| 634 | $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) { |
||
| 635 | 353 | if (!$event->isMasterRequest()) { |
|
| 636 | 98 | return; |
|
| 637 | } |
||
| 638 | 353 | $hookpoint = 'eccube.event.app.before'; |
|
| 639 | 353 | $app['eccube.event.dispatcher']->dispatch($hookpoint, $event); |
|
| 640 | 936 | }, self::EARLY_EVENT); |
|
| 641 | |||
| 642 | View Code Duplication | $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) { |
|
| 643 | 352 | if (!$event->isMasterRequest()) { |
|
| 644 | 98 | return; |
|
| 645 | } |
||
| 646 | 350 | $route = $event->getRequest()->attributes->get('_route'); |
|
| 647 | 350 | $hookpoint = "eccube.event.controller.$route.before"; |
|
| 648 | 350 | $app['eccube.event.dispatcher']->dispatch($hookpoint, $event); |
|
| 649 | 936 | }); |
|
| 650 | |||
| 651 | View Code Duplication | $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) { |
|
| 652 | 347 | if (!$event->isMasterRequest()) { |
|
| 653 | 98 | return; |
|
| 654 | } |
||
| 655 | 347 | $route = $event->getRequest()->attributes->get('_route'); |
|
| 656 | 347 | $hookpoint = "eccube.event.controller.$route.after"; |
|
| 657 | 347 | $app['eccube.event.dispatcher']->dispatch($hookpoint, $event); |
|
| 658 | 936 | }); |
|
| 659 | |||
| 660 | $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) { |
||
| 661 | 347 | if (!$event->isMasterRequest()) { |
|
| 662 | 98 | return; |
|
| 663 | } |
||
| 664 | 347 | $hookpoint = 'eccube.event.app.after'; |
|
| 665 | 347 | $app['eccube.event.dispatcher']->dispatch($hookpoint, $event); |
|
| 666 | 936 | }, self::LATE_EVENT); |
|
| 667 | |||
| 668 | $this->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($app) { |
||
| 669 | 347 | $route = $event->getRequest()->attributes->get('_route'); |
|
| 670 | 347 | $hookpoint = "eccube.event.controller.$route.finish"; |
|
| 671 | 347 | $app['eccube.event.dispatcher']->dispatch($hookpoint, $event); |
|
| 672 | 936 | }); |
|
| 673 | |||
| 674 | $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function(\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) { |
||
| 675 | 347 | $route = $event->getRequest()->attributes->get('_route'); |
|
| 676 | 347 | $app['eccube.event.dispatcher']->dispatch('eccube.event.render.'.$route.'.before', $event); |
|
| 677 | 936 | }); |
|
| 678 | |||
| 679 | // Request Event |
||
| 680 | View Code Duplication | $this->on(\Symfony\Component\HttpKernel\KernelEvents::REQUEST, function(\Symfony\Component\HttpKernel\Event\GetResponseEvent $event) use ($app) { |
|
| 681 | |||
| 682 | 352 | if (\Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { |
|
| 683 | 98 | return; |
|
| 684 | } |
||
| 685 | |||
| 686 | 352 | $route = $event->getRequest()->attributes->get('_route'); |
|
| 687 | |||
| 688 | 352 | if (is_null($route)) { |
|
| 689 | return; |
||
| 690 | } |
||
| 691 | |||
| 692 | 352 | $app['monolog']->debug('KernelEvents::REQUEST '.$route); |
|
| 693 | |||
| 694 | // 全体 |
||
| 695 | 352 | $app['eccube.event.dispatcher']->dispatch('eccube.event.app.request', $event); |
|
| 696 | |||
| 697 | 352 | if (strpos($route, 'admin') === 0) { |
|
| 698 | // 管理画面 |
||
| 699 | 187 | $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.request', $event); |
|
| 700 | } else { |
||
| 701 | // フロント画面 |
||
| 702 | 166 | $app['eccube.event.dispatcher']->dispatch('eccube.event.front.request', $event); |
|
| 703 | } |
||
| 704 | |||
| 705 | // ルーティング単位 |
||
| 706 | 352 | $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.request", $event); |
|
| 707 | |||
| 708 | 936 | }, 30); // Routing(32)が解決しし, 認証判定(8)が実行される前のタイミング. |
|
| 709 | |||
| 710 | // Controller Event |
||
| 711 | View Code Duplication | $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function(\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) { |
|
| 712 | |||
| 713 | 351 | if (\Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { |
|
| 714 | 98 | return; |
|
| 715 | } |
||
| 716 | |||
| 717 | |||
| 718 | 349 | $route = $event->getRequest()->attributes->get('_route'); |
|
| 719 | |||
| 720 | 349 | if (is_null($route)) { |
|
| 721 | return; |
||
| 722 | } |
||
| 723 | |||
| 724 | 349 | $app['monolog']->debug('KernelEvents::CONTROLLER '.$route); |
|
| 725 | |||
| 726 | // 全体 |
||
| 727 | 349 | $app['eccube.event.dispatcher']->dispatch('eccube.event.app.controller', $event); |
|
| 728 | |||
| 729 | 349 | if (strpos($route, 'admin') === 0) { |
|
| 730 | // 管理画面 |
||
| 731 | 185 | $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.controller', $event); |
|
| 732 | } else { |
||
| 733 | // フロント画面 |
||
| 734 | 165 | $app['eccube.event.dispatcher']->dispatch('eccube.event.front.controller', $event); |
|
| 735 | } |
||
| 736 | |||
| 737 | // ルーティング単位 |
||
| 738 | 349 | $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.controller", $event); |
|
| 739 | 936 | }); |
|
| 740 | |||
| 741 | // Response Event |
||
| 742 | View Code Duplication | $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function(\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) { |
|
| 743 | |||
| 744 | 347 | if (\Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { |
|
| 745 | 98 | return; |
|
| 746 | } |
||
| 747 | |||
| 748 | 347 | $route = $event->getRequest()->attributes->get('_route'); |
|
| 749 | |||
| 750 | 347 | if (is_null($route)) { |
|
| 751 | 1 | return; |
|
| 752 | } |
||
| 753 | |||
| 754 | 346 | $app['monolog']->debug('KernelEvents::RESPONSE '.$route); |
|
| 755 | |||
| 756 | // ルーティング単位 |
||
| 757 | 346 | $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.response", $event); |
|
| 758 | |||
| 759 | 346 | if (strpos($route, 'admin') === 0) { |
|
| 760 | // 管理画面 |
||
| 761 | 187 | $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.response', $event); |
|
| 762 | } else { |
||
| 763 | // フロント画面 |
||
| 764 | 160 | $app['eccube.event.dispatcher']->dispatch('eccube.event.front.response', $event); |
|
| 765 | } |
||
| 766 | |||
| 767 | // 全体 |
||
| 768 | 346 | $app['eccube.event.dispatcher']->dispatch('eccube.event.app.response', $event); |
|
| 769 | 936 | }); |
|
| 770 | |||
| 771 | // Exception Event |
||
| 772 | View Code Duplication | $this->on(\Symfony\Component\HttpKernel\KernelEvents::EXCEPTION, function(\Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event) use ($app) { |
|
| 773 | |||
| 774 | 12 | if (\Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { |
|
| 775 | return; |
||
| 776 | } |
||
| 777 | |||
| 778 | 12 | $route = $event->getRequest()->attributes->get('_route'); |
|
| 779 | |||
| 780 | 12 | if (is_null($route)) { |
|
| 781 | return; |
||
| 782 | } |
||
| 783 | |||
| 784 | 12 | $app['monolog']->debug('KernelEvents::EXCEPTION '.$route); |
|
| 785 | |||
| 786 | // ルーティング単位 |
||
| 787 | 12 | $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.exception", $event); |
|
| 788 | |||
| 789 | 12 | if (strpos($route, 'admin') === 0) { |
|
| 790 | // 管理画面 |
||
| 791 | 2 | $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.exception', $event); |
|
| 792 | } else { |
||
| 793 | // フロント画面 |
||
| 794 | 10 | $app['eccube.event.dispatcher']->dispatch('eccube.event.front.exception', $event); |
|
| 795 | } |
||
| 796 | |||
| 797 | // 全体 |
||
| 798 | 12 | $app['eccube.event.dispatcher']->dispatch('eccube.event.app.exception', $event); |
|
| 799 | 936 | }); |
|
| 800 | |||
| 801 | // Terminate Event |
||
| 802 | View Code Duplication | $this->on(\Symfony\Component\HttpKernel\KernelEvents::TERMINATE, function(\Symfony\Component\HttpKernel\Event\PostResponseEvent $event) use ($app) { |
|
| 803 | |||
| 804 | 347 | $route = $event->getRequest()->attributes->get('_route'); |
|
| 805 | |||
| 806 | 347 | if (is_null($route)) { |
|
| 807 | 1 | return; |
|
| 808 | } |
||
| 809 | |||
| 810 | 346 | $app['monolog']->debug('KernelEvents::TERMINATE '.$route); |
|
| 811 | |||
| 812 | // ルーティング単位 |
||
| 813 | 346 | $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.terminate", $event); |
|
| 814 | |||
| 815 | 346 | if (strpos($route, 'admin') === 0) { |
|
| 816 | // 管理画面 |
||
| 817 | 187 | $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.terminate', $event); |
|
| 818 | } else { |
||
| 819 | // フロント画面 |
||
| 820 | 160 | $app['eccube.event.dispatcher']->dispatch('eccube.event.front.terminate', $event); |
|
| 821 | } |
||
| 822 | |||
| 823 | // 全体 |
||
| 824 | 346 | $app['eccube.event.dispatcher']->dispatch('eccube.event.app.terminate', $event); |
|
| 825 | 936 | }); |
|
| 826 | } |
||
| 827 | |||
| 828 | 936 | public function loadPlugin() |
|
| 938 | |||
| 939 | /** |
||
| 940 | * PHPUnit を実行中かどうかを設定する. |
||
| 941 | * |
||
| 942 | * @param boolean $testMode PHPUnit を実行中の場合 true |
||
| 943 | */ |
||
| 944 | 923 | public function setTestMode($testMode) { |
|
| 947 | |||
| 948 | /** |
||
| 949 | * PHPUnit を実行中かどうか. |
||
| 950 | * |
||
| 951 | * @return boolean PHPUnit を実行中の場合 true |
||
| 952 | */ |
||
| 953 | 353 | public function isTestMode() |
|
| 957 | |||
| 958 | /** |
||
| 959 | * |
||
| 960 | * データベースの接続を確認 |
||
| 961 | * 成功 : trueを返却 |
||
| 962 | * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie() |
||
| 963 | * 備考 : app['debug']がtrueの際は処理を行わない |
||
| 964 | * @return boolean true |
||
| 965 | * |
||
| 966 | */ |
||
| 967 | 936 | protected function checkDatabaseConnection() |
|
| 990 | } |
||
| 991 |