http://www.mediawiki.org/wiki/Special:Code/MediaWiki/72089
Revision: 72089
Author: jeroendedauw
Date: 2010-09-01 08:03:18 +0000 (Wed, 01 Sep 2010)
Log Message:
-----------
Follow up to r72088
Modified Paths:
--------------
trunk/extensions/Validator/Validator.php
Added Paths:
-----------
trunk/extensions/Validator/includes/Validator.php
Removed Paths:
-------------
trunk/extensions/Validator/includes/Validator.class.php
Modified: trunk/extensions/Validator/Validator.php
===================================================================
--- trunk/extensions/Validator/Validator.php 2010-09-01 08:02:16 UTC (rev
72088)
+++ trunk/extensions/Validator/Validator.php 2010-09-01 08:03:18 UTC (rev
72089)
@@ -50,7 +50,7 @@
// Autoload the general classes.
$incDir = dirname( __FILE__ ) . '/includes/';
-$wgAutoloadClasses['Validator'] = $incDir .
'Validator.class.php';
+$wgAutoloadClasses['Validator'] = $incDir .
'Validator.php';
$wgAutoloadClasses['ParserHook'] = $incDir .
'ParserHook.php';
$wgAutoloadClasses['ValidatorFunctions'] = $incDir .
'Validator_Functions.php';
$wgAutoloadClasses['ValidatorFormats'] = $incDir .
'Validator_Formats.php';
Deleted: trunk/extensions/Validator/includes/Validator.class.php
===================================================================
--- trunk/extensions/Validator/includes/Validator.class.php 2010-09-01
08:02:16 UTC (rev 72088)
+++ trunk/extensions/Validator/includes/Validator.class.php 2010-09-01
08:03:18 UTC (rev 72089)
@@ -1,770 +0,0 @@
-<?php
-
-/**
- * File holding the Validator class.
- *
- * @file Validator.class.php
- * @ingroup Validator
- *
- * @author Jeroen De Dauw
- */
-
-if ( !defined( 'MEDIAWIKI' ) ) {
- die( 'Not an entry point.' );
-}
-
-/**
- * Class for parameter validation.
- *
- * @ingroup Validator
- *
- * @author Jeroen De Dauw
- *
- * TODO: break on fatal errors, such as missing required parameters that are
dependencies
- * TODO: correct invalid parameters in the main loop, as to have correct
dependency handling
- * TODO: settings of defaults should happen as a default behaviour that can be
overiden by the output format,
- * as it is not wished for all output formats in every case, and
now a hacky approach is required there.
- */
-final class Validator {
-
- /**
- * @var boolean Indicates whether parameters not found in the criteria
list
- * should be stored in case they are not accepted. The default is false.
- */
- public static $storeUnknownParameters = false;
-
- /**
- * @var boolean Indicates whether parameters not found in the criteria
list
- * should be stored in case they are not accepted. The default is false.
- */
- public static $accumulateParameterErrors = false;
-
- /**
- * @var boolean Indicates whether parameters that are provided more
then once
- * should be accepted, and use the first provided value, or not, and
generate an error.
- */
- public static $acceptOverriding = false;
-
- /**
- * @var boolean Indicates if errors in list items should cause the item
to be omitted,
- * versus having the whole list be set to it's default.
- */
- public static $perItemValidation = true;
-
- /**
- * @var mixed The default value for parameters the user did not set
and do not have their own
- * default specified.
- */
- public static $defaultDefaultValue = '';
-
- /**
- * @var string The default delimiter for lists, used when the parameter
definition does not
- * specify one.
- */
- public static $defaultListDelimeter = ',';
-
- /**
- * @var array Holder for the validation functions.
- */
- private static $mValidationFunctions = array(
- 'in_array' => array( 'ValidatorFunctions', 'in_array' ),
- 'in_range' => array( 'ValidatorFunctions', 'in_range' ),
- 'is_numeric' => array( 'ValidatorFunctions', 'is_numeric' ),
- 'is_float' => array( 'ValidatorFunctions', 'is_float' ),
- 'is_integer' => array( 'ValidatorFunctions', 'is_integer' ),
- 'not_empty' => array( 'ValidatorFunctions', 'not_empty' ),
- 'has_length' => array( 'ValidatorFunctions', 'has_length' ),
- 'regex' => array( 'ValidatorFunctions', 'regex' ),
- );
-
- /**
- * @var array Holder for the list validation functions.
- */
- private static $mListValidationFunctions = array(
- 'item_count' => array( 'ValidatorFunctions', 'has_item_count' ),
- 'unique_items' => array( 'ValidatorFunctions',
'has_unique_items' ),
- );
-
- /**
- * @var array Holder for the formatting functions.
- */
- private static $mOutputFormats = array(
- 'array' => array( 'ValidatorFormats', 'format_array' ),
- 'list' => array( 'ValidatorFormats', 'format_list' ),
- 'boolean' => array( 'ValidatorFormats', 'format_boolean' ),
- 'boolstr' => array( 'ValidatorFormats', 'format_boolean_string'
),
- 'string' => array( 'ValidatorFormats', 'format_string' ),
- 'unique_items' => array( 'ValidatorFormats',
'format_unique_items' ),
- 'filtered_array' => array( 'ValidatorFormats',
'format_filtered_array' ),
- );
-
- /**
- * An array containing the parameter definitions. The keys are main
parameter names,
- * and the values are associative arrays themselves, consisting out of
elements that
- * can be seen as properties of the parameter as they would be in the
case of objects.
- *
- * @var associative array
- */
- private $mParameterInfo;
-
- /**
- * An array initially containing the user provided values. Adittional
data about
- * the validation and formatting processes gets added later on, and so
stays
- * available for validation and formatting of other parameters.
- *
- * original-value
- * default
- * position
- * original-name
- * formatted-value
- *
- * @var associative array
- */
- private $mParameters = array();
-
- /**
- * Arrays for holding the (main) names of valid, invalid and unknown
parameters.
- */
- private $mValidParams = array();
- private $mInvalidParams = array();
- private $mUnknownParams = array();
-
- /**
- * Holds all errors and their meta data.
- *
- * @var associative array
- */
- private $mErrors = array();
-
- /**
- * Determines the names and values of all parameters. Also takes care
of default parameters.
- * After that the resulting parameter list is passed to
Validator::setParameters
- *
- * @param array $rawParams
- * @param array $parameterInfo
- * @param array $defaultParams
- * @param boolean $toLower Indicates if the parameter values should be
put to lower case. Defaults to true.
- */
- public function parseAndSetParams( array $rawParams, array
$parameterInfo, array $defaultParams = array(), $toLower = true ) {
- $parameters = array();
-
- $nr = 0;
- $defaultNr = 0;
-
- foreach ( $rawParams as $arg ) {
- // Only take into account strings. If the value is not
a string,
- // it is not a raw parameter, and can not be parsed
correctly in all cases.
- if ( is_string( $arg ) ) {
- $parts = explode( '=', $arg, 2 );
-
- // If there is only one part, no parameter name
is provided, so try default parameter assignment.
- if ( count( $parts ) == 1 ) {
- // Default parameter assignment is only
possible when there are default parameters!
- if ( count( $defaultParams ) > 0 ) {
- $defaultParam = strtolower(
array_shift( $defaultParams ) );
-
- $this->lowerCaseIfNeeded(
$parts[0], $defaultParam, $parameterInfo, $toLower );
-
- $parameters[$defaultParam] =
array(
- 'original-value' =>
trim( $parts[0] ),
- 'default' => $defaultNr,
- 'position' => $nr
- );
- $defaultNr++;
- }
- else {
- // It might be nice to have
some sort of warning or error here, as the value is simply ignored.
- }
- } else {
- $paramName = trim( strtolower(
$parts[0] ) );
-
- $this->lowerCaseIfNeeded( $parts[1],
$paramName, $parameterInfo, $toLower );
-
- $parameters[$paramName] = array(
- 'original-value' => trim(
$parts[1] ),
- 'default' => false,
- 'position' => $nr
- );
-
- // Let's not be evil, and remove the
used parameter name from the default parameter list.
- // This code is basically a remove
array element by value algorithm.
- $newDefaults = array();
-
- foreach( $defaultParams as
$defaultParam ) {
- if ( $defaultParam !=
$paramName ) $newDefaults[] = $defaultParam;
- }
-
- $defaultParams = $newDefaults;
- }
- }
- $nr++;
- }
-
- $this->setParameters( $parameters, $parameterInfo, false );
- }
-
- /**
- * Loops through a list of provided parameters, resolves aliasing and
stores errors
- * for unknown parameters and optionally for parameter overriding.
- *
- * @param array $parameters Parameter name as key, parameter value as
value
- * @param array $parameterInfo Main parameter name as key, parameter
meta data as valu
- * @param boolean $toLower Indicates if the parameter values should be
put to lower case. Defaults to true.
- */
- public function setParameters( array $parameters, array $parameterInfo,
$toLower = true ) {
- $this->mParameterInfo = $parameterInfo;
-
- // Loop through all the user provided parameters, and
destinguise between those that are allowed and those that are not.
- foreach ( $parameters as $paramName => $paramData ) {
- $paramName = trim( strtolower( $paramName ) );
-
- // Attempt to get the main parameter name (takes care
of aliases).
- $mainName = self::getMainParamName( $paramName );
-
- // If the parameter is found in the list of allowed
ones, add it to the $mParameters array.
- if ( $mainName ) {
- // Check for parameter overriding. In most
cases, this has already largely been taken care off,
- // in the form of later parameters overriding
earlier ones. This is not true for different aliases though.
- if ( !array_key_exists( $mainName,
$this->mParameters ) || self::$acceptOverriding ) {
- // If the valueis an array, this means
it has been procesed in parseAndSetParams already.
- // If it is not, setParameters was
called directly with an array of string parameter values.
- if ( is_array( $paramData ) &&
array_key_exists( 'original-value', $paramData ) ) {
- $paramData['original-name'] =
$paramName;
- $this->mParameters[$mainName] =
$paramData;
- }
- else {
- if ( is_string( $paramData ) ) {
- $paramData = trim(
$paramData );
-
$this->lowerCaseIfNeeded( $paramData, $mainName, $this->mParameterInfo,
$toLower );
- }
-
- $this->mParameters[$mainName] =
array(
- 'original-value' =>
$paramData,
- 'original-name' =>
$paramName,
- );
- }
- }
- else {
- $this->mErrors[] = array( 'type' =>
'override', 'name' => $mainName );
- }
- }
- else { // If the parameter is not found in the list of
allowed ones, add an item to the $this->mErrors array.
- if ( self::$storeUnknownParameters )
$this->mUnknownParams[] = $paramName;
- $this->mErrors[] = array( 'type' => 'unknown',
'name' => $paramName );
- }
- }
- }
-
- /**
- * Lowercases the provided $paramValue if needed.
- *
- * @since 0.3.6
- *
- * @param $paramValue String
- * @param $paramName String
- * @param $parameterInfo Array
- * @param $globalDefault Boolean
- */
- protected function lowerCaseIfNeeded( &$paramValue, $paramName, array
$parameterInfo, $globalDefault ) {
- $useLocal = array_key_exists( $paramName, $parameterInfo ) &&
array_key_exists( 'tolower', $parameterInfo[$paramName] );
- $lowerCase = $useLocal ? $parameterInfo[$paramName]['tolower']
: $globalDefault;
- if ( $lowerCase ) $paramValue = strtolower( $paramValue );
- }
-
- /**
- * Returns the main parameter name for a given parameter or alias, or
false
- * when it is not recognized as main parameter or alias.
- *
- * @param string $paramName
- *
- * @return string or false
- */
- protected function getMainParamName( $paramName ) {
- $result = false;
-
- if ( array_key_exists( $paramName, $this->mParameterInfo ) ) {
- $result = $paramName;
- }
- else {
- foreach ( $this->mParameterInfo as $name => $data ) {
- if ( array_key_exists( 'aliases', $data ) &&
in_array( $paramName, $data['aliases'] ) ) {
- $result = $name;
- break;
- }
- }
- }
-
- return $result;
- }
-
- /**
- * First determines the order of parameter handling based on the
dependency definitons,
- * and then goes through the parameters one by one, first validating
and then formatting,
- * storing any encountered errors along the way.
- *
- * The 'value' element is set here, either by the cleaned
'original-value' or default.
- */
- public function validateAndFormatParameters() {
- $dependencyList = array();
-
- foreach ( $this->mParameterInfo as $paramName => $paramInfo ) {
- $dependencyList[$paramName] =
- array_key_exists( 'dependencies', $paramInfo )
? (array)$paramInfo['dependencies'] : array();
- }
-
- $sorter = new TopologicalSort( $dependencyList, true );
- $orderedParameters = $sorter->doSort();
-
- foreach ( $orderedParameters as $paramName ) {
- $paramInfo = $this->mParameterInfo[$paramName];
-
- // If the user provided a value for this parameter,
validate and handle it.
- if ( array_key_exists( $paramName, $this->mParameters )
) {
-
- $this->cleanParameter( $paramName );
-
- if ( $this->validateParameter( $paramName ) ) {
- // If the validation succeeded, add the
parameter to the list of valid ones.
- $this->mValidParams[] = $paramName;
- $this->setOutputTypes( $paramName );
- }
- else {
- // If the validation failed, add the
parameter to the list of invalid ones.
- $this->mInvalidParams[] = $paramName;
- }
- }
- else {
- // If the parameter is required, add a new
error of type 'missing'.
- // TODO: break when has dependencies
- if ( array_key_exists( 'required', $paramInfo )
&& $paramInfo['required'] ) {
- $this->mErrors[] = array( 'type' =>
'missing', 'name' => $paramName );
- }
- else {
- // Set the default value (or default
'default value' if none is provided), and ensure the type is correct.
- $this->mParameters[$paramName]['value']
= array_key_exists( 'default', $paramInfo ) ? $paramInfo['default'] :
self::$defaultDefaultValue;
- $this->mValidParams[] = $paramName;
- $this->setOutputTypes( $paramName );
- }
- }
- }
- }
-
- /**
- * Ensures the parameter info is valid and parses list types.
- *
- * @param string $name
- */
- private function cleanParameter( $name ) {
- // Ensure there is a criteria array.
- if ( ! array_key_exists( 'criteria',
$this->mParameterInfo[$name] ) ) {
- $this->mParameterInfo[$name]['criteria'] = array();
- }
-
- // Ensure the type is set in array form.
- if ( ! array_key_exists( 'type', $this->mParameterInfo[$name] )
) {
- $this->mParameterInfo[$name]['type'] = array( 'string'
);
- }
- elseif ( ! is_array( $this->mParameterInfo[$name]['type'] ) ) {
- $this->mParameterInfo[$name]['type'] = array(
$this->mParameterInfo[$name]['type'] );
- }
-
- if ( array_key_exists( 'type', $this->mParameterInfo[$name] ) )
{
- // Add type specific criteria.
- switch( strtolower(
$this->mParameterInfo[$name]['type'][0] ) ) {
- case 'integer':
- $this->addTypeCriteria( $name,
'is_integer' );
- break;
- case 'float':
- $this->addTypeCriteria( $name,
'is_float' );
- break;
- case 'number': // Note: This accepts
non-decimal notations!
- $this->addTypeCriteria( $name,
'is_numeric' );
- break;
- case 'boolean':
- // TODO: work with list of true and
false values.
- // TODO: i18n
- $this->addTypeCriteria( $name,
'in_array', array( 'yes', 'no', 'on', 'off' ) );
- break;
- case 'char':
- $this->addTypeCriteria( $name,
'has_length', array( 1, 1 ) );
- break;
- }
- }
-
- // If the original-value element is set, clean it, and store as
value.
- if ( array_key_exists( 'original-value',
$this->mParameters[$name] ) ) {
- $value = $this->mParameters[$name]['original-value'];
-
- if ( count( $this->mParameterInfo[$name]['type'] ) > 1
&& $this->mParameterInfo[$name]['type'][1] == 'list' ) {
- // Trimming and splitting of list values.
- $delimiter = count(
$this->mParameterInfo[$name]['type'] ) > 2 ?
$this->mParameterInfo[$name]['type'][2] : self::$defaultListDelimeter;
- $value = preg_replace( '/((\s)*' . $delimiter .
'(\s)*)/', $delimiter, $value );
- $value = explode( $delimiter, $value );
- }
- elseif ( count( $this->mParameterInfo[$name]['type'] )
> 1 && $this->mParameterInfo[$name]['type'][1] == 'array' && is_array( $value )
) {
- // Trimming of array values.
- for ( $i = count( $value ); $i > 0; $i-- )
$value[$i] = trim( $value[$i] );
- }
-
- $this->mParameters[$name]['value'] = $value;
- }
- }
-
- private function addTypeCriteria( $paramName, $criteriaName,
$criteriaArgs = array() ) {
- $this->mParameterInfo[$paramName]['criteria'] = array_merge(
- array( $criteriaName => $criteriaArgs ),
- $this->mParameterInfo[$paramName]['criteria']
- );
- }
-
- /**
- * Valides the provided parameter.
- *
- * This method itself validates the list criteria, if any. After this
the regular criteria
- * are validated by calling the doItemValidation method.
- *
- * @param string $name
- *
- * @return boolean Indicates whether there the parameter value(s)
is/are valid.
- */
- private function validateParameter( $name ) {
- $hasNoErrors = $this->doListValidation( $name );
-
- if ( $hasNoErrors || self::$accumulateParameterErrors ) {
- $hasNoErrors = $hasNoErrors && $this->doItemValidation(
$name );
- }
-
- return $hasNoErrors;
- }
-
- /**
- * Validates the list criteria for a parameter, if there are any.
- *
- * @param string $name
- */
- private function doListValidation( $name ) {
- $hasNoErrors = true;
-
- if ( array_key_exists( 'list-criteria',
$this->mParameterInfo[$name] ) ) {
- foreach ( $this->mParameterInfo[$name]['list-criteria']
as $criteriaName => $criteriaArgs ) {
- // Get the validation function. If there is no
matching function, throw an exception.
- if ( array_key_exists( $criteriaName,
self::$mListValidationFunctions ) ) {
- $validationFunction =
self::$mListValidationFunctions[$criteriaName];
- $isValid = $this->doCriteriaValidation(
$validationFunction, $this->mParameters['value'], $name, $criteriaArgs );
-
- // Add a new error when the validation
failed, and break the loop if errors for one parameter should not be
accumulated.
- if ( ! $isValid ) {
- $hasNoErrors = false;
-
- $this->mErrors[] = array(
- 'type' => $criteriaName,
- 'args' => $criteriaArgs,
- 'name' =>
$this->mParameters[$name]['original-name'],
- 'list' => true,
- 'value' =>
$this->mParameters[$name]['original-value']
- );
-
- if (
!self::$accumulateParameterErrors ) {
- break;
- }
- }
- }
- else {
- $hasNoErrors = false;
- throw new Exception( 'There is no
validation function for list criteria type ' . $criteriaName );
- }
- }
- }
-
- return $hasNoErrors;
- }
-
- /**
- * Valides the provided parameter by matching the value against the
item criteria for the name.
- *
- * @param string $name
- *
- * @return boolean Indicates whether there the parameter value(s)
is/are valid.
- */
- private function doItemValidation( $name ) {
- $hasNoErrors = true;
-
- $value = &$this->mParameters[$name]['value'];
-
- // Go through all item criteria.
- foreach ( $this->mParameterInfo[$name]['criteria'] as
$criteriaName => $criteriaArgs ) {
- // Get the validation function. If there is no matching
function, throw an exception.
- if ( array_key_exists( $criteriaName,
self::$mValidationFunctions ) ) {
- $validationFunction =
self::$mValidationFunctions[$criteriaName];
-
- if ( is_array( $value ) ) {
- // Handling of list parameters
- $invalidItems = array();
- $validItems = array();
-
- // Loop through all the items in the
parameter value, and validate them.
- foreach ( $value as $item ) {
- $isValid =
$this->doCriteriaValidation( $validationFunction, $item, $name, $criteriaArgs );
- if ( $isValid ) {
- // If per item
validation is on, store the valid items, so only these can be returned by
Validator.
- if (
self::$perItemValidation ) $validItems[] = $item;
- }
- else {
- // If per item
validation is on, store the invalid items, so a fitting error message can be
created.
- if (
self::$perItemValidation ) {
- $invalidItems[]
= $item;
- }
- else {
- // If per item
validation is not on, an error to one item means the complete value is invalid.
- // Therefore
it's not required to validate the remaining items.
- break;
- }
- }
- }
-
- if ( self::$perItemValidation ) {
- // If per item validation is
on, the parameter value is valid as long as there is at least one valid item.
- $isValid = count( $validItems )
> 0;
-
- // If the value is valid, but
there are invalid items, add an error with a list of these items.
- if ( $isValid && count(
$invalidItems ) > 0 ) {
- $value = $validItems;
- $this->mErrors[] =
array(
- 'type' =>
$criteriaName,
- 'args' =>
$criteriaArgs,
- 'name' =>
$this->mParameters[$name]['original-name'],
- 'list' => true,
- 'invalid-items'
=> $invalidItems
- );
- }
- }
- }
- else {
- // Determine if the value is valid for
single valued parameters.
- $isValid = $this->doCriteriaValidation(
$validationFunction, $value, $name, $criteriaArgs );
- }
-
- // Add a new error when the validation failed,
and break the loop if errors for one parameter should not be accumulated.
- if ( !$isValid ) {
- $this->mErrors[] = array(
- 'type' => $criteriaName,
- 'args' => $criteriaArgs,
- 'name' =>
$this->mParameters[$name]['original-name'],
- 'list' => is_array( $value ),
- 'value' =>
$this->mParameters[$name]['original-value']
- );
-
- $hasNoErrors = false;
- if ( !self::$accumulateParameterErrors
) break;
- }
- }
- else {
- $hasNoErrors = false;
- throw new Exception( 'There is no validation
function for criteria type ' . $criteriaName );
- }
- }
-
- return $hasNoErrors;
- }
-
- /**
- * Calls the validation function for the provided list or single value
and returns it's result.
- * The call is made with these parameters:
- * - value: The value that is the complete list, or a single item.
- * - parameter name: For lookups in the param info array.
- * - parameter array: All data about the parameters gathered so far
(this includes dependencies!).
- * - output type info: Type info as provided by the parameter
definition. This can be zero or more parameters.
- *
- * @param $validationFunction
- * @param mixed $value
- * @param string $name
- * @param array $criteriaArgs
- *
- * @return boolean
- */
- private function doCriteriaValidation( $validationFunction, $value,
$name, array $criteriaArgs ) {
- // Call the validation function and store the result.
- $parameters = array( &$value, $name, $this->mParameters );
- $parameters = array_merge( $parameters, $criteriaArgs );
- return call_user_func_array( $validationFunction, $parameters );
- }
-
- /**
- * Changes the invalid parameters to their default values, and changes
their state to valid.
- */
- public function correctInvalidParams() {
- while ( $paramName = array_shift( $this->mInvalidParams ) ) {
- if ( array_key_exists( 'default',
$this->mParameterInfo[$paramName] ) ) {
- $this->mParameters[$paramName]['value'] =
$this->mParameterInfo[$paramName]['default'];
- }
- else {
- $this->mParameters[$paramName]['value'] =
self::$defaultDefaultValue;
- }
-
- $this->setOutputTypes( $paramName );
- $this->mValidParams[] = $paramName;
- }
- }
-
- /**
- * Ensures the output type values are arrays, and then calls
setOutputType.
- *
- * @param string $name
- */
- private function setOutputTypes( $name ) {
- $info = $this->mParameterInfo[$name];
-
- if ( array_key_exists( 'output-types', $info ) ) {
- for ( $i = 0, $c = count( $info['output-types'] ); $i <
$c; $i++ ) {
- if ( ! is_array( $info['output-types'][$i] ) )
$info['output-types'][$i] = array( $info['output-types'][$i] );
- $this->setOutputType( $name,
$info['output-types'][$i] );
- }
- }
- elseif ( array_key_exists( 'output-type', $info ) ) {
- if ( ! is_array( $info['output-type'] ) )
$info['output-type'] = array( $info['output-type'] );
- $this->setOutputType( $name, $info['output-type'] );
- }
-
- }
-
- /**
- * Calls the formatting function for the provided output format with
these parameters:
- * - parameter value: ByRef for easy manipulation.
- * - parameter name: For lookups in the param info array.
- * - parameter array: All data about the parameters gathered so far
(this includes dependencies!).
- * - output type info: Type info as provided by the parameter
definition. This can be zero or more parameters.
- *
- * @param string $name
- * @param array $typeInfo
- */
- private function setOutputType( $name, array $typeInfo ) {
- // The output type is the first value in the type info array.
- // The remaining ones will be any extra arguments.
- $outputType = strtolower( array_shift( $typeInfo ) );
-
- if ( !array_key_exists( 'formatted-value',
$this->mParameters[$name] ) ) {
- $this->mParameters[$name]['formatted-value'] =
$this->mParameters[$name]['value'];
- }
-
- if ( array_key_exists( $outputType, self::$mOutputFormats ) ) {
- $parameters = array(
&$this->mParameters[$name]['formatted-value'], $name, $this->mParameters );
- $parameters = array_merge( $parameters, $typeInfo );
- call_user_func_array(
self::$mOutputFormats[$outputType], $parameters );
- }
- else {
- throw new Exception( 'There is no formatting function
for output format ' . $outputType );
- }
- }
-
- /**
- * Returns the valid parameters.
- *
- * @param boolean $includeMetaData
- *
- * @return array
- */
- public function getValidParams( $includeMetaData ) {
- if ( $includeMetaData ) {
- return $this->mValidParams;
- }
- else {
- $validParams = array();
-
- foreach( $this->mValidParams as $name ) {
- $key = array_key_exists( 'formatted-value',
$this->mParameters[$name] ) ? 'formatted-value' : 'value';
- $validParams[$name] =
$this->mParameters[$name][$key];
- }
-
- return $validParams;
- }
- }
-
- /**
- * Returns the unknown parameters.
- *
- * @return array
- */
- public static function getUnknownParams() {
- $unknownParams = array();
-
- foreach( $this->mUnknownParams as $name ) {
- $unknownParams[$name] = $this->mParameters[$name];
- }
-
- return $unknownParams;
- }
-
- /**
- * Returns the errors.
- *
- * @return array
- */
- public function getErrors() {
- return $this->mErrors;
- }
-
- /**
- * @return boolean
- */
- public function hasErrors() {
- return count( $this->mErrors ) > 0;
- }
-
- /**
- * Returns wether there are any fatal errors. Fatal errors are either
missing or invalid required parameters,
- * or simply any sort of error when the validation level is equal to
(or bigger then) Validator_ERRORS_STRICT.
- *
- * @return boolean
- */
- public function hasFatalError() {
- global $egValidatorErrorLevel;
- $has = $this->hasErrors() && $egValidatorErrorLevel >=
Validator_ERRORS_STRICT;
-
- if ( !$has ) {
- foreach ( $this->mErrors as $error ) {
- if ( $error['type'] == 'missing' ) {
- $has = true;
- break;
- }
- }
- }
-
- return $has;
- }
-
- /**
- * Adds a new criteria type and the validation function that should
validate values of this type.
- * You can use this function to override existing criteria type
handlers.
- *
- * @param string $criteriaName The name of the cirteria.
- * @param array $functionName The functions location. If it's a global
function, only the name,
- * if it's in a class, first the class name, then the method name.
- */
- public static function addValidationFunction( $criteriaName, array
$functionName ) {
- self::$mValidationFunctions[$criteriaName] = $functionName;
- }
-
- /**
- * Adds a new list criteria type and the validation function that
should validate values of this type.
- * You can use this function to override existing criteria type
handlers.
- *
- * @param string $criteriaName The name of the list cirteria.
- * @param array $functionName The functions location. If it's a global
function, only the name,
- * if it's in a class, first the class name, then the method name.
- */
- public static function addListValidationFunction( $criteriaName, array
$functionName ) {
- self::$mListValidationFunctions[strtolower( $criteriaName )] =
$functionName;
- }
-
- /**
- * Adds a new output format and the formatting function that should
validate values of this type.
- * You can use this function to override existing criteria type
handlers.
- *
- * @param string $formatName The name of the format.
- * @param array $functionName The functions location. If it's a global
function, only the name,
- * if it's in a class, first the class name, then the method name.
- */
- public static function addOutputFormat( $formatName, array
$functionName ) {
- self::$mOutputFormats[strtolower( $formatName )] =
$functionName;
- }
-}
\ No newline at end of file
Copied: trunk/extensions/Validator/includes/Validator.php (from rev 72088,
trunk/extensions/Validator/includes/Validator.class.php)
===================================================================
--- trunk/extensions/Validator/includes/Validator.php
(rev 0)
+++ trunk/extensions/Validator/includes/Validator.php 2010-09-01 08:03:18 UTC
(rev 72089)
@@ -0,0 +1,770 @@
+<?php
+
+/**
+ * File holding the Validator class.
+ *
+ * @file Validator.class.php
+ * @ingroup Validator
+ *
+ * @author Jeroen De Dauw
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ die( 'Not an entry point.' );
+}
+
+/**
+ * Class for parameter validation.
+ *
+ * @ingroup Validator
+ *
+ * @author Jeroen De Dauw
+ *
+ * TODO: break on fatal errors, such as missing required parameters that are
dependencies
+ * TODO: correct invalid parameters in the main loop, as to have correct
dependency handling
+ * TODO: settings of defaults should happen as a default behaviour that can be
overiden by the output format,
+ * as it is not wished for all output formats in every case, and
now a hacky approach is required there.
+ */
+final class Validator {
+
+ /**
+ * @var boolean Indicates whether parameters not found in the criteria
list
+ * should be stored in case they are not accepted. The default is false.
+ */
+ public static $storeUnknownParameters = false;
+
+ /**
+ * @var boolean Indicates whether parameters not found in the criteria
list
+ * should be stored in case they are not accepted. The default is false.
+ */
+ public static $accumulateParameterErrors = false;
+
+ /**
+ * @var boolean Indicates whether parameters that are provided more
then once
+ * should be accepted, and use the first provided value, or not, and
generate an error.
+ */
+ public static $acceptOverriding = false;
+
+ /**
+ * @var boolean Indicates if errors in list items should cause the item
to be omitted,
+ * versus having the whole list be set to it's default.
+ */
+ public static $perItemValidation = true;
+
+ /**
+ * @var mixed The default value for parameters the user did not set
and do not have their own
+ * default specified.
+ */
+ public static $defaultDefaultValue = '';
+
+ /**
+ * @var string The default delimiter for lists, used when the parameter
definition does not
+ * specify one.
+ */
+ public static $defaultListDelimeter = ',';
+
+ /**
+ * @var array Holder for the validation functions.
+ */
+ private static $mValidationFunctions = array(
+ 'in_array' => array( 'ValidatorFunctions', 'in_array' ),
+ 'in_range' => array( 'ValidatorFunctions', 'in_range' ),
+ 'is_numeric' => array( 'ValidatorFunctions', 'is_numeric' ),
+ 'is_float' => array( 'ValidatorFunctions', 'is_float' ),
+ 'is_integer' => array( 'ValidatorFunctions', 'is_integer' ),
+ 'not_empty' => array( 'ValidatorFunctions', 'not_empty' ),
+ 'has_length' => array( 'ValidatorFunctions', 'has_length' ),
+ 'regex' => array( 'ValidatorFunctions', 'regex' ),
+ );
+
+ /**
+ * @var array Holder for the list validation functions.
+ */
+ private static $mListValidationFunctions = array(
+ 'item_count' => array( 'ValidatorFunctions', 'has_item_count' ),
+ 'unique_items' => array( 'ValidatorFunctions',
'has_unique_items' ),
+ );
+
+ /**
+ * @var array Holder for the formatting functions.
+ */
+ private static $mOutputFormats = array(
+ 'array' => array( 'ValidatorFormats', 'format_array' ),
+ 'list' => array( 'ValidatorFormats', 'format_list' ),
+ 'boolean' => array( 'ValidatorFormats', 'format_boolean' ),
+ 'boolstr' => array( 'ValidatorFormats', 'format_boolean_string'
),
+ 'string' => array( 'ValidatorFormats', 'format_string' ),
+ 'unique_items' => array( 'ValidatorFormats',
'format_unique_items' ),
+ 'filtered_array' => array( 'ValidatorFormats',
'format_filtered_array' ),
+ );
+
+ /**
+ * An array containing the parameter definitions. The keys are main
parameter names,
+ * and the values are associative arrays themselves, consisting out of
elements that
+ * can be seen as properties of the parameter as they would be in the
case of objects.
+ *
+ * @var associative array
+ */
+ private $mParameterInfo;
+
+ /**
+ * An array initially containing the user provided values. Adittional
data about
+ * the validation and formatting processes gets added later on, and so
stays
+ * available for validation and formatting of other parameters.
+ *
+ * original-value
+ * default
+ * position
+ * original-name
+ * formatted-value
+ *
+ * @var associative array
+ */
+ private $mParameters = array();
+
+ /**
+ * Arrays for holding the (main) names of valid, invalid and unknown
parameters.
+ */
+ private $mValidParams = array();
+ private $mInvalidParams = array();
+ private $mUnknownParams = array();
+
+ /**
+ * Holds all errors and their meta data.
+ *
+ * @var associative array
+ */
+ private $mErrors = array();
+
+ /**
+ * Determines the names and values of all parameters. Also takes care
of default parameters.
+ * After that the resulting parameter list is passed to
Validator::setParameters
+ *
+ * @param array $rawParams
+ * @param array $parameterInfo
+ * @param array $defaultParams
+ * @param boolean $toLower Indicates if the parameter values should be
put to lower case. Defaults to true.
+ */
+ public function parseAndSetParams( array $rawParams, array
$parameterInfo, array $defaultParams = array(), $toLower = true ) {
+ $parameters = array();
+
+ $nr = 0;
+ $defaultNr = 0;
+
+ foreach ( $rawParams as $arg ) {
+ // Only take into account strings. If the value is not
a string,
+ // it is not a raw parameter, and can not be parsed
correctly in all cases.
+ if ( is_string( $arg ) ) {
+ $parts = explode( '=', $arg, 2 );
+
+ // If there is only one part, no parameter name
is provided, so try default parameter assignment.
+ if ( count( $parts ) == 1 ) {
+ // Default parameter assignment is only
possible when there are default parameters!
+ if ( count( $defaultParams ) > 0 ) {
+ $defaultParam = strtolower(
array_shift( $defaultParams ) );
+
+ $this->lowerCaseIfNeeded(
$parts[0], $defaultParam, $parameterInfo, $toLower );
+
+ $parameters[$defaultParam] =
array(
+ 'original-value' =>
trim( $parts[0] ),
+ 'default' => $defaultNr,
+ 'position' => $nr
+ );
+ $defaultNr++;
+ }
+ else {
+ // It might be nice to have
some sort of warning or error here, as the value is simply ignored.
+ }
+ } else {
+ $paramName = trim( strtolower(
$parts[0] ) );
+
+ $this->lowerCaseIfNeeded( $parts[1],
$paramName, $parameterInfo, $toLower );
+
+ $parameters[$paramName] = array(
+ 'original-value' => trim(
$parts[1] ),
+ 'default' => false,
+ 'position' => $nr
+ );
+
+ // Let's not be evil, and remove the
used parameter name from the default parameter list.
+ // This code is basically a remove
array element by value algorithm.
+ $newDefaults = array();
+
+ foreach( $defaultParams as
$defaultParam ) {
+ if ( $defaultParam !=
$paramName ) $newDefaults[] = $defaultParam;
+ }
+
+ $defaultParams = $newDefaults;
+ }
+ }
+ $nr++;
+ }
+
+ $this->setParameters( $parameters, $parameterInfo, false );
+ }
+
+ /**
+ * Loops through a list of provided parameters, resolves aliasing and
stores errors
+ * for unknown parameters and optionally for parameter overriding.
+ *
+ * @param array $parameters Parameter name as key, parameter value as
value
+ * @param array $parameterInfo Main parameter name as key, parameter
meta data as valu
+ * @param boolean $toLower Indicates if the parameter values should be
put to lower case. Defaults to true.
+ */
+ public function setParameters( array $parameters, array $parameterInfo,
$toLower = true ) {
+ $this->mParameterInfo = $parameterInfo;
+
+ // Loop through all the user provided parameters, and
destinguise between those that are allowed and those that are not.
+ foreach ( $parameters as $paramName => $paramData ) {
+ $paramName = trim( strtolower( $paramName ) );
+
+ // Attempt to get the main parameter name (takes care
of aliases).
+ $mainName = self::getMainParamName( $paramName );
+
+ // If the parameter is found in the list of allowed
ones, add it to the $mParameters array.
+ if ( $mainName ) {
+ // Check for parameter overriding. In most
cases, this has already largely been taken care off,
+ // in the form of later parameters overriding
earlier ones. This is not true for different aliases though.
+ if ( !array_key_exists( $mainName,
$this->mParameters ) || self::$acceptOverriding ) {
+ // If the valueis an array, this means
it has been procesed in parseAndSetParams already.
+ // If it is not, setParameters was
called directly with an array of string parameter values.
+ if ( is_array( $paramData ) &&
array_key_exists( 'original-value', $paramData ) ) {
+ $paramData['original-name'] =
$paramName;
+ $this->mParameters[$mainName] =
$paramData;
+ }
+ else {
+ if ( is_string( $paramData ) ) {
+ $paramData = trim(
$paramData );
+
$this->lowerCaseIfNeeded( $paramData, $mainName, $this->mParameterInfo,
$toLower );
+ }
+
+ $this->mParameters[$mainName] =
array(
+ 'original-value' =>
$paramData,
+ 'original-name' =>
$paramName,
+ );
+ }
+ }
+ else {
+ $this->mErrors[] = array( 'type' =>
'override', 'name' => $mainName );
+ }
+ }
+ else { // If the parameter is not found in the list of
allowed ones, add an item to the $this->mErrors array.
+ if ( self::$storeUnknownParameters )
$this->mUnknownParams[] = $paramName;
+ $this->mErrors[] = array( 'type' => 'unknown',
'name' => $paramName );
+ }
+ }
+ }
+
+ /**
+ * Lowercases the provided $paramValue if needed.
+ *
+ * @since 0.3.6
+ *
+ * @param $paramValue String
+ * @param $paramName String
+ * @param $parameterInfo Array
+ * @param $globalDefault Boolean
+ */
+ protected function lowerCaseIfNeeded( &$paramValue, $paramName, array
$parameterInfo, $globalDefault ) {
+ $useLocal = array_key_exists( $paramName, $parameterInfo ) &&
array_key_exists( 'tolower', $parameterInfo[$paramName] );
+ $lowerCase = $useLocal ? $parameterInfo[$paramName]['tolower']
: $globalDefault;
+ if ( $lowerCase ) $paramValue = strtolower( $paramValue );
+ }
+
+ /**
+ * Returns the main parameter name for a given parameter or alias, or
false
+ * when it is not recognized as main parameter or alias.
+ *
+ * @param string $paramName
+ *
+ * @return string or false
+ */
+ protected function getMainParamName( $paramName ) {
+ $result = false;
+
+ if ( array_key_exists( $paramName, $this->mParameterInfo ) ) {
+ $result = $paramName;
+ }
+ else {
+ foreach ( $this->mParameterInfo as $name => $data ) {
+ if ( array_key_exists( 'aliases', $data ) &&
in_array( $paramName, $data['aliases'] ) ) {
+ $result = $name;
+ break;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * First determines the order of parameter handling based on the
dependency definitons,
+ * and then goes through the parameters one by one, first validating
and then formatting,
+ * storing any encountered errors along the way.
+ *
+ * The 'value' element is set here, either by the cleaned
'original-value' or default.
+ */
+ public function validateAndFormatParameters() {
+ $dependencyList = array();
+
+ foreach ( $this->mParameterInfo as $paramName => $paramInfo ) {
+ $dependencyList[$paramName] =
+ array_key_exists( 'dependencies', $paramInfo )
? (array)$paramInfo['dependencies'] : array();
+ }
+
+ $sorter = new TopologicalSort( $dependencyList, true );
+ $orderedParameters = $sorter->doSort();
+
+ foreach ( $orderedParameters as $paramName ) {
+ $paramInfo = $this->mParameterInfo[$paramName];
+
+ // If the user provided a value for this parameter,
validate and handle it.
+ if ( array_key_exists( $paramName, $this->mParameters )
) {
+
+ $this->cleanParameter( $paramName );
+
+ if ( $this->validateParameter( $paramName ) ) {
+ // If the validation succeeded, add the
parameter to the list of valid ones.
+ $this->mValidParams[] = $paramName;
+ $this->setOutputTypes( $paramName );
+ }
+ else {
+ // If the validation failed, add the
parameter to the list of invalid ones.
+ $this->mInvalidParams[] = $paramName;
+ }
+ }
+ else {
+ // If the parameter is required, add a new
error of type 'missing'.
+ // TODO: break when has dependencies
+ if ( array_key_exists( 'required', $paramInfo )
&& $paramInfo['required'] ) {
+ $this->mErrors[] = array( 'type' =>
'missing', 'name' => $paramName );
+ }
+ else {
+ // Set the default value (or default
'default value' if none is provided), and ensure the type is correct.
+ $this->mParameters[$paramName]['value']
= array_key_exists( 'default', $paramInfo ) ? $paramInfo['default'] :
self::$defaultDefaultValue;
+ $this->mValidParams[] = $paramName;
+ $this->setOutputTypes( $paramName );
+ }
+ }
+ }
+ }
+
+ /**
+ * Ensures the parameter info is valid and parses list types.
+ *
+ * @param string $name
+ */
+ private function cleanParameter( $name ) {
+ // Ensure there is a criteria array.
+ if ( ! array_key_exists( 'criteria',
$this->mParameterInfo[$name] ) ) {
+ $this->mParameterInfo[$name]['criteria'] = array();
+ }
+
+ // Ensure the type is set in array form.
+ if ( ! array_key_exists( 'type', $this->mParameterInfo[$name] )
) {
+ $this->mParameterInfo[$name]['type'] = array( 'string'
);
+ }
+ elseif ( ! is_array( $this->mParameterInfo[$name]['type'] ) ) {
+ $this->mParameterInfo[$name]['type'] = array(
$this->mParameterInfo[$name]['type'] );
+ }
+
+ if ( array_key_exists( 'type', $this->mParameterInfo[$name] ) )
{
+ // Add type specific criteria.
+ switch( strtolower(
$this->mParameterInfo[$name]['type'][0] ) ) {
+ case 'integer':
+ $this->addTypeCriteria( $name,
'is_integer' );
+ break;
+ case 'float':
+ $this->addTypeCriteria( $name,
'is_float' );
+ break;
+ case 'number': // Note: This accepts
non-decimal notations!
+ $this->addTypeCriteria( $name,
'is_numeric' );
+ break;
+ case 'boolean':
+ // TODO: work with list of true and
false values.
+ // TODO: i18n
+ $this->addTypeCriteria( $name,
'in_array', array( 'yes', 'no', 'on', 'off' ) );
+ break;
+ case 'char':
+ $this->addTypeCriteria( $name,
'has_length', array( 1, 1 ) );
+ break;
+ }
+ }
+
+ // If the original-value element is set, clean it, and store as
value.
+ if ( array_key_exists( 'original-value',
$this->mParameters[$name] ) ) {
+ $value = $this->mParameters[$name]['original-value'];
+
+ if ( count( $this->mParameterInfo[$name]['type'] ) > 1
&& $this->mParameterInfo[$name]['type'][1] == 'list' ) {
+ // Trimming and splitting of list values.
+ $delimiter = count(
$this->mParameterInfo[$name]['type'] ) > 2 ?
$this->mParameterInfo[$name]['type'][2] : self::$defaultListDelimeter;
+ $value = preg_replace( '/((\s)*' . $delimiter .
'(\s)*)/', $delimiter, $value );
+ $value = explode( $delimiter, $value );
+ }
+ elseif ( count( $this->mParameterInfo[$name]['type'] )
> 1 && $this->mParameterInfo[$name]['type'][1] == 'array' && is_array( $value )
) {
+ // Trimming of array values.
+ for ( $i = count( $value ); $i > 0; $i-- )
$value[$i] = trim( $value[$i] );
+ }
+
+ $this->mParameters[$name]['value'] = $value;
+ }
+ }
+
+ private function addTypeCriteria( $paramName, $criteriaName,
$criteriaArgs = array() ) {
+ $this->mParameterInfo[$paramName]['criteria'] = array_merge(
+ array( $criteriaName => $criteriaArgs ),
+ $this->mParameterInfo[$paramName]['criteria']
+ );
+ }
+
+ /**
+ * Valides the provided parameter.
+ *
+ * This method itself validates the list criteria, if any. After this
the regular criteria
+ * are validated by calling the doItemValidation method.
+ *
+ * @param string $name
+ *
+ * @return boolean Indicates whether there the parameter value(s)
is/are valid.
+ */
+ private function validateParameter( $name ) {
+ $hasNoErrors = $this->doListValidation( $name );
+
+ if ( $hasNoErrors || self::$accumulateParameterErrors ) {
+ $hasNoErrors = $hasNoErrors && $this->doItemValidation(
$name );
+ }
+
+ return $hasNoErrors;
+ }
+
+ /**
+ * Validates the list criteria for a parameter, if there are any.
+ *
+ * @param string $name
+ */
+ private function doListValidation( $name ) {
+ $hasNoErrors = true;
+
+ if ( array_key_exists( 'list-criteria',
$this->mParameterInfo[$name] ) ) {
+ foreach ( $this->mParameterInfo[$name]['list-criteria']
as $criteriaName => $criteriaArgs ) {
+ // Get the validation function. If there is no
matching function, throw an exception.
+ if ( array_key_exists( $criteriaName,
self::$mListValidationFunctions ) ) {
+ $validationFunction =
self::$mListValidationFunctions[$criteriaName];
+ $isValid = $this->doCriteriaValidation(
$validationFunction, $this->mParameters['value'], $name, $criteriaArgs );
+
+ // Add a new error when the validation
failed, and break the loop if errors for one parameter should not be
accumulated.
+ if ( ! $isValid ) {
+ $hasNoErrors = false;
+
+ $this->mErrors[] = array(
+ 'type' => $criteriaName,
+ 'args' => $criteriaArgs,
+ 'name' =>
$this->mParameters[$name]['original-name'],
+ 'list' => true,
+ 'value' =>
$this->mParameters[$name]['original-value']
+ );
+
+ if (
!self::$accumulateParameterErrors ) {
+ break;
+ }
+ }
+ }
+ else {
+ $hasNoErrors = false;
+ throw new Exception( 'There is no
validation function for list criteria type ' . $criteriaName );
+ }
+ }
+ }
+
+ return $hasNoErrors;
+ }
+
+ /**
+ * Valides the provided parameter by matching the value against the
item criteria for the name.
+ *
+ * @param string $name
+ *
+ * @return boolean Indicates whether there the parameter value(s)
is/are valid.
+ */
+ private function doItemValidation( $name ) {
+ $hasNoErrors = true;
+
+ $value = &$this->mParameters[$name]['value'];
+
+ // Go through all item criteria.
+ foreach ( $this->mParameterInfo[$name]['criteria'] as
$criteriaName => $criteriaArgs ) {
+ // Get the validation function. If there is no matching
function, throw an exception.
+ if ( array_key_exists( $criteriaName,
self::$mValidationFunctions ) ) {
+ $validationFunction =
self::$mValidationFunctions[$criteriaName];
+
+ if ( is_array( $value ) ) {
+ // Handling of list parameters
+ $invalidItems = array();
+ $validItems = array();
+
+ // Loop through all the items in the
parameter value, and validate them.
+ foreach ( $value as $item ) {
+ $isValid =
$this->doCriteriaValidation( $validationFunction, $item, $name, $criteriaArgs );
+ if ( $isValid ) {
+ // If per item
validation is on, store the valid items, so only these can be returned by
Validator.
+ if (
self::$perItemValidation ) $validItems[] = $item;
+ }
+ else {
+ // If per item
validation is on, store the invalid items, so a fitting error message can be
created.
+ if (
self::$perItemValidation ) {
+ $invalidItems[]
= $item;
+ }
+ else {
+ // If per item
validation is not on, an error to one item means the complete value is invalid.
+ // Therefore
it's not required to validate the remaining items.
+ break;
+ }
+ }
+ }
+
+ if ( self::$perItemValidation ) {
+ // If per item validation is
on, the parameter value is valid as long as there is at least one valid item.
+ $isValid = count( $validItems )
> 0;
+
+ // If the value is valid, but
there are invalid items, add an error with a list of these items.
+ if ( $isValid && count(
$invalidItems ) > 0 ) {
+ $value = $validItems;
+ $this->mErrors[] =
array(
+ 'type' =>
$criteriaName,
+ 'args' =>
$criteriaArgs,
+ 'name' =>
$this->mParameters[$name]['original-name'],
+ 'list' => true,
+ 'invalid-items'
=> $invalidItems
+ );
+ }
+ }
+ }
+ else {
+ // Determine if the value is valid for
single valued parameters.
+ $isValid = $this->doCriteriaValidation(
$validationFunction, $value, $name, $criteriaArgs );
+ }
+
+ // Add a new error when the validation failed,
and break the loop if errors for one parameter should not be accumulated.
+ if ( !$isValid ) {
+ $this->mErrors[] = array(
+ 'type' => $criteriaName,
+ 'args' => $criteriaArgs,
+ 'name' =>
$this->mParameters[$name]['original-name'],
+ 'list' => is_array( $value ),
+ 'value' =>
$this->mParameters[$name]['original-value']
+ );
+
+ $hasNoErrors = false;
+ if ( !self::$accumulateParameterErrors
) break;
+ }
+ }
+ else {
+ $hasNoErrors = false;
+ throw new Exception( 'There is no validation
function for criteria type ' . $criteriaName );
+ }
+ }
+
+ return $hasNoErrors;
+ }
+
+ /**
+ * Calls the validation function for the provided list or single value
and returns it's result.
+ * The call is made with these parameters:
+ * - value: The value that is the complete list, or a single item.
+ * - parameter name: For lookups in the param info array.
+ * - parameter array: All data about the parameters gathered so far
(this includes dependencies!).
+ * - output type info: Type info as provided by the parameter
definition. This can be zero or more parameters.
+ *
+ * @param $validationFunction
+ * @param mixed $value
+ * @param string $name
+ * @param array $criteriaArgs
+ *
+ * @return boolean
+ */
+ private function doCriteriaValidation( $validationFunction, $value,
$name, array $criteriaArgs ) {
+ // Call the validation function and store the result.
+ $parameters = array( &$value, $name, $this->mParameters );
+ $parameters = array_merge( $parameters, $criteriaArgs );
+ return call_user_func_array( $validationFunction, $parameters );
+ }
+
+ /**
+ * Changes the invalid parameters to their default values, and changes
their state to valid.
+ */
+ public function correctInvalidParams() {
+ while ( $paramName = array_shift( $this->mInvalidParams ) ) {
+ if ( array_key_exists( 'default',
$this->mParameterInfo[$paramName] ) ) {
+ $this->mParameters[$paramName]['value'] =
$this->mParameterInfo[$paramName]['default'];
+ }
+ else {
+ $this->mParameters[$paramName]['value'] =
self::$defaultDefaultValue;
+ }
+
+ $this->setOutputTypes( $paramName );
+ $this->mValidParams[] = $paramName;
+ }
+ }
+
+ /**
+ * Ensures the output type values are arrays, and then calls
setOutputType.
+ *
+ * @param string $name
+ */
+ private function setOutputTypes( $name ) {
+ $info = $this->mParameterInfo[$name];
+
+ if ( array_key_exists( 'output-types', $info ) ) {
+ for ( $i = 0, $c = count( $info['output-types'] ); $i <
$c; $i++ ) {
+ if ( ! is_array( $info['output-types'][$i] ) )
$info['output-types'][$i] = array( $info['output-types'][$i] );
+ $this->setOutputType( $name,
$info['output-types'][$i] );
+ }
+ }
+ elseif ( array_key_exists( 'output-type', $info ) ) {
+ if ( ! is_array( $info['output-type'] ) )
$info['output-type'] = array( $info['output-type'] );
+ $this->setOutputType( $name, $info['output-type'] );
+ }
+
+ }
+
+ /**
+ * Calls the formatting function for the provided output format with
these parameters:
+ * - parameter value: ByRef for easy manipulation.
+ * - parameter name: For lookups in the param info array.
+ * - parameter array: All data about the parameters gathered so far
(this includes dependencies!).
+ * - output type info: Type info as provided by the parameter
definition. This can be zero or more parameters.
+ *
+ * @param string $name
+ * @param array $typeInfo
+ */
+ private function setOutputType( $name, array $typeInfo ) {
+ // The output type is the first value in the type info array.
+ // The remaining ones will be any extra arguments.
+ $outputType = strtolower( array_shift( $typeInfo ) );
+
+ if ( !array_key_exists( 'formatted-value',
$this->mParameters[$name] ) ) {
+ $this->mParameters[$name]['formatted-value'] =
$this->mParameters[$name]['value'];
+ }
+
+ if ( array_key_exists( $outputType, self::$mOutputFormats ) ) {
+ $parameters = array(
&$this->mParameters[$name]['formatted-value'], $name, $this->mParameters );
+ $parameters = array_merge( $parameters, $typeInfo );
+ call_user_func_array(
self::$mOutputFormats[$outputType], $parameters );
+ }
+ else {
+ throw new Exception( 'There is no formatting function
for output format ' . $outputType );
+ }
+ }
+
+ /**
+ * Returns the valid parameters.
+ *
+ * @param boolean $includeMetaData
+ *
+ * @return array
+ */
+ public function getValidParams( $includeMetaData ) {
+ if ( $includeMetaData ) {
+ return $this->mValidParams;
+ }
+ else {
+ $validParams = array();
+
+ foreach( $this->mValidParams as $name ) {
+ $key = array_key_exists( 'formatted-value',
$this->mParameters[$name] ) ? 'formatted-value' : 'value';
+ $validParams[$name] =
$this->mParameters[$name][$key];
+ }
+
+ return $validParams;
+ }
+ }
+
+ /**
+ * Returns the unknown parameters.
+ *
+ * @return array
+ */
+ public static function getUnknownParams() {
+ $unknownParams = array();
+
+ foreach( $this->mUnknownParams as $name ) {
+ $unknownParams[$name] = $this->mParameters[$name];
+ }
+
+ return $unknownParams;
+ }
+
+ /**
+ * Returns the errors.
+ *
+ * @return array
+ */
+ public function getErrors() {
+ return $this->mErrors;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function hasErrors() {
+ return count( $this->mErrors ) > 0;
+ }
+
+ /**
+ * Returns wether there are any fatal errors. Fatal errors are either
missing or invalid required parameters,
+ * or simply any sort of error when the validation level is equal to
(or bigger then) Validator_ERRORS_STRICT.
+ *
+ * @return boolean
+ */
+ public function hasFatalError() {
+ global $egValidatorErrorLevel;
+ $has = $this->hasErrors() && $egValidatorErrorLevel >=
Validator_ERRORS_STRICT;
+
+ if ( !$has ) {
+ foreach ( $this->mErrors as $error ) {
+ if ( $error['type'] == 'missing' ) {
+ $has = true;
+ break;
+ }
+ }
+ }
+
+ return $has;
+ }
+
+ /**
+ * Adds a new criteria type and the validation function that should
validate values of this type.
+ * You can use this function to override existing criteria type
handlers.
+ *
+ * @param string $criteriaName The name of the cirteria.
+ * @param array $functionName The functions location. If it's a global
function, only the name,
+ * if it's in a class, first the class name, then the method name.
+ */
+ public static function addValidationFunction( $criteriaName, array
$functionName ) {
+ self::$mValidationFunctions[$criteriaName] = $functionName;
+ }
+
+ /**
+ * Adds a new list criteria type and the validation function that
should validate values of this type.
+ * You can use this function to override existing criteria type
handlers.
+ *
+ * @param string $criteriaName The name of the list cirteria.
+ * @param array $functionName The functions location. If it's a global
function, only the name,
+ * if it's in a class, first the class name, then the method name.
+ */
+ public static function addListValidationFunction( $criteriaName, array
$functionName ) {
+ self::$mListValidationFunctions[strtolower( $criteriaName )] =
$functionName;
+ }
+
+ /**
+ * Adds a new output format and the formatting function that should
validate values of this type.
+ * You can use this function to override existing criteria type
handlers.
+ *
+ * @param string $formatName The name of the format.
+ * @param array $functionName The functions location. If it's a global
function, only the name,
+ * if it's in a class, first the class name, then the method name.
+ */
+ public static function addOutputFormat( $formatName, array
$functionName ) {
+ self::$mOutputFormats[strtolower( $formatName )] =
$functionName;
+ }
+}
\ No newline at end of file
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs