Introduce SkinComponent and SkinComponentLogos
In preparation for refactoring SkinTemplate so that SkinMustache extends Skin rather than SkinTemplate, we take the opportunity to reorganize the skin code around the concept of components. Going forward a skin will consist of multiple components, each of which must return template data that can be passed to an associated template. This will result in code that is easier to work with, compared with the existing 3000 line skin class. This is the beginning of that journey. Other components will follow while maintaining backwards compatibility Bug: T263213 Change-Id: Ib62724c24601e04aa13ab09b3242e70d7d6436ca
This commit is contained in:
parent
7db80245b7
commit
f7693089a8
7 changed files with 240 additions and 23 deletions
|
|
@ -1090,6 +1090,9 @@ $wgAutoloadLocalClasses = [
|
|||
'MediaWiki\\Parser\\RevisionOutputCache' => __DIR__ . '/includes/parser/RevisionOutputCache.php',
|
||||
'MediaWiki\\ProcOpenError' => __DIR__ . '/includes/exception/ProcOpenError.php',
|
||||
'MediaWiki\\ShellDisabledError' => __DIR__ . '/includes/exception/ShellDisabledError.php',
|
||||
'MediaWiki\\Skin\\SkinComponent' => __DIR__ . '/includes/skins/components/SkinComponent.php',
|
||||
'MediaWiki\\Skin\\SkinComponentLogo' => __DIR__ . '/includes/skins/components/SkinComponentLogo.php',
|
||||
'MediaWiki\\Skin\\SkinComponentRegistry' => __DIR__ . '/includes/skins/components/SkinComponentRegistry.php',
|
||||
'MediaWiki\\Skins\\Hook\\SkinAfterPortletHook' => __DIR__ . '/includes/skins/Hook/SkinAfterPortletHook.php',
|
||||
'MediaWiki\\Skins\\Hook\\SkinPageReadyConfigHook' => __DIR__ . '/includes/skins/Hook/SkinPageReadyConfigHook.php',
|
||||
'MediaWiki\\Special\\SpecialPageFactory' => __DIR__ . '/includes/specialpage/SpecialPageFactory.php',
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
|
|||
use MediaWiki\MediaWikiServices;
|
||||
use MediaWiki\Revision\RevisionLookup;
|
||||
use MediaWiki\Revision\RevisionStore;
|
||||
use MediaWiki\Skin\SkinComponentRegistry;
|
||||
use MediaWiki\User\UserIdentity;
|
||||
use MediaWiki\User\UserIdentityValue;
|
||||
use Wikimedia\WrappedString;
|
||||
|
|
@ -83,6 +84,11 @@ abstract class Skin extends ContextSource {
|
|||
/** @var array|null Cache for buildSidebar() */
|
||||
private $sidebar;
|
||||
|
||||
/**
|
||||
* @var SkinComponentRegistry Initialised in constructor.
|
||||
*/
|
||||
private $componentRegistry = null;
|
||||
|
||||
/**
|
||||
* Get the current major version of Skin. This is used to manage changes
|
||||
* to underlying data and for providing support for older and new versions of code.
|
||||
|
|
@ -229,6 +235,11 @@ abstract class Skin extends ContextSource {
|
|||
'is-mainpage' => $isMainPage,
|
||||
'is-specialpage' => $title->isSpecialPage(),
|
||||
];
|
||||
|
||||
$components = $this->componentRegistry->getComponents();
|
||||
foreach ( $components as $componentName => $component ) {
|
||||
$data['data-' . $componentName] = $component->getTemplateData();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
|
@ -317,6 +328,9 @@ abstract class Skin extends ContextSource {
|
|||
$this->options = $options;
|
||||
$this->skinname = $name;
|
||||
}
|
||||
$this->componentRegistry = new SkinComponentRegistry(
|
||||
$this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -198,7 +198,6 @@ class SkinTemplate extends Skin {
|
|||
return parent::getTemplateData() + [
|
||||
// Data objects
|
||||
'data-search-box' => $this->buildSearchProps(),
|
||||
'data-logos' => $this->getLogoData(),
|
||||
] + $this->getPortletsTemplateData() + $this->getFooterTemplateData();
|
||||
}
|
||||
|
||||
|
|
@ -905,27 +904,6 @@ class SkinTemplate extends Skin {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of logo data localised to the current language variant
|
||||
*/
|
||||
private function getLogoData(): array {
|
||||
$logoData = ResourceLoaderSkinModule::getAvailableLogos( $this->getConfig() );
|
||||
// check if the logo supports variants
|
||||
$variantsLogos = $logoData['variants'] ?? null;
|
||||
if ( $variantsLogos ) {
|
||||
$preferred = $this->getOutput()->getTitle()
|
||||
->getPageViewLanguage()->getCode();
|
||||
$variantOverrides = $variantsLogos[$preferred] ?? null;
|
||||
// Overrides the logo
|
||||
if ( $variantOverrides ) {
|
||||
foreach ( $variantOverrides as $key => $val ) {
|
||||
$logoData[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $logoData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
|
|
|||
34
includes/skins/components/SkinComponent.php
Normal file
34
includes/skins/components/SkinComponent.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Skin;
|
||||
|
||||
/**
|
||||
* @internal for use inside Skin and SkinTemplate classes only
|
||||
* @unstable
|
||||
*/
|
||||
interface SkinComponent {
|
||||
/**
|
||||
* This returns all the data that is needed to the component.
|
||||
* Returned array must be seralized. This will be passed directly
|
||||
* to a template (usually Mustache) for rendering.
|
||||
*
|
||||
* @return array Data related to component required to render.
|
||||
*/
|
||||
public function getTemplateData(): array;
|
||||
}
|
||||
85
includes/skins/components/SkinComponentLogo.php
Normal file
85
includes/skins/components/SkinComponentLogo.php
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Skin;
|
||||
|
||||
use Config;
|
||||
use ResourceLoaderSkinModule;
|
||||
use Title;
|
||||
|
||||
/**
|
||||
* @internal for use inside Skin and SkinTemplate classes only
|
||||
* @unstable
|
||||
*/
|
||||
class SkinComponentLogo implements SkinComponent {
|
||||
/** @var Config */
|
||||
private $config;
|
||||
/** @var Title */
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* @param Config $config
|
||||
* @param Title|null $title
|
||||
*/
|
||||
public function __construct( Config $config, ?Title $title ) {
|
||||
$this->config = $config;
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Title|null
|
||||
*/
|
||||
private function getTitle(): ?Title {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Config
|
||||
*/
|
||||
private function getConfig(): Config {
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Since 1.35 (all fields optional):
|
||||
* - string 1x Path to a square icon at 1x resolution
|
||||
* - string 2x Path to a square icon at 2x resolution
|
||||
* - string icon Path to a square icon
|
||||
* - array wordmark with `src`, `width`, `height` and `style` keys.
|
||||
* - array tagline with `src`, `width`, `height` and `style` keys.
|
||||
*/
|
||||
public function getTemplateData(): array {
|
||||
$logoData = ResourceLoaderSkinModule::getAvailableLogos( $this->getConfig() );
|
||||
// check if the logo supports variants
|
||||
$variantsLogos = $logoData['variants'] ?? null;
|
||||
$title = $this->getTitle();
|
||||
if ( $variantsLogos && $title ) {
|
||||
$preferred = $title
|
||||
->getPageViewLanguage()->getCode();
|
||||
$variantOverrides = $variantsLogos[$preferred] ?? null;
|
||||
// Overrides the logo
|
||||
if ( $variantOverrides ) {
|
||||
foreach ( $variantOverrides as $key => $val ) {
|
||||
$logoData[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $logoData;
|
||||
}
|
||||
}
|
||||
103
includes/skins/components/SkinComponentRegistry.php
Normal file
103
includes/skins/components/SkinComponentRegistry.php
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Skin;
|
||||
|
||||
use RuntimeException;
|
||||
use Skin;
|
||||
|
||||
/**
|
||||
* @internal for use inside Skin and SkinTemplate classes only
|
||||
* @unstable
|
||||
*/
|
||||
class SkinComponentRegistry {
|
||||
/** @var SkinComponent[]|null null if not initialized. */
|
||||
private $components = null;
|
||||
|
||||
/** @var Skin */
|
||||
private $skin;
|
||||
|
||||
/**
|
||||
* @param Skin $skin
|
||||
*/
|
||||
public function __construct( Skin $skin ) {
|
||||
$this->skin = $skin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a component. This method has side effects in that
|
||||
* if registered components have been not initialized they
|
||||
* will be registered as part of this method.
|
||||
*
|
||||
* @param string $name
|
||||
* @throws RuntimeException with unknown name
|
||||
* @return SkinComponent
|
||||
*/
|
||||
public function getComponent( string $name ): SkinComponent {
|
||||
if ( $this->components === null ) {
|
||||
$this->registerComponents();
|
||||
}
|
||||
$component = $this->components[$name] ?? null;
|
||||
if ( !$component ) {
|
||||
throw new RuntimeException( 'Unknown component: ' . $name );
|
||||
}
|
||||
return $component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all registered components.
|
||||
*
|
||||
* @since 1.38
|
||||
* @return SkinComponent[]
|
||||
*/
|
||||
public function getComponents() {
|
||||
if ( $this->components === null ) {
|
||||
$this->registerComponents();
|
||||
}
|
||||
return $this->components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a component for use with the skin.
|
||||
* Private for now, but in future we may consider making this a
|
||||
* public method to allow skins to extend component definitions.
|
||||
*
|
||||
* @param string $name
|
||||
* @throws RuntimeException if given an unknown name
|
||||
*/
|
||||
private function registerComponent( string $name ) {
|
||||
switch ( $name ) {
|
||||
case 'logos':
|
||||
$component = new SkinComponentLogo(
|
||||
$this->skin->getConfig(),
|
||||
$this->skin->getOutput()->getTitle()
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException( 'Unknown component: ' . $name );
|
||||
}
|
||||
$this->components[$name] = $component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers components used by skin.
|
||||
*/
|
||||
private function registerComponents() {
|
||||
$this->registerComponent( 'logos' );
|
||||
}
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ class SkinMustacheTest extends MediaWikiIntegrationTestCase {
|
|||
|
||||
/**
|
||||
* @covers SkinTemplate::getTemplateData
|
||||
* @covers SkinTemplate::buildSearchProps
|
||||
* @covers MediaWiki\Skin\SkinComponentLogo::getTemplateData
|
||||
*/
|
||||
public function testGetTemplateData() {
|
||||
$config = $this->getServiceContainer()->getMainConfig();
|
||||
|
|
|
|||
Loading…
Reference in a new issue