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 %}
+
+{% 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() %}
+
+{% 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 @@
+
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 @@
+
- {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 */