*
* @var string
*/
public $headItemStart = '';
/**
* Heading List End
*
* @var string
*/
public $headItemEnd = '';
/**
* List(Section) Start
* Use %s for attribute placement. Example:
*
* @var string
*/
public $listStart = '';
/**
* List(Section) End
*
* @var string
*/
public $listEnd = '';
/**
* Item Start
* Use %s for attribute placement. Example:
*
* @var string
*/
public $itemStart = '';
/**
* Item End
*
* @var string
*/
public $itemEnd = '';
/**
* Extra head list HTML attributes.
*
* @var array
*/
public $headListAttributes = '';
/**
* Extra head item HTML attributes.
*
* @var array
*/
public $headItemAttributes = '';
/**
* Extra list HTML attributes.
*
* @var array
*/
public $listAttributes = '';
/**
* Extra item HTML attributes.
*
* @var array
*/
public $itemAttributes = '';
/**
* Count tipping point to mark a section as dominant.
*
* @var integer
*/
protected $dominantSectionCount = -1;
/**
* Template Suffix
*
* @var string
*/
protected $templateSuffix = '';
/**
* Trim included wiki text.
*
* @var boolean
*/
protected $trimIncluded = false;
/**
* Trim included wiki text.
*
* @var boolean
*/
protected $escapeLinks = true;
/**
* Index of the table column to sort by.
*
* @var integer
*/
protected $tableSortColumn = null;
/**
* Maximum title length.
*
* @var integer
*/
protected $titleMaxLength = null;
/**
* Section separators that separate transcluded pages/sections of wiki text.
*
* @var array
*/
protected $sectionSeparators = [];
/**
* Section separators that separate transcluded pages/sections that refer to the same chapter or tempalte of wiki text.
*
* @var array
*/
protected $multiSectionSeparators = [];
/**
* Include page text in output.
*
* @var boolean
*/
protected $includePageText = false;
/**
* Maximum length before truncated included wiki text.
*
* @var integer
*/
protected $includePageMaxLength = null;
/**
* Array of plain text matches for page transclusion. (include)
*
* @var array
*/
protected $pageTextMatch = null;
/**
* Array of regex text matches for page transclusion. (includematch)
*
* @var array
*/
protected $pageTextMatchRegex = null;
/**
* Array of not regex text matches for page transclusion. (includenotmatch)
*
* @var array
*/
protected $pageTextMatchNotRegex = null;
/**
* Parsed wiki text into HTML before running include/includematch/includenotmatch.
*
* @var boolean
*/
protected $includePageParsed = false;
/**
* Total result count after parsing, transcluding, and such.
*
* @var integer
*/
public $rowCount = 0;
/**
* \DPL\Parameters
*
* @var object
*/
protected $parameters = null;
/**
* Parser
*
* @var object
*/
protected $parser = null;
/**
* Main Constructor
*
* @access public
* @param object \DPL\Parameters
* @param object MediaWiki \Parser
* @return void
*/
public function __construct(\DPL\Parameters $parameters, \Parser $parser) {
$this->setHeadListAttributes($parameters->getParameter('hlistattr'));
$this->setHeadItemAttributes($parameters->getParameter('hitemattr'));
$this->setListAttributes($parameters->getParameter('listattr'));
$this->setItemAttributes($parameters->getParameter('itemattr'));
$this->setDominantSectionCount($parameters->getParameter('dominantsection'));
$this->setTemplateSuffix($parameters->getParameter('defaulttemplatesuffix'));
$this->setTrimIncluded($parameters->getParameter('includetrim'));
$this->setTableSortColumn($parameters->getParameter('tablesortcol'));
$this->setTitleMaxLength($parameters->getParameter('titlemaxlen'));
$this->setEscapeLinks($parameters->getParameter('escapelinks'));
$this->setSectionSeparators($parameters->getParameter('secseparators'));
$this->setMultiSectionSeparators($parameters->getParameter('multisecseparators'));
$this->setIncludePageText($parameters->getParameter('incpage'));
$this->setIncludePageMaxLength($parameters->getParameter('includemaxlen'));
$this->setPageTextMatch((array)$parameters->getParameter('seclabels'));
$this->setPageTextMatchRegex((array)$parameters->getParameter('seclabelsmatch'));
$this->setPageTextMatchNotRegex((array)$parameters->getParameter('seclabelsnotmatch'));
$this->setIncludePageParsed($parameters->getParameter('incparsed'));
$this->parameters = $parameters;
$this->parser = clone $parser;
}
/**
* Get a new List subclass based on user selection.
*
* @access public
* @param string List style.
* @param object \DPL\Parameters
* @param object MediaWiki \Parser
* @return object Lister subclass.
*/
public static function newFromStyle($style, \DPL\Parameters $parameters, \Parser $parser) {
$style = strtolower($style);
switch ($style) {
case 'category':
$class = 'CategoryList';
break;
case 'definition':
$class = 'DefinitionList';
break;
case 'gallery':
$class = 'GalleryList';
break;
case 'inline':
$class = 'InlineList';
break;
case 'ordered':
$class = 'OrderedList';
break;
case 'subpage':
$class = 'SubPageList';
break;
default:
case 'unordered':
$class = 'UnorderedList';
break;
case 'userformat':
$class = 'UserFormatList';
break;
}
$class = '\DPL\Lister\\' . $class;
return new $class($parameters, $parser);
}
/**
* Get the \DPL\Parameters object this object was constructed with.
*
* @access public
* @return object \DPL\Parameters
*/
public function getParameters() {
return $this->parameters;
}
/**
* Set extra list attributes for header wraps.
*
* @access public
* @param string Tag soup attributes, example: this="that" thing="no"
* @return void
*/
public function setHeadListAttributes($attributes) {
$this->headListAttributes = \Sanitizer::fixTagAttributes($attributes, 'ul');
}
/**
* Set extra item attributes for header items.
*
* @access public
* @param string Tag soup attributes, example: this="that" thing="no"
* @return void
*/
public function setHeadItemAttributes($attributes) {
$this->headItemAttributes = \Sanitizer::fixTagAttributes($attributes, 'li');
}
/**
* Set extra list attributes.
*
* @access public
* @param string Tag soup attributes, example: this="that" thing="no"
* @return void
*/
public function setListAttributes($attributes) {
$this->listAttributes = \Sanitizer::fixTagAttributes($attributes, 'ul');
}
/**
* Set extra item attributes.
*
* @access public
* @param string Tag soup attributes, example: this="that" thing="no"
* @return void
*/
public function setItemAttributes($attributes) {
$this->itemAttributes = \Sanitizer::fixTagAttributes($attributes, 'li');
}
/**
* Set the count of items to trigger a section as dominant.
*
* @access public
* @param integer Count
* @return void
*/
public function setDominantSectionCount($count = -1) {
$this->dominantSectionCount = intval($count);
}
/**
* Get the count of items to trigger a section as dominant.
*
* @access public
* @return integer Count
*/
public function getDominantSectionCount() {
return $this->dominantSectionCount;
}
/**
* Return the list style.
*
* @access public
* @return integer List style constant.
*/
public function getStyle() {
return $this->style;
}
/**
* Set the template suffix for whatever the hell uses it.
*
* @access public
* @param string Template Suffix
* @return void
*/
public function setTemplateSuffix($suffix = '.default') {
$this->templateSuffix = $suffix;
}
/**
* Get the template suffix for whatever the hell uses it.
*
* @access public
* @return string
*/
public function getTemplateSuffix() {
return $this->templateSuffix;
}
/**
* Set if included wiki text should be trimmed.
*
* @access public
* @param boolean [Optional] Trim
* @return void
*/
public function setTrimIncluded($trim = false) {
$this->trimIncluded = boolval($trim);
}
/**
* Get if included wiki text should be trimmed.
*
* @access public
* @return boolean Trim
*/
public function getTrimIncluded() {
return $this->trimIncluded;
}
/**
* Set if links should be escaped?
* @todo The naming of this parameter is weird and I am not sure what it does.
*
* @access public
* @param boolean [Optional] Escape
* @return void
*/
public function setEscapeLinks($escape = true) {
$this->escapeLinks = boolval($escape);
}
/**
* Get if links should be escaped.
*
* @access public
* @return boolean Escape
*/
public function getEscapeLinks() {
return $this->escapeLinks;
}
/**
* Set the index of the table column to sort by.
*
* @access public
* @param mixed [Optional] Integer index or null to disable.
* @return void
*/
public function setTableSortColumn($index = null) {
$this->tableSortColumn = $index === null ? null : intval($index);
}
/**
* Get the index of the table column to sort by.
*
* @access public
* @return mixed Integer index or null to disable.
*/
public function getTableSortColumn() {
return $this->tableSortColumn;
}
/**
* Set the maximum title length for display.
*
* @access public
* @param mixed [Optional] Integer length or null to disable.
* @return void
*/
public function setTitleMaxLength($length = null) {
$this->titleMaxLength = $length === null ? null : intval($length);
}
/**
* Get the maximum title length for display.
*
* @access public
* @return mixed Integer length or null to disable.
*/
public function getTitleMaxLength() {
return $this->titleMaxLength;
}
/**
* Set the separators that separate sections of matched page text.
*
* @access public
* @param array [Optional] Array of section separators.
* @return void
*/
public function setSectionSeparators(array $separators = []) {
$this->sectionSeparators = (array)$separators;
}
/**
* Set the separators that separate related sections of matched page text.
*
* @access public
* @param array [Optional] Array of section separators.
* @return void
*/
public function setMultiSectionSeparators(array $separators = []) {
$this->multiSectionSeparators = (array)$separators;
}
/**
* Set if wiki text should be included in output.
*
* @access public
* @param boolean [Optional] Parse
* @return void
*/
public function setIncludePageText($include = false) {
$this->includePageText = boolval($include);
}
/**
* Set the maximum included page text length before truncating.
*
* @access public
* @param mixed [Optional] Integer length or null to disable.
* @return void
*/
public function setIncludePageMaxLength($length = null) {
$this->includePageMaxLength = $length === null ? null : intval($length);
}
/**
* Set the plain string text matching for page transclusion.
*
* @access public
* @param array [Optional] Array of plain string matches.
* @return void
*/
public function setPageTextMatch(array $pageTextMatch = []) {
$this->pageTextMatch = (array)$pageTextMatch;
}
/**
* Set the regex text matching for page transclusion.
*
* @access public
* @param array [Optional] Array of regexes.
* @return void
*/
public function setPageTextMatchRegex(array $pageTextMatchRegex = []) {
$this->pageTextMatchRegex = (array)$pageTextMatchRegex;
}
/**
* Set the not regex text matching for page transclusion.
*
* @access public
* @param array [Optional] Array of regexes.
* @return void
*/
public function setPageTextMatchNotRegex(array $pageTextMatchNotRegex = []) {
$this->pageTextMatchNotRegex = (array)$pageTextMatchNotRegex;
}
/**
* Set if included wiki text should be parsed before being matched against.
*
* @access public
* @param boolean [Optional] Parse
* @return void
*/
public function setIncludePageParsed($parse = false) {
$this->includePageParsed = boolval($parse);
}
/**
* Shortcut to format all articles into a single formatted list.
*
* @access public
* @param array List of \DPL\Article
* @return string Formatted list.
*/
public function format($articles) {
return $this->formatList($articles, 0, count($articles));
}
/**
* Format a list of articles into a singular list.
*
* @access public
* @param array List of \DPL\Article
* @param integer Start position of the array to process.
* @param integer Total objects from the array to process.
* @return string Formatted list.
*/
public function formatList($articles, $start, $count) {
$filteredCount = 0;
$items = [];
for ($i = $start; $i < $start + $count; $i++) {
$article = $articles[$i];
if (empty($article) || empty($article->mTitle)) {
continue;
}
$pageText = null;
if ($this->includePageText) {
$pageText = $this->transcludePage($article, $filteredCount);
} else {
$filteredCount++;
}
$this->rowCount = $filteredCount;
$items[] = $this->formatItem($article, $pageText);
}
$this->rowCount = $filteredCount;
return $this->getListStart() . $this->implodeItems($items) . $this->listEnd;
}
/**
* Format a single item.
*
* @access public
* @param object DPL\Article
* @param string [Optional] Page text to include.
* @return string Item HTML
*/
public function formatItem(Article $article, $pageText = null) {
global $wgContLang, $wgLang;
$item = '';
//DPL Article, not MediaWiki.
$date = $article->getDate();
if ($date !== null) {
$item .= $date . ' ';
if ($article->mRevision !== null) {
$item .= '[{{fullurl:' . $article->mTitle . '|oldid=' . $article->mRevision . '}} ' . htmlspecialchars($article->mTitle) . ']';
} else {
$item .= $article->mLink;
}
} else {
// output the link to the article
$item .= $article->mLink;
}
if ($article->mSize != null) {
$byte = 'B';
$pageLength = $wgLang->formatNum($article->mSize);
$item .= " [{$pageLength} {$byte}]";
}
if ($article->mCounter !== null) {
$item .= ' ' . $wgContLang->getDirMark() . '(' . wfMessage('hitcounters-nviews', $wgLang->formatNum($article->mCounter))->escaped() . ')';
}
if ($article->mUserLink !== null) {
$item .= ' . . [[User:' . $article->mUser . '|' . $article->mUser . ']]';
if ($article->mComment != '') {
$item .= ' { ' . $article->mComment . ' }';
}
}
if ($article->mContributor !== null) {
$item .= ' . . [[User:' . $article->mContributor . '|' . $article->mContributor . " $article->mContrib]]";
}
if (!empty($article->mCategoryLinks)) {
$item .= ' . . ' . wfMessage('categories') . ': ' . implode(' | ', $article->mCategoryLinks) . '';
}
if ($this->getParameters()->getParameter('addexternallink') && $article->mExternalLink !== null) {
$item .= ' → ' . $article->mExternalLink;
}
if ($pageText !== null) {
//Include parsed/processed wiki markup content after each item before the closing tag.
$item .= $pageText;
}
$item = $this->getItemStart() . $item . $this->getItemEnd();
$item = $this->replaceTagParameters($item, $article);
return $item;
}
/**
* Return $this->headListStart with attributes replaced.
*
* @access public
* @return string Head List Start
*/
public function getHeadListStart() {
return sprintf($this->headListStart, $this->headListAttributes);
}
/**
* Return $this->headItemStart with attributes replaced.
*
* @access public
* @return string Head Item Start
*/
public function getHeadItemStart() {
return sprintf($this->headItemStart, $this->headItemAttributes);
}
/**
* Return $this->headItemStart with attributes replaced.
*
* @access public
* @return string Head Item End
*/
public function getHeadItemEnd() {
return $this->headItemEnd;
}
/**
* Return $this->listStart with attributes replaced.
*
* @access public
* @return string List Start
*/
public function getListStart() {
return sprintf($this->listStart, $this->listAttributes);
}
/**
* Return $this->itemStart with attributes replaced.
*
* @access public
* @return string Item Start
*/
public function getItemStart() {
return sprintf($this->itemStart, $this->itemAttributes);
}
/**
* Return $this->itemEnd with attributes replaced.
*
* @access public
* @return string Item End
*/
public function getItemEnd() {
return $this->itemEnd;
}
/**
* Join together items after being processed by formatItem().
*
* @access protected
* @param array Items as formatted by formatItem().
* @return string Imploded items.
*/
protected function implodeItems($items) {
return implode('', $items);
}
/**
* Replace user tag parameters.
*
* @access protected
* @param string Text to perform replacements on.
* @param object \DPL\Article
* @return string Text with replacements performed.
*/
protected function replaceTagParameters($tag, Article $article) {
global $wgContLang;
$namespaces = $wgContLang->getNamespaces();
if (strpos($tag, '%') === false) {
return $tag;
}
$imageUrl = $this->parseImageUrlWithPath($article);
$pagename = $article->mTitle->getPrefixedText();
if ($this->getEscapeLinks() && ($article->mNamespace == NS_CATEGORY || $article->mNamespace == NS_FILE)) {
// links to categories or images need an additional ":"
$pagename = ':' . $pagename;
}
$tag = str_replace('%PAGE%', $pagename, $tag);
$tag = str_replace('%PAGEID%', $article->mID, $tag);
$tag = str_replace('%NAMESPACE%', $namespaces[$article->mNamespace], $tag);
$tag = str_replace('%IMAGE%', $imageUrl, $tag);
$tag = str_replace('%EXTERNALLINK%', $article->mExternalLink, $tag);
$tag = str_replace('%EDITSUMMARY%', $article->mComment, $tag);
$title = $article->mTitle->getText();
$replaceInTitle = $this->getParameters()->getParameter('replaceintitle');
if (is_array($replaceInTitle) && count($replaceInTitle) === 2) {
$title = preg_replace($replaceInTitle[0], $replaceInTitle[1], $title);
}
$titleMaxLength = $this->getTitleMaxLength();
if ($titleMaxLength !== null && (strlen($title) > $titleMaxLength)) {
$title = substr($title, 0, $titleMaxLength) . '...';
}
$tag = str_replace('%TITLE%', $title, $tag);
$tag = str_replace('%COUNT%', $article->mCounter, $tag);
$tag = str_replace('%COUNTFS%', floor(log($article->mCounter) * 0.7), $tag);
$tag = str_replace('%COUNTFS2%', floor(sqrt(log($article->mCounter))), $tag);
$tag = str_replace('%SIZE%', $article->mSize, $tag);
$tag = str_replace('%SIZEFS%', floor(sqrt(log($article->mSize)) * 2.5 - 5), $tag);
$tag = str_replace('%DATE%', $article->getDate(), $tag);
$tag = str_replace('%REVISION%', $article->mRevision, $tag);
$tag = str_replace('%CONTRIBUTION%', $article->mContribution, $tag);
$tag = str_replace('%CONTRIB%', $article->mContrib, $tag);
$tag = str_replace('%CONTRIBUTOR%', $article->mContributor, $tag);
$tag = str_replace('%USER%', $article->mUser, $tag);
if ($article->mSelTitle != null) {
if ($article->mSelNamespace == 0) {
$tag = str_replace('%PAGESEL%', str_replace('_', ' ', $article->mSelTitle), $tag);
} else {
$tag = str_replace('%PAGESEL%', $namespaces[$article->mSelNamespace] . ':' . str_replace('_', ' ', $article->mSelTitle), $tag);
}
}
$tag = str_replace('%IMAGESEL%', str_replace('_', ' ', $article->mImageSelTitle), $tag);
$tag = $this->replaceTagCategory($tag, $article);
return $tag;
}
/**
* Replace user tag parameters for categories.
*
* @access protected
* @param string Text to perform replacements on.
* @param object \DPL\Article
* @return string Text with replacements performed.
*/
protected function replaceTagCategory($tag, Article $article) {
if (!empty($article->mCategoryLinks)) {
$tag = str_replace('%CATLIST%', implode(', ', $article->mCategoryLinks), $tag);
$tag = str_replace('%CATBULLETS%', '* ' . implode("\n* ", $article->mCategoryLinks), $tag);
$tag = str_replace('%CATNAMES%', implode(', ', $article->mCategoryTexts), $tag);
} else {
$tag = str_replace('%CATLIST%', '', $tag);
$tag = str_replace('%CATBULLETS%', '', $tag);
$tag = str_replace('%CATNAMES%', '', $tag);
}
return $tag;
}
/**
* Replace the %NR%(current article sequence number) in text.
*
* @access protected
* @param string Text to perform replacements on.
* @param integer The current article sequence number (starting from 1).
* @return string Text with replacements performed.
*/
protected function replaceTagCount($tag, $nr) {
return str_replace('%NR%', $nr, $tag);
}
//
/**
* Format one single item of an entry in the output list (i.e. one occurence of one item from the include parameter).
* @todo I am not exactly sure how this function differs from replaceTagParameters(). It has something to do with table row formatting. --Alexia
*
* @access private
* @param array String pieces to perform replacements on.
* @param mixed Index of the table row position.
* @param object \DPL\Article
* @return void
*/
private function replaceTagTableRow(&$pieces, $s, Article $article) {
$tableFormat = $this->getParameters()->getParameter('tablerow');
$firstCall = true;
foreach ($pieces as $key => $val) {
if (isset($tableFormat[$s])) {
if ($s == 0 || $firstCall) {
$pieces[$key] = str_replace('%%', $val, $tableFormat[$s]);
} else {
$n = strpos($tableFormat[$s], '|');
if ($n === false || !(strpos(substr($tableFormat[$s], 0, $n), '{') === false) || !(strpos(substr($tableFormat[$s], 0, $n), '[') === false)) {
$pieces[$key] = str_replace('%%', $val, $tableFormat[$s]);
} else {
$pieces[$key] = str_replace('%%', $val, substr($tableFormat[$s], $n + 1));
}
}
$pieces[$key] = str_replace('%IMAGE%', $this->parseImageUrlWithPath($val), $pieces[$key]);
$pieces[$key] = str_replace('%PAGE%', $article->mTitle->getPrefixedText(), $pieces[$key]);
$pieces[$key] = $this->replaceTagCategory($pieces[$key], $article);
}
$firstCall = false;
}
}
/**
* Format one single template argument of one occurence of one item from the include parameter. This is called via a backlink from LST::includeTemplate().
* @todo Again, another poorly documented function with vague functionality. --Alexia
*
* @access public
* @param string Argument to parse and replace.
* @param mixed Index of the table row position.
* @param mixed Other part of the index of the table row position?
* @param boolean Is this the first time this function was called in this context?
* @param integer Maximum text length allowed.
* @param object \DPL\Article
* @return strig Formatted text.
*/
public function formatTemplateArg($arg, $s, $argNr, $firstCall, $maxLength, Article $article) {
$tableFormat = $this->getParameters()->getParameter('tablerow');
// we could try to format fields differently within the first call of a template
// currently we do not make such a difference
// if the result starts with a '-' we add a leading space; thus we avoid a misinterpretation of |- as
// a start of a new row (wiki table syntax)
if (array_key_exists("$s.$argNr", $tableFormat)) {
$n = -1;
if ($s >= 1 && $argNr == 0 && !$firstCall) {
$n = strpos($tableFormat["$s.$argNr"], '|');
if ($n === false || !(strpos(substr($tableFormat["$s.$argNr"], 0, $n), '{') === false) || !(strpos(substr($tableFormat["$s.$argNr"], 0, $n), '[') === false)) {
$n = -1;
}
}
$result = str_replace('%%', $arg, substr($tableFormat["$s.$argNr"], $n + 1));
$result = str_replace('%PAGE%', $article->mTitle->getPrefixedText(), $result);
$result = str_replace('%IMAGE%', $this->parseImageUrlWithPath($arg), $result); //@TODO: This just blindly passes the argument through hoping it is an image. --Alexia
$result = $this->cutAt($maxLength, $result);
if (strlen($result) > 0 && $result[0] == '-') {
return ' ' . $result;
} else {
return $result;
}
}
$result = $this->cutAt($maxLength, $arg);
if (strlen($result) > 0 && $result[0] == '-') {
return ' ' . $result;
} else {
return $result;
}
}
/**
* Truncate a portion of wikitext so that ..
* ... it is not larger that $lim characters
* ... it is balanced in terms of braces, brackets and tags
* ... can be used as content of a wikitable field without spoiling the whole surrounding wikitext structure
*
* @access private
* @param $lim limit of character count for the result
* @param $text the wikitext to be truncated
* @return the truncated text; note that in some cases it may be slightly longer than the given limit
* if the text is alread shorter than the limit or if the limit is negative, the text
* will be returned without any checks for balance of tags
*/
private function cutAt($lim, $text) {
if ($lim < 0) {
return $text;
}
return LST::limitTranscludedText($text, $lim);
}
/**
* Prepends an image name with its hash path.
*
* @access protected
* @param mixed \DPL\Article or string image name of the image (may start with Image: or File:).
* @return string Image URL
*/
protected function parseImageUrlWithPath($article) {
$imageUrl = '';
if ($article instanceof \DPL\Article) {
if ($article->mNamespace == NS_FILE) {
// calculate URL for existing images
// $img = Image::newFromName($article->mTitle->getText());
$img = wfFindFile(\Title::makeTitle(NS_FILE, $article->mTitle->getText()));
if ($img && $img->exists()) {
$imageUrl = $img->getURL();
} else {
$fileTitle = \Title::makeTitleSafe(NS_FILE, $article->mTitle->getDBKey());
$imageUrl = \RepoGroup::singleton()->getLocalRepo()->newFile($fileTitle)->getPath();
}
}
} else {
$title = \Title::newfromText('File:' . $article);
if (!is_null($title)) {
$fileTitle = \Title::makeTitleSafe(6, $title->getDBKey());
$imageUrl = \RepoGroup::singleton()->getLocalRepo()->newFile($fileTitle)->getPath();
}
}
//@TODO: Check this preg_replace. Probably only works for stock file repositories. --Alexia
$imageUrl = preg_replace('~^.*images/(.*)~', '\1', $imageUrl);
return $imageUrl;
}
/**
* Transclude a page contents.
*
* @access public
* @param object \DPL\Article
* @param integer Filtered Article Count
* @return string Page Text
*/
public function transcludePage(Article $article, &$filteredCount) {
$matchFailed = false;
if (empty($this->pageTextMatch) || $this->pageTextMatch[0] == '*') { // include whole article
$title = $article->mTitle->getPrefixedText();
if ($this->getStyle() == self::LIST_USERFORMAT) {
$pageText = '';
} else {
$pageText = '
';
}
$text = $this->parser->fetchTemplate(\Title::newFromText($title));
if ((count($this->pageTextMatchRegex) <= 0 || $this->pageTextMatchRegex[0] == '' || !preg_match($this->pageTextMatchRegex[0], $text) == false) && (count($this->pageTextMatchNotRegex) <= 0 || $this->pageTextMatchNotRegex[0] == '' || preg_match($this->pageTextMatchNotRegex[0], $text) == false)) {
if ($this->includePageMaxLength > 0 && (strlen($text) > $this->includePageMaxLength)) {
$text = LST::limitTranscludedText($text, $this->includePageMaxLength, ' [[' . $title . '|..→]]');
}
$filteredCount = $filteredCount + 1;
// update article if include=* and updaterules are given
$updateRules = $this->getParameters()->getParameter('updaterules');
$deleteRules = $this->getParameters()->getParameter('deleterules');
if (!empty($updateRules)) {
$ruleOutput = UpdateArticle::updateArticleByRule($title, $text, $updateRules);
// append update message to output
$pageText .= $ruleOutput;
} elseif (!empty($deleteRules)) {
$ruleOutput = UpdateArticle::deleteArticleByRule($title, $text, $deleteRules);
// append delete message to output
$pageText .= $ruleOutput;
} else {
// append full text to output
if (is_array($this->sectionSeparators) && array_key_exists('0', $this->sectionSeparators)) {
$pageText .= $this->replaceTagCount($this->sectionSeparators[0], $filteredCount);
$pieces = [
0 => $text
];
$this->replaceTagTableRow($pieces, 0, $article);
$pageText .= $pieces[0];
} else {
$pageText .= $text;
}
}
} else {
return '';
}
} else {
// identify section pieces
$secPiece = [];
$dominantPieces = false;
// ONE section can be marked as "dominant"; if this section contains multiple entries
// we will create a separate output row for each value of the dominant section
// the values of all other columns will be repeated
foreach ($this->pageTextMatch as $s => $sSecLabel) {
$sSecLabel = trim($sSecLabel);
if ($sSecLabel == '') {
break;
}
// if sections are identified by number we have a % at the beginning
if ($sSecLabel[0] == '%') {
$sSecLabel = '#' . $sSecLabel;
}
$maxLength = -1;
if ($sSecLabel == '-') {
// '-' is used as a dummy parameter which will produce no output
// if maxlen was 0 we suppress all output; note that for matching we used the full text
$secPieces = [
''
];
$this->replaceTagTableRow($secPieces, $s, $article);
} elseif ($sSecLabel[0] != '{') {
$limpos = strpos($sSecLabel, '[');
$cutLink = 'default';
$skipPattern = [];
if ($limpos > 0 && $sSecLabel[strlen($sSecLabel) - 1] == ']') {
// regular expressions which define a skip pattern may precede the text
$fmtSec = explode('~', substr($sSecLabel, $limpos + 1, strlen($sSecLabel) - $limpos - 2));
$sSecLabel = substr($sSecLabel, 0, $limpos);
$cutInfo = explode(" ", $fmtSec[count($fmtSec) - 1], 2);
$maxLength = intval($cutInfo[0]);
if (array_key_exists('1', $cutInfo)) {
$cutLink = $cutInfo[1];
}
foreach ($fmtSec as $skipKey => $skipPat) {
if ($skipKey == count($fmtSec) - 1) {
continue;
}
$skipPattern[] = $skipPat;
}
}
if ($maxLength < 0) {
$maxLength = -1; // without valid limit include whole section
}
}
// find out if the user specified an includematch / includenotmatch condition
if (is_array($this->pageTextMatchRegex) && count($this->pageTextMatchRegex) > $s && !empty($this->pageTextMatchRegex[$s])) {
$mustMatch = $this->pageTextMatchRegex[$s];
} else {
$mustMatch = '';
}
if (is_array($this->pageTextMatchNotRegex) && count($this->pageTextMatchNotRegex) > $s && !empty($this->pageTextMatchNotRegex[$s])) {
$mustNotMatch = $this->pageTextMatchNotRegex[$s];
} else {
$mustNotMatch = '';
}
// if chapters are selected by number, text or regexp we get the heading from LST::includeHeading
$sectionHeading[0] = '';
if ($sSecLabel == '-') {
$secPiece[$s] = $secPieces[0];
} elseif ($sSecLabel[0] == '#' || $sSecLabel[0] == '@') {
$sectionHeading[0] = substr($sSecLabel, 1);
// Uses LST::includeHeading() from LabeledSectionTransclusion extension to include headings from the page
$secPieces = LST::includeHeading($this->parser, $article->mTitle->getPrefixedText(), substr($sSecLabel, 1), '', $sectionHeading, false, $maxLength, $cutLink, $this->getTrimIncluded(), $skipPattern);
if ($mustMatch != '' || $mustNotMatch != '') {
$secPiecesTmp = $secPieces;
$offset = 0;
foreach ($secPiecesTmp as $nr => $onePiece) {
if (($mustMatch != '' && preg_match($mustMatch, $onePiece) == false) || ($mustNotMatch != '' && preg_match($mustNotMatch, $onePiece) != false)) {
array_splice($secPieces, $nr - $offset, 1);
$offset++;
}
}
}
// if maxlen was 0 we suppress all output; note that for matching we used the full text
if ($maxLength == 0) {
$secPieces = [
''
];
}
$this->replaceTagTableRow($secPieces, $s, $article);
if (!array_key_exists(0, $secPieces)) {
// avoid matching against a non-existing array element
// and skip the article if there was a match condition
if ($mustMatch != '' || $mustNotMatch != '') {
$matchFailed = true;
}
break;
}
$secPiece[$s] = $secPieces[0];
for ($sp = 1; $sp < count($secPieces); $sp++) {
if (isset($this->multiSectionSeparators[$s])) {
$secPiece[$s] .= str_replace('%SECTION%', $sectionHeading[$sp], $this->replaceTagCount($this->multiSectionSeparators[$s], $filteredCount));
}
$secPiece[$s] .= $secPieces[$sp];
}
if ($this->getDominantSectionCount() >= 0 && $s == $this->getDominantSectionCount() && count($secPieces) > 1) {
$dominantPieces = $secPieces;
}
if (($mustMatch != '' || $mustNotMatch != '') && count($secPieces) <= 0) {
$matchFailed = true; // NOTHING MATCHED
break;
}
} elseif ($sSecLabel[0] == '{') {
// Uses LST::includeTemplate() from LabeledSectionTransclusion extension to include templates from the page
// primary syntax {template}suffix
$template1 = trim(substr($sSecLabel, 1, strpos($sSecLabel, '}') - 1));
$template2 = trim(str_replace('}', '', substr($sSecLabel, 1)));
// alternate syntax: {template|surrogate}
if ($template2 == $template1 && strpos($template1, '|') > 0) {
$template1 = preg_replace('/\|.*/', '', $template1);
$template2 = preg_replace('/^.+\|/', '', $template2);
}
//Why the hell was defaultTemplateSuffix be passed all over the place for just fucking here? --Alexia
$secPieces = LST::includeTemplate($this->parser, $this, $s, $article, $template1, $template2, $template2 . $this->getTemplateSuffix(), $mustMatch, $mustNotMatch, $this->includePageParsed, implode(', ', $article->mCategoryLinks));
$secPiece[$s] = implode(isset($this->multiSectionSeparators[$s]) ? $this->replaceTagCount($this->multiSectionSeparators[$s], $filteredCount) : '', $secPieces);
if ($this->getDominantSectionCount() >= 0 && $s == $this->getDominantSectionCount() && count($secPieces) > 1) {
$dominantPieces = $secPieces;
}
if (($mustMatch != '' || $mustNotMatch != '') && count($secPieces) <= 1 && $secPieces[0] == '') {
$matchFailed = true; // NOTHING MATCHED
break;
}
} else {
// Uses LST::includeSection() from LabeledSectionTransclusion extension to include labeled sections from the page
$secPieces = LST::includeSection($this->parser, $article->mTitle->getPrefixedText(), $sSecLabel, '', false, $this->getTrimIncluded(), $skipPattern);
$secPiece[$s] = implode(isset($this->multiSectionSeparators[$s]) ? $this->replaceTagCount($this->multiSectionSeparators[$s], $filteredCount) : '', $secPieces);
if ($this->getDominantSectionCount() >= 0 && $s == $this->getDominantSectionCount() && count($secPieces) > 1) {
$dominantPieces = $secPieces;
}
if (($mustMatch != '' && preg_match($mustMatch, $secPiece[$s]) == false) || ($mustNotMatch != '' && preg_match($mustNotMatch, $secPiece[$s]) != false)) {
$matchFailed = true;
break;
}
}
// separator tags
if (is_array($this->sectionSeparators) && count($this->sectionSeparators) == 1) {
// If there is only one separator tag use it always
$septag[$s * 2] = str_replace('%SECTION%', $sectionHeading[0], $this->replaceTagCount($this->sectionSeparators[0], $filteredCount));
} elseif (isset($this->sectionSeparators[$s * 2])) {
$septag[$s * 2] = str_replace('%SECTION%', $sectionHeading[0], $this->replaceTagCount($this->sectionSeparators[$s * 2], $filteredCount));
} else {
$septag[$s * 2] = '';
}
if (isset($this->sectionSeparators[$s * 2 + 1])) {
$septag[$s * 2 + 1] = str_replace('%SECTION%', $sectionHeading[0], $this->replaceTagCount($this->sectionSeparators[$s * 2 + 1], $filteredCount));
} else {
$septag[$s * 2 + 1] = '';
}
}
// if there was a match condition on included contents which failed we skip the whole page
if ($matchFailed) {
return '';
}
$filteredCount = $filteredCount + 1;
// assemble parts with separators
$pageText = '';
if ($dominantPieces != false) {
foreach ($dominantPieces as $dominantPiece) {
foreach ($secPiece as $s => $piece) {
if ($s == $this->getDominantSectionCount()) {
$pageText .= $this->joinSectionTagPieces($dominantPiece, $septag[$s * 2], $septag[$s * 2 + 1]);
} else {
$pageText .= $this->joinSectionTagPieces($piece, $septag[$s * 2], $septag[$s * 2 + 1]);
}
}
}
} else {
foreach ($secPiece as $s => $piece) {
$pageText .= $this->joinSectionTagPieces($piece, $septag[$s * 2], $septag[$s * 2 + 1]);
}
}
}
return $pageText;
}
/**
* Wrap seciton pieces with start and end tags.
*
* @access protected
* @param string Piece to be wrapped.
* @param string Text to prepend.
* @param string Text to append.
* @return string Wrapped text.
*/
protected function joinSectionTagPieces($piece, $start, $end) {
return $start . $piece . $end;
}
/**
* Get the count of listed items after formatting, transcluding, and such.
*
* @access public
* @return integer Row Count
*/
public function getRowCount() {
return $this->rowCount;
}
}