Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

container_builder.php

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 15.80 KiB


001  <?php
002  /**
003  *
004  * This file is part of the phpBB Forum Software package.
005  *
006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
007  * @license GNU General Public License, version 2 (GPL-2.0)
008  *
009  * For full copyright and license information, please see
010  * the docs/CREDITS.txt file.
011  *
012  */
013   
014  namespace phpbb\di;
015   
016  use phpbb\filesystem\filesystem;
017  use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
018  use Symfony\Component\Config\ConfigCache;
019  use Symfony\Component\Config\FileLocator;
020  use Symfony\Component\DependencyInjection\ContainerBuilder;
021  use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
022  use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
023  use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
024  use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
025  use Symfony\Component\Filesystem\Exception\IOException;
026  use Symfony\Component\Finder\Finder;
027  use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
028   
029  class container_builder
030  {
031      /**
032       * @var string The environment to use.
033       */
034      protected $environment;
035   
036      /**
037       * @var string phpBB Root Path
038       */
039      protected $phpbb_root_path;
040   
041      /**
042       * @var string php file extension
043       */
044      protected $php_ext;
045   
046      /**
047       * The container under construction
048       *
049       * @var ContainerBuilder
050       */
051      protected $container;
052   
053      /**
054       * @var \phpbb\db\driver\driver_interface
055       */
056      protected $dbal_connection = null;
057   
058      /**
059       * Indicates whether extensions should be used (default to true).
060       *
061       * @var bool
062       */
063      protected $use_extensions = true;
064   
065      /**
066       * Defines a custom path to find the configuration of the container (default to $this->phpbb_root_path . 'config')
067       *
068       * @var string
069       */
070      protected $config_path = null;
071   
072      /**
073       * Indicates whether the container should be dumped to the filesystem (default to true).
074       *
075       * If DEBUG_CONTAINER is set this option is ignored and a new container is build.
076       *
077       * @var bool
078       */
079      protected $use_cache = true;
080   
081      /**
082       * Indicates if the container should be compiled automatically (default to true).
083       *
084       * @var bool
085       */
086      protected $compile_container = true;
087   
088      /**
089       * Custom parameters to inject into the container.
090       *
091       * Default to:
092       *     array(
093       *         'core.root_path', $this->phpbb_root_path,
094       *         'core.php_ext', $this->php_ext,
095       * );
096       *
097       * @var array
098       */
099      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  }
699