From: Bartosz DziewoƄski Date: Tue, 10 Jun 2014 22:25:48 +0000 (+0200) Subject: Separate Vector skin from core X-Git-Tag: 1.31.0-rc.0~15310 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/ajouter.php?a=commitdiff_plain;h=a96afeb262f74455f654ad92c25e4103a608bdb4;p=lhc%2Fweb%2Fwiklou.git Separate Vector skin from core This makes it behave exactly like a custom skin, with the caveat that it is still hardcoded in several places :(, most notably lots of skinStyles in Resources.php, the installer and some tests. * Renamed directory to reflect skin name. * Split skin classes to separate PHP files. * Removed core autoloader entries for skin classes. * Changed the hack in Setup.php to require_once the skin PHP file, as the skin is now registered there. * Extracted skin-specific localisation messages. * Extracted skin-specific resources. Did not touch skinStyles yet. * Hacked up the installer not to fall over entirely if Vector is missing. * Adjusted hardcoded paths in some more places... Change-Id: Idfffc1430790b3a104cc9835a6367137bcbf0e4e --- diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 81c057d67d..f969f799cb 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -1181,8 +1181,6 @@ $wgAutoloadLocalClasses = array( # skins 'MonoBookTemplate' => 'skins/monobook/MonoBook.php', 'SkinMonoBook' => 'skins/monobook/MonoBook.php', - 'SkinVector' => 'skins/vector/Vector.php', - 'VectorTemplate' => 'skins/vector/Vector.php', ); class AutoLoader { diff --git a/includes/Setup.php b/includes/Setup.php index 51368b1730..91baefba7d 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -606,7 +606,7 @@ $wgDeferredUpdateList = array(); // These lines should eventually be placed in skins' meta definition files, and loaded by a // require_once for each skin file generated by the installer and placed in LocalSettings.php. $wgValidSkinNames['monobook'] = 'MonoBook'; -$wgValidSkinNames['vector'] = 'Vector'; +require_once "$wgStyleDirectory/Vector/Vector.php"; wfProfileOut( $fname . '-globals' ); wfProfileIn( $fname . '-extensions' ); diff --git a/includes/installer/WebInstallerOutput.php b/includes/installer/WebInstallerOutput.php index d81111b5fe..97f48300bf 100644 --- a/includes/installer/WebInstallerOutput.php +++ b/includes/installer/WebInstallerOutput.php @@ -124,6 +124,12 @@ class WebInstallerOutput { * @return string */ public function getCSS() { + // Horrible, horrible hack: the installer is currently hardcoded to use the Vector skin, so load + // it here. Include instead of require, as this will work without it, it will just look bad. + global $wgResourceModules; + global $wgStyleDirectory; + include_once "$wgStyleDirectory/Vector/Vector.php"; + $moduleNames = array( // See SkinTemplate::setupSkinUserCss 'mediawiki.legacy.shared', @@ -146,6 +152,10 @@ class WebInstallerOutput { foreach ( $moduleNames as $moduleName ) { /** @var ResourceLoaderFileModule $module */ $module = $resourceLoader->getModule( $moduleName ); + // One of the modules will be missing if Vector is unavailable + if ( !$module ) { + continue; + } // Based on: ResourceLoaderFileModule::getStyles (without the DB query) $styles = ResourceLoader::makeCombinedStyles( $module->readStyleFiles( diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 667b6f7c2c..1ad6a38f22 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -150,19 +150,7 @@ "faqpage": "Project:FAQ", "sitetitle": "{{SITENAME}}", "sitesubtitle": "", - "vector-action-addsection": "Add topic", - "vector-action-delete": "Delete", - "vector-action-move": "Move", - "vector-action-protect": "Protect", - "vector-action-undelete": "Undelete", - "vector-action-unprotect": "Change protection", - "vector-view-create": "Create", - "vector-view-edit": "Edit", - "vector-view-history": "View history", - "vector-view-view": "Read", - "vector-view-viewsource": "View source", "actions": "Actions", - "vector-more-actions": "More", "namespaces": "Namespaces", "variants": "Variants", "navigation-heading": "Navigation menu", @@ -2475,7 +2463,6 @@ "interlanguage-link-title-nonlangonly": "$1", "common.css": "/* CSS placed here will be applied to all skins */", "monobook.css": "/* CSS placed here will affect users of the MonoBook skin */", - "vector.css": "/* CSS placed here will affect users of the Vector skin */", "print.css": "/* CSS placed here will affect the print output */", "noscript.css": "/* CSS placed here will affect users with JavaScript disabled */", "group-autoconfirmed.css": "/* CSS placed here will affect autoconfirmed users only */", @@ -2485,7 +2472,6 @@ "group-bureaucrat.css": "/* CSS placed here will affect bureaucrats only */", "common.js": "/* Any JavaScript here will be loaded for all users on every page load. */", "monobook.js": "/* Any JavaScript here will be loaded for users using the MonoBook skin */", - "vector.js": "/* Any JavaScript here will be loaded for users using the Vector skin */", "group-autoconfirmed.js": "/* Any JavaScript here will be loaded for autoconfirmed users only */", "group-user.js": "/* Any JavaScript here will be loaded for registered users only */", "group-bot.js": "/* Any JavaScript here will be loaded for bots only */", @@ -2558,7 +2544,6 @@ "pageinfo-category-subcats": "Number of subcategories", "pageinfo-category-files": "Number of files", "skinname-monobook": "MonoBook", - "skinname-vector": "Vector", "markaspatrolleddiff": "Mark as patrolled", "markaspatrolledlink": "[$1]", "markaspatrolledtext": "Mark this page as patrolled", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index 455896100d..4d5d6e17bc 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -312,19 +312,7 @@ "faqpage": "{{doc-important|Do not translate Project: part.}}\n\"FAQ\" is short for \"frequently asked questions\".\n\nThis page is only linked in CologneBlue (an old skin), not in Monobook or Vector.", "sitetitle": "{{Ignore}}", "sitesubtitle": "{{Ignore}}", - "vector-action-addsection": "Used in the Vector skin. See for example {{canonicalurl:Talk:Main_Page|useskin=vector}}", - "vector-action-delete": "Used in the Vector skin, as the name of a tab at the top of the page. See for example {{canonicalurl:Main_Page|useskin=vector}}\n\n{{Identical|Delete}}", - "vector-action-move": "Used in the Vector skin, on the tabs at the top of the page. See for example {{canonicalurl:Talk:Main_Page|useskin=vector}}\n\n{{Identical|Move}}", - "vector-action-protect": "Tab at top of page, in vector skin\n\n{{Identical|Protect}}", - "vector-action-undelete": "Tab at top of page, in vector skin.\n{{Identical|Undelete}}", - "vector-action-unprotect": "Tab at top of page, in vector skin.\n{{Identical|Change protection}}", - "vector-view-create": "Tab label in the Vector skin. See for example {{canonicalurl:Foo|useskin=vector}}\n{{Identical|Create}}", - "vector-view-edit": "Tab label in the Vector skin. See for example {{canonicalurl:Main_Page|useskin=vector}}\n{{Identical|Edit}}", - "vector-view-history": "Tab label in the Vector skin. See for example {{canonicalurl:Main_Page|useskin=vector}}\n{{Identical|View history}}", - "vector-view-view": "Tab label in the Vector skin (verb). See for example {{canonicalurl:Main_Page|useskin=vector}}.\n{{Identical|Read}}", - "vector-view-viewsource": "Tab label in the Vector skin.\n{{Identical|View source}}", "actions": "{{Identical|Action}}", - "vector-more-actions": "Label in the Vector skin's menu for the less-important or rarer actions which are not shown as tabs (like moving the page, or for sysops deleting or protecting the page), as well as (for users with a narrow viewing window in their browser) the less-important tab actions which the user's browser is unable to fit in. {{Identical|More}}", "namespaces": "{{Identical|Namespace}}", "variants": "Used by the Vector skin.", "navigation-heading": "Heading shown above the navigation menu (sidebar) for screen-readers (or in non-standard skins).", @@ -2637,7 +2625,6 @@ "interlanguage-link-title-nonlangonly": "{{ignored}}Interlanguage link title. Parameters: $1 replaced with name of the target wiki (probably not a language name).", "common.css": "{{optional}}\nCSS applied to all users.", "monobook.css": "{{optional}}\nCSS applied to users using Monobook skin.", - "vector.css": "{{optional}}", "print.css": "{{optional}}", "noscript.css": "{{optional}}", "group-autoconfirmed.css": "{{doc-group|autoconfirmed|css}}", @@ -2647,7 +2634,6 @@ "group-bureaucrat.css": "{{doc-group|bureaucrat|css}}", "common.js": "{{optional}}\nJS for all users.", "monobook.js": "{{optional}}\nJS for users using Monobook skin.", - "vector.js": "{{optional}}", "group-autoconfirmed.js": "{{doc-group|autoconfirmed|js}}", "group-user.js": "{{doc-group|user|js}}", "group-bot.js": "{{doc-group|bot|js}}", @@ -2720,7 +2706,6 @@ "pageinfo-category-subcats": "See also:\n* {{msg-mw|Pageinfo-category-pages}}\n* {{msg-mw|Pageinfo-category-files}}", "pageinfo-category-files": "See also:\n* {{msg-mw|Pageinfo-category-pages}}\n* {{msg-mw|Pageinfo-category-subcats}}", "skinname-monobook": "{{optional}}", - "skinname-vector": "{{optional}}", "markaspatrolleddiff": "{{doc-actionlink}}\nSee also:\n* {{msg-mw|Markaspatrolledtext}}\n{{Identical|Mark as patrolled}}", "markaspatrolledlink": "{{notranslate}}\nParameters:\n* $1 - link which has text {{msg-mw|Markaspatrolledtext}}", "markaspatrolledtext": "{{doc-actionlink}}\nSee also:\n* {{msg-mw|Markaspatrolleddiff}}", diff --git a/resources/Resources.php b/resources/Resources.php index 93415a5b92..ec02e5b36f 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -128,15 +128,6 @@ return array( * * See Vector for an example. */ - 'skins.vector.styles' => array( - // Used in the web installer. Test it after modifying this definition! - 'styles' => array( - 'screen.less' => array( 'media' => 'screen' ), - 'screen-hd.less' => array( 'media' => 'screen and (min-width: 982px)' ), - ), - 'remoteSkinPath' => 'vector', - 'localBasePath' => $GLOBALS['wgStyleDirectory'] . '/vector', - ), 'skins.monobook.styles' => array( 'styles' => array( 'main.css' => array( 'media' => 'screen' ), @@ -144,19 +135,6 @@ return array( 'remoteSkinPath' => 'monobook', 'localBasePath' => $GLOBALS['wgStyleDirectory'] . '/monobook', ), - 'skins.vector.js' => array( - 'scripts' => array( - 'collapsibleTabs.js', - 'vector.js', - ), - 'position' => 'top', - 'dependencies' => array( - 'jquery.throttle-debounce', - 'jquery.tabIndex', - ), - 'remoteSkinPath' => 'vector', - 'localBasePath' => $GLOBALS['wgStyleDirectory'] . '/vector', - ), /* jQuery */ @@ -1229,7 +1207,7 @@ return array( 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.js', 'styles' => 'resources/src/mediawiki.special/mediawiki.special.css', 'skinStyles' => array( - 'vector' => 'skins/vector/special.less', // FIXME this should use $wgStyleDirectory + 'vector' => 'skins/Vector/special.less', // FIXME this should use $wgStyleDirectory ), ), 'mediawiki.special.block' => array( @@ -1278,7 +1256,7 @@ return array( 'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.css', 'position' => 'top', 'skinStyles' => array( - 'vector' => 'skins/vector/special.preferences.less', // FIXME this should use $wgStyleDirectory + 'vector' => 'skins/Vector/special.preferences.less', // FIXME this should use $wgStyleDirectory ), 'messages' => array( 'prefs-tabs-navigation-hint', diff --git a/skins/Vector/SkinVector.php b/skins/Vector/SkinVector.php new file mode 100644 index 0000000000..237a2419b9 --- /dev/null +++ b/skins/Vector/SkinVector.php @@ -0,0 +1,83 @@ +getRequest()->getFuzzyBool( 'debug' ) ? '' : '.min'; + $out->addHeadItem( 'csshover', + '" + ); + + $out->addModules( array( 'skins.vector.js' ) ); + } + + /** + * Loads skin and user CSS files. + * @param OutputPage $out + */ + function setupSkinUserCss( OutputPage $out ) { + parent::setupSkinUserCss( $out ); + + $styles = array( 'mediawiki.skinning.interface', 'skins.vector.styles' ); + wfRunHooks( 'SkinVectorStyleModules', array( $this, &$styles ) ); + $out->addModuleStyles( $styles ); + } + + /** + * Adds classes to the body element. + * + * @param OutputPage $out + * @param array &$bodyAttrs Array of attributes that will be set on the body element + */ + function addToBodyAttributes( $out, &$bodyAttrs ) { + if ( isset( $bodyAttrs['class'] ) && strlen( $bodyAttrs['class'] ) > 0 ) { + $bodyAttrs['class'] .= ' ' . implode( ' ', static::$bodyClasses ); + } else { + $bodyAttrs['class'] = implode( ' ', static::$bodyClasses ); + } + } +} diff --git a/skins/Vector/Vector.php b/skins/Vector/Vector.php new file mode 100644 index 0000000000..adc23067c7 --- /dev/null +++ b/skins/Vector/Vector.php @@ -0,0 +1,60 @@ + __FILE__, + 'name' => 'Vector', + 'url' => 'https://www.mediawiki.org/wiki/Skin:Vector', +); + +// Register files +$wgAutoloadClasses['SkinVector'] = __DIR__ . '/SkinVector.php'; +$wgAutoloadClasses['VectorTemplate'] = __DIR__ . '/VectorTemplate.php'; +$wgMessagesDirs['Vector'] = __DIR__ . '/i18n'; + +// Register skin +$wgValidSkinNames['vector'] = 'Vector'; + +// Register modules +$wgResourceModules['skins.vector.styles'] = array( + 'styles' => array( + 'screen.less' => array( 'media' => 'screen' ), + 'screen-hd.less' => array( 'media' => 'screen and (min-width: 982px)' ), + ), + 'remoteSkinPath' => 'Vector', + 'localBasePath' => __DIR__, +); +$wgResourceModules['skins.vector.js'] = array( + 'scripts' => array( + 'collapsibleTabs.js', + 'vector.js', + ), + 'position' => 'top', + 'dependencies' => array( + 'jquery.throttle-debounce', + 'jquery.tabIndex', + ), + 'remoteSkinPath' => 'Vector', + 'localBasePath' => __DIR__, +); diff --git a/skins/Vector/VectorTemplate.php b/skins/Vector/VectorTemplate.php new file mode 100644 index 0000000000..7dc376ae77 --- /dev/null +++ b/skins/Vector/VectorTemplate.php @@ -0,0 +1,596 @@ +data['content_navigation']; + + if ( $wgVectorUseIconWatch ) { + $mode = $this->getSkin()->getUser()->isWatched( $this->getSkin()->getRelevantTitle() ) + ? 'unwatch' + : 'watch'; + + if ( isset( $nav['actions'][$mode] ) ) { + $nav['views'][$mode] = $nav['actions'][$mode]; + $nav['views'][$mode]['class'] = rtrim( 'icon ' . $nav['views'][$mode]['class'], ' ' ); + $nav['views'][$mode]['primary'] = true; + unset( $nav['actions'][$mode] ); + } + } + + $xmlID = ''; + foreach ( $nav as $section => $links ) { + foreach ( $links as $key => $link ) { + if ( $section == 'views' && !( isset( $link['primary'] ) && $link['primary'] ) ) { + $link['class'] = rtrim( 'collapsible ' . $link['class'], ' ' ); + } + + $xmlID = isset( $link['id'] ) ? $link['id'] : 'ca-' . $xmlID; + $nav[$section][$key]['attributes'] = + ' id="' . Sanitizer::escapeId( $xmlID ) . '"'; + if ( $link['class'] ) { + $nav[$section][$key]['attributes'] .= + ' class="' . htmlspecialchars( $link['class'] ) . '"'; + unset( $nav[$section][$key]['class'] ); + } + if ( isset( $link['tooltiponly'] ) && $link['tooltiponly'] ) { + $nav[$section][$key]['key'] = + Linker::tooltip( $xmlID ); + } else { + $nav[$section][$key]['key'] = + Xml::expandAttributes( Linker::tooltipAndAccesskeyAttribs( $xmlID ) ); + } + } + } + $this->data['namespace_urls'] = $nav['namespaces']; + $this->data['view_urls'] = $nav['views']; + $this->data['action_urls'] = $nav['actions']; + $this->data['variant_urls'] = $nav['variants']; + + // Reverse horizontally rendered navigation elements + if ( $this->data['rtl'] ) { + $this->data['view_urls'] = + array_reverse( $this->data['view_urls'] ); + $this->data['namespace_urls'] = + array_reverse( $this->data['namespace_urls'] ); + $this->data['personal_urls'] = + array_reverse( $this->data['personal_urls'] ); + } + // Output HTML Page + $this->html( 'headelement' ); + ?> +
+
+
+ + + + data['sitenotice'] ) { + ?> +
html( 'sitenotice' ) ?>
+ +

html( 'title' ) ?>

+ html( 'prebodyhtml' ) ?> +
+ data['isarticle'] ) { + ?> +
msg( 'tagline' ) ?>
+ +
html( 'userlangattributes' ) + ?>>html( 'subtitle' ) ?>
+ data['undelete'] ) { + ?> +
html( 'undelete' ) ?>
+ + data['newtalk'] ) { + ?> +
html( 'newtalk' ) ?>
+ +
+ msg( 'jumpto' ) ?> + msg( 'jumptonavigation' ) + ?>msg( 'comma-separator' ) + ?> + msg( 'jumptosearch' ) ?> +
+ html( 'bodycontent' ) ?> + data['printfooter'] ) { + ?> +
+ html( 'printfooter' ); ?> +
+ + data['catlinks'] ) { + ?> + html( 'catlinks' ); + ?> + + data['dataAfterContent'] ) { + ?> + html( 'dataAfterContent' ); + ?> + +
+ html( 'debughtml' ); ?> +
+
+
+

msg( 'navigation-heading' ) ?>

+ +
+ renderNavigation( 'PERSONAL' ); ?> +
+ renderNavigation( array( 'NAMESPACES', 'VARIANTS' ) ); ?> +
+
+ renderNavigation( array( 'VIEWS', 'ACTIONS', 'SEARCH' ) ); ?> +
+
+
+ + renderPortals( $this->data['sidebar'] ); ?> +
+
+ + printTrail(); ?> + + + + $content ) { + if ( $content === false ) { + continue; + } + + switch ( $name ) { + case 'SEARCH': + break; + case 'TOOLBOX': + $this->renderPortal( 'tb', $this->getToolbox(), 'toolbox', 'SkinTemplateToolboxEnd' ); + break; + case 'LANGUAGES': + if ( $this->data['language_urls'] !== false ) { + $this->renderPortal( 'lang', $this->data['language_urls'], 'otherlanguages' ); + } + break; + default: + $this->renderPortal( $name, $content ); + break; + } + } + } + + /** + * @param string $name + * @param array $content + * @param null|string $msg + * @param null|string|array $hook + */ + protected function renderPortal( $name, $content, $msg = null, $hook = null ) { + if ( $msg === null ) { + $msg = $name; + } + $msgObj = wfMessage( $msg ); + ?> + + data['rtl'] ) { + $elements = array_reverse( $elements ); + } + // Render elements + foreach ( $elements as $name => $element ) { + switch ( $element ) { + case 'NAMESPACES': + ?> + + + + + + + + + + +