diff --git a/phpBB/phpbb/template/twig/extension/icon.php b/phpBB/phpbb/template/twig/extension/icon.php
index 27807c9ecc..b2a98fad3f 100644
--- a/phpBB/phpbb/template/twig/extension/icon.php
+++ b/phpBB/phpbb/template/twig/extension/icon.php
@@ -125,6 +125,9 @@ class icon extends \Twig\Extension\AbstractExtension
*/
protected function prepare_svg(\Twig\TemplateWrapper $file)
{
+ $code = $file->render();
+ $code = preg_replace( "/<\?xml.+?\?>/", '', $code);
+
$doc = new \DOMDocument();
$doc->preserveWhiteSpace = false;
@@ -132,7 +135,16 @@ class icon extends \Twig\Extension\AbstractExtension
* Suppression is needed as DOMDocument does not like HTML5 and SVGs.
* Options parameter prevents $dom->saveHTML() from adding an element.
*/
- @$doc->loadHTML($file->render(), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
+ @$doc->loadHTML($code, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
+
+ // Remove any DOCTYPE
+ foreach ($doc->childNodes as $child)
+ {
+ if ($child->nodeType === XML_DOCUMENT_TYPE_NODE)
+ {
+ $child->parentNode->removeChild($child);
+ }
+ }
$xpath = new \DOMXPath($doc);
diff --git a/tests/template/extension_test.php b/tests/template/extension_test.php
index 0e9f2110ed..4e8a71b7a9 100644
--- a/tests/template/extension_test.php
+++ b/tests/template/extension_test.php
@@ -15,7 +15,7 @@ require_once dirname(__FILE__) . '/template_test_case.php';
class phpbb_template_extension_test extends phpbb_template_template_test_case
{
- protected function setup_engine(array $new_config = array())
+ protected function setup_engine(array $new_config = [])
{
global $config, $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx;
@@ -28,6 +28,7 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
$this->lang = $lang = new \phpbb\language\language($lang_loader);
$this->user = new \phpbb\user($lang, '\phpbb\datetime');
+ $this->user->style['style_path'] = 'prosilver';
global $auth, $request, $symfony_request, $user;
$user = new phpbb_mock_user();
@@ -73,7 +74,7 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
$cache_path = $phpbb_root_path . 'cache/twig';
$context = new \phpbb\template\context();
- $loader = new \phpbb\template\twig\loader('');
+ $loader = new \phpbb\template\twig\loader([]);
$twig = new \phpbb\template\twig\environment(
$config,
$filesystem,
@@ -82,12 +83,12 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
null,
$loader,
new \phpbb\event\dispatcher($phpbb_container),
- array(
+ [
'cache' => false,
'debug' => false,
'auto_reload' => true,
'autoescape' => false,
- )
+ ]
);
$this->template = new phpbb\template\twig\twig(
$phpbb_path_helper,
@@ -100,11 +101,16 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
new \phpbb\template\twig\extension($context, $twig, $this->lang),
new \phpbb\template\twig\extension\avatar(),
new \phpbb\template\twig\extension\config($config),
+ new \phpbb\template\twig\extension\icon($this->user),
new \phpbb\template\twig\extension\username(),
]
);
$twig->setLexer(new \phpbb\template\twig\lexer($twig));
- $this->template->set_custom_style('tests', $this->template_path);
+ $this->template->set_style();
+ $this->template->set_custom_style('tests', [
+ $this->template_path,
+ $phpbb_root_path . 'styles/prosilver/template',
+ ]);
}
public function data_template_extensions()
@@ -253,8 +259,166 @@ class phpbb_template_extension_test extends phpbb_template_template_test_case
/**
* @dataProvider data_template_extensions
*/
- public function test_get_user_avatar($file, $vars, $block_vars, $destroy_array, $expected, $lang_vars = [])
+ public function test_template_extensions($file, $vars, $block_vars, $destroy_array, $expected, $lang_vars = [])
{
$this->run_template($file, $vars, $block_vars, $destroy_array, $expected, $lang_vars);
}
+
+ public function data_template_icon_extension()
+ {
+ return [
+ /** Font: default */
+ [
+ [
+ 'type' => 'font',
+ 'icon' => 'phone',
+ 'title' => 'ICON_PHONE',
+ 'hidden' => false,
+ 'classes' => '',
+ 'attributes' => [],
+ ],
+ [
+ 'ICON_PHONE' => 'Phone icon',
+ ],
+ 'Phone icon',
+
+ ],
+ /** Font: all options */
+ [
+ [
+ 'type' => 'font',
+ 'icon' => 'pencil',
+ 'title' => 'ICON_PENCIL',
+ 'hidden' => true,
+ 'classes' => 'a-class another-class',
+ 'attributes' => [
+ 'data-attr-1' => 'true',
+ 'data-attr-2' => 'two',
+ ],
+ ],
+ [
+ 'ICON_PENCIL' => 'Pencil icon',
+ ],
+ '
+ Pencil icon'
+ ],
+ /** PNG: default */
+ [
+ [
+ 'type' => 'png',
+ 'icon' => 'phone',
+ 'title' => 'ICON_PHONE',
+ 'hidden' => false,
+ 'classes' => '',
+ 'attributes' => [],
+ ],
+ [
+ 'ICON_PHONE' => 'Phone icon',
+ ],
+ '
',
+ ],
+ /** PNG: all options */
+ [
+ [
+ 'type' => 'png',
+ 'icon' => 'pencil',
+ 'title' => 'ICON_PENCIL',
+ 'hidden' => true,
+ 'classes' => 'my-class',
+ 'attributes' => [
+ 'data-url' => 'my-test-url/test-page.php?u=2',
+ ],
+ ],
+ [
+ 'ICON_PENCIL' => 'Pencil icon',
+ ],
+ '
',
+ ],
+ /** SVG: default */
+ [
+ [
+ 'type' => 'svg',
+ 'icon' => 'phone',
+ 'title' => 'ICON_PHONE',
+ 'hidden' => false,
+ 'classes' => '',
+ 'attributes' => [],
+ ],
+ [
+ 'ICON_PHONE' => 'Phone icon',
+ ],
+ '',
+ ],
+ /** SVG: all options */
+ [
+ [
+ 'type' => 'svg',
+ 'icon' => 'pencil',
+ 'title' => 'ICON_PENCIL',
+ 'hidden' => true,
+ 'classes' => 'my-svg-class',
+ 'attributes' => [
+ 'data-ajax' => 'my_ajax_callback',
+ ],
+ ],
+ [
+ 'ICON_PENCIL' => 'Pencil icon',
+ ],
+ '',
+ ],
+ /** SVG: Sanitization */
+ [
+ [
+ 'type' => 'svg',
+ 'icon' => 'dirty',
+ 'title' => '',
+ 'hidden' => false,
+ 'classes' => '',
+ 'attributes' => [],
+ ],
+ [],
+ '',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider data_template_icon_extension
+ */
+ public function test_template_icon_extension($vars, $lang_vars, $expected)
+ {
+ $file = 'extension_icon_test.html';
+
+ $this->template->set_filenames(array('test' => $file));
+ $this->template->assign_vars($vars);
+
+ foreach ($lang_vars as $name => $value)
+ {
+ self::$language_reflection_lang->setValue($this->lang, array_merge(
+ self::$language_reflection_lang->getValue($this->lang),
+ [$name => $value]
+ ));
+ }
+
+ $expected = str_replace(["\n", "\r", "\t"], '', $expected);
+ $output = str_replace(["\n", "\r", "\t"], '', $this->display('test'));
+
+ if ($vars['type'] === 'svg')
+ {
+ $prefix = strtolower($vars['title']) . '-';
+ $output = preg_replace('/' . $prefix . '\d+/', $prefix . '123456789', $output);
+ }
+
+ $this->assertEquals($expected, $output, "Testing {$file}");
+ }
}
diff --git a/tests/template/templates/extension_icon_test.html b/tests/template/templates/extension_icon_test.html
new file mode 100644
index 0000000000..4ea6eb0410
--- /dev/null
+++ b/tests/template/templates/extension_icon_test.html
@@ -0,0 +1 @@
+{{ Icon(type, icon, title, hidden, classes, attributes) }}
diff --git a/tests/template/templates/icons/svg/dirty.svg b/tests/template/templates/icons/svg/dirty.svg
new file mode 100644
index 0000000000..29c1500ffe
--- /dev/null
+++ b/tests/template/templates/icons/svg/dirty.svg
@@ -0,0 +1,6 @@
+
+
+
diff --git a/tests/template/templates/icons/svg/pencil.svg b/tests/template/templates/icons/svg/pencil.svg
new file mode 100644
index 0000000000..c9c021d811
--- /dev/null
+++ b/tests/template/templates/icons/svg/pencil.svg
@@ -0,0 +1 @@
+
diff --git a/tests/template/templates/icons/svg/phone.svg b/tests/template/templates/icons/svg/phone.svg
new file mode 100644
index 0000000000..5fbfe196ba
--- /dev/null
+++ b/tests/template/templates/icons/svg/phone.svg
@@ -0,0 +1 @@
+