DynamicPageList3/includes/Parse.php

1059 lines
35 KiB
PHP
Raw Normal View History

2020-11-22 20:00:48 +00:00
<?php
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
namespace DPL;
use DPL\Heading\Heading;
use DPL\Lister\Lister;
2021-10-01 22:52:30 +00:00
use ExtVariables;
use MediaWiki\MediaWikiServices;
use MWException;
use Parser;
2022-03-09 20:17:24 +00:00
use RequestContext;
2021-10-01 22:52:30 +00:00
use Title;
use WebRequest;
2020-11-22 20:00:48 +00:00
class Parse {
/**
2021-10-01 22:52:30 +00:00
* Parameters Object
2020-11-22 20:00:48 +00:00
*
2021-10-01 22:52:30 +00:00
* @var Parameters
2020-11-22 20:00:48 +00:00
*/
private $parameters = null;
/**
2021-10-01 22:52:30 +00:00
* Logger Object
2020-11-22 20:00:48 +00:00
*
2021-10-01 22:52:30 +00:00
* @var Logger
2020-11-22 20:00:48 +00:00
*/
private $logger = null;
/**
* Array of prequoted table names.
*
2021-10-01 22:52:30 +00:00
* @var string[]
2020-11-22 20:00:48 +00:00
*/
private $tableNames = [];
/**
* Cache Key for this tag parse.
*
2021-02-22 23:48:01 +00:00
* @var string
2020-11-22 20:00:48 +00:00
*/
private $cacheKey = null;
/**
* Header Output
*
2021-02-22 23:48:01 +00:00
* @var string
2020-11-22 20:00:48 +00:00
*/
private $header = '';
/**
* Footer Output
*
2021-02-22 23:48:01 +00:00
* @var string
2020-11-22 20:00:48 +00:00
*/
private $footer = '';
/**
* Body Output
*
2021-02-22 23:48:01 +00:00
* @var string
2020-11-22 20:00:48 +00:00
*/
private $output = '';
/**
* Replacement Variables
*
2021-02-22 23:48:01 +00:00
* @var array
2020-11-22 20:00:48 +00:00
*/
private $replacementVariables = [];
2021-10-01 22:52:30 +00:00
/**
* WebRequest object
*
* @var WebRequest
*/
private $request;
2020-11-22 20:00:48 +00:00
/**
* Array of possible URL arguments.
*
2021-02-22 23:48:01 +00:00
* @var array
2020-11-22 20:00:48 +00:00
*/
private $urlArguments = [
'DPL_offset',
'DPL_count',
'DPL_fromTitle',
'DPL_findTitle',
'DPL_toTitle'
];
public function __construct() {
2021-10-01 22:52:30 +00:00
$this->parameters = new Parameters();
$this->logger = new Logger();
$this->tableNames = Query::getTableNames();
2022-03-09 20:17:24 +00:00
$this->request = RequestContext::getMain()->getRequest();
2020-11-22 20:00:48 +00:00
}
/**
* The real callback function for converting the input text to wiki text output
*
2021-10-01 22:52:30 +00:00
* @param string $input
* @param Parser $parser
* @param array &$reset
* @param array &$eliminate
* @param bool $isParserTag
* @return string
*
* @suppress PhanUndeclaredProperty Use of Parser::mTemplatePath
2020-11-22 20:00:48 +00:00
*/
2021-10-01 22:52:30 +00:00
public function parse( $input, Parser $parser, &$reset, &$eliminate, $isParserTag = false ) {
2021-02-22 23:48:01 +00:00
$dplStartTime = microtime( true );
2020-11-22 20:00:48 +00:00
2021-10-01 22:52:30 +00:00
// Reset headings when being ran more than once in the same page load.
2020-11-22 20:00:48 +00:00
Article::resetHeadings();
2021-10-01 22:52:30 +00:00
// Check that we are not in an infinite transclusion loop
if ( isset( $parser->mTemplatePath[$parser->getTitle()->getPrefixedText()] ) ) {
$this->logger->addMessage( DynamicPageListHooks::WARN_TRANSCLUSIONLOOP, $parser->getTitle()->getPrefixedText() );
2020-11-22 20:00:48 +00:00
return $this->getFullOutput();
}
2021-10-01 22:52:30 +00:00
// Check if DPL shall only be executed from protected pages.
if ( Config::getSetting( 'runFromProtectedPagesOnly' ) === true && !$parser->getTitle()->isProtected( 'edit' ) ) {
// Ideally we would like to allow using a DPL query if the query istelf is coded on a template page which is protected. Then there would be no need for the article to be protected. However, how can one find out from which wiki source an extension has been invoked???
$this->logger->addMessage( DynamicPageListHooks::FATAL_NOTPROTECTED, $parser->getTitle()->getPrefixedText() );
2020-11-22 20:00:48 +00:00
return $this->getFullOutput();
}
/************************************/
/* Check for URL Arguments in Input */
/************************************/
2021-02-22 23:48:01 +00:00
if ( strpos( $input, '{%DPL_' ) >= 0 ) {
for ( $i = 1; $i <= 5; $i++ ) {
2020-11-22 20:00:48 +00:00
$this->urlArguments[] = 'DPL_arg' . $i;
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$input = $this->resolveUrlArguments( $input, $this->urlArguments );
2021-10-01 22:52:30 +00:00
$this->getUrlArgs( $parser );
2020-11-22 20:00:48 +00:00
2021-10-01 22:52:30 +00:00
$this->parameters->setParameter( 'offset', $this->request->getInt( 'DPL_offset', $this->parameters->getData( 'offset' )['default'] ) );
2021-02-22 23:48:01 +00:00
$offset = $this->parameters->getParameter( 'offset' );
2020-11-22 20:00:48 +00:00
/***************************************/
/* User Input preparation and parsing. */
/***************************************/
2021-02-22 23:48:01 +00:00
$cleanParameters = $this->prepareUserInput( $input );
if ( !is_array( $cleanParameters ) ) {
2021-10-01 22:52:30 +00:00
// Short circuit for dumb things.
$this->logger->addMessage( DynamicPageListHooks::FATAL_NOSELECTION );
2020-11-22 20:00:48 +00:00
return $this->getFullOutput();
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$cleanParameters = Parameters::sortByPriority( $cleanParameters );
$this->parameters->setParameter( 'includeuncat', false ); // to check if pseudo-category of Uncategorized pages is included
2020-11-22 20:00:48 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $cleanParameters as $parameter => $option ) {
foreach ( $option as $_option ) {
2021-10-01 22:52:30 +00:00
// Parameter functions return true or false. The full parameter data will be passed into the Query object later.
2021-02-22 23:48:01 +00:00
if ( $this->parameters->$parameter( $_option ) === false ) {
2021-10-01 22:52:30 +00:00
// Do not build this into the output just yet. It will be collected at the end.
$this->logger->addMessage( DynamicPageListHooks::WARN_WRONGPARAM, $parameter, $_option );
2020-11-22 20:00:48 +00:00
}
}
}
/*************************/
/* Execute and Exit Only */
/*************************/
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'execandexit' ) !== null ) {
2021-10-01 22:52:30 +00:00
// The keyword "geturlargs" is used to return the Url arguments and do nothing else.
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'execandexit' ) == 'geturlargs' ) {
2021-10-01 22:52:30 +00:00
return '';
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
// In all other cases we return the value of the argument which may contain parser function calls.
2021-02-22 23:48:01 +00:00
return $this->parameters->getParameter( 'execandexit' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
// Construct internal keys for TableRow according to the structure of "include". This will be needed in the output phase.
2021-02-22 23:48:01 +00:00
$secLabels = $this->parameters->getParameter( 'seclabels' );
if ( is_array( $secLabels ) && !empty( $this->parameters->getParameter( 'seclabels' ) ) ) {
$this->parameters->setParameter( 'tablerow', $this->updateTableRowKeys( $this->parameters->getParameter( 'tablerow' ), $this->parameters->getParameter( 'seclabels' ) ) );
2020-11-22 20:00:48 +00:00
}
/****************/
/* Check Errors */
/****************/
$errors = $this->doQueryErrorChecks();
2021-02-22 23:48:01 +00:00
if ( $errors === false ) {
2021-10-01 22:52:30 +00:00
// WHAT HAS HAPPENED OH NOOOOOOOOOOOOO.
2020-11-22 20:00:48 +00:00
return $this->getFullOutput();
}
$calcRows = false;
2021-02-22 23:48:01 +00:00
if ( !Config::getSetting( 'allowUnlimitedResults' ) && $this->parameters->getParameter( 'goal' ) != 'categories' && strpos( $this->parameters->getParameter( 'resultsheader' ) . $this->parameters->getParameter( 'noresultsheader' ) . $this->parameters->getParameter( 'resultsfooter' ), '%TOTALPAGES%' ) !== false ) {
2020-11-22 20:00:48 +00:00
$calcRows = true;
}
/*********/
/* Query */
/*********/
try {
2021-10-06 18:44:11 +00:00
$query = new Query( $this->parameters );
$rows = $query->buildAndSelect( $calcRows );
if ( $rows === false ) {
// This error path is very fast (We exit immediately if poolcounter is full)
// Thus it should be safe to try again in ~5 minutes.
$parser->getOutput()->updateCacheExpiry( 4 * 60 + mt_rand( 0, 120 ) );
// Pool counter all threads in use.
$this->logger->addMessage( DynamicPageListHooks::FATAL_POOLCOUNTER );
return $this->getFullOutput( true );
}
2021-02-22 23:48:01 +00:00
} catch ( MWException $e ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_SQLBUILDERROR, $e->getMessage() );
2020-11-22 20:00:48 +00:00
return $this->getFullOutput();
}
$numRows = count( $rows );
$articles = $this->processQueryResults( $rows, $parser );
2020-11-22 20:00:48 +00:00
global $wgDebugDumpSql;
2021-10-01 22:52:30 +00:00
if ( DynamicPageListHooks::getDebugLevel() >= 4 && $wgDebugDumpSql ) {
$this->addOutput( $query->getSqlQuery() . "\n" );
2020-11-22 20:00:48 +00:00
}
2021-02-22 23:48:01 +00:00
$this->addOutput( '{{Extension DPL}}' );
2020-11-22 20:00:48 +00:00
2021-10-01 22:52:30 +00:00
// Preset these to defaults.
$this->setVariable( 'TOTALPAGES', '0' );
$this->setVariable( 'PAGES', '0' );
$this->setVariable( 'VERSION', DynamicPageListHooks::getVersion() );
2020-11-22 20:00:48 +00:00
/*********************/
/* Handle No Results */
/*********************/
if ( $numRows == 0 || empty( $articles ) ) {
2021-02-22 23:48:01 +00:00
return $this->getFullOutput( 0, false );
2020-11-22 20:00:48 +00:00
}
$foundRows = null;
2021-02-22 23:48:01 +00:00
if ( $calcRows ) {
2021-10-01 22:52:30 +00:00
$foundRows = $query->getFoundRows();
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
// Backward scrolling: If the user specified only titlelt with descending reverse the output order.
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'titlelt' ) && !$this->parameters->getParameter( 'titlegt' ) && $this->parameters->getParameter( 'order' ) == 'descending' ) {
$articles = array_reverse( $articles );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
// Special sort for card suits (Bridge)
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'ordersuitsymbols' ) ) {
$articles = $this->cardSuitSort( $articles );
2020-11-22 20:00:48 +00:00
}
/*******************/
/* Generate Output */
/*******************/
2021-10-01 22:52:30 +00:00
$lister = Lister::newFromStyle( $this->parameters->getParameter( 'mode' ), $this->parameters, $parser );
2021-02-22 23:48:01 +00:00
$heading = Heading::newFromStyle( $this->parameters->getParameter( 'headingmode' ), $this->parameters );
if ( $heading !== null ) {
$this->addOutput( $heading->format( $articles, $lister ) );
2020-11-22 20:00:48 +00:00
} else {
2021-02-22 23:48:01 +00:00
$this->addOutput( $lister->format( $articles ) );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
// $this->addOutput($lister->format($articles));
2021-02-22 23:48:01 +00:00
if ( $foundRows === null ) {
2021-10-01 22:52:30 +00:00
$foundRows = $lister->getRowCount(); // Get row count after calling format() otherwise the count will be inaccurate.
2020-11-22 20:00:48 +00:00
}
/*******************************/
/* Replacement Variables */
/*******************************/
2021-10-01 22:52:30 +00:00
$this->setVariable( 'TOTALPAGES', (string)$foundRows ); // Guaranteed to be an accurate count if SQL_CALC_FOUND_ROWS was used. Otherwise only accurate if results are less than the SQL LIMIT.
$this->setVariable( 'PAGES', $lister->getRowCount() ); // This could be different than TOTALPAGES. PAGES represents the total results within the constraints of SQL LIMIT.
2020-11-22 20:00:48 +00:00
//Replace %DPLTIME% by execution time and timestamp in header and footer
2021-10-01 22:52:30 +00:00
$nowTimeStamp = date( 'Y/m/d H:i:s' );
2021-02-22 23:48:01 +00:00
$dplElapsedTime = sprintf( '%.3f sec.', microtime( true ) - $dplStartTime );
2020-11-22 20:00:48 +00:00
$dplTime = "{$dplElapsedTime} ({$nowTimeStamp})";
2021-02-22 23:48:01 +00:00
$this->setVariable( 'DPLTIME', $dplTime );
2020-11-22 20:00:48 +00:00
2021-10-01 22:52:30 +00:00
$firstNamespaceFound = '';
$firstTitleFound = '';
$lastNamespaceFound = '';
$lastTitleFound = '';
// Replace %LASTTITLE% / %LASTNAMESPACE% by the last title found in header and footer
$n = count( $articles );
if ( $n > 0 ) {
2021-02-22 23:48:01 +00:00
$firstNamespaceFound = str_replace( ' ', '_', $articles[0]->mTitle->getNamespace() );
2021-10-01 22:52:30 +00:00
$firstTitleFound = str_replace( ' ', '_', $articles[0]->mTitle->getText() );
$lastNamespaceFound = str_replace( ' ', '_', $articles[$n - 1]->mTitle->getNamespace() );
$lastTitleFound = str_replace( ' ', '_', $articles[$n - 1]->mTitle->getText() );
2021-02-22 23:48:01 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this->setVariable( 'FIRSTNAMESPACE', $firstNamespaceFound );
$this->setVariable( 'FIRSTTITLE', $firstTitleFound );
$this->setVariable( 'LASTNAMESPACE', $lastNamespaceFound );
$this->setVariable( 'LASTTITLE', $lastTitleFound );
$this->setVariable( 'SCROLLDIR', $this->parameters->getParameter( 'scrolldir' ) );
2020-11-22 20:00:48 +00:00
/*******************************/
/* Scroll Variables */
/*******************************/
$scrollVariables = [
2021-10-01 22:52:30 +00:00
'DPL_firstNamespace' => $firstNamespaceFound,
'DPL_firstTitle' => $firstTitleFound,
'DPL_lastNamespace' => $lastNamespaceFound,
'DPL_lastTitle' => $lastTitleFound,
'DPL_scrollDir' => $this->parameters->getParameter( 'scrolldir' ),
'DPL_time' => $dplTime,
'DPL_count' => $this->parameters->getParameter( 'count' ),
'DPL_totalPages' => $foundRows,
'DPL_pages' => $lister->getRowCount()
2020-11-22 20:00:48 +00:00
];
2021-10-01 22:52:30 +00:00
$this->defineScrollVariables( $scrollVariables, $parser );
2020-11-22 20:00:48 +00:00
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'allowcachedresults' ) || Config::getSetting( 'alwaysCacheResults' ) ) {
2021-10-01 22:52:30 +00:00
$parser->getOutput()->updateCacheExpiry( $this->parameters->getParameter( 'cacheperiod' ) ?? 3600 );
2020-11-22 20:00:48 +00:00
} else {
2021-10-01 22:52:30 +00:00
$parser->getOutput()->updateCacheExpiry( 0 );
2020-11-22 20:00:48 +00:00
}
2021-02-22 23:48:01 +00:00
$finalOutput = $this->getFullOutput( $foundRows, false );
2020-11-22 20:00:48 +00:00
2021-10-01 22:52:30 +00:00
$this->triggerEndResets( $finalOutput, $reset, $eliminate, $isParserTag, $parser );
2020-11-22 20:00:48 +00:00
return $finalOutput;
}
/**
* Process Query Results
*
* @param $rows
2021-10-01 22:52:30 +00:00
* @param Parser $parser
* @return array
2020-11-22 20:00:48 +00:00
*/
private function processQueryResults( $rows, Parser $parser ) {
2020-11-22 20:00:48 +00:00
/*******************************/
/* Random Count Pick Generator */
/*******************************/
2021-02-22 23:48:01 +00:00
$randomCount = $this->parameters->getParameter( 'randomcount' );
if ( $randomCount > 0 ) {
$nResults = count( $rows );
// Constrain the total amount of random results to not be greater than the total results.
2021-02-22 23:48:01 +00:00
if ( $randomCount > $nResults ) {
2020-11-22 20:00:48 +00:00
$randomCount = $nResults;
}
2021-10-01 22:52:30 +00:00
// Generate pick numbers for results.
2021-02-22 23:48:01 +00:00
$pick = range( 1, $nResults );
2021-10-01 22:52:30 +00:00
// Shuffle the pick numbers.
2021-02-22 23:48:01 +00:00
shuffle( $pick );
2021-10-01 22:52:30 +00:00
// Select pick numbers from the beginning to the maximum of $randomCount.
2021-02-22 23:48:01 +00:00
$pick = array_slice( $pick, 0, $randomCount );
2020-11-22 20:00:48 +00:00
}
$articles = [];
/**********************/
/* Article Processing */
/**********************/
$i = 0;
foreach ( $rows as $row ) {
2020-11-22 20:00:48 +00:00
$i++;
2021-10-01 22:52:30 +00:00
// In random mode skip articles which were not chosen.
if ( $randomCount > 0 && !in_array( $i, $pick ?? [] ) ) {
2020-11-22 20:00:48 +00:00
continue;
}
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'goal' ) == 'categories' ) {
2020-11-22 20:00:48 +00:00
$pageNamespace = NS_CATEGORY;
$pageTitle = $row->cl_to;
2021-02-22 23:48:01 +00:00
} elseif ( $this->parameters->getParameter( 'openreferences' ) ) {
if ( count( $this->parameters->getParameter( 'imagecontainer' ) ) > 0 ) {
2020-11-22 20:00:48 +00:00
$pageNamespace = NS_FILE;
$pageTitle = $row->il_to;
2020-11-22 20:00:48 +00:00
} else {
2021-10-01 22:52:30 +00:00
// Maybe non-existing title
$pageNamespace = $row->pl_namespace;
$pageTitle = $row->pl_title;
2020-11-22 20:00:48 +00:00
}
if (
$this->parameters->getParameter( 'openreferences' ) === 'missing' &&
Title::makeTitle( $pageNamespace, $pageTitle )->exists()
) {
continue;
}
2020-11-22 20:00:48 +00:00
} else {
2021-10-01 22:52:30 +00:00
// Existing PAGE TITLE
$pageNamespace = $row->page_namespace;
$pageTitle = $row->page_title;
2020-11-22 20:00:48 +00:00
}
// if subpages are to be excluded: skip them
2021-02-22 23:48:01 +00:00
if ( !$this->parameters->getParameter( 'includesubpages' ) && strpos( $pageTitle, '/' ) !== false ) {
2020-11-22 20:00:48 +00:00
continue;
}
2021-10-01 22:52:30 +00:00
$title = Title::makeTitle( $pageNamespace, $pageTitle );
$thisTitle = $parser->getTitle();
2020-11-22 20:00:48 +00:00
2021-10-01 22:52:30 +00:00
// Block recursion from happening by seeing if this result row is the page the DPL query was ran from.
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'skipthispage' ) && $thisTitle->equals( $title ) ) {
2020-11-22 20:00:48 +00:00
continue;
}
2021-02-22 23:48:01 +00:00
$articles[] = Article::newFromRow( $row, $this->parameters, $title, $pageNamespace, $pageTitle );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return $articles;
}
/**
* Do basic clean up and structuring of raw user input.
*
2021-10-01 22:52:30 +00:00
* @param string $input
* @return array
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function prepareUserInput( $input ) {
2021-10-01 22:52:30 +00:00
// We replace double angle brackets with single angle brackets to avoid premature tag expansion in the input.
// The ¦ symbol is an alias for |.
// The combination '²{' and '}²'will be translated to double curly braces; this allows postponed template execution which is crucial for DPL queries which call other DPL queries.
2021-02-22 23:48:01 +00:00
$input = str_replace( [ '«', '»', '¦', '²{', '}²' ], [ '<', '>', '|', '{{', '}}' ], $input );
2020-11-22 20:00:48 +00:00
2021-10-01 22:52:30 +00:00
// Standard new lines into the standard \n and clean up any hanging new lines.
2021-02-22 23:48:01 +00:00
$input = str_replace( [ "\r\n", "\r" ], "\n", $input );
$input = trim( $input, "\n" );
$rawParameters = explode( "\n", $input );
2020-11-22 20:00:48 +00:00
2021-10-01 22:52:30 +00:00
$parameters = [];
2021-02-22 23:48:01 +00:00
foreach ( $rawParameters as $parameterOption ) {
if ( empty( $parameterOption ) ) {
2021-10-01 22:52:30 +00:00
// Softly ignore blank lines.
2020-11-22 20:00:48 +00:00
continue;
}
2021-02-22 23:48:01 +00:00
if ( strpos( $parameterOption, '=' ) === false ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::WARN_PARAMNOOPTION, $parameterOption );
2020-11-22 20:00:48 +00:00
continue;
}
2021-10-01 22:52:30 +00:00
[ $parameter, $option ] = explode( '=', $parameterOption, 2 );
2021-02-22 23:48:01 +00:00
$parameter = trim( $parameter );
2021-10-01 22:52:30 +00:00
$option = trim( $option );
2020-11-22 20:00:48 +00:00
2021-02-22 23:48:01 +00:00
if ( strpos( $parameter, '<' ) !== false || strpos( $parameter, '>' ) !== false ) {
2021-10-01 22:52:30 +00:00
// Having the actual less than and greater than symbols is nasty for programatic look up. The old parameter is still supported along with the new, but we just fix it here before calling it.
2021-02-22 23:48:01 +00:00
$parameter = str_replace( '<', 'lt', $parameter );
$parameter = str_replace( '>', 'gt', $parameter );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
$parameter = strtolower( $parameter ); // Force lower case for ease of use.
2021-02-22 23:48:01 +00:00
if ( empty( $parameter ) || substr( $parameter, 0, 1 ) == '#' || ( $this->parameters->exists( $parameter ) && !$this->parameters->testRichness( $parameter ) ) ) {
2020-11-22 20:00:48 +00:00
continue;
}
2021-02-22 23:48:01 +00:00
if ( !$this->parameters->exists( $parameter ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::WARN_UNKNOWNPARAM, $parameter, implode( ', ', $this->parameters->getParametersForRichness() ) );
2020-11-22 20:00:48 +00:00
continue;
}
2021-10-01 22:52:30 +00:00
// Ignore parameter settings without argument (except namespace and category).
2021-02-22 23:48:01 +00:00
if ( !strlen( $option ) ) {
if ( $parameter != 'namespace' && $parameter != 'notnamespace' && $parameter != 'category' && $this->parameters->exists( $parameter ) ) {
2020-11-22 20:00:48 +00:00
continue;
}
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$parameters[$parameter][] = $option;
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return $parameters;
}
/**
* Concatenate output
*
2021-10-01 22:52:30 +00:00
* @param string $output
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function addOutput( $output ) {
2020-11-22 20:00:48 +00:00
$this->output .= $output;
}
/**
* Set the output text.
*
2021-10-01 22:52:30 +00:00
* @return string
2020-11-22 20:00:48 +00:00
*/
private function getOutput() {
2021-10-01 22:52:30 +00:00
// @TODO: 2015-08-28 Consider calling $this->replaceVariables() here. Might cause issues with text returned in the results.
2020-11-22 20:00:48 +00:00
return $this->output;
}
/**
* Return output optionally including header and footer.
*
2021-10-01 22:52:30 +00:00
* @param bool|int $totalResults
* @param bool $skipHeaderFooter
* @return string
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function getFullOutput( $totalResults = false, $skipHeaderFooter = true ) {
if ( !$skipHeaderFooter ) {
2020-11-22 20:00:48 +00:00
$header = '';
$footer = '';
2021-10-01 22:52:30 +00:00
// Only override header and footers if specified.
$_headerType = $this->getHeaderFooterType( 'header', (int)$totalResults );
2021-02-22 23:48:01 +00:00
if ( $_headerType !== false ) {
$header = $this->parameters->getParameter( $_headerType );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
$_footerType = $this->getHeaderFooterType( 'footer', (int)$totalResults );
2021-02-22 23:48:01 +00:00
if ( $_footerType !== false ) {
$footer = $this->parameters->getParameter( $_footerType );
2020-11-22 20:00:48 +00:00
}
2021-02-22 23:48:01 +00:00
$this->setHeader( $header );
$this->setFooter( $footer );
2020-11-22 20:00:48 +00:00
}
2021-02-22 23:48:01 +00:00
if ( !$totalResults && !strlen( $this->getHeader() ) && !strlen( $this->getFooter() ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::WARN_NORESULTS );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$messages = $this->logger->getMessages( false );
2020-11-22 20:00:48 +00:00
2021-02-22 23:48:01 +00:00
return ( count( $messages ) ? implode( "<br/>\n", $messages ) : null ) . $this->getHeader() . $this->getOutput() . $this->getFooter();
2020-11-22 20:00:48 +00:00
}
/**
* Set the header text.
*
2021-10-01 22:52:30 +00:00
* @param string $header
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function setHeader( $header ) {
2021-10-01 22:52:30 +00:00
if ( DynamicPageListHooks::getDebugLevel() == 5 ) {
2020-11-22 20:00:48 +00:00
$header = '<pre><nowiki>' . $header;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this->header = $this->replaceVariables( $header );
2020-11-22 20:00:48 +00:00
}
/**
* Set the header text.
*
2021-10-01 22:52:30 +00:00
* @return string
2020-11-22 20:00:48 +00:00
*/
private function getHeader() {
return $this->header;
}
/**
* Set the footer text.
*
2021-10-01 22:52:30 +00:00
* @param string $footer
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function setFooter( $footer ) {
2021-10-01 22:52:30 +00:00
if ( DynamicPageListHooks::getDebugLevel() == 5 ) {
2020-11-22 20:00:48 +00:00
$footer .= '</nowiki></pre>';
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$this->footer = $this->replaceVariables( $footer );
2020-11-22 20:00:48 +00:00
}
/**
* Set the footer text.
*
2021-10-01 22:52:30 +00:00
* @return string
2020-11-22 20:00:48 +00:00
*/
private function getFooter() {
return $this->footer;
}
/**
* Determine the header/footer type to use based on what output format parameters were chosen and the number of results.
*
2021-10-01 22:52:30 +00:00
* @param string $position
* @param int $count
* @return mixed Type to use: 'results', 'oneresult', or 'noresults'. False if invalid or none should be used.
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function getHeaderFooterType( $position, $count ) {
$count = intval( $count );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $position != 'header' && $position != 'footer' ) {
2020-11-22 20:00:48 +00:00
return false;
}
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'results' . $position ) !== null && ( $count >= 2 || ( $this->parameters->getParameter( 'oneresult' . $position ) === null && $count >= 1 ) ) ) {
2020-11-22 20:00:48 +00:00
$_type = 'results' . $position;
2021-02-22 23:48:01 +00:00
} elseif ( $count === 1 && $this->parameters->getParameter( 'oneresult' . $position ) !== null ) {
2020-11-22 20:00:48 +00:00
$_type = 'oneresult' . $position;
2021-02-22 23:48:01 +00:00
} elseif ( $count === 0 && $this->parameters->getParameter( 'noresults' . $position ) !== null ) {
2020-11-22 20:00:48 +00:00
$_type = 'noresults' . $position;
} else {
$_type = false;
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return $_type;
}
/**
* Set a variable to be replaced with the provided text later at the end of the output.
*
2021-10-01 22:52:30 +00:00
* @param string $variable
* @param string $replacement
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function setVariable( $variable, $replacement ) {
$variable = "%" . mb_strtoupper( $variable, "UTF-8" ) . "%";
2020-11-22 20:00:48 +00:00
$this->replacementVariables[$variable] = $replacement;
}
/**
* Return text with variables replaced.
*
2021-10-01 22:52:30 +00:00
* @param string $text
* @return string
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function replaceVariables( $text ) {
$text = self::replaceNewLines( $text );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $this->replacementVariables as $variable => $replacement ) {
$text = str_replace( $variable, $replacement, $text );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return $text;
}
/**
* Return text with custom new line characters replaced.
*
2021-10-01 22:52:30 +00:00
* @param string $text
* @return string
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
public static function replaceNewLines( $text ) {
return str_replace( [ '\n', "" ], "\n", $text );
2020-11-22 20:00:48 +00:00
}
/**
* Work through processed parameters and check for potential issues.
*
2021-10-01 22:52:30 +00:00
* @return bool
2020-11-22 20:00:48 +00:00
*/
private function doQueryErrorChecks() {
/**************************/
/* Parameter Error Checks */
/**************************/
$totalCategories = 0;
2021-02-22 23:48:01 +00:00
if ( is_array( $this->parameters->getParameter( 'category' ) ) ) {
foreach ( $this->parameters->getParameter( 'category' ) as $comparisonType => $operatorTypes ) {
foreach ( $operatorTypes as $operatorType => $categoryGroups ) {
foreach ( $categoryGroups as $categories ) {
if ( is_array( $categories ) ) {
$totalCategories += count( $categories );
2020-11-22 20:00:48 +00:00
}
}
}
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( is_array( $this->parameters->getParameter( 'notcategory' ) ) ) {
foreach ( $this->parameters->getParameter( 'notcategory' ) as $comparisonType => $operatorTypes ) {
foreach ( $operatorTypes as $operatorType => $categories ) {
if ( is_array( $categories ) ) {
$totalCategories += count( $categories );
2020-11-22 20:00:48 +00:00
}
}
}
}
2021-10-01 22:52:30 +00:00
// Too many categories.
2021-02-22 23:48:01 +00:00
if ( $totalCategories > Config::getSetting( 'maxCategoryCount' ) && !Config::getSetting( 'allowUnlimitedCategories' ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_TOOMANYCATS, Config::getSetting( 'maxCategoryCount' ) );
2020-11-22 20:00:48 +00:00
return false;
}
2021-10-01 22:52:30 +00:00
// Not enough categories.(Really?)
2021-02-22 23:48:01 +00:00
if ( $totalCategories < Config::getSetting( 'minCategoryCount' ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_TOOFEWCATS, Config::getSetting( 'minCategoryCount' ) );
2020-11-22 20:00:48 +00:00
return false;
}
2021-10-01 22:52:30 +00:00
// Selection criteria needs to be found.
2021-02-22 23:48:01 +00:00
if ( !$totalCategories && !$this->parameters->isSelectionCriteriaFound() ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_NOSELECTION );
2020-11-22 20:00:48 +00:00
return false;
}
2021-10-01 22:52:30 +00:00
// ordermethod=sortkey requires ordermethod=category
// Delayed to the construction of the SQL query, see near line 2211, gs
// if (in_array('sortkey',$aOrderMethods) && ! in_array('category',$aOrderMethods)) $aOrderMethods[] = 'category';
2020-11-22 20:00:48 +00:00
2021-02-22 23:48:01 +00:00
$orderMethods = (array)$this->parameters->getParameter( 'ordermethod' );
2021-10-01 22:52:30 +00:00
// Throw an error in no categories were selected when using category sorting modes or requesting category information.
2021-02-22 23:48:01 +00:00
if ( $totalCategories == 0 && ( in_array( 'categoryadd', $orderMethods ) || $this->parameters->getParameter( 'addfirstcategorydate' ) === true ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_CATDATEBUTNOINCLUDEDCATS );
2020-11-22 20:00:48 +00:00
return false;
}
2021-10-01 22:52:30 +00:00
// No more than one type of date at a time!
// @TODO: Can this be fixed to allow all three later after fixing the article class?
2021-02-22 23:48:01 +00:00
if ( ( intval( $this->parameters->getParameter( 'addpagetoucheddate' ) ) + intval( $this->parameters->getParameter( 'addfirstcategorydate' ) ) + intval( $this->parameters->getParameter( 'addeditdate' ) ) ) > 1 ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_MORETHAN1TYPEOFDATE );
2020-11-22 20:00:48 +00:00
return false;
}
// the dominant section must be one of the sections mentioned in includepage
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'dominantsection' ) > 0 && count( $this->parameters->getParameter( 'seclabels' ) ) < $this->parameters->getParameter( 'dominantsection' ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_DOMINANTSECTIONRANGE, count( $this->parameters->getParameter( 'seclabels' ) ) );
2020-11-22 20:00:48 +00:00
return false;
}
// category-style output requested with not compatible order method
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'mode' ) == 'category' && !array_intersect( $orderMethods, [ 'sortkey', 'title', 'titlewithoutnamespace' ] ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_WRONGORDERMETHOD, 'mode=category', 'sortkey | title | titlewithoutnamespace' );
2020-11-22 20:00:48 +00:00
return false;
}
// addpagetoucheddate=true with unappropriate order methods
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'addpagetoucheddate' ) && !array_intersect( $orderMethods, [ 'pagetouched', 'title' ] ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_WRONGORDERMETHOD, 'addpagetoucheddate=true', 'pagetouched | title' );
2020-11-22 20:00:48 +00:00
return false;
}
// addeditdate=true but not (ordermethod=...,firstedit or ordermethod=...,lastedit)
2021-10-01 22:52:30 +00:00
// firstedit (resp. lastedit) -> add date of first (resp. last) revision
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'addeditdate' ) && !array_intersect( $orderMethods, [ 'firstedit', 'lastedit' ] ) && ( $this->parameters->getParameter( 'allrevisionsbefore' ) || $this->parameters->getParameter( 'allrevisionssince' ) || $this->parameters->getParameter( 'firstrevisionsince' ) || $this->parameters->getParameter( 'lastrevisionbefore' ) ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_WRONGORDERMETHOD, 'addeditdate=true', 'firstedit | lastedit' );
2020-11-22 20:00:48 +00:00
return false;
}
// adduser=true but not (ordermethod=...,firstedit or ordermethod=...,lastedit)
/**
* @todo allow to add user for other order methods.
* The fact is a page may be edited by multiple users. Which user(s) should we show? all? the first or the last one?
* Ideally, we could use values such as 'all', 'first' or 'last' for the adduser parameter.
*/
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'adduser' ) && !array_intersect( $orderMethods, [ 'firstedit', 'lastedit' ] ) && !$this->parameters->getParameter( 'allrevisionsbefore' ) && !$this->parameters->getParameter( 'allrevisionssince' ) && !$this->parameters->getParameter( 'firstrevisionsince' ) && !$this->parameters->getParameter( 'lastrevisionbefore' ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_WRONGORDERMETHOD, 'adduser=true', 'firstedit | lastedit' );
2020-11-22 20:00:48 +00:00
return false;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'minoredits' ) && !array_intersect( $orderMethods, [ 'firstedit', 'lastedit' ] ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_WRONGORDERMETHOD, 'minoredits', 'firstedit | lastedit' );
2020-11-22 20:00:48 +00:00
return false;
}
2021-10-01 22:52:30 +00:00
// add*** parameters have no effect with 'mode=category' (only namespace/title can be viewed in this mode)
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'mode' ) == 'category' && ( $this->parameters->getParameter( 'addcategories' ) || $this->parameters->getParameter( 'addeditdate' ) || $this->parameters->getParameter( 'addfirstcategorydate' ) || $this->parameters->getParameter( 'addpagetoucheddate' ) || $this->parameters->getParameter( 'incpage' ) || $this->parameters->getParameter( 'adduser' ) || $this->parameters->getParameter( 'addauthor' ) || $this->parameters->getParameter( 'addcontribution' ) || $this->parameters->getParameter( 'addlasteditor' ) ) ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::WARN_CATOUTPUTBUTWRONGPARAMS );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
// headingmode has effects with ordermethod on multiple components only
2021-02-22 23:48:01 +00:00
if ( $this->parameters->getParameter( 'headingmode' ) !== 'none' && count( $orderMethods ) < 2 ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::WARN_HEADINGBUTSIMPLEORDERMETHOD, $this->parameters->getParameter( 'headingmode' ), 'none' );
2021-02-22 23:48:01 +00:00
$this->parameters->setParameter( 'headingmode', 'none' );
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
// The 'openreferences' parameter is incompatible with many other options.
2021-02-22 23:48:01 +00:00
if ( $this->parameters->isOpenReferencesConflict() && $this->parameters->getParameter( 'openreferences' ) === true ) {
2021-10-01 22:52:30 +00:00
$this->logger->addMessage( DynamicPageListHooks::FATAL_OPENREFERENCES );
2020-11-22 20:00:48 +00:00
return false;
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return true;
}
/**
* Create keys for TableRow which represent the structure of the "include=" arguments.
*
2021-10-01 22:52:30 +00:00
* @param array $tableRow
* @param array $sectionLabels
* @return array
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private static function updateTableRowKeys( $tableRow, $sectionLabels ) {
2021-10-01 22:52:30 +00:00
$_tableRow = (array)$tableRow;
$tableRow = [];
$groupNr = -1;
$t = -1;
2021-02-22 23:48:01 +00:00
foreach ( $sectionLabels as $label ) {
2020-11-22 20:00:48 +00:00
$t++;
$groupNr++;
2021-02-22 23:48:01 +00:00
$cols = explode( '}:', $label );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( count( $cols ) <= 1 ) {
if ( array_key_exists( $t, $_tableRow ) ) {
2020-11-22 20:00:48 +00:00
$tableRow[$groupNr] = $_tableRow[$t];
}
} else {
2021-10-01 22:52:30 +00:00
$n = count( explode( ':', $cols[1] ) );
2020-11-22 20:00:48 +00:00
$colNr = -1;
$t--;
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
for ( $i = 1; $i <= $n; $i++ ) {
2020-11-22 20:00:48 +00:00
$colNr++;
$t++;
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( array_key_exists( $t, $_tableRow ) ) {
2020-11-22 20:00:48 +00:00
$tableRow[$groupNr . '.' . $colNr] = $_tableRow[$t];
}
}
}
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return $tableRow;
}
/**
* Resolve arguments in the input that would normally be in the URL.
*
2021-10-01 22:52:30 +00:00
* @param string $input
* @param array $arguments
* @return string
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function resolveUrlArguments( $input, $arguments ) {
2020-11-22 20:00:48 +00:00
$arguments = (array)$arguments;
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $arguments as $arg ) {
2021-10-01 22:52:30 +00:00
$dplArg = $this->request->getVal( $arg, '' );
2021-02-22 23:48:01 +00:00
if ( $dplArg == '' ) {
$input = preg_replace( '/\{%' . $arg . ':(.*)%\}/U', '\1', $input );
$input = str_replace( '{%' . $arg . '%}', '', $input );
2020-11-22 20:00:48 +00:00
} else {
2021-02-22 23:48:01 +00:00
$input = preg_replace( '/\{%' . $arg . ':.*%\}/U ', $dplArg, $input );
$input = str_replace( '{%' . $arg . '%}', $dplArg, $input );
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return $input;
}
/**
* This function uses the Variables extension to provide URL-arguments like &DPL_xyz=abc in the form of a variable which can be accessed as {{#var:xyz}} if Extension:Variables is installed.
*
2021-10-01 22:52:30 +00:00
* @param Parser $parser
2020-11-22 20:00:48 +00:00
*/
2021-10-01 22:52:30 +00:00
private function getUrlArgs( Parser $parser ) {
$args = $this->request->getValues();
2021-02-22 23:48:01 +00:00
foreach ( $args as $argName => $argValue ) {
if ( strpos( $argName, 'DPL_' ) === false ) {
2020-11-22 20:00:48 +00:00
continue;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
Variables::setVar( [ '', '', $argName, $argValue ] );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( defined( 'ExtVariables::VERSION' ) ) {
2021-10-01 22:52:30 +00:00
ExtVariables::get( $parser )->setVarValue( $argName, $argValue );
2020-11-22 20:00:48 +00:00
}
}
}
/**
2021-10-01 22:52:30 +00:00
* This function uses the Variables extension to provide navigation aids such as DPL_firstTitle, DPL_lastTitle, or DPL_findTitle. These variables can be accessed as {{#var:DPL_firstTitle}} if Extension:Variables is installed.
2020-11-22 20:00:48 +00:00
*
2021-10-01 22:52:30 +00:00
* @param array $scrollVariables
* @param Parser $parser
2020-11-22 20:00:48 +00:00
*/
2021-10-01 22:52:30 +00:00
private function defineScrollVariables( $scrollVariables, Parser $parser ) {
2020-11-22 20:00:48 +00:00
$scrollVariables = (array)$scrollVariables;
2021-02-22 23:48:01 +00:00
foreach ( $scrollVariables as $variable => $value ) {
Variables::setVar( [ '', '', $variable, $value ] );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( defined( 'ExtVariables::VERSION' ) ) {
2021-10-01 22:52:30 +00:00
ExtVariables::get( $parser )->setVarValue( $variable, $value );
2020-11-22 20:00:48 +00:00
}
}
}
/**
* Trigger Resets and Eliminates that run at the end of parsing.
*
2021-10-01 22:52:30 +00:00
* @param string $output
* @param array &$reset
* @param array &$eliminate
* @param bool $isParserTag
* @param Parser $parser
2020-11-22 20:00:48 +00:00
*/
2021-10-01 22:52:30 +00:00
private function triggerEndResets( $output, &$reset, &$eliminate, $isParserTag, Parser $parser ) {
2020-11-22 20:00:48 +00:00
global $wgHooks;
2021-10-01 22:52:30 +00:00
$localParser = MediaWikiServices::getInstance()->getParserFactory()->create();
$parserOutput = $localParser->parse( $output, $parser->getTitle(), $parser->getOptions() );
2020-11-22 20:00:48 +00:00
2021-02-22 23:48:01 +00:00
if ( !is_array( $reset ) ) {
2020-11-22 20:00:48 +00:00
$reset = [];
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$reset = array_merge( $reset, (array)$this->parameters->getParameter( 'reset' ) );
2020-11-22 20:00:48 +00:00
2021-02-22 23:48:01 +00:00
if ( !is_array( $eliminate ) ) {
2020-11-22 20:00:48 +00:00
$eliminate = [];
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
$eliminate = array_merge( $eliminate, (array)$this->parameters->getParameter( 'eliminate' ) );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $isParserTag === true ) {
2021-10-01 22:52:30 +00:00
// In tag mode 'eliminate' is the same as 'reset' for templates, categories, and images.
2021-02-22 23:48:01 +00:00
if ( isset( $eliminate['templates'] ) && $eliminate['templates'] ) {
2020-11-22 20:00:48 +00:00
$reset['templates'] = true;
$eliminate['templates'] = false;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( isset( $eliminate['categories'] ) && $eliminate['categories'] ) {
2020-11-22 20:00:48 +00:00
$reset['categories'] = true;
$eliminate['categories'] = false;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( isset( $eliminate['images'] ) && $eliminate['images'] ) {
2020-11-22 20:00:48 +00:00
$reset['images'] = true;
$eliminate['images'] = false;
}
} else {
2021-02-22 23:48:01 +00:00
if ( isset( $reset['templates'] ) && $reset['templates'] ) {
2021-10-01 22:52:30 +00:00
DynamicPageListHooks::$createdLinks['resetTemplates'] = true;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( isset( $reset['categories'] ) && $reset['categories'] ) {
2021-10-01 22:52:30 +00:00
DynamicPageListHooks::$createdLinks['resetCategories'] = true;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( isset( $reset['images'] ) && $reset['images'] ) {
2021-10-01 22:52:30 +00:00
DynamicPageListHooks::$createdLinks['resetImages'] = true;
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( ( $isParserTag === true && isset( $reset['links'] ) ) || $isParserTag === false ) {
if ( isset( $reset['links'] ) ) {
2021-10-01 22:52:30 +00:00
DynamicPageListHooks::$createdLinks['resetLinks'] = true;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
// Register a hook to reset links which were produced during parsing DPL output.
if ( !isset( $wgHooks['ParserAfterTidy'] ) || !is_array( $wgHooks['ParserAfterTidy'] ) || !in_array( 'DPL\\DynamicPageListHooks::endReset', $wgHooks['ParserAfterTidy'] ) ) {
$wgHooks['ParserAfterTidy'][] = 'DPL\\DynamicPageListHooks::endReset';
2020-11-22 20:00:48 +00:00
}
}
2021-02-22 23:48:01 +00:00
if ( array_sum( $eliminate ) ) {
2021-10-01 22:52:30 +00:00
// Register a hook to reset links which were produced during parsing DPL output
if ( !isset( $wgHooks['ParserAfterTidy'] ) || !is_array( $wgHooks['ParserAfterTidy'] ) || !in_array( 'DPL\\DynamicPageListHooks::endEliminate', $wgHooks['ParserAfterTidy'] ) ) {
$wgHooks['ParserAfterTidy'][] = 'DPL\\DynamicPageListHooks::endEliminate';
2020-11-22 20:00:48 +00:00
}
2021-02-22 23:48:01 +00:00
if ( isset( $eliminate['links'] ) && $eliminate['links'] ) {
2021-10-01 22:52:30 +00:00
// Trigger the mediawiki parser to find links, images, categories etc. which are contained in the DPL output. This allows us to remove these links from the link list later. If the article containing the DPL statement itself uses one of these links they will be thrown away!
DynamicPageListHooks::$createdLinks[0] = [];
2021-02-22 23:48:01 +00:00
foreach ( $parserOutput->getLinks() as $nsp => $link ) {
2021-10-01 22:52:30 +00:00
DynamicPageListHooks::$createdLinks[0][$nsp] = $link;
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( isset( $eliminate['templates'] ) && $eliminate['templates'] ) {
2021-10-01 22:52:30 +00:00
DynamicPageListHooks::$createdLinks[1] = [];
2021-02-22 23:48:01 +00:00
foreach ( $parserOutput->getTemplates() as $nsp => $tpl ) {
2021-10-01 22:52:30 +00:00
DynamicPageListHooks::$createdLinks[1][$nsp] = $tpl;
2020-11-22 20:00:48 +00:00
}
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( isset( $eliminate['categories'] ) && $eliminate['categories'] ) {
2021-10-01 22:52:30 +00:00
DynamicPageListHooks::$createdLinks[2] = $parserOutput->mCategories;
2020-11-22 20:00:48 +00:00
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( isset( $eliminate['images'] ) && $eliminate['images'] ) {
2021-10-01 22:52:30 +00:00
DynamicPageListHooks::$createdLinks[3] = $parserOutput->mImages;
2020-11-22 20:00:48 +00:00
}
}
}
/**
* Sort an array of Article objects by the card suit symbol.
*
2021-10-01 22:52:30 +00:00
* @param array $articles
* @return array
2020-11-22 20:00:48 +00:00
*/
2021-02-22 23:48:01 +00:00
private function cardSuitSort( $articles ) {
2020-11-22 20:00:48 +00:00
$sortKeys = [];
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $articles as $key => $article ) {
2021-10-01 22:52:30 +00:00
$title = preg_replace( '/.*:/', '', $article->mTitle );
$tokens = preg_split( '/ - */', $title );
2020-11-22 20:00:48 +00:00
$newKey = '';
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
foreach ( $tokens as $token ) {
$initial = substr( $token, 0, 1 );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $initial >= '1' && $initial <= '7' ) {
2020-11-22 20:00:48 +00:00
$newKey .= $initial;
2021-02-22 23:48:01 +00:00
$suit = substr( $token, 1 );
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
if ( $suit == '♣' ) {
2020-11-22 20:00:48 +00:00
$newKey .= '1';
2021-02-22 23:48:01 +00:00
} elseif ( $suit == '♦' ) {
2020-11-22 20:00:48 +00:00
$newKey .= '2';
2021-02-22 23:48:01 +00:00
} elseif ( $suit == '♥' ) {
2020-11-22 20:00:48 +00:00
$newKey .= '3';
2021-02-22 23:48:01 +00:00
} elseif ( $suit == '♠' ) {
2020-11-22 20:00:48 +00:00
$newKey .= '4';
2021-02-22 23:48:01 +00:00
} elseif ( strtolower( $suit ) == 'sa' || strtolower( $suit ) == 'nt' ) {
2020-11-22 20:00:48 +00:00
$newKey .= '5 ';
} else {
$newKey .= $suit;
}
2021-02-22 23:48:01 +00:00
} elseif ( strtolower( $initial ) == 'p' ) {
2020-11-22 20:00:48 +00:00
$newKey .= '0 ';
2021-02-22 23:48:01 +00:00
} elseif ( strtolower( $initial ) == 'x' ) {
2020-11-22 20:00:48 +00:00
$newKey .= '8 ';
} else {
$newKey .= $token;
}
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
$sortKeys[$key] = $newKey;
}
2021-10-01 22:52:30 +00:00
2021-02-22 23:48:01 +00:00
asort( $sortKeys );
2021-10-01 22:52:30 +00:00
$sortedArticles = [];
2021-02-22 23:48:01 +00:00
foreach ( $sortKeys as $oldKey => $newKey ) {
2020-11-22 20:00:48 +00:00
$sortedArticles[] = $articles[$oldKey];
}
2021-10-01 22:52:30 +00:00
2020-11-22 20:00:48 +00:00
return $sortedArticles;
}
}