jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/372186 )

Change subject: Prepare to break the server side MobileFrontend dependency on 
Minerva
......................................................................


Prepare to break the server side MobileFrontend dependency on Minerva

Changes:
* Minerva now maintains a MinervaUI - a simplified version of
MobileUI that provides iconClass and buttonClass helpers.
* Minerva now maintains its own ResourceLoaderParserMessageModule

Remaining issues:
* Main menu links to '#'
* Unknown dependency errors are thrown due to the missing
JS libraries e.g. mobile.watchstar
thus JS based UI components are unusable e.g. search autocomplete,
and edit button
* Language button navigates to a missing special page without
MobileFrontend (see T104660)

Bug: T169569
Change-Id: I89e2e15faabab73b0cba91afc2f2c5e785edef29
---
A includes/MinervaResourceLoaderParsedMessageModule.php
A includes/MinervaUI.php
M includes/skins/MinervaTemplate.php
M includes/skins/SkinMinerva.php
M skin.json
M tests/phpunit/skins/SkinMinervaTest.php
6 files changed, 186 insertions(+), 24 deletions(-)

Approvals:
  jenkins-bot: Verified
  Jdlrobson: Looks good to me, approved



diff --git a/includes/MinervaResourceLoaderParsedMessageModule.php 
b/includes/MinervaResourceLoaderParsedMessageModule.php
new file mode 100644
index 0000000..2cab60b
--- /dev/null
+++ b/includes/MinervaResourceLoaderParsedMessageModule.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * ResourceLoaderModule subclass for Minerva
+ * Allows basic server side parsing of messages without arguments
+ */
+class MinervaResourceLoaderParsedMessageModule extends 
ResourceLoaderFileModule {
+       /** @var array Saves a list of messages which have been marked as 
needing parsing. */
+       protected $parsedMessages = [];
+       /** @var array Saves a list of message keys used by this module. */
+       protected $messages = [];
+       /** @var array Saves the target for the module (e.g. desktop and 
mobile). */
+       protected $targets = [ 'mobile', 'desktop' ];
+       /** @var boolean Whether the module abuses getScript. */
+       protected $hasHackedScriptMode = false;
+
+       /**
+        * Registers core modules and runs registration hooks.
+        * @param array $options List of options; if not given or empty,
+        *  an empty module will be constructed
+        */
+       public function __construct( $options ) {
+               foreach ( $options as $member => $option ) {
+                       switch ( $member ) {
+                               case 'messages':
+                                       $this->processMessages( $option );
+                                       $this->hasHackedScriptMode = true;
+                                       // Prevent them being reinitialised 
when parent construct is called.
+                                       unset( $options[$member] );
+                                       break;
+                       }
+               }
+
+               parent::__construct( $options );
+       }
+
+       /**
+        * Process messages which have been marked as needing parsing
+        *
+        * @param ResourceLoaderContext $context
+        * @return string JavaScript code
+        */
+       public function addParsedMessages( ResourceLoaderContext $context ) {
+               if ( !$this->parsedMessages ) {
+                       return '';
+               }
+               $messages = [];
+               foreach ( $this->parsedMessages as $key ) {
+                       $messages[ $key ] = $context->msg( $key )->parse();
+               }
+               return Xml::encodeJsCall( 'mw.messages.set', [ $messages ] );
+       }
+
+       /**
+        * Separate messages which have been marked as needing parsing from 
standard messages
+        * @param array $messages Array of messages to process
+        */
+       private function processMessages( $messages ) {
+               foreach ( $messages as $key => $value ) {
+                       if ( is_array( $value ) ) {
+                               foreach ( $value as $directive ) {
+                                       if ( $directive == 'parse' ) {
+                                               $this->parsedMessages[] = $key;
+                                       }
+                               }
+                       } else {
+                               $this->messages[] = $value;
+                       }
+               }
+       }
+
+       /**
+        * Gets all scripts for a given context concatenated together including 
processed messages
+        *
+        * @param ResourceLoaderContext $context Context in which to generate 
script
+        * @return string JavaScript code for $context
+        */
+       public function getScript( ResourceLoaderContext $context ) {
+               $script = parent::getScript( $context );
+               return $this->addParsedMessages( $context ) . $script;
+       }
+
+       /**
+        * Get the URL or URLs to load for this module's JS in debug mode.
+        * @param ResourceLoaderContext $context
+        * @return array list of urls
+        * @see ResourceLoaderModule::getScriptURLsForDebug
+        */
+       public function getScriptURLsForDebug( ResourceLoaderContext $context ) 
{
+               if ( $this->hasHackedScriptMode ) {
+                       $derivative = new DerivativeResourceLoaderContext( 
$context );
+                       $derivative->setDebug( true );
+                       $derivative->setModules( [ $this->getName() ] );
+                       // @todo FIXME: Make this templates and update
+                       // makeModuleResponse so that it only outputs template 
code.
+                       // When this is done you can merge with parent array and
+                       // retain file names.
+                       $derivative->setOnly( 'scripts' );
+                       $rl = $derivative->getResourceLoader();
+                       $urls = [
+                               $rl->createLoaderURL( $this->getSource(), 
$derivative ),
+                       ];
+               } else {
+                       $urls = parent::getScriptURLsForDebug( $context );
+               }
+               return $urls;
+       }
+}
diff --git a/includes/MinervaUI.php b/includes/MinervaUI.php
new file mode 100644
index 0000000..d800514
--- /dev/null
+++ b/includes/MinervaUI.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * MinervaUI.php
+ */
+
+// FIXME: Use OOUI PHP when available.
+/**
+ * Helper methods for generating parts of the UI.
+ */
+class MinervaUI {
+
+       /**
+        * Get CSS classes for icons
+        * @param string $iconName
+        * @param string $iconType element or before
+        * @param string $additionalClassNames additional class names you want 
to associate
+        *  with the iconed element
+        * @return string class name for use with HTML element
+        */
+       public static function iconClass( $iconName, $iconType = 'element', 
$additionalClassNames = '' ) {
+               $base = 'mw-ui-icon';
+               $modifiers = 'mw-ui-icon-' . $iconType;
+               if ( $iconName ) {
+                       $modifiers .= ' mw-ui-icon-' . $iconName;
+               }
+               return $base . ' ' . $modifiers . ' ' . $additionalClassNames;
+       }
+
+       /**
+        * Get CSS classes for a mediawiki ui semantic element
+        * @param string $base The base class
+        * @param string $modifier Type of anchor (progressive, constructive, 
destructive)
+        * @param string $additionalClassNames additional class names you want 
to associate
+        *  with the iconed element
+        * @return string class name for use with HTML element
+        */
+       public static function semanticClass( $base, $modifier, 
$additionalClassNames = '' ) {
+               $modifier = empty( $modifier ) ? '' : 'mw-ui-' . $modifier;
+               return $base . ' ' . $modifier . ' ' . $additionalClassNames;
+       }
+
+       /**
+        * Get CSS classes for buttons
+        * @param string $modifier Type of button (progressive, constructive, 
destructive)
+        * @param string $additionalClassNames additional class names you want 
to associate
+        *  with the button element
+        * @return string class name for use with HTML element
+        */
+       public static function buttonClass( $modifier = '', 
$additionalClassNames = '' ) {
+               return self::semanticClass( 'mw-ui-button', $modifier, 
$additionalClassNames );
+       }
+}
diff --git a/includes/skins/MinervaTemplate.php 
b/includes/skins/MinervaTemplate.php
index 4e15ec9..c6853f3 100644
--- a/includes/skins/MinervaTemplate.php
+++ b/includes/skins/MinervaTemplate.php
@@ -109,8 +109,8 @@
                if ( isset( $data['historyLink'] ) && $action === 'view' ) {
                        $historyLink = $data['historyLink'];
                        $args = [
-                               'clockIconClass' => MobileUI::iconClass( 
'clock-gray', 'before' ),
-                               'arrowIconClass' => MobileUI::iconClass(
+                               'clockIconClass' => MinervaUI::iconClass( 
'clock-gray', 'before' ),
+                               'arrowIconClass' => MinervaUI::iconClass(
                                        'arrow-gray', 'element', 
'mw-ui-icon-small mf-mw-ui-icon-rotate-anti-clockwise indicator' ),
                                'isMainPage' => 
$this->getSkin()->getTitle()->isMainPage(),
                                'link' => $historyLink['href'],
@@ -146,7 +146,7 @@
         * @return string
         */
        protected function getSecondaryActionsHtml() {
-               $baseClass = MobileUI::buttonClass( '', 'button' );
+               $baseClass = MinervaUI::buttonClass( '', 'button' );
                $html = Html::openElement( 'div', [
                        'class' => 'post-content',
                        'id' => 'page-secondary-actions'
@@ -281,7 +281,7 @@
                        // which is problematic in Opera Mini (see T140490)
                        'searchButton' => Html::rawElement( 'button', [
                                'id' => 'searchIcon',
-                               'class' => MobileUI::iconClass( 
'magnifying-glass', 'element' ),
+                               'class' => MinervaUI::iconClass( 
'magnifying-glass', 'element' ),
                        ], wfMessage( 'searchbutton' ) ),
                        'secondaryButtonData' => $data['secondaryButtonData'],
                        'mainmenuhtml' => $this->getMainMenuHtml( $data ),
diff --git a/includes/skins/SkinMinerva.php b/includes/skins/SkinMinerva.php
index 102bef4..2214508 100644
--- a/includes/skins/SkinMinerva.php
+++ b/includes/skins/SkinMinerva.php
@@ -236,7 +236,7 @@
                                'data-section' => $section,
                                // Note visibility of the edit section link 
button is controlled by .edit-page in ui.less so
                                // we default to enabled even though this may 
not be true.
-                               'class' => MobileUI::iconClass( 'edit-enabled', 
'element', 'edit-page' ),
+                               'class' => MinervaUI::iconClass( 
'edit-enabled', 'element', 'edit-page' ),
                        ], $message );
                        $html .= Html::closeElement( 'span' );
                        return $html;
@@ -408,7 +408,7 @@
                                [ 'returnto' => 
$currentTitle->getPrefixedText() ] );
 
                        $tpl->set( 'secondaryButtonData', [
-                               'notificationIconClass' => MobileUI::iconClass( 
'notifications' ),
+                               'notificationIconClass' => 
MinervaUI::iconClass( 'notifications' ),
                                'title' => $notificationsMsg,
                                'url' => $url,
                                'notificationCount' => $countLabel,
@@ -452,7 +452,7 @@
                        ->addComponent(
                                $this->msg( 
'mobile-frontend-main-menu-contributions' )->escaped(),
                                SpecialPage::getTitleFor( 'Contributions', 
$user->getName() )->getLocalUrl(),
-                               MobileUI::iconClass( 'mf-contributions', 
'before' ),
+                               MinervaUI::iconClass( 'mf-contributions', 
'before' ),
                                [ 'data-event-name' => 'contributions' ]
                        );
        }
@@ -490,7 +490,7 @@
                                        'mobile-frontend-watchlist-purpose',
                                        $watchlistQuery
                                ),
-                               MobileUI::iconClass( 'mf-watchlist', 'before' ),
+                               MinervaUI::iconClass( 'mf-watchlist', 'before' 
),
                                [ 'data-event-name' => 'watchlist' ]
                        );
        }
@@ -512,7 +512,7 @@
                                        $this->msg( 
'mobile-frontend-main-menu-settings' )->escaped(),
                                        SpecialPage::getTitleFor( 
'MobileOptions' )->
                                                getLocalUrl( [ 'returnto' => 
$returnToTitle ] ),
-                                       MobileUI::iconClass( 'mf-settings', 
'before' ),
+                                       MinervaUI::iconClass( 'mf-settings', 
'before' ),
                                        [ 'data-event-name' => 'settings' ]
                                );
 
