mediawiki-skins-MinervaNeue/includes/menu/Group.php
Piotr Miazga 6905b85d67 Provide IMenuEntry interface
The Group shouldn't depend upon concrete MenuEntry definition.
Different Menus can present different MenuElements. Code should
allow easy extensions, not limit only to single MenuEntry
definition.

Changes:
 - introduced IMenuEntry interface
 - MenuEntry implements IMenuEntry
 - removed isJSOnly from logic as it's related only to one menu
 element (Watchstar) and Group shouldn't be aware of some special
 handling for some elements. The IMenuEntry shouldn't define this
 method
 - getName, getComponents, getCSSClasses should have defined return
 types

Bug: 1221792
Change-Id: I0646df734e869c26bfa8c3a772200e8258a8acce
2019-05-14 13:12:37 +02:00

150 lines
3.9 KiB
PHP

<?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
*
* @file
*/
namespace MediaWiki\Minerva\Menu;
use DomainException;
/**
* Model for a menu that can be presented in a skin.
*/
class Group {
/**
* @var IMenuEntry[]
*/
private $entries = [];
/**
* Return entries count
*
* @return int
*/
public function hasEntries() {
return count( $this->entries ) > 0;
}
/**
* Get all entries represented as plain old PHP arrays.
*
* @return array
*/
public function getEntries() {
$entryPresenter = function ( IMenuEntry $entry ) {
$result = [
'name' => $entry->getName(),
'components' => $entry->getComponents(),
];
$classes = $entry->getCSSClasses();
if ( $classes ) {
$result[ 'class' ] = implode( ' ', $classes );
}
return $result;
};
return array_map( $entryPresenter, $this->entries );
}
/**
* Helper method to verify that the $name of entry is unique (do not exists
* in current Group )
* @param string $name
* @throws DomainException When the entry already exists
*/
private function throwIfNotUnique( $name ) {
if ( $this->search( $name ) !== -1 ) {
throw new DomainException( "The \"${name}\" entry already exists." );
}
}
/**
* Insert new menu entry
* @param IMenuEntry $entry
* @throws DomainException When the entry already exists
*/
public function insertEntry( IMenuEntry $entry ) {
$this->throwIfNotUnique( $entry->getName() );
$this->entries[] = $entry;
}
/**
* Insert an entry into the menu.
*
* @param string $name A unique name identifying the menu entry
* @param bool $isJSOnly Whether the menu entry works without JS
* @throws DomainException When the entry already exists
* @return MenuEntry
*/
public function insert( $name, $isJSOnly = false ) {
$this->throwIfNotUnique( $name );
$this->entries[] = $entry = new MenuEntry( $name, $isJSOnly );
return $entry;
}
/**
* Searches for a menu entry by name.
*
* @param string $name
* @return integer If the menu entry exists, then the 0-based index of the entry; otherwise, -1
*/
private function search( $name ) {
$count = count( $this->entries );
for ( $i = 0; $i < $count; ++$i ) {
if ( $this->entries[$i]->getName() === $name ) {
return $i;
}
}
return -1;
}
/**
* Insert an entry after an existing one.
*
* @param string $targetName The name of the existing entry to insert
* the new entry after
* @param string $name The name of the new entry
* @param bool $isJSOnly Whether the entry works without JS
* @throws DomainException When the existing entry doesn't exist
* @return MenuEntry
*/
public function insertAfter( $targetName, $name, $isJSOnly = false ) {
$this->throwIfNotUnique( $name );
$index = $this->search( $targetName );
if ( $index === -1 ) {
throw new DomainException( "The \"{$targetName}\" entry doesn't exist." );
}
$entry = new MenuEntry( $name, $isJSOnly );
array_splice( $this->entries, $index + 1, 0, [ $entry ] );
return $entry;
}
}
/**
* make sure BlueSpiceMultiUpload and GrowthExperiments use the new class
* @TODO remove after updating all extensions that still depend upon MenuBuilder
*/
class_alias( 'MediaWiki\Minerva\Menu\Group', 'MediaWiki\Minerva\MenuBuilder' );