1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-08-06 16:56:44 +02:00

[feature/compiled-dic] Compile the DI Container into a cached class

PHPBB3-11152
This commit is contained in:
David King
2012-10-19 19:53:29 -04:00
committed by Igor Wiedler
parent 957508c8b1
commit f48709f5bb
20 changed files with 692 additions and 273 deletions

View File

@@ -214,7 +214,7 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base
while (($entry = readdir($dir)) !== false)
{
if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0)
if (strpos($entry, 'container') !== 0 && strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0)
{
continue;
}

View File

@@ -162,7 +162,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base
while (($entry = readdir($dir)) !== false)
{
if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0)
if (strpos($entry, 'container') !== 0 && strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0)
{
continue;
}

View File

@@ -16,40 +16,33 @@ if (!defined('IN_PHPBB'))
}
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\Config\FileLocator;
/**
* Configure the container for phpBB's services though
* user-defined parameters defined in the config.php file.
* Container config extension
*/
class phpbb_di_processor_config implements phpbb_di_processor_interface
class phpbb_di_extension_config extends Extension
{
private $config_file;
private $phpbb_root_path;
private $php_ext;
/**
* Constructor.
*
* @param string $config_file The config file
* @param string $phpbb_root_path The root path
* @param string $php_ext The PHP extension
*/
public function __construct($config_file, $phpbb_root_path, $php_ext)
public function __construct($config_file)
{
$this->config_file = $config_file;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
}
/**
* @inheritdoc
* Loads a specific configuration.
*
* @param array $config An array of configuration values
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @throws InvalidArgumentException When provided tag is not defined in this extension
*
* @api
*/
public function process(ContainerBuilder $container)
public function load(array $config, ContainerBuilder $container)
{
require $this->config_file;
$container->setParameter('core.root_path', $this->phpbb_root_path);
$container->setParameter('core.php_ext', $this->php_ext);
require($this->config_file);
$container->setParameter('core.table_prefix', $table_prefix);
$container->setParameter('cache.driver.class', $this->fix_acm_type($acm_type));
@@ -60,10 +53,28 @@ class phpbb_di_processor_config implements phpbb_di_processor_interface
$container->setParameter('dbal.dbname', $dbname);
$container->setParameter('dbal.dbport', $dbport);
$container->setParameter('dbal.new_link', defined('PHPBB_DB_NEW_LINK') && PHPBB_DB_NEW_LINK);
$container->set('container', $container);
}
/**
* Returns the recommended alias to use in XML.
*
* This alias is also the mandatory prefix to use when using YAML.
*
* @return string The alias
*
* @api
*/
public function getAlias()
{
return 'config';
}
/**
* Convert old (3.0) values to 3.1 class names
*
* @param style $acm_type ACM type
* @return ACM type class
*/
protected function fix_acm_type($acm_type)
{
if (preg_match('#^[a-z]+$#', $acm_type))

View File

@@ -0,0 +1,76 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Config\FileLocator;
/**
* Container core extension
*/
class phpbb_di_extension_core extends Extension
{
/**
* phpBB Root path
* @var string
*/
protected $phpbb_root_path;
/**
* Constructor
*
* @param string $phpbb_root_path Root path
*/
public function __construct($phpbb_root_path)
{
$this->phpbb_root_path = $phpbb_root_path;
}
/**
* Loads a specific configuration.
*
* @param array $config An array of configuration values
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @throws InvalidArgumentException When provided tag is not defined in this extension
*
* @api
*/
public function load(array $config, ContainerBuilder $container)
{
if (file_exists($this->phpbb_root_path . 'config/services.yml'))
{
$loader = new YamlFileLoader($container, new FileLocator(realpath($this->phpbb_root_path . 'config')));
$loader->load('services.yml');
}
}
/**
* Returns the recommended alias to use in XML.
*
* This alias is also the mandatory prefix to use when using YAML.
*
* @return string The alias
*
* @api
*/
public function getAlias()
{
return 'core';
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Config\FileLocator;
/**
* Container ext extension
*/
class phpbb_di_extension_ext extends Extension
{
protected $paths = array();
public function __construct($enabled_extensions)
{
foreach ($enabled_extensions as $ext => $path)
{
$this->paths[] = $path;
}
}
/**
* Loads a specific configuration.
*
* @param array $config An array of configuration values
* @param ContainerBuilder $container A ContainerBuilder instance
*
* @throws InvalidArgumentException When provided tag is not defined in this extension
*
* @api
*/
public function load(array $config, ContainerBuilder $container)
{
foreach ($this->paths as $path)
{
if (file_exists($path . '/config/services.yml'))
{
$loader = new YamlFileLoader($container, new FileLocator($path . '/config'));
$loader->load('services.yml');
}
}
}
/**
* Returns the recommended alias to use in XML.
*
* This alias is also the mandatory prefix to use when using YAML.
*
* @return string The alias
*
* @api
*/
public function getAlias()
{
return 'ext';
}
}

View File

@@ -1,54 +0,0 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
/**
* Load the service configurations from all extensions into the container.
*/
class phpbb_di_processor_ext implements phpbb_di_processor_interface
{
private $extension_manager;
/**
* Constructor.
*
* @param string $extension_manager The extension manager
*/
public function __construct($extension_manager)
{
$this->extension_manager = $extension_manager;
}
/**
* @inheritdoc
*/
public function process(ContainerBuilder $container)
{
$enabled_exts = $this->extension_manager->all_enabled();
foreach ($enabled_exts as $name => $path)
{
if (file_exists($path . '/config/services.yml'))
{
$loader = new YamlFileLoader($container, new FileLocator($path . '/config'));
$loader->load('services.yml');
}
}
}
}

View File

@@ -1,28 +0,0 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
use Symfony\Component\DependencyInjection\ContainerBuilder;
interface phpbb_di_processor_interface
{
/**
* Mutate the container.
*
* @param ContainerBuilder $container The container
*/
public function process(ContainerBuilder $container);
}

View File

@@ -15,7 +15,7 @@ if (!defined('IN_PHPBB'))
exit;
}
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
/**
* Extension of the Symfony2 EventDispatcher
@@ -31,7 +31,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
* extract($phpbb_dispatcher->trigger_event('core.index', compact($vars)));
*
*/
class phpbb_event_dispatcher extends EventDispatcher
class phpbb_event_dispatcher extends ContainerAwareEventDispatcher
{
public function trigger_event($eventName, $data = array())
{

View File

@@ -0,0 +1,72 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
class phpbb_event_kernel_compiler_pass implements CompilerPassInterface
{
/**
* Modify the container before it is passed to the rest of the code
*
* @param ContainerBuilder $container ContainerBuilder object
* @return null
*/
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('dispatcher');
$user = $container->get('user');
foreach ($container->findTaggedServiceIds('kernel.event_listener') as $id => $events)
{
foreach ($events as $event)
{
$priority = isset($event['priority']) ? $event['priority'] : 0;
if (!isset($event['event']))
{
throw new InvalidArgumentException($user->lang('NO_EVENT_ATTRIBUTE', $id));
}
if (!isset($event['method']))
{
$event['method'] = 'on'.preg_replace(array(
'/(?<=\b)[a-z]/ie',
'/[^a-z0-9]/i'
), array('strtoupper("\\0")', ''), $event['event']);
}
$definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority));
}
}
foreach ($container->findTaggedServiceIds('kernel.event_subscriber') as $id => $attributes)
{
// We must assume that the class value has been correctly filled, even if the service is created by a factory
$class = $container->getDefinition($id)->getClass();
$refClass = new ReflectionClass($class);
$interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
if (!$refClass->implementsInterface($interface))
{
throw new InvalidArgumentException($user->lang('SUBSCRIBER_WRONG_TYPE', $id, $interface));
}
$definition->addMethodCall('addSubscriberService', array($id, $class));
}
}
}

View File

@@ -0,0 +1,94 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
class phpbb_event_kernel_subscriber implements EventSubscriberInterface
{
/**
* Template object
* @var phpbb_template
*/
protected $template;
/**
* User object
* @var phpbb_user
*/
protected $user;
/**
* Construct method
*
* @param phpbb_template $template Template object
* @param phpbb_user $user User object
*/
public function __construct(phpbb_template $template, phpbb_user $user)
{
$this->template = $template;
$this->user = $user;
}
/**
* This listener is run when the KernelEvents::TERMINATE event is triggered
* This comes after a Response has been sent to the server; this is
* primarily cleanup stuff.
*
* @param PostResponseEvent $event
* @return null
*/
public function on_kernel_terminate(PostResponseEvent $event)
{
exit_handler();
}
/**
* This listener is run when the KernelEvents::EXCEPTION event is triggered
*
* @param GetResponseForExceptionEvent $event
* @return null
*/
public function on_kernel_exception(GetResponseForExceptionEvent $event)
{
page_header($this->user->lang('INFORMATION'));
$this->template->assign_vars(array(
'MESSAGE_TITLE' => $this->user->lang('INFORMATION'),
'MESSAGE_TEXT' => $event->getException()->getMessage(),
));
$this->template->set_filenames(array(
'body' => 'message_body.html',
));
page_footer(true, false, false);
$event->setResponse(new Response($this->template->return_display('body'), 404));
}
public static function getSubscribedEvents()
{
return array(
KernelEvents::TERMINATE => 'on_kernel_terminate',
KernelEvents::EXCEPTION => 'on_kernel_exception',
);
}
}

View File

@@ -1,84 +0,0 @@
<?php
/**
*
* @package extension
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Abstract class extended by extension front controller classes
*
* @package extension
*/
abstract class phpbb_extension_controller implements phpbb_extension_controller_interface
{
/**
* Request class object
* @var phpbb_request
*/
protected $request;
/**
* DBAL class object
* @var dbal
*/
protected $db;
/**
* User class object
* @var phpbb_user
*/
protected $user;
/**
* Template class object
* @var phpbb_template
*/
protected $template;
/**
* Config object
* @var phpbb_config
*/
protected $config;
/**
* PHP Extension
* @var string
*/
protected $php_ext;
/**
* Relative path to board root
* @var string
*/
protected $phpbb_root_path;
/**
* Constructor method that provides the common phpBB objects as inherited class
* properties for automatic availability in extension controllers
*/
public function __construct()
{
global $request, $db, $user, $template, $config;
global $phpEx, $phpbb_root_path;
$this->request = $request;
$this->db = $db;
$this->user = $user;
$this->template = $template;
$this->config = $config;
$this->php_ext = $phpEx;
$this->phpbb_root_path = $phpbb_root_path;
}
}

View File

@@ -1,31 +0,0 @@
<?php
/**
*
* @package extension
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* The interface that extension classes have to implement to run front pages
*
* @package extension
*/
interface phpbb_extension_controller_interface
{
/**
* Handle the request to display a page from an extension
*
* @return null
*/
public function handle();
}

View File

@@ -7,6 +7,13 @@
*
*/
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
/**
* @ignore
*/
@@ -5412,3 +5419,98 @@ function phpbb_to_numeric($input)
{
return ($input > PHP_INT_MAX) ? (float) $input : (int) $input;
}
/**
* Create the ContainerBuilder object
*
* @param array $extensions Array of Container extension objects
* @param string $phpbb_root_path Root path
* @param string $phpEx PHP Extension
* @return ContainerBuilder object
*/
function phpbb_create_container(array $extensions, $phpbb_root_path, $phpEx)
{
$container = new ContainerBuilder();
foreach ($extensions as $extension)
{
$container->registerExtension($extension);
$container->loadFromExtension($extension->getAlias());
}
$container->set('container', $container);
$container->setParameter('core.root_path', $phpbb_root_path);
$container->setParameter('core.php_ext', $phpEx);
return $container;
}
/**
* Create installer container
*
* @param string $phpbb_root_path Root path
* @param string $phpEx PHP Extension
* @return ContainerBuilder object
*/
function phpbb_create_install_container($phpbb_root_path, $phpEx)
{
// We have to do it like this instead of with extensions
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
$loader->load('services.yml');
$container->setParameter('core.root_path', $phpbb_root_path);
$container->setParameter('core.php_ext', $phpEx);
$container->setAlias('cache.driver', 'cache.driver.install');
return $container;
}
/**
* Create a compiled ContainerBuilder object
*
* @param array $extensions Array of Container extension objects
* @param array $passes Array of Compiler Pass objects
* @param string $phpbb_root_path Root path
* @param string $phpEx PHP Extension
* @return ContainerBuilder object (compiled)
*/
function phpbb_create_compiled_container(array $extensions, array $passes, $config_file_path, $phpbb_root_path, $phpEx)
{
// Check for our cached container; if it exists, use it
if (file_exists("{$phpbb_root_path}cache/container.$phpEx"))
{
require("{$phpbb_root_path}cache/container.$phpEx");
return new phpbb_cache_container();
}
// If we don't have the cached container class, we make it now
// First, we create the temporary container so we can access the
// extension_manager
$tmp_container = phpbb_create_container($extensions, $phpbb_root_path, $phpEx);
$tmp_container->compile();
// Now we pass the enabled extension paths into the ext compiler extension
$extensions[] = new phpbb_di_extension_ext($tmp_container->get('ext.manager')->all_enabled());
// And create our final container
$container = phpbb_create_container($extensions, $phpbb_root_path, $phpEx);
foreach ($passes as $pass)
{
$container->addCompilerPass($pass);
}
$container->compile();
// Lastly, we create our cached container class
$dumper = new PhpDumper($container);
$cached_container_dump = $dumper->dump(array(
'class' => 'phpbb_cache_container',
'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder',
));
$file = file_put_contents("{$phpbb_root_path}cache/container.$phpEx", $cached_container_dump);
return $container;
}