[FEATURE] Allow module menu items to use sprite icons 16/39316/2
authorBenjamin Mack <benni@typo3.org>
Thu, 7 May 2015 04:49:25 +0000 (12:49 +0800)
committerWouter Wolters <typo3@wouterwolters.nl>
Sat, 9 May 2015 15:06:23 +0000 (17:06 +0200)
In the course of the 7.x development, the main modules (web / file etc.)
have received a hard-coded list of fontawesome sprite icons. This way
it is not (easily) possible to override the icons and to give a custom
main module its own custom sprite icon.

A new property in the module configuration "icon" allows now to
hand in a sprite icon instead of a path to png/gif file.

At the same time the property handling for the "icon" property
inside the module menu is now simplified as a string instead
of an array with all additional information as everything is already
compiled together in the BackendModuleRepository.

All main modules shipped with the core now have proper icons
mapped inside ext_tables.php in the core.

Resolves: #66822
Releases: master
Change-Id: If1a62528d9de56034a0330c0051dfcb66e59469c
Reviewed-on: http://review.typo3.org/39316
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez <typo3@scripting-base.de>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
typo3/sysext/backend/Classes/Backend/ToolbarItems/HelpToolbarItem.php
typo3/sysext/backend/Classes/Backend/ToolbarItems/UserToolbarItem.php
typo3/sysext/backend/Classes/Domain/Model/Module/BackendModule.php
typo3/sysext/backend/Classes/Domain/Repository/Module/BackendModuleRepository.php
typo3/sysext/backend/Resources/Private/Templates/ModuleMenu/Main.html
typo3/sysext/core/Documentation/Changelog/master/Feature-66822-SpriteIconsInBackendModules.rst [new file with mode: 0644]
typo3/sysext/core/ext_tables.php
typo3/sysext/t3skin/Classes/Slot/IconStyleModifier.php

