mirror of
https://github.com/StarCitizenTools/mediawiki-skins-Citizen.git
synced 2024-11-27 15:50:34 +00:00
refactor(core): ♻️ convert main menu to use Components
This commit is contained in:
parent
b873871e50
commit
85b8fe34e4
14
includes/Components/CitizenComponent.php
Normal file
14
includes/Components/CitizenComponent.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
namespace MediaWiki\Skins\Citizen\Components;
|
||||
|
||||
/**
|
||||
* Component interface for managing Citizen-modified components
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface CitizenComponent {
|
||||
/**
|
||||
* @return array of Mustache compatible data
|
||||
*/
|
||||
public function getTemplateData(): array;
|
||||
}
|
41
includes/Components/CitizenComponentMainMenu.php
Normal file
41
includes/Components/CitizenComponentMainMenu.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
namespace MediaWiki\Skins\Citizen\Components;
|
||||
|
||||
|
||||
/**
|
||||
* CitizenComponentMainMenu component
|
||||
*/
|
||||
class CitizenComponentMainMenu implements CitizenComponent {
|
||||
/** @var array */
|
||||
private $sidebarData;
|
||||
|
||||
/**
|
||||
* @param array $sidebarData
|
||||
*/
|
||||
public function __construct( array $sidebarData ) {
|
||||
$this->sidebarData = $sidebarData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getTemplateData(): array {
|
||||
$portletsRest = [];
|
||||
foreach ( $this->sidebarData[ 'array-portlets-rest' ] as $data ) {
|
||||
/**
|
||||
* Remove toolbox from main menu as we moved it to article tools
|
||||
* TODO: Move handling to SkinCitizen.php after we convert pagetools to component
|
||||
*/
|
||||
if ( $data['id'] === 'p-tb' ) {
|
||||
continue;
|
||||
}
|
||||
$portletsRest[] = ( new CitizenComponentMenu( $data ) )->getTemplateData();
|
||||
}
|
||||
$firstPortlet = new CitizenComponentMenu( $this->sidebarData['data-portlets-first'] );
|
||||
|
||||
return [
|
||||
'data-portlets-first' => $firstPortlet->getTemplateData(),
|
||||
'array-portlets-rest' => $portletsRest
|
||||
];
|
||||
}
|
||||
}
|
49
includes/Components/CitizenComponentMenu.php
Normal file
49
includes/Components/CitizenComponentMenu.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
namespace MediaWiki\Skins\Citizen\Components;
|
||||
|
||||
use Countable;
|
||||
|
||||
/**
|
||||
* CitizenComponentMenu component
|
||||
*/
|
||||
class CitizenComponentMenu implements CitizenComponent, Countable {
|
||||
/** @var array */
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct( array $data ) {
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts how many items the menu has.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(): int {
|
||||
$items = $this->data['array-list-items'] ?? null;
|
||||
if ( $items ) {
|
||||
return count( $items );
|
||||
}
|
||||
$htmlItems = $this->data['html-items'] ?? '';
|
||||
return substr_count( $htmlItems, '<li' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getTemplateData(): array {
|
||||
return $this->data + [
|
||||
'class' => '',
|
||||
'label' => '',
|
||||
'html-tooltip' => '',
|
||||
'label-class' => '',
|
||||
'html-before-portal' => '',
|
||||
'html-items' => '',
|
||||
'html-after-portal' => '',
|
||||
'array-list-items' => null,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -32,31 +32,10 @@ use NumberFormatter;
|
|||
* Drawer partial of Skin Citizen
|
||||
* Generates the following partials:
|
||||
* - Logo
|
||||
* - Drawer
|
||||
* + Special Pages Link
|
||||
* + Upload Link
|
||||
*/
|
||||
final class Drawer extends Partial {
|
||||
/**
|
||||
* Decorate main menu template data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function decorateMainMenuData( $mainMenuData ) {
|
||||
for ( $i = 0; $i < count( $mainMenuData['array-portlets-rest'] ); $i++ ) {
|
||||
if ( $mainMenuData['array-portlets-rest'][$i]['id'] === 'p-tb' ) {
|
||||
// Remove toolbox since it is handled by page tools
|
||||
unset( $mainMenuData['array-portlets-rest'][$i] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset index after unsetting toolbox
|
||||
$mainMenuData['array-portlets-rest'] = array_values( $mainMenuData['array-portlets-rest'] );
|
||||
|
||||
return $mainMenuData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messages used for site stats in the drawer
|
||||
*
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
namespace MediaWiki\Skins\Citizen;
|
||||
|
||||
use MediaWiki\Skins\Citizen\Components\CitizenComponentMainMenu;
|
||||
use MediaWiki\Skins\Citizen\Partials\BodyContent;
|
||||
use MediaWiki\Skins\Citizen\Partials\Drawer;
|
||||
use MediaWiki\Skins\Citizen\Partials\Footer;
|
||||
|
@ -116,13 +117,23 @@ class SkinCitizen extends SkinMustache {
|
|||
'msg-citizen-footer-tagline' => $this->msg( "citizen-footer-tagline" )->inContentLanguage()->parse(),
|
||||
// Decorate data provided by core
|
||||
'data-search-box' => $header->decorateSearchBoxData( $parentData['data-search-box'] ),
|
||||
'data-main-menu' => $drawer->decorateMainMenuData( $parentData['data-portlets-sidebar'] ),
|
||||
'data-footer' => $footer->decorateFooterData( $parentData['data-footer'] ),
|
||||
];
|
||||
|
||||
$data += $sidebar->getSidebarData( $parentData );
|
||||
$data += $tools->getPageToolsData( $parentData );
|
||||
|
||||
$components = [
|
||||
'data-main-menu' => new CitizenComponentMainMenu( $parentData['data-portlets-sidebar'] )
|
||||
];
|
||||
|
||||
foreach ( $components as $key => $component ) {
|
||||
// Array of components or null values.
|
||||
if ( $component ) {
|
||||
$parentData[$key] = $component->getTemplateData();
|
||||
}
|
||||
}
|
||||
|
||||
return array_merge( $parentData, $data );
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,7 @@
|
|||
</div>
|
||||
</header>
|
||||
{{#data-main-menu}}
|
||||
<section class="citizen-drawer__menu">
|
||||
{{#data-portlets-first}}{{>Menu}}{{/data-portlets-first}}
|
||||
{{#array-portlets-rest}}{{>Menu}}{{/array-portlets-rest}}
|
||||
</section>
|
||||
{{>MainMenu}}
|
||||
{{/data-main-menu}}
|
||||
</aside>
|
||||
</div>
|
4
templates/MainMenu.mustache
Normal file
4
templates/MainMenu.mustache
Normal file
|
@ -0,0 +1,4 @@
|
|||
<section id="citizen-main-menu" class="citizen-main-menu citizen-drawer__menu">
|
||||
{{#data-portlets-first}}{{>Menu}}{{/data-portlets-first}}
|
||||
{{#array-portlets-rest}}{{>Menu}}{{/array-portlets-rest}}
|
||||
</section>
|
|
@ -11,38 +11,7 @@ use MediaWiki\Skins\Citizen\SkinCitizen;
|
|||
* @group Citizen
|
||||
* @group Database
|
||||
*/
|
||||
class DrawerTest extends \MediaWikiIntegrationTestCase {
|
||||
/**
|
||||
* @covers \MediaWiki\Skins\Citizen\Partials\Drawer::decorateMainMenuData
|
||||
* @return void
|
||||
*/
|
||||
public function testDecorateMainMenuDataEmpty() {
|
||||
$partial = new Drawer( new SkinCitizen() );
|
||||
|
||||
$this->assertEmpty( $partial->decorateMainMenuData( [
|
||||
'array-portlets-rest' => [],
|
||||
] )['array-portlets-rest'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \MediaWiki\Skins\Citizen\Partials\Drawer::decorateMainMenuData
|
||||
* @return void
|
||||
*/
|
||||
public function testDecorateMainMenuRemovePageTools() {
|
||||
$partial = new Drawer( new SkinCitizen() );
|
||||
|
||||
$mainMenuData = [
|
||||
'array-portlets-rest' => [
|
||||
[ 'id' => 'foo' ],
|
||||
[ 'id' => 'p-tb' ],
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertNotEmpty( $partial->decorateMainMenuData( $mainMenuData ) );
|
||||
$this->assertArrayHasKey( 'array-portlets-rest', $partial->decorateMainMenuData( $mainMenuData ) );
|
||||
$this->assertNotContains( [ 'id' => 'pt-tb' ], $partial->decorateMainMenuData( $mainMenuData )['array-portlets-rest'] );
|
||||
}
|
||||
|
||||
class DrawerTest extends MediaWikiIntegrationTestCase {
|
||||
/**
|
||||
* @covers \MediaWiki\Skins\Citizen\Partials\Drawer::getSiteStatsData
|
||||
* @return void
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
declare( strict_types=1 );
|
||||
|
||||
namespace MediaWiki\Skins\Citizen\Tests\Unit\Components;
|
||||
|
||||
use MediaWiki\Skins\Citizen\Components\CitizenComponent;
|
||||
use MediaWiki\Skins\Citizen\Components\CitizenComponentMainMenu;
|
||||
use MediaWikiUnitTestCase;
|
||||
|
||||
/**
|
||||
* @group Citizen
|
||||
* @group Components
|
||||
* @coversDefaultClass \MediaWiki\Skins\Citizen\Components\CitizenComponentMainMenu
|
||||
*/
|
||||
class CitizenComponentMainMenuTest extends MediaWikiUnitTestCase {
|
||||
|
||||
/**
|
||||
* This test checks if the CitizenComponentMainMenu class can be instantiated
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConstruct() {
|
||||
// Mock the sidebar data
|
||||
$sidebarData = [];
|
||||
|
||||
// Create a new CitizenComponentMainMenu object
|
||||
$mainMenu = new CitizenComponentMainMenu(
|
||||
$sidebarData
|
||||
);
|
||||
|
||||
// Assert that the object is an instance of CitizenComponent
|
||||
$this->assertInstanceOf( CitizenComponent::class, $mainMenu );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getTemplateData
|
||||
*/
|
||||
public function testGetTemplateData( array $sidebarData, array $languageData, bool $isPinned ) {
|
||||
// Create a new CitizenComponentMainMenu object
|
||||
$mainMenu = new CitizenComponentMainMenu(
|
||||
$sidebarData
|
||||
);
|
||||
|
||||
// Call the getTemplateData method
|
||||
$templateData = $mainMenu->getTemplateData();
|
||||
|
||||
// Assert main menu id
|
||||
$this->assertSame( 'citizen-main-menu', $templateData['id'] );
|
||||
|
||||
// Assert the structure and types of expected keys
|
||||
$this->assertIsArray( $templateData['data-portlets-first'] );
|
||||
$this->assertIsArray( $templateData['array-portlets-rest'] );
|
||||
|
||||
// Assert the structure and types of expected keys
|
||||
$this->assertArrayHasKey( 'data-portlets-first', $templateData );
|
||||
$this->assertArrayHasKey( 'array-portlets-rest', $templateData );
|
||||
}
|
||||
}
|
98
tests/phpunit/Unit/Components/CitizenComponentMenuTest.php
Normal file
98
tests/phpunit/Unit/Components/CitizenComponentMenuTest.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
declare( strict_types=1 );
|
||||
|
||||
namespace MediaWiki\Skins\Citizen\Tests\Unit\Components;
|
||||
|
||||
use MediaWiki\Skins\Citizen\Components\CitizenComponent;
|
||||
use MediaWiki\Skins\Citizen\Components\CitizenComponentMenu;
|
||||
use MediaWikiUnitTestCase;
|
||||
|
||||
/**
|
||||
* @group Citizen
|
||||
* @group Components
|
||||
* @coversDefaultClass \MediaWiki\Skins\Citizen\Components\CitizenComponentMenu
|
||||
*/
|
||||
class CitizenComponentMenuTest extends MediaWikiUnitTestCase {
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function provideMenuData(): array {
|
||||
return [
|
||||
[
|
||||
[
|
||||
'class' => 'some-class',
|
||||
'label' => 'Some label',
|
||||
'html-tooltip' => 'Some tooltip',
|
||||
'label-class' => 'some-label-class',
|
||||
'html-before-portal' => 'Some before portal',
|
||||
'html-items' => 'Some items',
|
||||
'html-after-portal' => 'Some after portal',
|
||||
'array-list-items' => [ 'some-item-one', 'some-item-2', 'some-item-3' ]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function provideCountData(): array {
|
||||
return [
|
||||
[
|
||||
[
|
||||
'array-list-items' => [ 'some-item-one', 'some-item-2', 'some-item-3' ]
|
||||
],
|
||||
3
|
||||
],
|
||||
[
|
||||
[
|
||||
'html-items' => '<li>Some item</li><li>Some item</li><li>Some item</li>'
|
||||
],
|
||||
3
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This test checks if the CitizenComponentMenu class can be instantiated
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConstruct() {
|
||||
// Create a new CitizenComponentMenu object
|
||||
$menu = new CitizenComponentMenu( [] );
|
||||
|
||||
// Check if the object is an instance of CitizenComponent
|
||||
$this->assertInstanceOf( CitizenComponent::class, $menu );
|
||||
}
|
||||
|
||||
/**
|
||||
* This test checks if the count method returns the correct number of items
|
||||
* @covers ::count
|
||||
* @dataProvider provideCountData
|
||||
*/
|
||||
public function testCount( array $data, int $expected ) {
|
||||
// Create a new CitizenComponentMenu object
|
||||
$menu = new CitizenComponentMenu( $data );
|
||||
|
||||
// Check if the count method returns the correct number of items
|
||||
$this->assertSame( $expected, $menu->count() );
|
||||
}
|
||||
|
||||
/**
|
||||
* This test checks if the getTemplateData method returns the correct data
|
||||
* @covers ::getTemplateData
|
||||
* @dataProvider provideMenuData
|
||||
*/
|
||||
public function testGetTemplateData( array $data ) {
|
||||
// Create a new CitizenComponentMenu object
|
||||
$menu = new CitizenComponentMenu( $data );
|
||||
|
||||
// Call the getTemplateData method
|
||||
$actualData = $menu->getTemplateData();
|
||||
|
||||
// Check if the getTemplateData method returns the correct data
|
||||
$this->assertSame( $data, $actualData );
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue