1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-02-24 12:03:21 +01:00

Merge remote-tracking branch 'p/feature/template-events' into develop

# By Oleg Pudeyev (36) and others
# Via Oleg Pudeyev
* p/feature/template-events: (47 commits)
  [feature/template-events] Pass arguments in correct order.
  [feature/template-events] Order extensions in mock extension manager.
  [feature/template-events] Changes per imkingdavid's review.
  [feature/template-events] Make style names private on template.
  [feature/template-events] Test for event that is defined in parent style only.
  [feature/template-events] Specify style names, add inheritance tests.
  [feature/template-events] Normalize expected directory trees.
  [feature/template-events] Allow dataset to be correctly selectable.
  [feature/template-events] Dataset for template event testing with inheritance.
  [feature/template-events] Use style names array in template filter.
  [feature/template-events] Generate style names array in set_style.
  [feature/template-events] Convert a single style name to array of them.
  [feature/template-events] Chase dependency injection for template context.
  [feature/template-events] Adjust template events test to use the dataset.
  [feature/template-events] Create a dataset for template event tests.
  [feature/template-events] Indentation fix.
  [feature/template-events] Cosmetic changes.
  [feature/template-events] Wording: wrongly -> improperly.
  [feature/template-events] Indentation fix.
  [feature/template-events] Rename template_name to style_name.
  ...
This commit is contained in:
David King 2012-12-10 14:09:10 -05:00
commit a9db155c28
34 changed files with 389 additions and 28 deletions

View File

@ -52,7 +52,7 @@ $mode = request_var('mode', '');
// Set custom style for admin area
$phpbb_style->set_ext_dir_prefix('adm/');
$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', '');
$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', array(), '');
$template->assign_var('T_ASSETS_PATH', $phpbb_root_path . 'assets');
$template->assign_var('T_TEMPLATE_PATH', $phpbb_admin_path . 'style');

View File

@ -24,7 +24,7 @@ $user->setup();
$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : './';
// Set custom template for admin area
$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', '');
$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', array(), '');
$template->set_filenames(array(
'body' => 'colour_swatch.html')

View File

@ -180,6 +180,7 @@ services:
- @user
- @style.resource_locator
- @template_context
- @ext.manager
template_context:
class: phpbb_template_context

View File

@ -134,7 +134,7 @@ class bbcode
$style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider());
$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context());
$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager);
$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $template);
$style->set_style();
$template->set_filenames(array('bbcode.html' => 'bbcode.html'));

View File

@ -210,7 +210,7 @@ class messenger
{
$style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider());
$tpl = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context());
$tpl = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $extension_manager);
$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $tpl);
$this->tpl_msg[$template_lang . $template_file] = $tpl;
@ -231,7 +231,7 @@ class messenger
}
}
$style->set_custom_style($template_lang . '_email', array($template_path, $fallback_template_path), '');
$style->set_custom_style($template_lang . '_email', array($template_path, $fallback_template_path), array(), '');
$tpl->set_filenames(array(
'body' => $template_file . '.txt',

View File

@ -91,16 +91,22 @@ class phpbb_style
{
$style_path = $this->user->style['style_path'];
$style_dirs = ($this->user->style['style_parent_id']) ? array_reverse(explode('/', $this->user->style['style_parent_tree'])) : array();
$paths = array($this->get_style_path($style_path));
$names = array($style_path);
foreach ($style_dirs as $dir)
{
$paths[] = $this->get_style_path($dir);
$names[] = $dir;
}
// Add 'all' path, used as last fallback path by events and extensions
//$names[] = 'all';
$paths = array();
foreach ($names as $name)
{
$paths[] = $this->get_style_path($name);
}
// Add 'all' path, used as last fallback path by hooks and extensions
$paths[] = $this->get_style_path('all');
return $this->set_custom_style($style_path, $paths);
return $this->set_custom_style($style_path, $paths, $paths);
}
/**
@ -110,18 +116,27 @@ class phpbb_style
*
* @param string $name Name of style, used for cache prefix. Examples: "admin", "prosilver"
* @param array or string $paths Array of style paths, relative to current root directory
* @param array $names Array of names of templates in inheritance tree order, used by extensions. If empty, $name will be used.
* @param string $template_path Path to templates, relative to style directory. False if path should be set to default (templates/).
*/
public function set_custom_style($name, $paths, $template_path = false)
public function set_custom_style($name, $paths, $names = array(), $template_path = false)
{
if (is_string($paths))
{
$paths = array($paths);
}
if (empty($names))
{
$names = array($name);
}
$this->names = $names;
$this->provider->set_styles($paths);
$this->locator->set_paths($this->provider);
$this->template->set_style_names($names);
if ($template_path !== false)
{
$this->locator->set_template_path($template_path);

View File

@ -35,16 +35,23 @@ class phpbb_template_compile
/**
* Constructor.
*
* @param bool @allow_php Whether PHP code will be allowed in templates (inline PHP code, PHP tag and INCLUDEPHP tag)
* @param bool $allow_php Whether PHP code will be allowed in templates (inline PHP code, PHP tag and INCLUDEPHP tag)
* @param array $style_names Name of style to which the template being compiled belongs and parents in style tree order
* @param phpbb_style_resource_locator $locator Resource locator
* @param string $phpbb_root_path Path to phpBB root directory
* @param phpbb_extension_manager $extension_manager Extension manager to use for finding template fragments in extensions; if null, template events will not be invoked
* @param phpbb_user $user Current user
*/
public function __construct($allow_php, $locator, $phpbb_root_path)
public function __construct($allow_php, $style_names, $locator, $phpbb_root_path, $extension_manager = null, $user = null)
{
$this->filter_params = array(
'allow_php' => $allow_php,
'style_names' => $style_names,
'locator' => $locator,
'phpbb_root_path' => $phpbb_root_path
'phpbb_root_path' => $phpbb_root_path,
'extension_manager' => $extension_manager,
'user' => $user,
'template_compile' => $this,
);
}

View File

@ -87,6 +87,37 @@ class phpbb_template_filter extends php_user_filter
*/
private $phpbb_root_path;
/**
* Name of the style that the template being compiled and/or rendered
* belongs to, and its parents, in inheritance tree order.
*
* Used to invoke style-specific template events.
*
* @var array
*/
private $style_names;
/**
* Extension manager.
*
* @var phpbb_extension_manager
*/
private $extension_manager;
/**
* Current user
*
* @var phpbb_user
*/
private $user;
/**
* Template compiler.
*
* @var phpbb_template_compile
*/
private $template_compile;
/**
* Stream filter
*
@ -138,8 +169,10 @@ class phpbb_template_filter extends php_user_filter
/**
* Initializer, called on creation.
*
* Get the allow_php option, root directory and locator from params,
* Get the allow_php option, style_names, root directory and locator from params,
* which are passed to stream_filter_append.
*
* @return boolean Returns true
*/
public function onCreate()
{
@ -148,6 +181,13 @@ class phpbb_template_filter extends php_user_filter
$this->allow_php = $this->params['allow_php'];
$this->locator = $this->params['locator'];
$this->phpbb_root_path = $this->params['phpbb_root_path'];
$this->style_names = $this->params['style_names'];
$this->extension_manager = $this->params['extension_manager'];
if (isset($this->params['user']))
{
$this->user = $this->params['user'];
}
$this->template_compile = $this->params['template_compile'];
return true;
}
@ -229,7 +269,9 @@ class phpbb_template_filter extends php_user_filter
}
/**
* Callback for replacing matched tokens with PHP code
* Callback for replacing matched tokens with compiled template code.
*
* Compiled template code is an HTML stream with embedded PHP.
*
* @param array $matches Regular expression matches
* @return string compiled template code
@ -317,6 +359,10 @@ class phpbb_template_filter extends php_user_filter
return '<!-- ENDPHP -->';
break;
case 'EVENT':
return '<?php ' . $this->compile_tag_event($matches[2]) . '?>';
break;
default:
return $matches[0];
break;
@ -835,6 +881,97 @@ class phpbb_template_filter extends php_user_filter
return "\$_template->_php_include('$tag_args');";
}
/**
* Compile EVENT tag.
*
* $tag_args should be a single string identifying the event.
* The event name can contain letters, numbers and underscores only.
* If an invalid event name is specified, an E_USER_ERROR will be
* triggered.
*
* Event tags are only functional when the template engine has
* an instance of the extension manager. Extension manager would
* be called upon to find all extensions listening for the specified
* event, and to obtain additional template fragments. All such
* template fragments will be compiled and included in the generated
* compiled template code for the current template being compiled.
*
* The above means that whenever an extension is enabled or disabled,
* template cache should be cleared in order to update the compiled
* template code for the active set of template event listeners.
*
* This also means that extensions cannot return different template
* fragments at different times. Once templates are compiled, changing
* such template fragments would have no effect.
*
* @param string $tag_args EVENT tag arguments, as a string - for EVENT this is the event name
* @return string compiled template code
*/
private function compile_tag_event($tag_args)
{
if (!preg_match('/^\w+$/', $tag_args))
{
// The event location is improperly formatted,
if ($this->user)
{
trigger_error($this->user->lang('ERR_TEMPLATE_EVENT_LOCATION', $tag_args), E_USER_ERROR);
}
else
{
trigger_error(sprintf('The specified template event location <em>[%s]</em> is improperly formatted.', $tag_args), E_USER_ERROR);
}
}
$location = $tag_args;
if ($this->extension_manager)
{
$finder = $this->extension_manager->get_finder();
$files = $finder
->extension_prefix($location)
->extension_suffix('.html')
->extension_directory("/styles/all/template")
->get_files();
foreach ($this->style_names as $style_name)
{
$more_files = $finder
->extension_prefix($location)
->extension_suffix('.html')
->extension_directory("/styles/" . $style_name . "/template")
->get_files();
if (!empty($more_files))
{
$files = array_merge($files, $more_files);
break;
}
}
$all_compiled = '';
foreach ($files as $file)
{
$compiled = $this->template_compile->compile_file($file);
if ($compiled === false)
{
if ($this->user)
{
trigger_error($this->user->lang('ERR_TEMPLATE_COMPILATION', phpbb_filter_root_path($file)), E_USER_ERROR);
}
else
{
trigger_error(sprintf('The file could not be compiled: %s', phpbb_filter_root_path($file)), E_USER_ERROR);
}
}
$all_compiled .= $compiled;
}
// Need spaces inside php tags as php cannot grok
// < ?php? > sans the spaces
return ' ?' . '>' . $all_compiled . '<?php ';
}
}
/**
* parse expression
* This is from Smarty

View File

@ -39,7 +39,7 @@ interface phpbb_template_locator
* Sets the template filenames for handles. $filename_array
* should be a hash of handle => filename pairs.
*
* @param array $filname_array Should be a hash of handle => filename pairs.
* @param array $filename_array Should be a hash of handle => filename pairs.
*/
public function set_filenames(array $filename_array);
@ -66,7 +66,7 @@ interface phpbb_template_locator
* returns actually exists, it is faster than get_source_file_for_handle.
*
* Use get_source_file_for_handle to obtain the actual path that is
* guaranteed to exist (which might come from the parent style
* guaranteed to exist (which might come from the parent style
* directory if primary style has parent styles).
*
* This function will trigger an error if the handle was never

View File

@ -74,6 +74,23 @@ class phpbb_template
*/
private $locator;
/**
* Extension manager.
*
* @var phpbb_extension_manager
*/
private $extension_manager;
/**
* Name of the style that the template being compiled and/or rendered
* belongs to, and its parents, in inheritance tree order.
*
* Used to invoke style-specific template events.
*
* @var array
*/
private $style_names;
/**
* Constructor.
*
@ -81,8 +98,9 @@ class phpbb_template
* @param user $user current user
* @param phpbb_template_locator $locator template locator
* @param phpbb_template_context $context template context
* @param phpbb_extension_manager $extension_manager extension manager, if null then template events will not be invoked
*/
public function __construct($phpbb_root_path, $php_ext, $config, $user, phpbb_template_locator $locator, phpbb_template_context $context)
public function __construct($phpbb_root_path, $php_ext, $config, $user, phpbb_template_locator $locator, phpbb_template_context $context, phpbb_extension_manager $extension_manager = null)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
@ -90,12 +108,13 @@ class phpbb_template
$this->user = $user;
$this->locator = $locator;
$this->context = $context;
$this->extension_manager = $extension_manager;
}
/**
* Sets the template filenames for handles.
*
* @param array $filname_array Should be a hash of handle => filename pairs.
* @param array $filename_array Should be a hash of handle => filename pairs.
*/
public function set_filenames(array $filename_array)
{
@ -104,6 +123,18 @@ class phpbb_template
return true;
}
/**
* Sets the style names corresponding to style hierarchy being compiled
* and/or rendered.
*
* @param array $style_names List of style names in inheritance tree order
* @return null
*/
public function set_style_names(array $style_names)
{
$this->style_names = $style_names;
}
/**
* Clears all variables and blocks assigned to this template.
*/
@ -282,7 +313,7 @@ class phpbb_template
return new phpbb_template_renderer_include($output_file, $this);
}
$compile = new phpbb_template_compile($this->config['tpl_allow_php'], $this->locator, $this->phpbb_root_path);
$compile = new phpbb_template_compile($this->config['tpl_allow_php'], $this->style_names, $this->locator, $this->phpbb_root_path, $this->extension_manager, $this->user);
if ($compile->compile_file_to_file($source_file, $output_file) !== false)
{

View File

@ -215,7 +215,7 @@ $phpbb_style_path_provider = new phpbb_style_path_provider();
$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $phpbb_style_resource_locator, new phpbb_template_context());
$phpbb_style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $phpbb_style_resource_locator, $phpbb_style_path_provider, $template);
$phpbb_style->set_ext_dir_prefix('adm/');
$phpbb_style->set_custom_style('admin', '../adm/style', '');
$phpbb_style->set_custom_style('admin', '../adm/style', array(), '');
$template->assign_var('T_ASSETS_PATH', '../assets');
$template->assign_var('T_TEMPLATE_PATH', '../adm/style');

View File

@ -131,7 +131,7 @@ class install_update extends module
}
// Set custom template again. ;)
$phpbb_style->set_custom_style('admin', '../adm/style', '');
$phpbb_style->set_custom_style('admin', '../adm/style', array(), '');
$template->assign_vars(array(
'S_USER_LANG' => $user->lang['USER_LANG'],

View File

@ -186,6 +186,8 @@ $lang = array_merge($lang, array(
'ERR_CONNECTING_SERVER' => 'Error connecting to the server.',
'ERR_JAB_AUTH' => 'Could not authorise on Jabber server.',
'ERR_JAB_CONNECT' => 'Could not connect to Jabber server.',
'ERR_TEMPLATE_EVENT_LOCATION' => 'The specified template event location <em>[%s]</em> is improperly formatted.',
'ERR_TEMPLATE_COMPILATION' => 'The file could not be compiled: %s',
'ERR_UNABLE_TO_LOGIN' => 'The specified username or password is incorrect.',
'ERR_UNWATCHING' => 'An error occured while trying to unsubscribe.',
'ERR_WATCHING' => 'An error occured while trying to subscribe.',

View File

@ -0,0 +1,32 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_mock_filesystem_extension_manager extends phpbb_mock_extension_manager
{
public function __construct($phpbb_root_path)
{
$extensions = array();
$iterator = new DirectoryIterator($phpbb_root_path . 'ext/');
foreach ($iterator as $fileinfo)
{
if ($fileinfo->isDir() && substr($fileinfo->getFilename(), 0, 1) != '.')
{
$name = $fileinfo->getFilename();
$extension = array(
'ext_name' => $name,
'ext_active' => true,
'ext_path' => 'ext/' . $name . '/',
);
$extensions[$name] = $extension;
}
}
ksort($extensions);
parent::__construct($phpbb_root_path, $extensions);
}
}

View File

@ -0,0 +1 @@
Kappa test event in all

View File

@ -0,0 +1 @@
Kappa test event in silver

View File

@ -0,0 +1 @@
Kappa test event in silver_inherit

View File

@ -0,0 +1 @@
Omega test event in all

View File

@ -0,0 +1 @@
Omega test event in silver

View File

@ -0,0 +1 @@
two in silver in omega

View File

@ -0,0 +1 @@
Zeta test event in all

View File

@ -0,0 +1 @@
<!-- EVENT test -->

View File

@ -0,0 +1 @@
<!-- EVENT two -->

View File

@ -0,0 +1 @@
<!-- EVENT test -->

View File

@ -0,0 +1 @@
Universal in trivial extension.

View File

@ -0,0 +1 @@
Simple in trivial extension.

View File

@ -0,0 +1 @@
<!-- EVENT simple -->

View File

@ -0,0 +1 @@
<!-- EVENT universal -->

View File

@ -48,7 +48,7 @@ class phpbb_template_includephp_test extends phpbb_template_template_test_case
$this->setup_engine(array('tpl_allow_php' => true));
$this->style->set_custom_style('tests', $cache_dir, '');
$this->style->set_custom_style('tests', $cache_dir, array(), '');
$cache_file = $this->template->cachepath . 'includephp_absolute.html.php';
$this->run_template('includephp_absolute.html', array(), array(), array(), "Path is absolute.\ntesting included php", $cache_file);

View File

@ -16,7 +16,7 @@ class phpbb_template_template_compile_test extends phpbb_test_case
protected function setUp()
{
$this->template_compile = new phpbb_template_compile(false, null, '');
$this->template_compile = new phpbb_template_compile(false, null, $this->style_resource_locator, '');
$this->template_path = dirname(__FILE__) . '/templates';
}

View File

@ -0,0 +1,118 @@
<?php
/**
*
* @package testing
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
require_once dirname(__FILE__) . '/template_test_case.php';
class phpbb_template_template_events_test extends phpbb_template_template_test_case
{
public function template_data()
{
return array(
/*
array(
'', // file
'', // dataset
array(), // style names
array(), // vars
array(), // block vars
array(), // destroy
'', // expected result
),
*/
array(
'Simple template event',
'ext_trivial',
array(),
'event_simple.html',
array(),
array(),
array(),
"Simple in trivial extension.",
),
array(
'Universal template event ("all" style)',
'ext_trivial',
array(),
'event_universal.html',
array(),
array(),
array(),
"Universal in trivial extension.",
),
array(
'Template event with inheritance - parent',
'event_inheritance',
array('silver'),
'event_test.html',
array(),
array(),
array(),
'Kappa test event in all
Omega test event in all
Zeta test event in all
Kappa test event in silver
Omega test event in silver',
),
array(
'Template event with inheritance - child',
'event_inheritance',
array('silver_inherit', 'silver'),
'event_test.html',
array(),
array(),
array(),
'Kappa test event in all
Omega test event in all
Zeta test event in all
Kappa test event in silver_inherit',
),
array(
'Definition in parent style',
'event_inheritance',
array('silver_inherit', 'silver'),
'event_two.html',
array(),
array(),
array(),
'two in silver in omega',
),
);
}
/**
* @dataProvider template_data
*/
public function test_event($desc, $dataset, $style_names, $file, array $vars, array $block_vars, array $destroy, $expected)
{
// Reset the engine state
$this->setup_engine_for_events($dataset, $style_names);
// Run test
$cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.php';
$this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
}
protected function setup_engine_for_events($dataset, $style_names, array $new_config = array())
{
global $phpbb_root_path, $phpEx, $user;
$defaults = $this->config_defaults();
$config = new phpbb_config(array_merge($defaults, $new_config));
$this->template_path = dirname(__FILE__) . "/datasets/$dataset/styles/silver/template";
$this->style_resource_locator = new phpbb_style_resource_locator();
$this->extension_manager = new phpbb_mock_filesystem_extension_manager(
dirname(__FILE__) . "/datasets/$dataset/"
);
$this->template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, new phpbb_template_context, $this->extension_manager);
$this->style_provider = new phpbb_style_path_provider();
$this->style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, $this->style_provider, $this->template);
$this->style->set_custom_style('silver', array($this->template_path), $style_names, '');
}
}

View File

@ -69,7 +69,7 @@ class phpbb_template_template_test_case extends phpbb_test_case
$this->style_provider = new phpbb_style_path_provider();
$this->template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, new phpbb_template_context());
$this->style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, $this->style_provider, $this->template);
$this->style->set_custom_style('tests', $this->template_path, '');
$this->style->set_custom_style('tests', $this->template_path, array(), '');
}
protected function setUp()

View File

@ -24,6 +24,6 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat
$this->style_provider = new phpbb_style_path_provider();
$this->template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, new phpbb_template_context());
$this->style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, $this->style_provider, $this->template);
$this->style->set_custom_style('tests', array($this->template_path, $this->parent_template_path), '');
$this->style->set_custom_style('tests', array($this->template_path, $this->parent_template_path), array(), '');
}
}

View File

@ -0,0 +1,4 @@
<!-- EVENT child_only -->
<!-- EVENT parent_only -->
<!-- EVENT parent_and_child -->
<!-- EVENT random_event -->