client/includes/Hooks/BeforePageDisplayHandler.php
<?php
declare( strict_types = 1 );
namespace Wikibase\Client\Hooks;
use MediaWiki\Output\Hook\BeforePageDisplayHook;
use MediaWiki\Output\OutputPage;
use MediaWiki\Title\Title;
use MediaWiki\User\User;
use Skin;
use Wikibase\Client\NamespaceChecker;
use Wikibase\Lib\SettingsArray;
/**
* Adds CSS for the edit links sidebar link or JS to create a new item
* or to link with an existing one.
*
* @license GPL-2.0-or-later
* @author Katie Filbert < aude.wiki@gmail.com >
*/
class BeforePageDisplayHandler implements BeforePageDisplayHook {
private bool $isMobileView;
private NamespaceChecker $namespaceChecker;
private bool $dataBridgeEnabled;
public function __construct(
bool $isMobileView,
NamespaceChecker $namespaceChecker,
bool $dataBridgeEnabled
) {
$this->isMobileView = $isMobileView;
$this->namespaceChecker = $namespaceChecker;
$this->dataBridgeEnabled = $dataBridgeEnabled;
}
public static function factory(
bool $isMobileView,
NamespaceChecker $namespaceChecker,
SettingsArray $clientSettings
): self {
return new self(
$isMobileView,
$namespaceChecker,
$clientSettings->getSetting( 'dataBridgeEnabled' )
);
}
/**
* @param OutputPage $outputPage
* @param Skin $skin
*/
public function onBeforePageDisplay( $outputPage, $skin ): void {
$actionName = $outputPage->getActionName();
$this->addModules( $outputPage, $actionName, $skin );
}
public function addModules( OutputPage $outputPage, string $actionName, Skin $skin ): void {
$title = $outputPage->getTitle();
if ( !$title || !$this->namespaceChecker->isWikibaseEnabled( $title->getNamespace() ) ) {
return;
}
$this->addStyleModules( $outputPage, $title, $actionName );
$this->addJsModules( $outputPage, $title, $actionName, $skin );
}
private function addStyleModules( OutputPage $outputPage, Title $title, string $actionName ): void {
// styles are not appropriate for cologne blue and should leave styling up to other skins
if ( $this->hasEditOrAddLinks( $outputPage, $title, $actionName ) ) {
$outputPage->addModuleStyles( 'wikibase.client.init' );
}
if ( $this->dataBridgeEnabled ) {
$outputPage->addModuleStyles( 'wikibase.client.data-bridge.externalModifiers' );
}
}
private function addJsModules( OutputPage $outputPage, Title $title, $actionName, Skin $skin ): void {
$user = $outputPage->getUser();
if ( $this->hasLinkItemWidget( $user, $outputPage, $title, $actionName ) ) {
// Add the JavaScript which lazy-loads the link item widget
// (needed as jquery.wikibase.linkitem has pretty heavy dependencies)
// T324991
if ( !$this->isMobileView ) {
$outputPage->addModules( 'wikibase.client.linkitem.init' );
}
}
if ( $skin->getSkinName() === 'vector-2022' && $outputPage->getProperty( 'wikibase_item' ) !== null ) {
$outputPage->addModules( 'wikibase.client.vector-2022' );
}
if ( $this->dataBridgeEnabled ) {
$outputPage->addModules( 'wikibase.client.data-bridge.init' );
}
}
private function hasEditOrAddLinks( OutputPage $outputPage, Title $title, string $actionName ): bool {
if (
!in_array( $actionName, [ 'view', 'submit' ] ) ||
$this->allLinksAreSuppressed( $outputPage ) ||
!$title->exists()
) {
return false;
}
return true;
}
private function allLinksAreSuppressed( OutputPage $outputPage ): bool {
$noexternallanglinks = $outputPage->getProperty( 'noexternallanglinks' );
if ( $noexternallanglinks !== null ) {
return in_array( '*', $noexternallanglinks );
}
return false;
}
private function hasLinkItemWidget( User $user, OutputPage $outputPage, Title $title, string $actionName ): bool {
if (
$outputPage->getLanguageLinks() !== [] || !$user->isNamed()
|| !$this->hasEditOrAddLinks( $outputPage, $title, $actionName )
) {
return false;
}
return true;
}
}