summaryrefslogtreecommitdiff
path: root/www/wiki/vendor/param-processor/param-processor/src/PackagePrivate/Param.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/vendor/param-processor/param-processor/src/PackagePrivate/Param.php')
-rw-r--r--www/wiki/vendor/param-processor/param-processor/src/PackagePrivate/Param.php418
1 files changed, 418 insertions, 0 deletions
diff --git a/www/wiki/vendor/param-processor/param-processor/src/PackagePrivate/Param.php b/www/wiki/vendor/param-processor/param-processor/src/PackagePrivate/Param.php
new file mode 100644
index 00000000..49011579
--- /dev/null
+++ b/www/wiki/vendor/param-processor/param-processor/src/PackagePrivate/Param.php
@@ -0,0 +1,418 @@
+<?php
+
+namespace ParamProcessor\PackagePrivate;
+
+use DataValues\DataValue;
+use Exception;
+use ParamProcessor\IParam;
+use ParamProcessor\IParamDefinition;
+use ParamProcessor\Options;
+use ParamProcessor\ParamDefinition;
+use ParamProcessor\ParamDefinitionFactory;
+use ParamProcessor\ProcessingError;
+use ValueParsers\NullParser;
+use ValueParsers\ParseException;
+use ValueParsers\ValueParser;
+
+/**
+ * Package private!
+ *
+ * Parameter class, representing the "instance" of a parameter.
+ * Holds a ParamDefinition, user provided input (name & value) and processing state.
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class Param implements IParam {
+
+ /**
+ * Indicates whether parameters not found in the criteria list
+ * should be stored in case they are not accepted. The default is false.
+ *
+ * @deprecated since 1.7
+ */
+ public static $accumulateParameterErrors = false;
+
+ /**
+ * The original parameter name as provided by the user. This can be the
+ * main name or an alias.
+ * @var string
+ */
+ protected $originalName;
+
+ /**
+ * The original value as provided by the user. This is mainly retained for
+ * usage in error messages when the parameter turns out to be invalid.
+ * @var string
+ */
+ protected $originalValue;
+
+ /**
+ * @var mixed
+ */
+ protected $value;
+
+ /**
+ * Keeps track of how many times the parameter has been set by the user.
+ * This is used to detect overrides and for figuring out a parameter is missing.
+ * @var integer
+ */
+ protected $setCount = 0;
+
+ /**
+ * @var ProcessingError[]
+ */
+ protected $errors = [];
+
+ /**
+ * Indicates if the parameter was set to it's default.
+ * @var boolean
+ */
+ protected $defaulted = false;
+
+ /**
+ * @var ParamDefinition
+ */
+ protected $definition;
+
+ public function __construct( IParamDefinition $definition ) {
+ $this->definition = $definition;
+ }
+
+ /**
+ * Sets and cleans the original value and name.
+ */
+ public function setUserValue( string $paramName, $paramValue, Options $options ): bool {
+ if ( $this->setCount > 0 && !$options->acceptOverriding() ) {
+ // TODO
+ return false;
+ }
+
+ $this->originalName = $paramName;
+ $this->originalValue = $paramValue;
+
+ $this->cleanValue( $options );
+
+ $this->setCount++;
+
+ return true;
+ }
+
+ /**
+ * @param mixed $value
+ */
+ public function setValue( $value ) {
+ $this->value = $value;
+ }
+
+ /**
+ * Sets the $value to a cleaned value of $originalValue.
+ */
+ protected function cleanValue( Options $options ) {
+ if ( $this->definition->isList() ) {
+ $this->value = explode( $this->definition->getDelimiter(), $this->originalValue );
+ }
+ else {
+ $this->value = $this->originalValue;
+ }
+
+ if ( $this->shouldTrim( $options ) ) {
+ $this->trimValue();
+ }
+
+ if ( $this->shouldLowercase( $options ) ) {
+ $this->lowercaseValue();
+ }
+ }
+
+ private function shouldTrim( Options $options ): bool {
+ $trim = $this->definition->trimDuringClean();
+
+ if ( $trim === true ) {
+ return true;
+ }
+
+ return is_null( $trim ) && $options->trimValues();
+ }
+
+ private function trimValue() {
+ if ( is_string( $this->value ) ) {
+ $this->value = trim( $this->value );
+ }
+ elseif ( $this->definition->isList() ) {
+ foreach ( $this->value as &$element ) {
+ if ( is_string( $element ) ) {
+ $element = trim( $element );
+ }
+ }
+ }
+ }
+
+ private function shouldLowercase( Options $options ): bool {
+ if ( $options->lowercaseValues() ) {
+ return true;
+ }
+
+ $definitionOptions = $this->definition->getOptions();
+
+ return array_key_exists( 'tolower', $definitionOptions ) && $definitionOptions['tolower'];
+ }
+
+ private function lowercaseValue() {
+ if ( $this->definition->isList() ) {
+ foreach ( $this->value as &$element ) {
+ if ( is_string( $element ) ) {
+ $element = strtolower( $element );
+ }
+ }
+ }
+ elseif ( is_string( $this->value ) ) {
+ $this->value = strtolower( $this->value );
+ }
+ }
+
+ /**
+ * Parameter processing entry point.
+ * Processes the parameter. This includes parsing, validation and additional formatting.
+ *
+ * @param ParamDefinition[] $definitions
+ * @param Param[] $params
+ * @param Options $options
+ *
+ * @throws Exception
+ */
+ public function process( array &$definitions, array $params, Options $options ) {
+ if ( $this->setCount == 0 ) {
+ if ( $this->definition->isRequired() ) {
+ // This should not occur, so throw an exception.
+ throw new Exception( 'Attempted to validate a required parameter without first setting a value.' );
+ }
+ else {
+ $this->setToDefault();
+ }
+ }
+ else {
+ $this->parseAndValidate( $options );
+ }
+
+ if ( !$this->hasFatalError() && ( $this->definition->shouldManipulateDefault() || !$this->wasSetToDefault() ) ) {
+ $this->definition->format( $this, $definitions, $params );
+ }
+ }
+
+ public function getValueParser( Options $options ): ValueParser {
+ $parser = $this->definition->getValueParser();
+
+ if ( !( $parser instanceof NullParser ) ) {
+ return $parser;
+ }
+
+ // TODO: inject factory
+ $type = ParamDefinitionFactory::singleton()->getType( $this->definition->getType() );
+
+ $parserClass = $options->isStringlyTyped() ? $type->getStringParserClass() : $type->getTypedParserClass();
+
+ return new $parserClass( new \ValueParsers\ParserOptions( $this->definition->getOptions() ) );
+ }
+
+ protected function parseAndValidate( Options $options ) {
+ $parser = $this->getValueParser( $options );
+
+ if ( $this->definition->isList() ) {
+ $values = [];
+
+ foreach ( $this->getValue() as $value ) {
+ $parsedValue = $this->parseAndValidateValue( $parser, $value );
+
+ if ( is_array( $parsedValue ) ) {
+ $values[] = $parsedValue[0];
+ }
+ }
+
+ $this->value = $values;
+ }
+ else {
+ $parsedValue = $this->parseAndValidateValue( $parser, $this->getValue() );
+
+ if ( is_array( $parsedValue ) ) {
+ $this->value = $parsedValue[0];
+ }
+ }
+
+ $this->setToDefaultIfNeeded();
+ }
+
+ /**
+ * Parses and validates the provided with with specified parser.
+ * The result is returned in an array on success. On fail, false is returned.
+ * The result is wrapped in an array since we need to be able to distinguish
+ * between the method returning false and the value being false.
+ *
+ * Parsing and validation errors get added to $this->errors.
+ *
+ * @since 1.0
+ *
+ * @param ValueParser $parser
+ * @param mixed $value
+ *
+ * @return array|bool
+ */
+ protected function parseAndValidateValue( ValueParser $parser, $value ) {
+ try {
+ $value = $parser->parse( $value );
+ }
+ catch ( ParseException $parseException ) {
+ $this->registerProcessingError( $parseException->getMessage() );
+ return false;
+ }
+
+ if ( $value instanceof DataValue ) {
+ $value = $value->getValue();
+ }
+
+ $this->validateValue( $value );
+
+ return [ $value ];
+ }
+
+ protected function registerProcessingError( string $message ) {
+ $this->errors[] = $this->newProcessingError( $message );
+ }
+
+ protected function newProcessingError( string $message ): ProcessingError {
+ $severity = $this->isRequired() ? ProcessingError::SEVERITY_FATAL : ProcessingError::SEVERITY_NORMAL;
+ return new ProcessingError( $message, $severity );
+ }
+
+ /**
+ * @param mixed $value
+ */
+ protected function validateValue( $value ) {
+ $validationCallback = $this->definition->getValidationCallback();
+
+ if ( $validationCallback !== null && $validationCallback( $value ) !== true ) {
+ $this->registerProcessingError( 'Validation callback failed' );
+ }
+ else {
+ $validator = $this->definition->getValueValidator();
+ if ( method_exists( $validator, 'setOptions' ) ) {
+ $validator->setOptions( $this->definition->getOptions() );
+ }
+ $validationResult = $validator->validate( $value );
+
+ if ( !$validationResult->isValid() ) {
+ foreach ( $validationResult->getErrors() as $error ) {
+ $this->registerProcessingError( $error->getText() );
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the parameter value to the default if needed.
+ */
+ protected function setToDefaultIfNeeded() {
+ if ( $this->shouldSetToDefault() ) {
+ $this->setToDefault();
+ }
+ }
+
+ private function shouldSetToDefault(): bool {
+ if ( $this->hasFatalError() ) {
+ return false;
+ }
+
+ if ( $this->definition->isList() ) {
+ return $this->errors !== [] && $this->value === [];
+ }
+
+ return $this->errors !== [];
+ }
+
+ /**
+ * Returns the original use-provided name.
+ *
+ * @throws Exception
+ * @return string
+ */
+ public function getOriginalName(): string {
+ if ( $this->setCount == 0 ) {
+ throw new Exception( 'No user input set to the parameter yet, so the original name does not exist' );
+ }
+ return $this->originalName;
+ }
+
+ /**
+ * Returns the original use-provided value.
+ *
+ * @throws Exception
+ * @return mixed
+ */
+ public function getOriginalValue() {
+ if ( $this->setCount == 0 ) {
+ throw new Exception( 'No user input set to the parameter yet, so the original value does not exist' );
+ }
+ return $this->originalValue;
+ }
+
+ /**
+ * Returns all validation errors that occurred so far.
+ *
+ * @return ProcessingError[]
+ */
+ public function getErrors(): array {
+ return $this->errors;
+ }
+
+ /**
+ * Sets the parameter value to the default.
+ */
+ protected function setToDefault() {
+ $this->defaulted = true;
+ $this->value = $this->definition->getDefault();
+ }
+
+ public function wasSetToDefault(): bool {
+ return $this->defaulted;
+ }
+
+ public function hasFatalError(): bool {
+ foreach ( $this->errors as $error ) {
+ if ( $error->isFatal() ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the ParamDefinition this Param was constructed from.
+ */
+ public function getDefinition(): ParamDefinition {
+ return $this->definition;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function &getValue() {
+ return $this->value;
+ }
+
+ public function isRequired(): bool {
+ return $this->definition->isRequired();
+ }
+
+ public function getName(): string {
+ return $this->definition->getName();
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getAliases(): array {
+ return $this->definition->getAliases();
+ }
+
+} \ No newline at end of file