index 550a8cb..e86af44 100644 (file)
@@ -58,7 +58,7 @@ class HelpToolbarItem implements ToolbarItemInterface {
         * @return string Help
         */
        public function getItem() {
-               return '<span class="fa fa-fw fa-question-circle"></span>';
+               return $this->helpModuleMenu->getIcon();
        }
 
        /**
@@ -81,7 +81,7 @@ class HelpToolbarItem implements ToolbarItemInterface {
                                . ' data-navigationframescriptparameters="' . htmlspecialchars($module->getNavigationFrameScriptParameters()) . '"'
                                . '>';
                        $dropdown[] = '<a title="' . htmlspecialchars($module->getDescription()) . '" href="' . htmlspecialchars($module->getLink()) . '" class="dropdown-list-link modlink">';
-                       $dropdown[] = '<span class="submodule-icon typo3-app-icon"><span><span>' . ($moduleIcon['html'] ?: $moduleIcon['html']) . '</span></span></span>';
+                       $dropdown[] = '<span class="submodule-icon typo3-app-icon"><span><span>' . $moduleIcon . '</span></span></span>';
                        $dropdown[] = '<span class="submodule-label">' . htmlspecialchars($module->getTitle()) . '</span>';
                        $dropdown[] = '</a>';
                        $dropdown[] = '</li>';
index a3a01c5..406ac73 100644 (file)
@@ -84,7 +84,6 @@ class UserToolbarItem implements ToolbarItemInterface {
                if ($userModuleMenu != FALSE && $userModuleMenu->getChildren()->count() > 0) {
                        foreach ($userModuleMenu->getChildren() as $module) {
                                /** @var BackendModule $module */
-                               $moduleIcon = $module->getIcon();
                                $dropdown[] ='<li'
                                        . ' id="' . htmlspecialchars($module->getName()) . '"'
                                        . ' class="typo3-module-menu-item submodule mod-' . htmlspecialchars($module->getName()) . '" '
@@ -94,7 +93,7 @@ class UserToolbarItem implements ToolbarItemInterface {
                                        . ' data-navigationframescriptparameters="' . htmlspecialchars($module->getNavigationFrameScriptParameters()) . '"'
                                        . '>';
                                $dropdown[] = '<a title="' . htmlspecialchars($module->getDescription()) . '" href="' . htmlspecialchars($module->getLink()) . '" class="dropdown-list-link modlink">';
-                               $dropdown[] = '<span class="submodule-icon typo3-app-icon"><span><span>' . ($moduleIcon['html'] ?: $moduleIcon['html']) . '</span></span></span>';
+                               $dropdown[] = '<span class="submodule-icon typo3-app-icon"><span><span>' . $module->getIcon() . '</span></span></span>';
                                $dropdown[] = '<span class="submodule-label">' . htmlspecialchars($module->getTitle()) . '</span>';
                                $dropdown[] = '</a>';
                                $dropdown[] = '</li>';
index 5869777..ee06a74 100644 (file)
@@ -32,9 +32,9 @@ class BackendModule {
        protected $name = '';
 
        /**
-        * @var array
+        * @var string
         */
-       protected $icon = array();
+       protected $icon = '';
 
        /**
         * @var string
@@ -110,17 +110,17 @@ class BackendModule {
        /**
         * Set icon
         *
-        * @param array $icon
+        * @param string $icon
         * @return void
         */
-       public function setIcon(array $icon) {
+       public function setIcon($icon) {
                $this->icon = $icon;
        }
 
        /**
         * Get icon
         *
-        * @return array
+        * @return string
         */
        public function getIcon() {
                return $this->icon;
index 5c21c6a..9e1488e 100644 (file)
@@ -159,7 +159,7 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface {
                if (!empty($module['description']) && is_string($module['description'])) {
                        $entry->setDescription($module['description']);
                }
-               if (!empty($module['icon']) && is_array($module['icon'])) {
+               if (!empty($module['icon'])) {
                        $entry->setIcon($module['icon']);
                }
                if (!empty($module['navigationComponentId']) && is_string($module['navigationComponentId'])) {
@@ -240,12 +240,11 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface {
                        }
                        $moduleLink = GeneralUtility::resolveBackPath($moduleLink);
                        $moduleKey = 'modmenu_' . $moduleName;
-                       $moduleIcon = $this->getModuleIcon($moduleKey);
                        $modules[$moduleKey] = array(
                                'name' => $moduleName,
                                'title' => $GLOBALS['LANG']->moduleLabels['tabs'][$moduleName . '_tab'],
                                'onclick' => 'top.goToModule(' . GeneralUtility::quoteJSvalue($moduleName) . ');',
-                               'icon' => $moduleIcon,
+                               'icon' => $this->getModuleIcon($moduleName, $moduleData),
                                'link' => $moduleLink,
                                'description' => $GLOBALS['LANG']->moduleLabels['labels'][$moduleKey . 'label']
                        );
@@ -255,7 +254,7 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface {
                                        'name' => $moduleName,
                                        'title' => $GLOBALS['LANG']->moduleLabels['tabs'][$moduleName . '_tab'],
                                        'onclick' => 'top.goToModule(' . GeneralUtility::quoteJSvalue($moduleName) . ');',
-                                       'icon' => $this->getModuleIcon($moduleName . '_tab'),
+                                       'icon' => $this->getModuleIcon($moduleName . '_tab', $moduleData),
                                        'link' => $moduleLink,
                                        'originalLink' => $moduleLink,
                                        'description' => $GLOBALS['LANG']->moduleLabels['labels'][$moduleKey . 'label'],
@@ -271,7 +270,6 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface {
                                                $submoduleLink = BackendUtility::getModuleUrl($submoduleData['name']);
                                        }
                                        $submoduleKey = $moduleName . '_' . $submoduleName . '_tab';
-                                       $submoduleIcon = $this->getModuleIcon($submoduleKey);
                                        $submoduleDescription = $GLOBALS['LANG']->moduleLabels['labels'][$submoduleKey . 'label'];
                                        $originalLink = $submoduleLink;
                                        if (isset($submoduleData['navigationFrameModule'])) {
@@ -288,7 +286,7 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface {
                                                'name' => $moduleName . '_' . $submoduleName,
                                                'title' => $GLOBALS['LANG']->moduleLabels['tabs'][$submoduleKey],
                                                'onclick' => 'top.goToModule(' . GeneralUtility::quoteJSvalue($moduleName . '_' . $submoduleName) . ');',
-                                               'icon' => $submoduleIcon,
+                                               'icon' => $this->getModuleIcon($submoduleKey, $submoduleData),
                                                'link' => $submoduleLink,
                                                'originalLink' => $originalLink,
                                                'description' => $submoduleDescription,
@@ -342,27 +340,22 @@ class BackendModuleRepository implements \TYPO3\CMS\Core\SingletonInterface {
         * gets the module icon and its size
         *
         * @param string $moduleKey Module key
-        * @return array Icon data array with 'filename', 'size', and 'html'
+        * @param array $moduleData the compiled data associated with it
+        * @return string Icon data, either sprite or <img> tag
         */
-       protected function getModuleIcon($moduleKey) {
-               $icon = array(
-                       'filename' => '',
-                       'size' => '',
-                       'title' => '',
-                       'html' => ''
-               );
+       protected function getModuleIcon($moduleKey, $moduleData) {
+               $icon = '';
 
-               if (!empty($GLOBALS['LANG']->moduleLabels['tabs_images'][$moduleKey])) {
+               // add as a sprite icon
+               if ($moduleData['configuration']['icon']) {
+                       $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon($moduleData['configuration']['icon'], array('tagName' => 'i'));
+               } elseif (!empty($GLOBALS['LANG']->moduleLabels['tabs_images'][$moduleKey])) {
                        $imageReference = $GLOBALS['LANG']->moduleLabels['tabs_images'][$moduleKey];
                        $iconFileRelative = $this->getModuleIconRelative($imageReference);
                        if (!empty($iconFileRelative)) {
                                $iconTitle = $GLOBALS['LANG']->moduleLabels['tabs'][$moduleKey];
-                               $iconFileAbsolute = $this->getModuleIconAbsolute($imageReference);
-                               $iconSizes = @getimagesize($iconFileAbsolute);
-                               $icon['filename'] = $iconFileRelative;
-                               $icon['size'] = $iconSizes[3];
-                               $icon['title'] = htmlspecialchars($iconTitle);
-                               $icon['html'] = '<img src="' . $iconFileRelative . '" ' . $iconSizes[3] . ' title="' . htmlspecialchars($iconTitle) . '" alt="' . htmlspecialchars($iconTitle) . '" />';
+                               $iconSizes = @getimagesize($this->getModuleIconAbsolute($imageReference));
+                               $icon = '<img src="' . $iconFileRelative . '" ' . $iconSizes[3] . ' title="' . htmlspecialchars($iconTitle) . '" alt="' . htmlspecialchars($iconTitle) . '" />';
                        }
                }
                return $icon;
index efb3751..3768003 100644 (file)
@@ -5,18 +5,12 @@
                                <span class="typo3-app-icon typo3-module-menu-group-icon">
                                        <span>
                                                <span>
-                                                       <f:if condition="{mainModule.icon.html}">
+                                                       <f:if condition="{mainModule.icon}">
                                                                <f:then>
-                                                                       <f:format.raw>{mainModule.icon.html}</f:format.raw>
+                                                                       <f:format.raw>{mainModule.icon}</f:format.raw>
                                                                </f:then>
                                                                <f:else>
-                                                                       <f:switch expression="{mainModule.name}">
-                                                                               <f:case value="web"><i class="fa fa-file-o"></i></f:case>
-                                                                               <f:case value="system"><i class="fa fa-plug"></i></f:case>
-                                                                               <f:case value="file"><i class="fa fa-image"></i></f:case>
-                                                                               <f:case value="tools"><i class="fa fa-rocket"></i></f:case>
-                                                                               <f:case default="TRUE"><i class="fa fa-bars"></i></f:case>
-                                                                       </f:switch>
+                                                                       <i class="fa fa-bars"></i>
                                                                </f:else>
                                                        </f:if>
                                                </span>
@@ -33,7 +27,7 @@
                                                        <span class="typo3-app-icon typo3-module-menu-item-icon">
                                                                <span>
                                                                        <span>
-                                                                               <f:format.raw>{subModule.icon.html}</f:format.raw>
+                                                                               <f:format.raw>{subModule.icon}</f:format.raw>
                                                                        </span>
                                                                </span>
                                                        </span>
@@ -46,4 +40,4 @@
                        </ul>
                </li>
        </f:for>
-</ul>
\ No newline at end of file
+</ul>
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-66822-SpriteIconsInBackendModules.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-66822-SpriteIconsInBackendModules.rst
new file mode 100644 (file)
index 0000000..a52c09d
--- /dev/null
@@ -0,0 +1,33 @@
+===================================================
+Feature: #66822 - Allow Sprites For Backend Modules
+===================================================
+
+Description
+===========
+
+Backend Modules (both Main Modules like "Web" and Submodules like "Filelist") can now use sprites instead of images for
+displaying the icons in the module menu on the left side of the TYPO3 Backend.
+
+Registering a module can now look like this (as an example the "Page" module):
+
+.. code-block:: [php]
+
+       \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule(
+               'web',
+               'layout',
+               'top',
+               \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY) . 'Modules/Layout/',
+               array(
+                       'script' => '_DISPATCH',
+                       'access' => 'user,group',
+                       'name' => 'web_layout',
+                       'configuration' => array(
+                               'icon' => 'module-web',
+                       ),
+                       'labels' => array(
+                               'll_ref' => 'LLL:EXT:cms/layout/locallang_mod.xlf',
+                       ),
+               )
+       );
+
+One can use any available sprite icon known to TYPO3.
index 5587e0b..f9a1b3f 100644 (file)
@@ -65,43 +65,43 @@ $GLOBALS['TBE_MODULES'] = array(
        '_configuration' => array(
                'web' => array(
                        'labels' => array(
-                               'tabs_images' => array('tab' => 'website.gif'),
                                'll_ref' => 'LLL:EXT:lang/locallang_mod_web.xlf'
                        ),
                        'configuration' => array(
                                'name' => 'web',
-                               'access' => 'user,group'
+                               'access' => 'user,group',
+                               'icon' => 'module-web'
                        )
                ),
                'file' => array(
                        'labels' => array(
-                               'tabs_images' => array('tab' => 'file.gif'),
                                'll_ref' => 'LLL:EXT:lang/locallang_mod_file.xlf'
                        ),
                        'configuration' => array(
                                'name' => 'file',
                                'access' => 'user,group',
-                               'workspaces' => 'online,custom'
+                               'workspaces' => 'online,custom',
+                               'icon' => 'module-file'
                        )
                ),
                'user' => array(
                        'labels' => array(
-                               'tabs_images' => array('tab' => 'user.gif'),
                                'll_ref' => 'LLL:EXT:lang/locallang_mod_usertools.xlf'
                        ),
                        'configuration' => array(
                                'name' => 'user',
-                               'access' => 'user,group'
+                               'access' => 'user,group',
+                               'icon' => 'status-user-backend'
                        )
                ),
                'tools' => array(
                        'labels' => array(
-                               'tabs_images' => array('tab' => 'tool.gif'),
                                'll_ref' => 'LLL:EXT:lang/locallang_mod_admintools.xlf'
                        ),
                        'configuration' => array(
                                'name' => 'tools',
-                               'access' => 'admin'
+                               'access' => 'admin',
+                               'icon' => 'module-tools'
                        )
                ),
                'system' => array(
@@ -110,7 +110,8 @@ $GLOBALS['TBE_MODULES'] = array(
                        ),
                        'configuration' => array(
                                'name' => 'system',
-                               'access' => 'admin'
+                               'access' => 'admin',
+                               'icon' => 'module-system'
                        )
                ),
                'help' => array(
@@ -118,7 +119,8 @@ $GLOBALS['TBE_MODULES'] = array(
                                'll_ref' => 'LLL:EXT:lang/locallang_mod_help.xlf'
                        ),
                        'configuration' => array(
-                               'name' => 'help'
+                               'name' => 'help',
+                               'icon' => 'module-help'
                        )
                )
        )
@@ -577,7 +579,13 @@ $GLOBALS['TBE_STYLES']['spriteIconApi']['coreSpriteImageNames'] = array(
        'treeline-plus',
        'treeline-plusbottom',
        'treeline-plusonly',
-       'treeline-stopper'
+       'treeline-stopper',
+       'module-web',
+       'module-file',
+       'module-system',
+       'module-tools',
+       'module-user',
+       'module-help',
 );
 
 
index 852d2ce..02f0e11 100644 (file)
@@ -126,7 +126,12 @@ class IconStyleModifier {
                't3-icon t3-icon-actions t3-icon-actions-move t3-icon-move-move sortableHandle' => 'fa-reorder sortableHandle',
                't3-icon t3-icon-actions t3-icon-actions-move t3-icon-move-move' => 'fa-reorder',
                't3-icon t3-icon-actions t3-icon-actions-document t3-icon-document-paste-into' => 'fa-clipboard',
-               't3-icon t3-icon-actions t3-icon-actions-system t3-icon-system-options-view' => 'fa-list-alt'
+               't3-icon t3-icon-actions t3-icon-actions-system t3-icon-system-options-view' => 'fa-list-alt',
+               't3-icon t3-icon-module t3-icon-module-web t3-icon-web' => 'fa-file-o',
+               't3-icon t3-icon-module t3-icon-module-file t3-icon-file' => 'fa-image',
+               't3-icon t3-icon-module t3-icon-module-tools t3-icon-tools' => 'fa-rocket',
+               't3-icon t3-icon-module t3-icon-module-system t3-icon-system' => 'fa-plug',
+               't3-icon t3-icon-module t3-icon-module-help t3-icon-help' => 'fa-fw fa-question-circle'
        );
 
        /**
@@ -138,9 +143,14 @@ class IconStyleModifier {
         * @return array
         */
        public function buildSpriteHtmlIconTag(array $tagAttributes, $innerHtml, $tagName) {
-               $class = !empty($this->flatSpriteIconName[$tagAttributes['class']]) ? $this->flatSpriteIconName[$tagAttributes['class']] : NULL;
-               if ($class !== NULL) {
-                       $tagAttributes['class'] = 't3-icon fa ' . $class;
+               $classNames = $tagAttributes['class'];
+               if (strpos($classNames, 'fa-') !== FALSE) {
+                       $tagAttributes['class'] = 't3-icon fa ' . $classNames;
+               } else {
+                       $classNames = !empty($this->flatSpriteIconName[$classNames]) ? $this->flatSpriteIconName[$classNames] : NULL;
+                       if ($classNames !== NULL) {
+                               $tagAttributes['class'] = 't3-icon fa ' . $classNames;
+                       }
                }
 
                return array($tagAttributes, $innerHtml, $tagName);
@@ -154,7 +164,9 @@ class IconStyleModifier {
         * @return string
         */
        public function buildSpriteIconClasses($iconName, &$cssClasses) {
-               if (isset($this->flatSpriteIconName[$cssClasses])) {
+               if (strpos($iconName, 'fa-') !== FALSE) {
+                       $cssClasses = 't3-icon fa ' . $iconName;
+               } elseif (isset($this->flatSpriteIconName[$cssClasses])) {
                        $cssClasses = 't3-icon fa ' . $this->flatSpriteIconName[$cssClasses];
                }
        }