[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/phpbb/di/ -> container_builder.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  namespace phpbb\di;
  15  
  16  use phpbb\filesystem\filesystem;
  17  use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
  18  use Symfony\Component\Config\ConfigCache;
  19  use Symfony\Component\Config\FileLocator;
  20  use Symfony\Component\DependencyInjection\ContainerBuilder;
  21  use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
  22  use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
  23  use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  24  use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
  25  use Symfony\Component\Filesystem\Exception\IOException;
  26  use Symfony\Component\Finder\Finder;
  27  use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
  28  
  29  class container_builder
  30  {
  31      /**
  32       * @var string The environment to use.
  33       */
  34      protected $environment;
  35  
  36      /**
  37       * @var string phpBB Root Path
  38       */
  39      protected $phpbb_root_path;
  40  
  41      /**
  42       * @var string php file extension
  43       */
  44      protected $php_ext;
  45  
  46      /**
  47       * The container under construction
  48       *
  49       * @var ContainerBuilder
  50       */
  51      protected $container;
  52  
  53      /**
  54       * @var \phpbb\db\driver\driver_interface
  55       */
  56      protected $dbal_connection = null;
  57  
  58      /**
  59       * Indicates whether extensions should be used (default to true).
  60       *
  61       * @var bool
  62       */
  63      protected $use_extensions = true;
  64  
  65      /**
  66       * Defines a custom path to find the configuration of the container (default to $this->phpbb_root_path . 'config')
  67       *
  68       * @var string
  69       */
  70      protected $config_path = null;
  71  
  72      /**
  73       * Indicates whether the container should be dumped to the filesystem (default to true).
  74       *
  75       * If DEBUG_CONTAINER is set this option is ignored and a new container is build.
  76       *
  77       * @var bool
  78       */
  79      protected $use_cache = true;
  80  
  81      /**
  82       * Indicates if the container should be compiled automatically (default to true).
  83       *
  84       * @var bool
  85       */
  86      protected $compile_container = true;
  87  
  88      /**
  89       * Custom parameters to inject into the container.
  90       *
  91       * Default to:
  92       *     array(
  93       *         'core.root_path', $this->phpbb_root_path,
  94       *         'core.php_ext', $this->php_ext,
  95       * );
  96       *
  97       * @var array
  98       */
  99      protected $custom_parameters = [];
 100  
 101      /**
 102       * @var \phpbb\config_php_file
 103       */
 104      protected $config_php_file;
 105  
 106      /**
 107       * @var string
 108       */
 109      protected $cache_dir;
 110  
 111      /**
 112       * @var array
 113       */
 114      private $container_extensions;
 115  
 116      /** @var \Exception */
 117      private $build_exception;
 118  
 119      /**
 120       * @var array
 121       */
 122      private $env_parameters = [];
 123  
 124      /**
 125       * Constructor
 126       *
 127       * @param string $phpbb_root_path Path to the phpbb includes directory.
 128       * @param string $php_ext php file extension
 129       */
 130  	public function __construct($phpbb_root_path, $php_ext)
 131      {
 132          $this->phpbb_root_path    = $phpbb_root_path;
 133          $this->php_ext            = $php_ext;
 134          $this->env_parameters    = $this->get_env_parameters();
 135  
 136          if (isset($this->env_parameters['core.cache_dir']))
 137          {
 138              $this->with_cache_dir($this->env_parameters['core.cache_dir']);
 139          }
 140      }
 141  
 142      /**
 143       * Build and return a new Container respecting the current configuration
 144       *
 145       * @return \phpbb_cache_container|ContainerBuilder
 146       */
 147  	public function get_container()
 148      {
 149          try
 150          {
 151              $build_container = true;
 152  
 153              if ($this->use_cache)
 154              {
 155                  if ($this->use_extensions)
 156                  {
 157                      $autoload_cache = new ConfigCache($this->get_autoload_filename(), defined('DEBUG'));
 158  
 159                      if (!$autoload_cache->isFresh())
 160                      {
 161                          // autoload cache should be refreshed
 162                          $this->load_extensions();
 163                      }
 164  
 165                      require($this->get_autoload_filename());
 166                  }
 167  
 168                  $container_filename = $this->get_container_filename();
 169                  $config_cache = new ConfigCache($container_filename, defined('DEBUG'));
 170  
 171                  if ($config_cache->isFresh())
 172                  {
 173                      require($config_cache->getPath());
 174                      $this->container = new \phpbb_cache_container();
 175                      $build_container = false;
 176                  }
 177              }
 178  
 179              if ($build_container)
 180              {
 181                  $this->container_extensions = [
 182                      new extension\core($this->get_config_path()),
 183                  ];
 184  
 185                  if ($this->use_extensions)
 186                  {
 187                      $this->load_extensions();
 188                  }
 189  
 190                  // Add tables extension after all extensions
 191                  $this->container_extensions[] = new extension\tables();
 192  
 193                  // Inject the config
 194                  if ($this->config_php_file)
 195                  {
 196                      $this->container_extensions[] = new extension\config($this->config_php_file);
 197                  }
 198  
 199                  $this->container = $this->create_container($this->container_extensions);
 200  
 201                  // Easy collections through tags
 202                  $this->container->addCompilerPass(new pass\collection_pass());
 203  
 204                  // Event listeners "phpBB style"
 205                  $this->container->addCompilerPass(new RegisterListenersPass('dispatcher', 'event.listener_listener', 'event.listener'));
 206  
 207                  // Event listeners "Symfony style"
 208                  $this->container->addCompilerPass(new RegisterListenersPass('dispatcher'));
 209  
 210                  if ($this->use_extensions)
 211                  {
 212                      $this->register_ext_compiler_pass();
 213                  }
 214  
 215                  $filesystem = new filesystem();
 216                  $loader     = new YamlFileLoader($this->container, new FileLocator($filesystem->realpath($this->get_config_path())));
 217                  $loader->load($this->container->getParameter('core.environment') . '/config.yml');
 218  
 219                  $this->inject_custom_parameters();
 220  
 221                  if ($this->compile_container)
 222                  {
 223                      $this->container->compile();
 224  
 225                      if ($this->use_cache)
 226                      {
 227                          $this->dump_container($config_cache);
 228                      }
 229                  }
 230              }
 231  
 232              if ($this->config_php_file)
 233              {
 234                  $this->container->set('config.php', $this->config_php_file);
 235              }
 236  
 237              $this->inject_dbal_driver();
 238  
 239              return $this->container;
 240          }
 241          catch (\Exception $e)
 242          {
 243              // Don't try to recover if we are in the development environment
 244              if ($this->get_environment() === 'development')
 245              {
 246                  throw $e;
 247              }
 248  
 249              if ($this->build_exception === null)
 250              {
 251                  $this->build_exception = $e;
 252  
 253                  return $this
 254                      ->without_extensions()
 255                      ->without_cache()
 256                      ->with_custom_parameters(array_merge($this->custom_parameters, [
 257                          'container_exception' => $e,
 258                      ]))
 259                      ->get_container();
 260              }
 261              else
 262              {
 263                  // Rethrow the original exception if it's still failing
 264                  throw $this->build_exception;
 265              }
 266          }
 267      }
 268  
 269      /**
 270       * Enable the extensions.
 271       *
 272       * @param string $environment The environment to use
 273       * @return $this
 274       */
 275  	public function with_environment($environment)
 276      {
 277          $this->environment = $environment;
 278  
 279          return $this;
 280      }
 281  
 282      /**
 283       * Enable the extensions.
 284       *
 285       * @return $this
 286       */
 287  	public function with_extensions()
 288      {
 289          $this->use_extensions = true;
 290  
 291          return $this;
 292      }
 293  
 294      /**
 295       * Disable the extensions.
 296       *
 297       * @return $this
 298       */
 299  	public function without_extensions()
 300      {
 301          $this->use_extensions = false;
 302  
 303          return $this;
 304      }
 305  
 306      /**
 307       * Enable the caching of the container.
 308       *
 309       * If DEBUG_CONTAINER is set this option is ignored and a new container is build.
 310       *
 311       * @return $this
 312       */
 313  	public function with_cache()
 314      {
 315          $this->use_cache = true;
 316  
 317          return $this;
 318      }
 319  
 320      /**
 321       * Disable the caching of the container.
 322       *
 323       * @return $this
 324       */
 325  	public function without_cache()
 326      {
 327          $this->use_cache = false;
 328  
 329          return $this;
 330      }
 331  
 332      /**
 333       * Set the cache directory.
 334       *
 335       * @param string $cache_dir The cache directory.
 336       * @return $this
 337       */
 338  	public function with_cache_dir($cache_dir)
 339      {
 340          $this->cache_dir = $cache_dir;
 341  
 342          return $this;
 343      }
 344  
 345      /**
 346       * Enable the compilation of the container.
 347       *
 348       * @return $this
 349       */
 350  	public function with_compiled_container()
 351      {
 352          $this->compile_container = true;
 353  
 354          return $this;
 355      }
 356  
 357      /**
 358       * Disable the compilation of the container.
 359       *
 360       * @return $this
 361       */
 362  	public function without_compiled_container()
 363      {
 364          $this->compile_container = false;
 365  
 366          return $this;
 367      }
 368  
 369      /**
 370       * Set a custom path to find the configuration of the container.
 371       *
 372       * @param string $config_path
 373       * @return $this
 374       */
 375  	public function with_config_path($config_path)
 376      {
 377          $this->config_path = $config_path;
 378  
 379          return $this;
 380      }
 381  
 382      /**
 383       * Set custom parameters to inject into the container.
 384       *
 385       * @param array $custom_parameters
 386       * @return $this
 387       */
 388  	public function with_custom_parameters($custom_parameters)
 389      {
 390          $this->custom_parameters = $custom_parameters;
 391  
 392          return $this;
 393      }
 394  
 395      /**
 396       * Set custom parameters to inject into the container.
 397       *
 398       * @param \phpbb\config_php_file $config_php_file
 399       * @return $this
 400       */
 401  	public function with_config(\phpbb\config_php_file $config_php_file)
 402      {
 403          $this->config_php_file = $config_php_file;
 404  
 405          return $this;
 406      }
 407  
 408      /**
 409       * Returns the path to the container configuration (default: root_path/config)
 410       *
 411       * @return string
 412       */
 413  	protected function get_config_path()
 414      {
 415          return $this->config_path ?: $this->phpbb_root_path . 'config';
 416      }
 417  
 418      /**
 419       * Returns the path to the cache directory (default: root_path/cache/environment).
 420       *
 421       * @return string Path to the cache directory.
 422       */
 423  	public function get_cache_dir()
 424      {
 425          return $this->cache_dir ?: $this->phpbb_root_path . 'cache/' . $this->get_environment() . '/';
 426      }
 427  
 428      /**
 429       * Load the enabled extensions.
 430       */
 431  	protected function load_extensions()
 432      {
 433          if ($this->config_php_file !== null)
 434          {
 435              // Build an intermediate container to load the ext list from the database
 436              $container_builder = new container_builder($this->phpbb_root_path, $this->php_ext);
 437              $ext_container = $container_builder
 438                  ->without_cache()
 439                  ->without_extensions()
 440                  ->with_config($this->config_php_file)
 441                  ->with_config_path($this->get_config_path())
 442                  ->with_environment('production')
 443                  ->without_compiled_container()
 444                  ->get_container()
 445              ;
 446  
 447              $ext_container->register('cache.driver', '\\phpbb\\cache\\driver\\dummy');
 448              $ext_container->compile();
 449  
 450              $extensions = $ext_container->get('ext.manager')->all_enabled();
 451  
 452              // Load each extension found
 453              $autoloaders = '<?php
 454  /**
 455   * Loads all extensions custom auto-loaders.
 456   *
 457   * This file has been auto-generated
 458   * by phpBB while loading the extensions.
 459   */
 460  
 461  ';
 462              foreach ($extensions as $ext_name => $path)
 463              {
 464                  $extension_class = '\\' . str_replace('/', '\\', $ext_name) . '\\di\\extension';
 465  
 466                  if (!class_exists($extension_class))
 467                  {
 468                      $extension_class = '\\phpbb\\extension\\di\\extension_base';
 469                  }
 470  
 471                  $this->container_extensions[] = new $extension_class($ext_name, $path);
 472  
 473                  // Load extension autoloader
 474                  $filename = $path . 'vendor/autoload.php';
 475                  if (file_exists($filename))
 476                  {
 477                      $autoloaders .= "require('{$filename}');\n";
 478                  }
 479              }
 480  
 481              $configCache = new ConfigCache($this->get_autoload_filename(), false);
 482              $configCache->write($autoloaders);
 483  
 484              require($this->get_autoload_filename());
 485          }
 486          else
 487          {
 488              // To load the extensions we need the database credentials.
 489              // Automatically disable the extensions if we don't have them.
 490              $this->use_extensions = false;
 491          }
 492      }
 493  
 494      /**
 495       * Dump the container to the disk.
 496       *
 497       * @param ConfigCache $cache The config cache
 498       */
 499  	protected function dump_container($cache)
 500      {
 501          try
 502          {
 503              $dumper = new PhpDumper($this->container);
 504              $proxy_dumper = new ProxyDumper();
 505              $dumper->setProxyDumper($proxy_dumper);
 506  
 507              $cached_container_dump = $dumper->dump(array(
 508                  'class'      => 'phpbb_cache_container',
 509                  'base_class' => 'Symfony\\Component\\DependencyInjection\\Container',
 510              ));
 511  
 512              $cache->write($cached_container_dump, $this->container->getResources());
 513          }
 514          catch (IOException $e)
 515          {
 516              // Don't fail if the cache isn't writeable
 517          }
 518      }
 519  
 520      /**
 521       * Create the ContainerBuilder object
 522       *
 523       * @param array $extensions Array of Container extension objects
 524       * @return ContainerBuilder object
 525       */
 526  	protected function create_container(array $extensions)
 527      {
 528          $container = new ContainerBuilder(new ParameterBag($this->get_core_parameters()));
 529          $container->setProxyInstantiator(new proxy_instantiator($this->get_cache_dir()));
 530  
 531          $extensions_alias = array();
 532  
 533          foreach ($extensions as $extension)
 534          {
 535              $container->registerExtension($extension);
 536              $extensions_alias[] = $extension->getAlias();
 537          }
 538  
 539          $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions_alias));
 540  
 541          return $container;
 542      }
 543  
 544      /**
 545       * Inject the customs parameters into the container
 546       */
 547  	protected function inject_custom_parameters()
 548      {
 549          foreach ($this->custom_parameters as $key => $value)
 550          {
 551              $this->container->setParameter($key, $value);
 552          }
 553      }
 554  
 555      /**
 556       * Inject the dbal connection driver into container
 557       */
 558  	protected function inject_dbal_driver()
 559      {
 560          if (empty($this->config_php_file))
 561          {
 562              return;
 563          }
 564  
 565          $config_data = $this->config_php_file->get_all();
 566          if (!empty($config_data))
 567          {
 568              if ($this->dbal_connection === null)
 569              {
 570                  $dbal_driver_class = $this->config_php_file->convert_30_dbms_to_31($this->config_php_file->get('dbms'));
 571                  /** @var \phpbb\db\driver\driver_interface $dbal_connection */
 572                  $this->dbal_connection = new $dbal_driver_class();
 573                  $this->dbal_connection->sql_connect(
 574                      $this->config_php_file->get('dbhost'),
 575                      $this->config_php_file->get('dbuser'),
 576                      $this->config_php_file->get('dbpasswd'),
 577                      $this->config_php_file->get('dbname'),
 578                      $this->config_php_file->get('dbport'),
 579                      false,
 580                      defined('PHPBB_DB_NEW_LINK') && PHPBB_DB_NEW_LINK
 581                  );
 582              }
 583              $this->container->set('dbal.conn.driver', $this->dbal_connection);
 584          }
 585      }
 586  
 587      /**
 588       * Returns the core parameters.
 589       *
 590       * @return array An array of core parameters
 591       */
 592  	protected function get_core_parameters()
 593      {
 594          return array_merge(
 595              [
 596                  'core.root_path'     => $this->phpbb_root_path,
 597                  'core.php_ext'       => $this->php_ext,
 598                  'core.environment'   => $this->get_environment(),
 599                  'core.debug'         => defined('DEBUG') ? DEBUG : false,
 600                  'core.cache_dir'     => $this->get_cache_dir(),
 601              ],
 602              $this->env_parameters
 603          );
 604      }
 605  
 606      /**
 607       * Gets the environment parameters.
 608       *
 609       * Only the parameters starting with "PHPBB__" are considered.
 610       *
 611       * @return array An array of parameters
 612       */
 613  	protected function get_env_parameters()
 614      {
 615          $parameters = array();
 616          foreach ($_SERVER as $key => $value)
 617          {
 618              if (0 === strpos($key, 'PHPBB__'))
 619              {
 620                  $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
 621              }
 622          }
 623  
 624          return $parameters;
 625      }
 626  
 627      /**
 628       * Get the filename under which the dumped container will be stored.
 629       *
 630       * @return string Path for dumped container
 631       */
 632  	protected function get_container_filename()
 633      {
 634          $container_params = [
 635              'phpbb_root_path' => $this->phpbb_root_path,
 636              'use_extensions' => $this->use_extensions,
 637              'config_path' => $this->config_path,
 638          ];
 639  
 640          return $this->get_cache_dir() . 'container_' . md5(implode(',', $container_params)) . '.' . $this->php_ext;
 641      }
 642  
 643      /**
 644       * Get the filename under which the dumped extensions autoloader will be stored.
 645       *
 646       * @return string Path for dumped extensions autoloader
 647       */
 648  	protected function get_autoload_filename()
 649      {
 650          $container_params = [
 651              'phpbb_root_path' => $this->phpbb_root_path,
 652              'use_extensions' => $this->use_extensions,
 653              'config_path' => $this->config_path,
 654          ];
 655  
 656          return $this->get_cache_dir() . 'autoload_' . md5(implode(',', $container_params)) . '.' . $this->php_ext;
 657      }
 658  
 659      /**
 660       * Return the name of the current environment.
 661       *
 662       * @return string
 663       */
 664  	protected function get_environment()
 665      {
 666          return $this->environment ?: PHPBB_ENVIRONMENT;
 667      }
 668  
 669  	private function register_ext_compiler_pass()
 670      {
 671          $finder = new Finder();
 672          $finder
 673              ->name('*_pass.php')
 674              ->path('di/pass')
 675              ->files()
 676              ->ignoreDotFiles(true)
 677              ->ignoreUnreadableDirs(true)
 678              ->ignoreVCS(true)
 679              ->followLinks()
 680              ->in($this->phpbb_root_path . 'ext')
 681          ;
 682  
 683          /** @var \SplFileInfo $pass */
 684          foreach ($finder as $pass)
 685          {
 686              $filename = $pass->getPathname();
 687              $filename = substr($filename, 0, -strlen('.' . $pass->getExtension()));
 688              $filename = str_replace(DIRECTORY_SEPARATOR, '/', $filename);
 689              $className = preg_replace('#^.*ext/#', '', $filename);
 690              $className = '\\' . str_replace('/', '\\', $className);
 691  
 692              if (class_exists($className) && in_array('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface', class_implements($className), true))
 693              {
 694                  $this->container->addCompilerPass(new $className());
 695              }
 696          }
 697      }
 698  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1