diff --git a/phpBB/config/default/container/services_twig.yml b/phpBB/config/default/container/services_twig.yml index 24ee24484b..3e3d1a4674 100644 --- a/phpBB/config/default/container/services_twig.yml +++ b/phpBB/config/default/container/services_twig.yml @@ -54,6 +54,13 @@ services: tags: - { name: twig.extension } + template.twig.extensions.icon: + class: phpbb\template\twig\extension\icon + arguments: + - '@user' + tags: + - { name: twig.extension } + template.twig.extensions.routing: class: phpbb\template\twig\extension\routing arguments: diff --git a/phpBB/phpbb/template/twig/extension/icon.php b/phpBB/phpbb/template/twig/extension/icon.php new file mode 100644 index 0000000000..be83222a62 --- /dev/null +++ b/phpBB/phpbb/template/twig/extension/icon.php @@ -0,0 +1,198 @@ + +* @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 +{ + /** @var \phpbb\user */ + protected $user; + + /** + * Constructor. + * + * @param \phpbb\user $user User object + */ + public function __construct(\phpbb\user $user) + { + $this->user = $user; + } + + /** + * 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. + * + * @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 + */ + public function icon(environment $environment, $type = '', $icon = '', $classes = '', $title = '', $hidden = false, array $attributes = []) + { + 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; + } + + 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, + ]); + } + catch (\Twig_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; + + /** + * Suppression is needed as DOMDocument does not like HTML5 and SVGs. + * Options parameter prevents $dom->saveHTML() from adding an element. + */ + @$dom->loadHTML($svg, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + + /** @var \DOMXPath $xpath */ + $xpath = new \DOMXPath($dom); + + /** @var \DOMNode $element */ + foreach ($xpath->query('//svg | //title') as $element) + { + if ($element->nodeName === 'svg') + { + $children = []; + + /** @var \DOMNode $node */ + foreach ($element->childNodes as $node) + { + $children[] = $node; + } + + /** @var \DOMNode $child */ + foreach ($children as $child) + { + $element->parentNode->insertBefore($child, $element); + } + } + + $element->parentNode->removeChild($element); + } + + /** @var \DOMElement $attribute */ + foreach ($xpath->query('//@fill') as $attribute) + { + if ($attribute->nodeName === 'fill' && $attribute->nodeValue === 'none') + { + continue; + } + + $attribute->parentNode->removeAttribute($attribute->nodeName); + } + + return $dom->saveHTML(); + } +} diff --git a/phpBB/styles/prosilver/template/icons/font.html b/phpBB/styles/prosilver/template/icons/font.html new file mode 100644 index 0000000000..488d434fa9 --- /dev/null +++ b/phpBB/styles/prosilver/template/icons/font.html @@ -0,0 +1,11 @@ +{% spaceless %} + +{% if TITLE %}{{ lang(TITLE) }}{% endif %} +{% endspaceless %} diff --git a/phpBB/styles/prosilver/template/icons/png.html b/phpBB/styles/prosilver/template/icons/png.html new file mode 100644 index 0000000000..dafdece71e --- /dev/null +++ b/phpBB/styles/prosilver/template/icons/png.html @@ -0,0 +1,8 @@ +{% spaceless %} +{{ lang(TITLE) }} +{% endspaceless %} diff --git a/phpBB/styles/prosilver/template/icons/png/bars.png b/phpBB/styles/prosilver/template/icons/png/bars.png new file mode 100644 index 0000000000..e8dcba56ec Binary files /dev/null and b/phpBB/styles/prosilver/template/icons/png/bars.png differ diff --git a/phpBB/styles/prosilver/template/icons/png/envelope.png b/phpBB/styles/prosilver/template/icons/png/envelope.png new file mode 100644 index 0000000000..d435a9b648 Binary files /dev/null and b/phpBB/styles/prosilver/template/icons/png/envelope.png differ diff --git a/phpBB/styles/prosilver/template/icons/png/pencil.png b/phpBB/styles/prosilver/template/icons/png/pencil.png new file mode 100644 index 0000000000..9ec4db8f9d Binary files /dev/null and b/phpBB/styles/prosilver/template/icons/png/pencil.png differ diff --git a/phpBB/styles/prosilver/template/icons/png/phone.png b/phpBB/styles/prosilver/template/icons/png/phone.png new file mode 100644 index 0000000000..7a7e756311 Binary files /dev/null and b/phpBB/styles/prosilver/template/icons/png/phone.png differ diff --git a/phpBB/styles/prosilver/template/icons/svg.html b/phpBB/styles/prosilver/template/icons/svg.html new file mode 100644 index 0000000000..67339b6ea2 --- /dev/null +++ b/phpBB/styles/prosilver/template/icons/svg.html @@ -0,0 +1,21 @@ +{% spaceless %} + {% set TITLE_ID = TITLE ? TITLE|lower|replace({' ': '-'}) ~ '-' ~ random() %} + + {% if TITLE %} + + {{ lang(TITLE) }} + + {% endif %} + + {{ SOURCE }} + +{% endspaceless %} diff --git a/phpBB/styles/prosilver/template/icons/svg/bars.svg b/phpBB/styles/prosilver/template/icons/svg/bars.svg new file mode 100644 index 0000000000..c3317edaf5 --- /dev/null +++ b/phpBB/styles/prosilver/template/icons/svg/bars.svg @@ -0,0 +1 @@ + diff --git a/phpBB/styles/prosilver/template/icons/svg/envelope.svg b/phpBB/styles/prosilver/template/icons/svg/envelope.svg new file mode 100644 index 0000000000..4f073b3362 --- /dev/null +++ b/phpBB/styles/prosilver/template/icons/svg/envelope.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/phpBB/styles/prosilver/template/icons/svg/pencil.svg b/phpBB/styles/prosilver/template/icons/svg/pencil.svg new file mode 100644 index 0000000000..c9c021d811 --- /dev/null +++ b/phpBB/styles/prosilver/template/icons/svg/pencil.svg @@ -0,0 +1 @@ +My fake title! diff --git a/phpBB/styles/prosilver/template/icons/svg/phone.svg b/phpBB/styles/prosilver/template/icons/svg/phone.svg new file mode 100644 index 0000000000..c542ecee29 --- /dev/null +++ b/phpBB/styles/prosilver/template/icons/svg/phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/phpBB/styles/prosilver/template/index_body.html b/phpBB/styles/prosilver/template/index_body.html index 94d069b597..3e37fb788e 100644 --- a/phpBB/styles/prosilver/template/index_body.html +++ b/phpBB/styles/prosilver/template/index_body.html @@ -34,6 +34,36 @@ +
+