@@ -527,7 +527,7 @@
                                                SpecialPage::getTitleFor( 
'Preferences' ),
                                                'prefsnologintext2'
                                        ),
-                                       MobileUI::iconClass( 'mf-settings', 
'before' ),
+                                       MinervaUI::iconClass( 'mf-settings', 
'before' ),
                                        [ 'data-event-name' => 'preferences' ]
                                );
                }
@@ -613,7 +613,7 @@
                        ->addComponent(
                                $this->msg( 'mobile-frontend-home-button' 
)->escaped(),
                                Title::newMainPage()->getLocalUrl(),
-                               MobileUI::iconClass( 'mf-home', 'before' ),
+                               MinervaUI::iconClass( 'mf-home', 'before' ),
                                [ 'data-event-name' => 'home' ]
                        );
 
@@ -622,7 +622,7 @@
                        ->addComponent(
                                $this->msg( 'mobile-frontend-random-button' 
)->escaped(),
                                SpecialPage::getTitleFor( 'Randompage' 
)->getLocalUrl() . '#/random',
-                               MobileUI::iconClass( 'mf-random', 'before' ),
+                               MinervaUI::iconClass( 'mf-random', 'before' ),
                                [
                                        'id' => 'randomButton',
                                        'data-event-name' => 'random',
@@ -639,7 +639,7 @@
                                ->addComponent(
                                        $this->msg( 
'mobile-frontend-main-menu-nearby' )->escaped(),
                                        SpecialPage::getTitleFor( 'Nearby' 
)->getLocalURL(),
-                                       MobileUI::iconClass( 'mf-nearby', 
'before', 'nearby' ),
+                                       MinervaUI::iconClass( 'mf-nearby', 
'before', 'nearby' ),
                                        [ 'data-event-name' => 'nearby' ]
                                );
                }
@@ -689,13 +689,13 @@
                                ->addComponent(
                                        $username,
                                        Title::newFromText( $username, NS_USER 
)->getLocalUrl(),
-                                       MobileUI::iconClass( 'mf-profile', 
'before', 'truncated-text primary-action' ),
+                                       MinervaUI::iconClass( 'mf-profile', 
'before', 'truncated-text primary-action' ),
                                        [ 'data-event-name' => 'profile' ]
                                )
                                ->addComponent(
                                        $this->msg( 
'mobile-frontend-main-menu-logout' )->escaped(),
                                        $url,
-                                       MobileUI::iconClass(
+                                       MinervaUI::iconClass(
                                                'mf-logout', 'element', 
'secondary-action truncated-text' ),
                                        [ 'data-event-name' => 'logout' ]
                                );
@@ -711,7 +711,7 @@
                                ->addComponent(
                                        $this->msg( 
'mobile-frontend-main-menu-login' )->escaped(),
                                        $url,
-                                       MobileUI::iconClass( 'mf-anonymous', 
'before' ),
+                                       MinervaUI::iconClass( 'mf-anonymous', 
'before' ),
                                        [ 'data-event-name' => 'login' ]
                                );
                }
@@ -913,7 +913,7 @@
                        Html::element( 'a', [
                                'title' => $this->msg( 
'mobile-frontend-main-menu-button-tooltip' ),
                                'href' => $url,
-                               'class' => MobileUI::iconClass( 'mainmenu', 
'element', 'main-menu-button' ),
+                               'class' => MinervaUI::iconClass( 'mainmenu', 
'element', 'main-menu-button' ),
                                'id' => 'mw-mf-main-menu-button',
                        ], $this->msg( 
'mobile-frontend-main-menu-button-tooltip' ) )
                );
