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. |
|
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
container_builder.php
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