| Current Path : /var/www/html/mediawiki-1.43.1/extensions/BreadCrumbs2/ |
| Current File : /var/www/html/mediawiki-1.43.1/extensions/BreadCrumbs2/BreadCrumbs2.class.php |
<?php
/*
* This file is part of Extension:BreadCrumbs2
*
* Copyright (C) 2007; Eric Hartwell and Ike Hecht.
*
* Distributed under the terms of the CC-BY-3.0 license.
* Terms and conditions of the license can be found at
* <https://creativecommons.org/licenses/by/3.0/>
*
* @author Eric Hartwell (http://www.ehartwell.com/InfoDabble/BreadCrumbs2)
* @author Ike Hecht
* @license CC-BY-3.0
*/
use MediaWiki\MediaWikiServices;
class BreadCrumbs2 {
/**
* Constants
*/
const DELIM = '@';
/**
* Full text for the breadcrumbs, if any
*
* @var string
*/
private $crumbPath;
/**
* Sidebar text to look for
*
* @var string
*/
private $sidebarText;
/**
* Path to the logo, to be appended to $wgScriptPath
*
* @var string
*/
private $logoPath;
/**
* Final full breadcrumb path, including page title
* Will always contain at least the current page title
*
* @var string
*/
private $breadcrumb;
/**
* Stores the title of the first category in the page. Used for FIRSTCATEGORY variable.
*
* @var string
*/
private $firstCategoryInPage;
/**
* @var User
*/
private $user;
/**
* Does this page have breadcrumbs defined for it?
*
* @return bool
*/
public function hasBreadCrumbs() {
return (bool)$this->crumbPath;
}
/**
* Get the full output to be inserted into the wiki page
*
* @return string HTML
*/
public function getOutput() {
return Html::rawElement( 'div', [ 'id' => 'breadcrumbs2' ], $this->breadcrumb );
}
/**
*
* @param array $categories
* @param Title $title
* @param User $user
*/
public function __construct( array $categories, Title $title, User $user ) {
$this->user = $user;
if ( !empty( $categories ) ) {
$this->firstCategoryInPage = $categories[0];
}
/** @todo Support main namespace */
# Treat the namespace as a category too
if ( $title->getNsText() ) {
$categories[] = $title->getNsText();
}
$crumbs = $this->matchFirstCategory( $categories );
$this->crumbPath = $crumbs[0];
global $wgAllowDisplayTitle;
$htmlTitle = htmlspecialchars( $title->getText() );
if ( $wgAllowDisplayTitle ) {
$services = MediaWikiServices::getInstance();
if ( method_exists( $services, 'getPageProps' ) ) {
// MW 1.36+
$pageProps = $services->getPageProps();
} else {
$pageProps = PageProps::getInstance();
}
$displayTitle = $pageProps->getProperties( $title, 'displaytitle' )[ $title->getArticleID() ] ?? '';
$plainTextDisplayTitle = trim( Sanitizer::stripAllTags( $displayTitle ) );
// There is no need to check $wgRestrictDisplayTitle, as core already
// does that prior to setting the page property
if ( $plainTextDisplayTitle !== '' ) {
$htmlTitle = $displayTitle;
}
}
# add current title
$currentTitle = Html::rawElement( 'span', [ 'id' => 'breadcrumbs2-currentitle' ], $htmlTitle );
$this->breadcrumb = trim( $this->crumbPath . ' ' . $currentTitle );
$categories[] = $title->getText();
# Mark the corresponding tab of the sidebar as active
$crumbs = $this->matchFirstCategory( $categories );
$this->sidebarText = $crumbs[1];
$this->logoPath = $crumbs[2];
return true;
}
/**
* Look up the menu corresponding to the first matching category from the list
*
* @param array $categories
* @return array
*/
function matchFirstCategory( array $categories ) {
# First load and parse the template page
$content = $this->loadTemplate();
# Navigation list
$breadcrumb = '';
preg_match_all( "`<li>\s*?(.*?)\s*</li>`", $content, $matches, PREG_PATTERN_ORDER );
# Look for the first matching category or a default string
foreach ( $matches[1] as $nav ) {
$pos = strpos( $nav, self::DELIM ); // End of category
if ( $pos !== false ) {
$cat = trim( substr( $nav, 0, $pos ) );
$crumb = trim( substr( $nav, $pos + 1 ) );
// Is there a match for any of our page's categories?
if ( $cat == 'default' ) {
$breadcrumb = $crumb;
} elseif ( in_array( $cat, $categories ) ) {
$breadcrumb = $crumb;
break;
}
}
}
return self::normalizeParameters( $breadcrumb, self::DELIM, 3 );
}
/**
* Loads and preprocesses the template page
*
* @return string
*/
function loadTemplate() {
$msg = wfMessage( 'breadcrumbs' );
$template = $msg->plain();
if ( $template ) {
# Drop leading and trailing blanks and escape delimiter before parsing
# Substitute a few skin-related variables before parsing
$template = preg_replace( '/(^\s+|\s+$)/m', '', $template );
$template = str_replace( self::DELIM . self::DELIM . self::DELIM, "\x07", $template );
$template = preg_replace_callback(
'/' . self::DELIM . self::DELIM . '(.*?)' . self::DELIM . self::DELIM . '/',
[ __CLASS__, 'translate_variable' ],
$template
);
# Use the parser preprocessor to evaluate conditionals in the template
# Copy the parser to make sure we don't trash the parser state too much
$parser = clone self::getParser();
// It is needed for MW older 1.34,
// in other case $msg->getTitle() throws exception: Call to a member function equals() on boolean
$msg->inLanguage( RequestContext::getMain()->getLanguage() );
$template = $parser->parse(
$template,
$msg->getTitle(),
ParserOptions::newFromUser( $this->user )
);
try {
$template = str_replace( ' ', ' ', $template->getText() );
} catch ( MWException $e ) {
MWDebug::warning( $e->getText() );
$template = '';
}
return $template;
}
return '';
}
/**
* Normalize a delimited parameter line: trim leading and trailing blanks,
* restore escaped delimiter characters, add null elements until all optional
* parameters are accounted for, and drop extra parameters
*
* @param string $input
* @param string $delimiter
* @param int $count
* @return array
*/
private static function normalizeParameters( $input, $delimiter, $count ) {
# Split the parameters into an array
$params = explode( $delimiter, $input );
$output = [];
for ( $i = 0; $i < $count; $i++ ) {
$output[] = str_replace(
"\x07", $delimiter, ( $i < count( $params ) ) ? trim( $params[$i] ) : '' );
}
return $output;
}
/**
* Returns HTML text for the specified pseudo-variable
*
* @param array $matches
* @return string|null
*/
function translate_variable( $matches ) {
$tag = $matches[1];
switch ( strtoupper( $tag ) ) {
case 'USERGROUPS': // @@USERGROUPS@@ pseudo-variable: Groups this user belongs to
self::disableCache();
$ugm = MediaWikiServices::getInstance()->getUserGroupManager();
$groups = $ugm->getUserGroups( $this->user );
return implode( ",", $groups );
case 'USERID': // @@USERID@@ pseudo-variable: User Name, blank if anonymous
self::disableCache();
# getName() returns IP for anonymous users, so check if logged in first
return $this->user->isRegistered() ? $this->user->getName() : '';
case 'FIRSTCATEGORY':
return $this->firstCategoryInPage;
}
return null;
}
/**
* Set a flag in the output object indicating that the content is dynamic and
* shouldn't be cached.
*/
private static function disableCache() {
self::getParser()->getOutput()->updateCacheExpiry( 0 );
}
/**
* @return Parser
*/
private static function getParser() {
return MediaWikiServices::getInstance()->getParser();
}
public function getSidebarText() {
return $this->sidebarText;
}
public function getLogoPath() {
return $this->logoPath;
}
}