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