@@ -1105,7 +1105,7 @@
                        'id' => 'ca-edit',
                        'text' => '',
                        'itemtitle' => $this->msg( 
'mobile-frontend-pageaction-edit-tooltip' ),
-                       'class' => MobileUI::iconClass( 'edit-enabled', 
'element' ),
+                       'class' => MinervaUI::iconClass( 'edit-enabled', 
'element' ),
                        'links' => [
                                'edit' => [
                                        'href' => $title->getLocalURL( 
$editArgs )
@@ -1127,7 +1127,7 @@
                $baseResult = [
                        'id' => 'ca-watch',
                        // Use blank icon to reserve space for watchstar icon 
once JS loads
-                       'class' => MobileUI::iconClass( '', 'element', 
'watch-this-article' ),
+                       'class' => MinervaUI::iconClass( '', 'element', 
'watch-this-article' ),
                        'is_js_only' => true
                ];
                $title = $this->getTitle();
@@ -1170,7 +1170,7 @@
                return [
                        'text' => '',
                        'itemtitle' => $this->msg( 
'mobile-frontend-language-article-heading' ),
-                       'class' => MobileUI::iconClass( 'language-switcher', 
'element', $languageSwitcherClasses ),
+                       'class' => MinervaUI::iconClass( 'language-switcher', 
'element', $languageSwitcherClasses ),
                        'links' => $languageSwitcherLinks,
                        'is_js_only' => false
                ];
diff --git a/skin.json b/skin.json
index 319e415..1312f37 100644
--- a/skin.json
+++ b/skin.json
@@ -1,5 +1,7 @@
 {
        "AutoloadClasses": {
+               "MinervaResourceLoaderParsedMessageModule": 
"includes/MinervaResourceLoaderParsedMessageModule.php",
+               "MinervaUI": "includes/MinervaUI.php",
                "MinervaHooks": "includes/Minerva.hooks.php",
                "MinervaTemplate": "includes/skins/MinervaTemplate.php",
                "SkinMinerva": "includes/skins/SkinMinerva.php",
@@ -350,7 +352,7 @@
                        ]
                },
                "skins.minerva.editor": {
-                       "class": "MFResourceLoaderParsedMessageModule",
+                       "class": "MinervaResourceLoaderParsedMessageModule",
                        "dependencies": [
                                "mediawiki.util",
                                "mediawiki.router",
@@ -426,7 +428,7 @@
                        ]
                },
                "skins.minerva.toggling": {
-                       "class": "MFResourceLoaderParsedMessageModule",
+                       "class": "MinervaResourceLoaderParsedMessageModule",
                        "dependencies": [
                                "mobile.toggle",
                                "skins.minerva.icons.images.variants",
diff --git a/tests/phpunit/skins/SkinMinervaTest.php 
b/tests/phpunit/skins/SkinMinervaTest.php
index c1f5166..9ce2d91 100644
--- a/tests/phpunit/skins/SkinMinervaTest.php
+++ b/tests/phpunit/skins/SkinMinervaTest.php
@@ -3,7 +3,7 @@
 namespace Tests\MediaWiki\Minerva;
 
 use MediaWikiTestCase;
-use MobileUI;
+use MinervaUI;
 use MWTimestamp;
 use OutputPage;
 use QuickTemplate;
@@ -289,7 +289,7 @@
                $hasUnseen
        ) {
                return [
-                       'notificationIconClass' => MobileUI::iconClass( 
'notifications' ),
+                       'notificationIconClass' => MinervaUI::iconClass( 
'notifications' ),
                        'title' => $notificationsMsg,
                        'url' => SpecialPage::getTitleFor( $notificationsTitle )
                                ->getLocalURL(

-- 
To view, visit https://gerrit.wikimedia.org/r/372186
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I89e2e15faabab73b0cba91afc2f2c5e785edef29
Gerrit-PatchSet: 11
Gerrit-Project: mediawiki/skins/MinervaNeue
Gerrit-Branch: master
Gerrit-Owner: Jdlrobson <jrob...@wikimedia.org>
Gerrit-Reviewer: Jdlrobson <jrob...@wikimedia.org>
Gerrit-Reviewer: Pmiazga <pmia...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to