mirror of
https://github.com/Universal-Omega/DynamicPageList3
synced 2024-11-24 00:04:19 +00:00
8dd8d03d61
This adds support for 1.39, and drops support for older versions, since 1.39 is the current LTS release.
782 lines
20 KiB
PHP
782 lines
20 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Extension\DynamicPageList3;
|
|
|
|
use Article;
|
|
use CommentStoreComment;
|
|
use MediaWiki\MediaWikiServices;
|
|
use MediaWiki\Revision\SlotRecord;
|
|
use ReadOnlyError;
|
|
use RequestContext;
|
|
use Title;
|
|
|
|
class UpdateArticle {
|
|
/**
|
|
* This fucntion hast three tasks (depending on $exec):
|
|
* (1) show an edit dialogue for template fields (exec = edit)
|
|
* (2) set template parameters to values specified in the query (exec=set)v
|
|
* (2) preview the source code including any changes of these parameters made in the edit form or with other changes (exec=preview)
|
|
* (3) save the article with the changed value set or with other changes (exec=save)
|
|
* "other changes" means that a regexp can be applied to the source text or arbitrary text can be
|
|
* inserted before or after a pattern occuring in the text
|
|
*
|
|
* @param string $title
|
|
* @param string $text
|
|
* @param string $rulesText
|
|
* @return string
|
|
*/
|
|
public static function updateArticleByRule( $title, $text, $rulesText ) {
|
|
// we use ; as command delimiter; \; stands for a semicolon
|
|
// \n is translated to a real linefeed
|
|
$rulesText = str_replace( ";", '°', $rulesText );
|
|
$rulesText = str_replace( '\°', ';', $rulesText );
|
|
$rulesText = str_replace( "\\n", "\n", $rulesText );
|
|
$rules = explode( '°', $rulesText );
|
|
$exec = 'edit';
|
|
$replaceThis = '';
|
|
$replacement = '';
|
|
$after = '';
|
|
$insertionAfter = '';
|
|
$before = '';
|
|
$insertionBefore = '';
|
|
$template = '';
|
|
$parameter = [];
|
|
$value = [];
|
|
$afterparm = [];
|
|
$format = [];
|
|
$preview = [];
|
|
$save = [];
|
|
$tooltip = [];
|
|
$optional = [];
|
|
|
|
$lastCmd = '';
|
|
$summary = '';
|
|
$editForm = false;
|
|
$action = '';
|
|
$hidden = [];
|
|
$legendPage = '';
|
|
$instructionPage = '';
|
|
$table = '';
|
|
$fieldFormat = '';
|
|
|
|
$nr = -1;
|
|
foreach ( $rules as $rule ) {
|
|
if ( preg_match( '/^\s*#/', $rule ) > 0 ) {
|
|
continue;
|
|
}
|
|
|
|
$rule = preg_replace( '/^[\s]*/', '', $rule );
|
|
$cmd = preg_split( "/ +/", $rule, 2 );
|
|
|
|
if ( count( $cmd ) > 1 ) {
|
|
$arg = $cmd[1];
|
|
} else {
|
|
$arg = '';
|
|
}
|
|
|
|
$cmd[0] = trim( $cmd[0] );
|
|
|
|
// after ... insert ..., before ... insert ...
|
|
if ( $cmd[0] == 'before' ) {
|
|
$before = $arg;
|
|
$lastCmd = 'B';
|
|
}
|
|
if ( $cmd[0] == 'after' ) {
|
|
$after = $arg;
|
|
$lastCmd = 'A';
|
|
}
|
|
|
|
if ( $cmd[0] == 'insert' && $lastCmd != '' ) {
|
|
if ( $lastCmd == 'A' ) {
|
|
$insertionAfter = $arg;
|
|
}
|
|
|
|
if ( $lastCmd == 'B' ) {
|
|
$insertionBefore = $arg;
|
|
}
|
|
}
|
|
|
|
if ( $cmd[0] == 'template' ) {
|
|
$template = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'parameter' ) {
|
|
$nr++;
|
|
$parameter[$nr] = $arg;
|
|
if ( $nr > 0 ) {
|
|
$afterparm[$nr] = [
|
|
$parameter[$nr - 1]
|
|
];
|
|
|
|
$n = $nr - 1;
|
|
while ( $n > 0 && array_key_exists( $n, $optional ) ) {
|
|
$n--;
|
|
$afterparm[$nr][] = $parameter[$n];
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( $cmd[0] == 'value' ) {
|
|
$value[$nr] = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'format' ) {
|
|
$format[$nr] = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'tooltip' ) {
|
|
$tooltip[$nr] = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'optional' ) {
|
|
$optional[$nr] = true;
|
|
}
|
|
|
|
if ( $cmd[0] == 'afterparm' ) {
|
|
$afterparm[$nr] = [
|
|
$arg
|
|
];
|
|
}
|
|
|
|
if ( $cmd[0] == 'legend' ) {
|
|
$legendPage = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'instruction' ) {
|
|
$instructionPage = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'table' ) {
|
|
$table = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'field' ) {
|
|
$fieldFormat = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'replace' ) {
|
|
$replaceThis = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'by' ) {
|
|
$replacement = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'editform' ) {
|
|
$editForm = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'action' ) {
|
|
$action = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'hidden' ) {
|
|
$hidden[] = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'preview' ) {
|
|
$preview[] = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'save' ) {
|
|
$save[] = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'summary' ) {
|
|
$summary = $arg;
|
|
}
|
|
|
|
if ( $cmd[0] == 'exec' ) {
|
|
// desired action (set or edit or preview)
|
|
$exec = $arg;
|
|
}
|
|
}
|
|
|
|
if ( $summary == '' ) {
|
|
$summary .= "\nbulk update:";
|
|
if ( $replaceThis != '' ) {
|
|
$summary .= "\n replace $replaceThis\n by $replacement";
|
|
}
|
|
|
|
if ( $before != '' ) {
|
|
$summary .= "\n before $before\n insertionBefore";
|
|
}
|
|
|
|
if ( $after != '' ) {
|
|
$summary .= "\n after $after\n insertionAfter";
|
|
}
|
|
}
|
|
|
|
// perform changes to the wiki source text =======================================
|
|
|
|
if ( $replaceThis != '' ) {
|
|
$text = preg_replace( "$replaceThis", $replacement, $text );
|
|
}
|
|
|
|
if ( $insertionBefore != '' && $before != '' ) {
|
|
$text = preg_replace( "/($before)/", $insertionBefore . '\1', $text );
|
|
}
|
|
|
|
if ( $insertionAfter != '' && $after != '' ) {
|
|
$text = preg_replace( "/($after)/", '\1' . $insertionAfter, $text );
|
|
}
|
|
|
|
// deal with template parameters =================================================
|
|
$user = RequestContext::getMain()->getUser();
|
|
|
|
if ( $template != '' ) {
|
|
if ( $exec == 'edit' ) {
|
|
$tpv = self::getTemplateParmValues( $text, $template );
|
|
$legendText = '';
|
|
|
|
if ( $legendPage != '' ) {
|
|
$legendTitle = '';
|
|
|
|
$parser = clone MediaWikiServices::getInstance()->getParser();
|
|
|
|
LST::text( $parser, $legendPage, $legendTitle, $legendText );
|
|
$legendText = preg_replace( '/^.*?\<section\s+begin\s*=\s*legend\s*\/\>/s', '', $legendText );
|
|
$legendText = preg_replace( '/\<section\s+end\s*=\s*legend\s*\/\>.*/s', '', $legendText );
|
|
}
|
|
|
|
$instructionText = '';
|
|
$instructions = [];
|
|
|
|
if ( $instructionPage != '' ) {
|
|
$instructionTitle = '';
|
|
|
|
$parser = clone MediaWikiServices::getInstance()->getParser();
|
|
|
|
LST::text( $parser, $instructionPage, $instructionTitle, $instructionText );
|
|
$instructions = self::getTemplateParmValues( $instructionText, 'Template field' );
|
|
}
|
|
|
|
// construct an edit form containing all template invocations
|
|
$form = "<html><form method=post action=\"$action\" $editForm>\n";
|
|
|
|
foreach ( $tpv as $call => $tplValues ) {
|
|
$form .= "<table $table>\n";
|
|
foreach ( $parameter as $nr => $parm ) {
|
|
// try to extract legend from the docs of the template
|
|
$myToolTip = '';
|
|
|
|
if ( array_key_exists( $nr, $tooltip ) ) {
|
|
$myToolTip = $tooltip[$nr];
|
|
}
|
|
|
|
$myInstruction = '';
|
|
$myType = '';
|
|
|
|
foreach ( $instructions as $instruct ) {
|
|
if ( array_key_exists( 'field', $instruct ) && $instruct['field'] == $parm ) {
|
|
if ( array_key_exists( 'doc', $instruct ) ) {
|
|
$myInstruction = $instruct['doc'];
|
|
}
|
|
|
|
if ( array_key_exists( 'type', $instruct ) ) {
|
|
$myType = $instruct['type'];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
$myFormat = '';
|
|
if ( array_key_exists( $nr, $format ) ) {
|
|
$myFormat = $format[$nr];
|
|
}
|
|
|
|
if ( $legendText != '' && $myToolTip == '' ) {
|
|
$myToolTip = preg_replace( '/^.*\<section\s+begin\s*=\s*' . preg_quote( $parm, '/' ) . '\s*\/\>/s', '', $legendText );
|
|
|
|
if ( strlen( $myToolTip ) == strlen( $legendText ) ) {
|
|
$myToolTip = '';
|
|
} else {
|
|
$myToolTip = preg_replace( '/\<section\s+end\s*=\s*' . preg_quote( $parm, '/' ) . '\s*\/\>.*/s', '', $myToolTip );
|
|
}
|
|
}
|
|
|
|
$myValue = '';
|
|
if ( array_key_exists( $parm, $tpv[$call] ) ) {
|
|
$myValue = $tpv[$call][$parm];
|
|
}
|
|
|
|
$form .= self::editTemplateCall( $call, $parm, $myType, $myValue, $myFormat, $myToolTip, $myInstruction, $fieldFormat );
|
|
}
|
|
|
|
$form .= "</table>\n<br/><br/>";
|
|
}
|
|
|
|
foreach ( $hidden as $hide ) {
|
|
$form .= "<input type='hidden' " . $hide . " />";
|
|
}
|
|
|
|
$csrfTokenSet = RequestContext::getMain()->getCsrfTokenSet();
|
|
$form .= "<input type='hidden' name='wpEditToken' value='{$csrfTokenSet->getToken()}'/>";
|
|
foreach ( $preview as $prev ) {
|
|
$form .= "<input type='submit' " . $prev . " /> ";
|
|
}
|
|
|
|
$form .= "</form></html>\n";
|
|
|
|
return $form;
|
|
} elseif ( $exec == 'set' || $exec == 'preview' ) {
|
|
// loop over all invocations and parameters, this could be improved to enhance performance
|
|
$matchCount = 10;
|
|
|
|
for ( $call = 0; $call < 10; $call++ ) {
|
|
foreach ( $parameter as $nr => $parm ) {
|
|
// set parameters to values specified in the dpl source or get them from the http request
|
|
if ( $exec == 'set' ) {
|
|
$myValue = $value[$nr];
|
|
} else {
|
|
if ( $call >= $matchCount ) {
|
|
break;
|
|
}
|
|
|
|
$request = RequestContext::getMain()->getRequest();
|
|
$myValue = $request->getVal( urlencode( $call . '_' . $parm ), '' );
|
|
}
|
|
|
|
$myOptional = array_key_exists( $nr, $optional );
|
|
$myAfterParm = [];
|
|
|
|
if ( array_key_exists( $nr, $afterparm ) ) {
|
|
$myAfterParm = $afterparm[$nr];
|
|
}
|
|
|
|
$text = self::updateTemplateCall( $matchCount, $text, $template, $call, $parm, $myValue ?? '', $myAfterParm, $myOptional );
|
|
}
|
|
|
|
if ( $exec == 'set' ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( $exec == 'set' ) {
|
|
return self::doUpdateArticle( $title, $text, $summary );
|
|
} elseif ( $exec == 'preview' ) {
|
|
global $wgScriptPath;
|
|
|
|
$request = RequestContext::getMain()->getRequest();
|
|
|
|
$titleX = Title::newFromText( $title );
|
|
$articleX = new Article( $titleX );
|
|
|
|
$userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
|
|
|
|
$form = '<html>
|
|
<form id="editform" name="editform" method="post" action="' . $wgScriptPath . '/index.php?title=' . urlencode( $title ) . '&action=submit" enctype="multipart/form-data">
|
|
<input type="hidden" value="" name="wpSection" />
|
|
<input type="hidden" value="' . wfTimestampNow() . '" name="wpStarttime" />
|
|
<input type="hidden" value="' . $articleX->getPage()->getTimestamp() . '" name="wpEdittime" />
|
|
<input type="hidden" value="" name="wpScrolltop" id="wpScrolltop" />
|
|
<textarea tabindex="1" accesskey="," name="wpTextbox1" id="wpTextbox1" rows="' . $userOptionsLookup->getIntOption( $user, 'rows' ) . '" cols="' . $userOptionsLookup->getIntOption( $user, 'cols' ) . '" >' . htmlspecialchars( $text ) . '</textarea>
|
|
<input type="hidden" name="wpSummary value="' . $summary . '" id="wpSummary" />
|
|
<input name="wpAutoSummary" type="hidden" value="" />
|
|
<input id="wpSave" name="wpSave" type="submit" value="Save page" accesskey="s" title="Save your changes [s]" />
|
|
<input type="hidden" value="' . $request->getVal( 'token' ) . '" name="wpEditToken" />
|
|
</form>
|
|
</html>';
|
|
return $form;
|
|
}
|
|
|
|
return "exec must be one of the following: edit, preview, set";
|
|
}
|
|
|
|
/**
|
|
* @param string $title
|
|
* @param string $text
|
|
* @param string $summary
|
|
* @return string
|
|
*/
|
|
private static function doUpdateArticle( $title, $text, $summary ) {
|
|
$context = RequestContext::getMain();
|
|
$out = $context->getOutput();
|
|
$user = $context->getUser();
|
|
|
|
if ( !$context->getCsrfTokenSet()->matchTokenField( 'wpEditToken' ) ) {
|
|
$out->addWikiMsg( 'sessionfailure' );
|
|
|
|
return 'session failure';
|
|
}
|
|
|
|
$titleX = Title::newFromText( $title );
|
|
$permission_errors = MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors( 'edit', $user, $titleX );
|
|
|
|
if ( count( $permission_errors ) == 0 ) {
|
|
$services = MediaWikiServices::getInstance();
|
|
$wikiPageFactory = $services->getWikiPageFactory();
|
|
$page = $wikiPageFactory->newFromTitle( $titleX );
|
|
|
|
$updater = $page->newPageUpdater( $user );
|
|
$content = $page->getContentHandler()->makeContent( $text, $titleX );
|
|
$updater->setContent( SlotRecord::MAIN, $content );
|
|
$comment = CommentStoreComment::newUnsavedComment( $summary );
|
|
|
|
$updater->saveRevision(
|
|
$comment,
|
|
EDIT_UPDATE | EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY
|
|
);
|
|
|
|
$out->redirect( $titleX->getFullUrl( $page->isRedirect() ? 'redirect=no' : '' ) );
|
|
|
|
return '';
|
|
} else {
|
|
$out->showPermissionsErrorPage( $permission_errors );
|
|
|
|
return 'permission error';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $call
|
|
* @param string $parameter
|
|
* @param string $type
|
|
* @param string $value
|
|
* @param string $format
|
|
* @param string $legend
|
|
* @param string $instruction
|
|
* @param string $fieldFormat
|
|
* @return string
|
|
*/
|
|
private static function editTemplateCall( $call, $parameter, $type, $value, $format, $legend, $instruction, $fieldFormat ) {
|
|
$matches = [];
|
|
$nlCount = preg_match_all( '/\n/', $value, $matches );
|
|
|
|
if ( $nlCount > 0 ) {
|
|
$rows = $nlCount + 1;
|
|
} else {
|
|
$rows = floor( strlen( $value ) / 50 ) + 1;
|
|
}
|
|
|
|
if ( preg_match( '/rows\s*=/', $format ) <= 0 ) {
|
|
$format .= " rows=$rows";
|
|
}
|
|
|
|
$cols = 50;
|
|
if ( preg_match( '/cols\s*=/', $format ) <= 0 ) {
|
|
$format .= " cols=$cols";
|
|
}
|
|
|
|
$textArea = "<textarea name=\"" . urlencode( $call . '_' . $parameter ) . "\" $format/>" . htmlspecialchars( $value ) . "</textarea>";
|
|
|
|
return str_replace( '%NAME%', htmlspecialchars( str_replace( '_', ' ', $parameter ) ), str_replace( '%TYPE%', $type, str_replace( '%INPUT%', $textArea, str_replace( '%LEGEND%', "</html>" . htmlspecialchars( $legend ) . "<html>", str_replace( '%INSTRUCTION%', "</html>" . htmlspecialchars( $instruction ) . "<html>", $fieldFormat ) ) ) ) );
|
|
}
|
|
|
|
/**
|
|
* @param string $text
|
|
* @param string $template
|
|
* @return array|string
|
|
*/
|
|
private static function getTemplateParmValues( $text, $template ) {
|
|
$matches = [];
|
|
$noMatches = preg_match_all( '/\{\{\s*' . preg_quote( $template, '/' ) . '\s*[|}]/i', $text, $matches, PREG_OFFSET_CAPTURE );
|
|
|
|
if ( $noMatches <= 0 ) {
|
|
return '';
|
|
}
|
|
|
|
$textLen = strlen( $text );
|
|
$tval = [];
|
|
$call = -1;
|
|
|
|
foreach ( $matches as $matchA ) {
|
|
foreach ( $matchA as $matchB ) {
|
|
$match = $matchB[0];
|
|
$start = $matchB[1];
|
|
$tval[++$call] = [];
|
|
$nr = 0;
|
|
$parmValue = '';
|
|
$parmName = '';
|
|
$parm = '';
|
|
|
|
if ( $match[strlen( $match ) - 1] == '}' ) {
|
|
break;
|
|
}
|
|
|
|
// search to the end of the template call
|
|
$cbrackets = 2;
|
|
|
|
for ( $i = $start + strlen( $match ); $i < $textLen; $i++ ) {
|
|
$c = $text[$i];
|
|
if ( $c == '{' || $c == '[' ) {
|
|
$cbrackets++;
|
|
}
|
|
|
|
if ( $c == '}' || $c == ']' ) {
|
|
$cbrackets--;
|
|
}
|
|
|
|
if ( ( $cbrackets == 2 && $c == '|' ) || ( $cbrackets == 1 && $c == '}' ) ) {
|
|
// parameter (name or value) found
|
|
if ( $parmName == '' ) {
|
|
$tval[$call][++$nr] = trim( $parm );
|
|
} else {
|
|
$tval[$call][$parmName] = trim( $parmValue );
|
|
}
|
|
|
|
$parmName = '';
|
|
$parmValue = '';
|
|
$parm = '';
|
|
|
|
continue;
|
|
} else {
|
|
if ( $parmName == '' ) {
|
|
if ( $c == '=' ) {
|
|
$parmName = trim( $parm );
|
|
}
|
|
} else {
|
|
$parmValue .= $c;
|
|
}
|
|
}
|
|
|
|
$parm .= $c;
|
|
if ( $cbrackets == 0 ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $tval;
|
|
}
|
|
|
|
/**
|
|
* Changes a single parameter value within a certain call of a template
|
|
*
|
|
* @param int &$matchCount
|
|
* @param string $text
|
|
* @param string $template
|
|
* @param int $call
|
|
* @param string $parameter
|
|
* @param string $value
|
|
* @param array $afterParm
|
|
* @param bool $optional
|
|
* @return string
|
|
*/
|
|
private static function updateTemplateCall( &$matchCount, $text, $template, $call, $parameter, $value, $afterParm, $optional ) {
|
|
// if parameter is optional and value is empty we leave everything as it is (i.e. we do not remove the parm)
|
|
if ( $optional && $value == '' ) {
|
|
return $text;
|
|
}
|
|
|
|
$matches = [];
|
|
$noMatches = preg_match_all( '/\{\{\s*' . preg_quote( $template, '/' ) . '\s*[|}]/i', $text, $matches, PREG_OFFSET_CAPTURE );
|
|
|
|
if ( $noMatches <= 0 ) {
|
|
return $text;
|
|
}
|
|
|
|
$beginSubst = -1;
|
|
$endSubst = -1;
|
|
$posInsertAt = 0;
|
|
$apNrLast = 1000;
|
|
|
|
foreach ( $matches as $matchA ) {
|
|
$matchCount = count( $matchA );
|
|
|
|
foreach ( $matchA as $occurence => $matchB ) {
|
|
if ( $occurence < $call ) {
|
|
continue;
|
|
}
|
|
|
|
$match = $matchB[0];
|
|
$start = $matchB[1];
|
|
|
|
if ( $match[strlen( $match ) - 1] == '}' ) {
|
|
// template was called without parameters, add new parameter and value
|
|
// append parameter and value
|
|
$beginSubst = 0;
|
|
$endSubst = 0;
|
|
$substitution = "|$parameter = $value";
|
|
break;
|
|
} else {
|
|
// there is already a list of parameters; we search to the end of the template call
|
|
$cbrackets = 2;
|
|
$parm = '';
|
|
$pos = $start + strlen( $match ) - 1;
|
|
$textLen = strlen( $text );
|
|
|
|
for ( $i = $pos + 1; $i < $textLen; $i++ ) {
|
|
$c = $text[$i];
|
|
|
|
if ( $c == '{' || $c == '[' ) {
|
|
// we count both types of brackets
|
|
$cbrackets++;
|
|
}
|
|
|
|
if ( $c == '}' || $c == ']' ) {
|
|
$cbrackets--;
|
|
}
|
|
|
|
if ( ( $cbrackets == 2 && $c == '|' ) || ( $cbrackets == 1 && $c == '}' ) ) {
|
|
// parameter (name / value) found
|
|
|
|
$token = explode( '=', $parm, 2 );
|
|
if ( count( $token ) == 2 ) {
|
|
// we need a pair of name / value
|
|
$parmName = trim( $token[0] );
|
|
|
|
if ( $parmName == $parameter ) {
|
|
// we found the parameter, now replace the current value
|
|
$parmValue = trim( $token[1] );
|
|
|
|
if ( $parmValue == $value ) {
|
|
// no need to change when values are identical
|
|
break;
|
|
}
|
|
|
|
// keep spaces;
|
|
if ( $parmValue == '' ) {
|
|
if ( strlen( $token[1] ) > 0 && $token[1][strlen( $token[1] ) - 1] == "\n" ) {
|
|
$substitution = str_replace( "\n", $value . "\n", $token[1] );
|
|
} else {
|
|
$substitution = $value . $token[1];
|
|
}
|
|
} else {
|
|
$substitution = str_replace( $parmValue, $value, $token[1] );
|
|
}
|
|
|
|
$beginSubst = $pos + strlen( $token[0] ) + 2;
|
|
$endSubst = $i;
|
|
break;
|
|
} else {
|
|
foreach ( $afterParm as $apNr => $ap ) {
|
|
// store position for insertion
|
|
if ( $parmName == $ap && $apNr < $apNrLast ) {
|
|
$posInsertAt = $i;
|
|
$apNrLast = $apNr;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( $c == '}' ) {
|
|
// end of template call reached, insert at stored position or here
|
|
if ( $posInsertAt != 0 ) {
|
|
$beginSubst = $posInsertAt;
|
|
} else {
|
|
$beginSubst = $i;
|
|
}
|
|
|
|
$substitution = "|$parameter = $value";
|
|
if ( $text[$beginSubst - 1] == "\n" ) {
|
|
--$beginSubst;
|
|
$substitution = "\n" . $substitution;
|
|
}
|
|
|
|
$endSubst = $beginSubst;
|
|
break;
|
|
}
|
|
|
|
$pos = $i;
|
|
$parm = '';
|
|
} else {
|
|
$parm .= $c;
|
|
}
|
|
|
|
if ( $cbrackets == 0 ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( $beginSubst < 0 ) {
|
|
return $text;
|
|
}
|
|
|
|
return substr( $text, 0, $beginSubst ) . ( $substitution ?? '' ) . substr( $text, $endSubst );
|
|
}
|
|
|
|
/**
|
|
* @param string $title
|
|
* @param string $text
|
|
* @param string $rulesText
|
|
* @return string
|
|
*/
|
|
public static function deleteArticleByRule( $title, $text, $rulesText ) {
|
|
// return "deletion of articles by DPL is disabled.";
|
|
|
|
// we use ; as command delimiter; \; stands for a semicolon
|
|
// \n is translated to a real linefeed
|
|
$rulesText = str_replace( ";", '°', $rulesText );
|
|
$rulesText = str_replace( '\°', ';', $rulesText );
|
|
$rulesText = str_replace( "\\n", "\n", $rulesText );
|
|
$rules = explode( '°', $rulesText );
|
|
$exec = false;
|
|
$message = '';
|
|
$reason = '';
|
|
|
|
foreach ( $rules as $rule ) {
|
|
if ( preg_match( '/^\s*#/', $rule ) > 0 ) {
|
|
// # is comment symbol
|
|
continue;
|
|
}
|
|
|
|
$rule = preg_replace( '/^[\s]*/', '', $rule );
|
|
$cmd = preg_split( "/ +/", $rule, 2 );
|
|
|
|
if ( count( $cmd ) > 1 ) {
|
|
$arg = $cmd[1];
|
|
} else {
|
|
$arg = '';
|
|
}
|
|
|
|
$cmd[0] = trim( $cmd[0] );
|
|
|
|
if ( $cmd[0] == 'reason' ) {
|
|
$reason = $arg;
|
|
}
|
|
|
|
// we execute only if "exec" is given, otherwise we merely show what would be done
|
|
if ( $cmd[0] == 'exec' ) {
|
|
$exec = true;
|
|
}
|
|
}
|
|
|
|
$reason .= "\nbulk delete by DPL query";
|
|
|
|
$titleX = Title::newFromText( $title );
|
|
|
|
if ( $exec ) {
|
|
$context = RequestContext::getMain();
|
|
$out = $context->getOutput();
|
|
$user = $context->getUser();
|
|
|
|
# Check permissions
|
|
$permission_errors = MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors( 'delete', $user, $titleX );
|
|
$isReadOnly = MediaWikiServices::getInstance()->getReadOnlyMode()->isReadOnly();
|
|
|
|
if ( count( $permission_errors ) > 0 ) {
|
|
$out->showPermissionsErrorPage( $permission_errors );
|
|
|
|
return 'permission error';
|
|
} elseif ( $isReadOnly ) {
|
|
throw new ReadOnlyError;
|
|
} else {
|
|
$wikiPageFactory = MediaWikiServices::getInstance()->getWikiPageFactory();
|
|
$deletePageFactory = MediaWikiServices::getInstance()->getDeletePageFactory();
|
|
$deletePage = $deletePageFactory->newDeletePage(
|
|
$wikiPageFactory->newFromTitle( $titleX ),
|
|
$user
|
|
);
|
|
|
|
$deletePage->deleteIfAllowed( $reason );
|
|
}
|
|
} else {
|
|
$message .= "set 'exec yes' to delete     <big>'''$title'''</big>\n";
|
|
}
|
|
|
|
$message .= "<pre><nowiki>\n{$text}</nowiki></pre>";
|
|
|
|
return $message;
|
|
}
|
|
}
|