2016-12-17 17:52:36 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
class AbuseFilterVariableHolder {
|
2017-06-15 14:23:34 +00:00
|
|
|
public $mVars = [];
|
2016-12-17 17:52:36 +00:00
|
|
|
|
2017-06-15 14:23:34 +00:00
|
|
|
public static $varBlacklist = [ 'context' ];
|
2016-12-17 17:52:36 +00:00
|
|
|
|
|
|
|
public function __construct() {
|
|
|
|
// Backwards-compatibility (unused now)
|
|
|
|
$this->setVar( 'minor_edit', false );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $variable
|
|
|
|
* @param $datum
|
|
|
|
*/
|
|
|
|
function setVar( $variable, $datum ) {
|
|
|
|
$variable = strtolower( $variable );
|
|
|
|
if ( !( $datum instanceof AFPData || $datum instanceof AFComputedVariable ) ) {
|
|
|
|
$datum = AFPData::newFromPHPVar( $datum );
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->mVars[$variable] = $datum;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $variable
|
|
|
|
* @param $method
|
|
|
|
* @param $parameters
|
|
|
|
*/
|
|
|
|
function setLazyLoadVar( $variable, $method, $parameters ) {
|
|
|
|
$placeholder = new AFComputedVariable( $method, $parameters );
|
|
|
|
$this->setVar( $variable, $placeholder );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a variable from the current object
|
|
|
|
*
|
|
|
|
* @param $variable string
|
|
|
|
* @return AFPData
|
|
|
|
*/
|
|
|
|
function getVar( $variable ) {
|
|
|
|
$variable = strtolower( $variable );
|
|
|
|
if ( isset( $this->mVars[$variable] ) ) {
|
|
|
|
if ( $this->mVars[$variable] instanceof AFComputedVariable ) {
|
|
|
|
$value = $this->mVars[$variable]->compute( $this );
|
|
|
|
$this->setVar( $variable, $value );
|
|
|
|
return $value;
|
|
|
|
} elseif ( $this->mVars[$variable] instanceof AFPData ) {
|
|
|
|
return $this->mVars[$variable];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new AFPData();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return AbuseFilterVariableHolder
|
|
|
|
*/
|
|
|
|
public static function merge() {
|
|
|
|
$newHolder = new AbuseFilterVariableHolder;
|
2017-06-15 14:23:34 +00:00
|
|
|
call_user_func_array( [ $newHolder, "addHolders" ], func_get_args() );
|
2016-12-17 17:52:36 +00:00
|
|
|
|
|
|
|
return $newHolder;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $addHolder
|
|
|
|
* @throws MWException
|
|
|
|
* @deprecated use addHolders() instead
|
|
|
|
*/
|
|
|
|
public function addHolder( $addHolder ) {
|
|
|
|
$this->addHolders( $addHolder );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Merge any number of holders given as arguments into this holder.
|
|
|
|
*
|
|
|
|
* @throws MWException
|
|
|
|
*/
|
|
|
|
public function addHolders() {
|
|
|
|
$holders = func_get_args();
|
|
|
|
|
|
|
|
foreach ( $holders as $addHolder ) {
|
|
|
|
if ( !is_object( $addHolder ) ) {
|
|
|
|
throw new MWException( 'Invalid argument to AbuseFilterVariableHolder::addHolders' );
|
|
|
|
}
|
|
|
|
$this->mVars = array_merge( $this->mVars, $addHolder->mVars );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function __wakeup() {
|
|
|
|
// Reset the context.
|
|
|
|
$this->setVar( 'context', 'stored' );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Export all variables stored in this object as string
|
|
|
|
*
|
|
|
|
* @return string[]
|
|
|
|
*/
|
|
|
|
function exportAllVars() {
|
|
|
|
$exported = [];
|
|
|
|
foreach ( array_keys( $this->mVars ) as $varName ) {
|
|
|
|
if ( !in_array( $varName, self::$varBlacklist ) ) {
|
|
|
|
$exported[$varName] = $this->getVar( $varName )->toString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $exported;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Export all non-lazy variables stored in this object as string
|
|
|
|
*
|
|
|
|
* @return string[]
|
|
|
|
*/
|
|
|
|
function exportNonLazyVars() {
|
|
|
|
$exported = [];
|
|
|
|
foreach ( $this->mVars as $varName => $data ) {
|
|
|
|
if (
|
|
|
|
!( $data instanceof AFComputedVariable )
|
|
|
|
&& !in_array( $varName, self::$varBlacklist )
|
|
|
|
) {
|
|
|
|
$exported[$varName] = $this->getVar( $varName )->toString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $exported;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dump all variables stored in this object in their native types.
|
|
|
|
* If you want a not yet set variable to be included in the results you can
|
|
|
|
* either set $compute to an array with the name of the variable or set
|
|
|
|
* $compute to true to compute all not yet set variables.
|
|
|
|
*
|
|
|
|
* @param $compute array|bool Variables we should copute if not yet set
|
|
|
|
* @param $includeUserVars bool Include user set variables
|
|
|
|
* @return array
|
|
|
|
*/
|
2017-06-15 14:23:34 +00:00
|
|
|
public function dumpAllVars( $compute = [], $includeUserVars = false ) {
|
2016-12-17 17:52:36 +00:00
|
|
|
$allVarNames = array_keys( $this->mVars );
|
2017-06-15 14:23:34 +00:00
|
|
|
$exported = [];
|
|
|
|
$coreVariables = [];
|
2016-12-17 17:52:36 +00:00
|
|
|
|
|
|
|
if ( !$includeUserVars ) {
|
|
|
|
// Compile a list of all variables set by the extension to be able
|
|
|
|
// to filter user set ones by name
|
|
|
|
global $wgRestrictionTypes;
|
|
|
|
|
|
|
|
$coreVariables = AbuseFilter::getBuilderValues();
|
|
|
|
$coreVariables = array_keys( $coreVariables['vars'] );
|
|
|
|
|
|
|
|
// Title vars can have several prefixes
|
2017-06-15 14:23:34 +00:00
|
|
|
$prefixes = [ 'ARTICLE', 'MOVED_FROM', 'MOVED_TO' ];
|
|
|
|
$titleVars = [
|
2016-12-17 17:52:36 +00:00
|
|
|
'_ARTICLEID',
|
|
|
|
'_NAMESPACE',
|
|
|
|
'_TEXT',
|
|
|
|
'_PREFIXEDTEXT',
|
|
|
|
'_recent_contributors'
|
2017-06-15 14:23:34 +00:00
|
|
|
];
|
2016-12-17 17:52:36 +00:00
|
|
|
foreach ( $wgRestrictionTypes as $action ) {
|
|
|
|
$titleVars[] = "_restrictions_$action";
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ( $titleVars as $var ) {
|
|
|
|
foreach ( $prefixes as $prefix ) {
|
|
|
|
$coreVariables[] = $prefix . $var;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$coreVariables = array_map( 'strtolower', $coreVariables );
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ( $allVarNames as $varName ) {
|
|
|
|
if (
|
|
|
|
( $includeUserVars || in_array( strtolower( $varName ), $coreVariables ) ) &&
|
|
|
|
// Only include variables set in the extension in case $includeUserVars is false
|
|
|
|
!in_array( $varName, self::$varBlacklist ) &&
|
|
|
|
( $compute === true ||
|
|
|
|
( is_array( $compute ) && in_array( $varName, $compute ) ) ||
|
|
|
|
$this->mVars[$varName] instanceof AFPData
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
$exported[$varName] = $this->getVar( $varName )->toNative();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $exported;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $var
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
function varIsSet( $var ) {
|
|
|
|
return array_key_exists( $var, $this->mVars );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compute all vars which need DB access. Useful for vars which are going to be saved
|
|
|
|
* cross-wiki or used for offline analysis.
|
|
|
|
*/
|
|
|
|
function computeDBVars() {
|
2017-06-15 14:23:34 +00:00
|
|
|
static $dbTypes = [
|
2016-12-17 17:52:36 +00:00
|
|
|
'links-from-wikitext-or-database',
|
|
|
|
'load-recent-authors',
|
|
|
|
'get-page-restrictions',
|
|
|
|
'simple-user-accessor',
|
|
|
|
'user-age',
|
|
|
|
'user-groups',
|
|
|
|
'user-rights',
|
|
|
|
'revision-text-by-id',
|
|
|
|
'revision-text-by-timestamp'
|
2017-06-15 14:23:34 +00:00
|
|
|
];
|
2016-12-17 17:52:36 +00:00
|
|
|
|
|
|
|
foreach ( $this->mVars as $name => $value ) {
|
|
|
|
if ( $value instanceof AFComputedVariable &&
|
|
|
|
in_array( $value->mMethod, $dbTypes )
|
|
|
|
) {
|
|
|
|
$value = $value->compute( $this );
|
|
|
|
$this->setVar( $name, $value );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|