1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-07-31 14:00:31 +02:00

[ticket/15538] Create macro and remove icons

PHPBB3-15538
This commit is contained in:
mrgoldy
2019-09-30 16:42:03 +02:00
committed by Marc Alexander
parent 094f0f663c
commit d8274c19c8
14 changed files with 200 additions and 178 deletions

View File

@@ -1,165 +1,120 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\template\twig\extension;
use phpbb\template\twig\environment;
class icon extends \Twig_Extension
abstract class icon extends \Twig\Extension\AbstractExtension implements \Twig\Extension\GlobalsInterface
{
/** @var \phpbb\user */
protected $twig;
protected $user;
/**
* Constructor.
*
* @param \phpbb\user $user User object
*/
public function __construct(\phpbb\user $user)
public function __construct(environment $twig, \phpbb\user $user)
{
$this->twig = $twig;
$this->user = $user;
}
/**
* Get the name of this extension.
*
* @return string
*/
* Get the name of this extension.
*
* @return string
*/
public function getName()
{
return 'icon';
}
/**
* Returns a list of global functions to add to the existing list.
*
* @return array An array of global functions
*/
public function getFunctions()
{
return [
new \Twig_SimpleFunction('Icon', [$this, 'icon'], ['needs_environment' => true]),
];
}
/**
* Generate icon HTML for use in the template, depending on the mode.
* Returns a list of global variables to add to the existing list.
*
* @param environment $environment Twig environment object
* @param string $type Icon type (font|png|svg)
* @param string $icon Icon name (eg. "bold")
* @param string $classes Additional classes (eg. "fa-fw")
* @param string $title Icon title
* @param bool $hidden Hide the icon title from view
* @param array $attributes Additional attributes for the icon, where the key is the attribute.
* {'data-ajax': 'mark_forums'} results in ' data-ajax="mark_forums"'
* @return string
* @return array An array of global variables
*/
public function icon(environment $environment, $type = '', $icon = '', $classes = '', $title = '', $hidden = false, array $attributes = [])
public function getGlobals()
{
switch ($type)
{
case 'font':
$src = '';
break;
case 'png':
$board_url = defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH;
$web_path = $board_url ? generate_board_url() . '/' : $environment->get_web_root_path();
$src = "{$web_path}styles/" . $this->user->style['style_path'] . "/template/icons/png/{$icon}.png";
break;
case 'svg':
try
{
$file = $environment->load('icons/svg/' . $icon . '.svg');
}
catch (\Twig_Error $e)
{
return '';
}
$src = $this->filter_svg($file);
break;
default:
// Not a supported icon type (font|png|svg), return an empty string
return '';
break;
}
$macros = null;
try
{
return $environment->render("icons/{$type}.html", [
'ATTRIBUTES' => (string) $this->implode_attributes($attributes),
'CLASSES' => (string) $classes,
'ICON' => (string) $icon,
'SOURCE' => (string) $src,
'TITLE' => (string) $title,
'S_HIDDEN' => (bool) $hidden,
]);
$macros = $this->twig->loadTemplate('macros.html');
}
catch (\Twig_Error $e)
catch (\Twig\Error\Error $e)
{
}
return [
'macro' => $macros,
];
}
public function getFilters()
{
return [
new \Twig\TwigFilter('Png_path', [$this, 'png_path'], ['needs_environment' => true]),
];
}
public function getFunctions()
{
return [
new \Twig\TwigFunction('Svg_clean', [$this, 'svg_clean'], ['needs_environment' => true]),
new \Twig\TwigFunction('Implode_attributes', [$this, 'implode_attributes']),
new \Twig\TwigFunction('Implode_classes', [$this, 'implode_classes']),
];
}
protected function png_path(environment $environment, $icon)
{
$board_url = defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH;
$web_path = $board_url ? generate_board_url() . '/' : $environment->get_web_root_path();
$style_path = $this->user->style['style_path'];
return "{$web_path}styles/{$style_path}/template/icons/png/{$icon}.png";
}
protected function svg_clean(environment $environment, $icon)
{
try
{
$file = $environment->load('icons/svg/' . $icon . '.svg');
}
catch (\Twig\Error\Error $e)
{
return '';
}
}
/**
* Implode an associated array of attributes to a string for usage in a template.
*
* @param array $attributes Associated array of attributes
* @return string
*/
protected function implode_attributes(array $attributes)
{
$attr_str = '';
foreach ($attributes as $attribute => $value)
{
$attr_str .= ' ' . $attribute . '="' . $value . '"';
}
return $attr_str;
}
/**
* Filter a SVG for usage in the template.
*
* @param \Twig_TemplateWrapper $file The svg file loaded from the environment
* @return string
*/
protected function filter_svg(\Twig_TemplateWrapper $file)
{
/** @var \Twig_Source $src */
$src = $file->getSourceContext();
$svg = $src->getCode();
/** @var \DOMDocument $dom */
$dom = new \DOMDocument();
$dom->preserveWhiteSpace = false;
$doc = new \DOMDocument();
$doc->formatOutput = false;
$doc->preserveWhiteSpace = false;
$doc->strictErrorChecking = false;
/**
* Suppression is needed as DOMDocument does not like HTML5 and SVGs.
* Options parameter prevents $dom->saveHTML() from adding an <html> element.
*/
@$dom->loadHTML($svg, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
if (!$doc->loadXML($svg))
{
return '';
}
/** @var \DOMXPath $xpath */
$xpath = new \DOMXPath($dom);
foreach ($doc->childNodes as $child) {
if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
$child->parentNode->removeChild($child);
}
}
$xpath = new \DOMXPath($doc);
/** @var \DOMNode $element */
foreach ($xpath->query('//svg | //title') as $element)
{
if ($element->nodeName === 'svg')
@@ -182,17 +137,95 @@ class icon extends \Twig_Extension
$element->parentNode->removeChild($element);
}
/** @var \DOMElement $attribute */
foreach ($xpath->query('//@fill') as $attribute)
{
if ($attribute->nodeName === 'fill' && $attribute->nodeValue === 'none')
{
continue;
}
$string = $doc->saveXML($doc->documentElement, LIBXML_NOEMPTYTAG);
$string = preg_replace('/\s+/', ' ', $string);
$attribute->parentNode->removeAttribute($attribute->nodeName);
return $string;
}
protected function implode_attributes(...$arguments)
{
$string = '';
$attributes = [];
foreach ($arguments as $argument)
{
if (is_string($argument))
{
$attributes[] = $argument;
}
else if (is_array($argument))
{
foreach ($argument as $key => $value)
{
if (is_integer($key) && is_string($value))
{
$attributes[] = $value;
}
else
{
$attributes[$key] = $value;
}
}
}
}
return $dom->saveHTML();
foreach ($attributes as $attribute => $value)
{
if (is_string($attribute))
{
$string .= ' ' . $attribute . '="' . $value . '"';
}
else
{
$string .= ' ' . $attribute;
}
}
return $string;
}
protected function implode_classes(...$arguments)
{
$classes = [];
foreach ($arguments as $argument)
{
if (is_string($argument))
{
$classes[] = $argument;
}
else if (is_array($argument))
{
foreach ($argument as $key => $value)
{
if (is_integer($key) && is_string($value))
{
$classes[] = $value;
}
else if (is_string($key))
{
if ($value)
{
$classes[] = $key;
}
}
else if (is_array($value))
{
foreach ($value as $class => $condition)
{
if ($condition)
{
$classes[] = $class;
}
}
}
}
}
}
$string = implode(' ', array_unique($classes));
return $string ? ' ' . $string : $string;
}
}