src/Eccube/Kernel.php line 140

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of EC-CUBE
  4. *
  5. * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6. *
  7. * http://www.ec-cube.co.jp/
  8. *
  9. * For the full copyright and license information, please view the LICENSE
  10. * file that was distributed with this source code.
  11. */
  12. namespace Eccube;
  13. use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass;
  14. use Eccube\Common\EccubeNav;
  15. use Eccube\Common\EccubeTwigBlock;
  16. use Eccube\DependencyInjection\Compiler\AutoConfigurationTagPass;
  17. use Eccube\DependencyInjection\Compiler\NavCompilerPass;
  18. use Eccube\DependencyInjection\Compiler\PaymentMethodPass;
  19. use Eccube\DependencyInjection\Compiler\PluginPass;
  20. use Eccube\DependencyInjection\Compiler\PurchaseFlowPass;
  21. use Eccube\DependencyInjection\Compiler\QueryCustomizerPass;
  22. use Eccube\DependencyInjection\Compiler\TwigBlockPass;
  23. use Eccube\DependencyInjection\Compiler\TwigExtensionPass;
  24. use Eccube\DependencyInjection\Compiler\WebServerDocumentRootPass;
  25. use Eccube\DependencyInjection\EccubeExtension;
  26. use Eccube\DependencyInjection\Facade\AnnotationReaderFacade;
  27. use Eccube\DependencyInjection\Facade\LoggerFacade;
  28. use Eccube\DependencyInjection\Facade\TranslatorFacade;
  29. use Eccube\Doctrine\DBAL\Types\UTCDateTimeType;
  30. use Eccube\Doctrine\DBAL\Types\UTCDateTimeTzType;
  31. use Eccube\Doctrine\ORM\Mapping\Driver\AnnotationDriver;
  32. use Eccube\Doctrine\Query\QueryCustomizer;
  33. use Eccube\Service\Payment\PaymentMethodInterface;
  34. use Eccube\Service\PurchaseFlow\DiscountProcessor;
  35. use Eccube\Service\PurchaseFlow\ItemHolderPostValidator;
  36. use Eccube\Service\PurchaseFlow\ItemHolderPreprocessor;
  37. use Eccube\Service\PurchaseFlow\ItemHolderValidator;
  38. use Eccube\Service\PurchaseFlow\ItemPreprocessor;
  39. use Eccube\Service\PurchaseFlow\ItemValidator;
  40. use Eccube\Service\PurchaseFlow\PurchaseProcessor;
  41. use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
  42. use Symfony\Component\Config\Loader\LoaderInterface;
  43. use Symfony\Component\DependencyInjection\Compiler\PassConfig;
  44. use Symfony\Component\DependencyInjection\ContainerBuilder;
  45. use Symfony\Component\DependencyInjection\Definition;
  46. use Symfony\Component\DependencyInjection\Reference;
  47. use Symfony\Component\Finder\Finder;
  48. use Symfony\Component\HttpKernel\Kernel as BaseKernel;
  49. use Symfony\Component\Routing\RouteCollectionBuilder;
  50. class Kernel extends BaseKernel
  51. {
  52. use MicroKernelTrait;
  53. public const CONFIG_EXTS = '.{php,xml,yaml,yml}';
  54. public function __construct(string $environment, bool $debug)
  55. {
  56. parent::__construct($environment, $debug);
  57. $this->loadEntityProxies();
  58. }
  59. public function getCacheDir()
  60. {
  61. return $this->getProjectDir().'/var/cache/'.$this->environment;
  62. }
  63. public function getLogDir()
  64. {
  65. return $this->getProjectDir().'/var/log';
  66. }
  67. public function registerBundles()
  68. {
  69. $contents = require $this->getProjectDir().'/app/config/eccube/bundles.php';
  70. foreach ($contents as $class => $envs) {
  71. if (isset($envs['all']) || isset($envs[$this->environment])) {
  72. yield new $class();
  73. }
  74. }
  75. $pluginDir = $this->getProjectDir().'/app/Plugin';
  76. $finder = (new Finder())
  77. ->in($pluginDir)
  78. ->sortByName()
  79. ->depth(0)
  80. ->directories();
  81. $plugins = array_map(function ($dir) {
  82. return $dir->getBaseName();
  83. }, iterator_to_array($finder));
  84. foreach ($plugins as $code) {
  85. $pluginBundles = $pluginDir.'/'.$code.'/Resource/config/bundles.php';
  86. if (file_exists($pluginBundles)) {
  87. $contents = require $pluginBundles;
  88. foreach ($contents as $class => $envs) {
  89. if (isset($envs['all']) || isset($envs[$this->environment])) {
  90. yield new $class();
  91. }
  92. }
  93. }
  94. }
  95. }
  96. /**
  97. * {@inheritdoc}
  98. *
  99. * @see \Symfony\Component\HttpKernel\Kernel::boot()
  100. */
  101. public function boot()
  102. {
  103. // Symfonyがsrc/Eccube/Entity以下を読み込む前にapp/proxy/entity以下をロードする
  104. // $this->loadEntityProxies();
  105. parent::boot();
  106. $container = $this->getContainer();
  107. // DateTime/DateTimeTzのタイムゾーンを設定.
  108. $timezone = $container->getParameter('timezone');
  109. UTCDateTimeType::setTimeZone($timezone);
  110. UTCDateTimeTzType::setTimeZone($timezone);
  111. date_default_timezone_set($timezone);
  112. $Logger = $container->get('eccube.logger');
  113. if ($Logger !== null && $Logger instanceof \Eccube\Log\Logger) {
  114. LoggerFacade::init($container, $Logger);
  115. }
  116. $Translator = $container->get('translator');
  117. if ($Translator !== null && $Translator instanceof \Symfony\Contracts\Translation\TranslatorInterface) {
  118. TranslatorFacade::init($Translator);
  119. }
  120. /** @var AnnotationReaderFacade $AnnotationReaderFacade */
  121. $AnnotationReaderFacade = $container->get(AnnotationReaderFacade::class);
  122. $AnnotationReader = $AnnotationReaderFacade->getAnnotationReader();
  123. if ($AnnotationReader !== null && $AnnotationReader instanceof \Doctrine\Common\Annotations\Reader) {
  124. AnnotationReaderFacade::init($AnnotationReader);
  125. }
  126. }
  127. protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
  128. {
  129. $confDir = $this->getProjectDir().'/app/config/eccube';
  130. $loader->load($confDir.'/services'.self::CONFIG_EXTS, 'glob');
  131. $loader->load($confDir.'/packages/*'.self::CONFIG_EXTS, 'glob');
  132. if (is_dir($confDir.'/packages/'.$this->environment)) {
  133. $loader->load($confDir.'/packages/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
  134. }
  135. $loader->load($confDir.'/services_'.$this->environment.self::CONFIG_EXTS, 'glob');
  136. // プラグインのservices.phpをロードする.
  137. $dir = dirname(__DIR__).'/../app/Plugin/*/Resource/config';
  138. $loader->load($dir.'/services'.self::CONFIG_EXTS, 'glob');
  139. $loader->load($dir.'/services_'.$this->environment.self::CONFIG_EXTS, 'glob');
  140. // カスタマイズディレクトリのservices.phpをロードする.
  141. $dir = dirname(__DIR__).'/../app/Customize/Resource/config';
  142. $loader->load($dir.'/services'.self::CONFIG_EXTS, 'glob');
  143. $loader->load($dir.'/services_'.$this->environment.self::CONFIG_EXTS, 'glob');
  144. }
  145. protected function configureRoutes(RouteCollectionBuilder $routes)
  146. {
  147. $container = $this->getContainer();
  148. $scheme = ['https', 'http'];
  149. $forceSSL = $container->getParameter('eccube_force_ssl');
  150. if ($forceSSL) {
  151. $scheme = 'https';
  152. }
  153. $routes->setSchemes($scheme);
  154. $confDir = $this->getProjectDir().'/app/config/eccube';
  155. if (is_dir($confDir.'/routes/')) {
  156. $builder = $routes->import($confDir.'/routes/*'.self::CONFIG_EXTS, '/', 'glob');
  157. $builder->setSchemes($scheme);
  158. }
  159. if (is_dir($confDir.'/routes/'.$this->environment)) {
  160. $builder = $routes->import($confDir.'/routes/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
  161. $builder->setSchemes($scheme);
  162. }
  163. $builder = $routes->import($confDir.'/routes'.self::CONFIG_EXTS, '/', 'glob');
  164. $builder->setSchemes($scheme);
  165. $builder = $routes->import($confDir.'/routes_'.$this->environment.self::CONFIG_EXTS, '/', 'glob');
  166. $builder->setSchemes($scheme);
  167. // 有効なプラグインのルーティングをインポートする.
  168. $plugins = $container->getParameter('eccube.plugins.enabled');
  169. $pluginDir = $this->getProjectDir().'/app/Plugin';
  170. foreach ($plugins as $plugin) {
  171. $dir = $pluginDir.'/'.$plugin.'/Controller';
  172. if (file_exists($dir)) {
  173. $builder = $routes->import($dir, '/', 'annotation');
  174. $builder->setSchemes($scheme);
  175. }
  176. if (file_exists($pluginDir.'/'.$plugin.'/Resource/config')) {
  177. $builder = $routes->import($pluginDir.'/'.$plugin.'/Resource/config/routes'.self::CONFIG_EXTS, '/', 'glob');
  178. $builder->setSchemes($scheme);
  179. }
  180. }
  181. }
  182. protected function build(ContainerBuilder $container)
  183. {
  184. $this->addEntityExtensionPass($container);
  185. $container->registerExtension(new EccubeExtension());
  186. // サービスタグの自動設定を行う
  187. $container->addCompilerPass(new AutoConfigurationTagPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 11);
  188. // サービスタグの収集より先に実行し, 付与されているタグをクリアする.
  189. // FormPassは優先度0で実行されているので, それより速いタイミングで実行させる.
  190. // 自動登録されるタグやコンパイラパスの登録タイミングは, FrameworkExtension::load(), FrameworkBundle::build()を参考に.
  191. $container->addCompilerPass(new PluginPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 10);
  192. // DocumentRootをルーティディレクトリに設定する.
  193. $container->addCompilerPass(new WebServerDocumentRootPass('%kernel.project_dir%/'));
  194. // twigのurl,path関数を差し替え
  195. $container->addCompilerPass(new TwigExtensionPass());
  196. // クエリカスタマイズの拡張.
  197. $container->registerForAutoconfiguration(QueryCustomizer::class)
  198. ->addTag(QueryCustomizerPass::QUERY_CUSTOMIZER_TAG);
  199. $container->addCompilerPass(new QueryCustomizerPass());
  200. // 管理画面ナビの拡張
  201. $container->registerForAutoconfiguration(EccubeNav::class)
  202. ->addTag(NavCompilerPass::NAV_TAG);
  203. $container->addCompilerPass(new NavCompilerPass());
  204. // TwigBlockの拡張
  205. $container->registerForAutoconfiguration(EccubeTwigBlock::class)
  206. ->addTag(TwigBlockPass::TWIG_BLOCK_TAG);
  207. $container->addCompilerPass(new TwigBlockPass());
  208. // PaymentMethod の拡張
  209. $container->registerForAutoconfiguration(PaymentMethodInterface::class)
  210. ->addTag(PaymentMethodPass::PAYMENT_METHOD_TAG);
  211. $container->addCompilerPass(new PaymentMethodPass());
  212. // PurchaseFlow の拡張
  213. $container->registerForAutoconfiguration(ItemPreprocessor::class)
  214. ->addTag(PurchaseFlowPass::ITEM_PREPROCESSOR_TAG);
  215. $container->registerForAutoconfiguration(ItemValidator::class)
  216. ->addTag(PurchaseFlowPass::ITEM_VALIDATOR_TAG);
  217. $container->registerForAutoconfiguration(ItemHolderPreprocessor::class)
  218. ->addTag(PurchaseFlowPass::ITEM_HOLDER_PREPROCESSOR_TAG);
  219. $container->registerForAutoconfiguration(ItemHolderValidator::class)
  220. ->addTag(PurchaseFlowPass::ITEM_HOLDER_VALIDATOR_TAG);
  221. $container->registerForAutoconfiguration(ItemHolderPostValidator::class)
  222. ->addTag(PurchaseFlowPass::ITEM_HOLDER_POST_VALIDATOR_TAG);
  223. $container->registerForAutoconfiguration(DiscountProcessor::class)
  224. ->addTag(PurchaseFlowPass::DISCOUNT_PROCESSOR_TAG);
  225. $container->registerForAutoconfiguration(PurchaseProcessor::class)
  226. ->addTag(PurchaseFlowPass::PURCHASE_PROCESSOR_TAG);
  227. $container->addCompilerPass(new PurchaseFlowPass());
  228. }
  229. protected function addEntityExtensionPass(ContainerBuilder $container)
  230. {
  231. $projectDir = $container->getParameter('kernel.project_dir');
  232. // Eccube
  233. $paths = ['%kernel.project_dir%/src/Eccube/Entity'];
  234. $namespaces = ['Eccube\\Entity'];
  235. $reader = new Reference('annotation_reader');
  236. $driver = new Definition(AnnotationDriver::class, [$reader, $paths]);
  237. $driver->addMethodCall('setTraitProxiesDirectory', [$projectDir.'/app/proxy/entity']);
  238. $container->addCompilerPass(new DoctrineOrmMappingsPass($driver, $namespaces, []));
  239. // Customize
  240. $container->addCompilerPass(DoctrineOrmMappingsPass::createAnnotationMappingDriver(
  241. ['Customize\\Entity'],
  242. ['%kernel.project_dir%/app/Customize/Entity']
  243. ));
  244. // Plugin
  245. $pluginDir = $projectDir.'/app/Plugin';
  246. $finder = (new Finder())
  247. ->in($pluginDir)
  248. ->sortByName()
  249. ->depth(0)
  250. ->directories();
  251. $plugins = array_map(function ($dir) {
  252. return $dir->getBaseName();
  253. }, iterator_to_array($finder));
  254. foreach ($plugins as $code) {
  255. if (file_exists($pluginDir.'/'.$code.'/Entity')) {
  256. $paths = ['%kernel.project_dir%/app/Plugin/'.$code.'/Entity'];
  257. $namespaces = ['Plugin\\'.$code.'\\Entity'];
  258. $reader = new Reference('annotation_reader');
  259. $driver = new Definition(AnnotationDriver::class, [$reader, $paths]);
  260. $driver->addMethodCall('setTraitProxiesDirectory', [$projectDir.'/app/proxy/entity']);
  261. $container->addCompilerPass(new DoctrineOrmMappingsPass($driver, $namespaces, []));
  262. }
  263. }
  264. }
  265. protected function loadEntityProxies()
  266. {
  267. // see https://github.com/EC-CUBE/ec-cube/issues/4727
  268. // キャッシュクリアなど、コード内でコマンドを利用している場合に2回実行されてしまう
  269. if (true === $this->booted) {
  270. return;
  271. }
  272. $files = Finder::create()
  273. ->in(__DIR__.'/../../app/proxy/entity/')
  274. ->name('*.php')
  275. ->files();
  276. foreach ($files as $file) {
  277. require_once $file->getRealPath();
  278. }
  279. }
  280. }