Font

+
+ {{ icon('font', 'bars', 'fa-fw icon-blue') }} + {{ icon('font', 'envelope-o') }} + {{ icon('font', 'pencil', '', '', true, {'data-ajax': 'true', 'data-refresh': 'true'}) }} + {{ icon('font', 'phone') }} + {{ icon('font', 'pencil', 'fa-fw', 'POST_REPLY') }} + {{ icon('font', 'pencil', 'fa-fw', 'POST_REPLY') }} +
+

PNG

+
+ {{ icon('png', 'bars') }} + {{ icon('png', 'envelope') }} + {{ icon('png', 'pencil') }} + {{ icon('png', 'phone') }} + {{ icon('png', 'pencil', 'fa-fw', 'POST_REPLY') }} + {{ icon('png', 'pencil', 'fa-fw', 'POST_REPLY') }} +
+

SVG

+
+ {{ icon('svg', 'bars', 'fa-fw icon-blue') }} + {{ icon('svg', 'envelope', '', 'USERNAME', false) }} + {{ icon('svg', 'pencil') }} + {{ icon('svg', 'phone') }} + {{ icon('svg', 'pencil') }} + {{ icon('svg', 'pencil', 'fa-fw', 'POST_REPLY') }} +
+
+ @@ -41,7 +71,7 @@

{L_WHO_IS_ONLINE}

{L_WHO_IS_ONLINE}

- {TOTAL_USERS_ONLINE} ({L_ONLINE_EXPLAIN})
{RECORD_USERS}
+ {TOTAL_USERS_ONLINE} ({L_ONLINE_EXPLAIN})
{RECORD_USERS}

{LOGGED_IN_USER_LIST}
{L_LEGEND}{L_COLON} {LEGEND} diff --git a/phpBB/styles/prosilver/theme/icons.css b/phpBB/styles/prosilver/theme/icons.css index 1268627d51..5a2e288e3d 100644 --- a/phpBB/styles/prosilver/theme/icons.css +++ b/phpBB/styles/prosilver/theme/icons.css @@ -5,6 +5,11 @@ /* Global module setup ---------------------------------------- */ +/* Global svg colours fix */ +svg { + fill: currentColor; +} + /* Renamed version of .fa class for agnostic usage of icon fonts. * Just change the name of the font after the 14/1 to the name of * the font you wish to use. @@ -27,6 +32,14 @@ blockquote cite:before, text-rendering: auto; /* optimizelegibility throws things off #1094 */ } +img.icon, +svg.icon { + width: 14px; + height: 14px; + display: inline-block; + vertical-align: middle; +} + .icon:before { padding-right: 2px; } @@ -39,18 +52,26 @@ blockquote cite:before, .icon.icon-xl { font-size: 20px; + width: 20px; + height: 20px; } .icon.icon-lg { font-size: 16px; + width: 16px; + height: 16px; } .icon.icon-md { font-size: 10px; + width: 10px; + height: 10px; } .icon.icon-sm { font-size: 8px; + width: 8px; + height: 8px; } /* icon modifiers */