wikimedia/mediawiki-extensions-Wikibase

View on GitHub
repo/includes/Validators/StringLengthValidator.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace Wikibase\Repo\Validators;

use ValueValidators\Error;
use ValueValidators\Result;
use ValueValidators\ValueValidator;
use Wikimedia\Assert\Assert;

/**
 * StringLengthValidator checks a string's length
 *
 * @license GPL-2.0-or-later
 * @author Daniel Kinzler
 */
class StringLengthValidator implements ValueValidator {

    /**
     * @var int
     */
    private $minLength;

    /**
     * @var int
     */
    private $maxLength;

    /**
     * @var callable
     */
    private $measure;

    /**
     * @var string
     */
    private $errorCodePrefix;

    /**
     * @param int $minLength
     * @param int $maxLength
     * @param callable|string $measure The function to use to measure the string's length.
     *                        Use 'strlen' for byte length and 'mb_strlen' for character length.
     *                        A callable can be used to provide an alternative measure.
     * @param string $errorCodePrefix
     */
    public function __construct( $minLength, $maxLength, $measure = 'strlen', $errorCodePrefix = '' ) {
        Assert::parameterType( 'integer', $minLength, '$minLength' );
        Assert::parameterType( 'integer', $maxLength, '$maxLength' );
        $this->minLength = $minLength;
        $this->maxLength = $maxLength;

        Assert::parameterType( 'callable', $measure, '$measure' );
        $this->measure = $measure;

        Assert::parameterType( 'string', $errorCodePrefix, '$errorCodePrefix' );
        $this->errorCodePrefix = $errorCodePrefix;
    }

    /**
     * @see ValueValidator::validate()
     *
     * @param string $value The value to validate
     *
     * @return Result
     */
    public function validate( $value ) {
        // Possible messages:
        // wikibase-validator-too-short, wikibase-validator-too-long,
        // wikibase-validator-label-too-short, wikibase-validator-label-too-long,
        // wikibase-validator-description-too-short, wikibase-validator-description-too-long,
        // wikibase-validator-alias-too-short, wikibase-validator-alias-too-long

        $length = call_user_func( $this->measure, $value );

        if ( $length < $this->minLength ) {
            // XXX: having to provide an array is quite inconvenient
            return Result::newError( [
                Error::newError(
                    'Too short, minimum length is ' . $this->minLength,
                    null,
                    $this->errorCodePrefix . 'too-short',
                    [ $this->minLength, $value ]
                ),
            ] );
        }

        if ( $length > $this->maxLength ) {
            return Result::newError( [
                Error::newError(
                    'Too long, maximum length is ' . $this->maxLength,
                    null,
                    $this->errorCodePrefix . 'too-long',
                    [ $this->maxLength, $this->truncateValue( $value ) ]
                ),
            ] );
        }

        return Result::newSuccess();
    }

    /**
     * @see ValueValidator::setOptions()
     *
     * @param array $options
     *
     * @codeCoverageIgnore
     */
    public function setOptions( array $options ) {
        // Do nothing. This method shouldn't even be in the interface.
    }

    /**
     * Truncates the value to the max length, if the value is larger than some maximum length.
     * To be used only for informative purposes (such as error messages) when the value is
     * already known to be longer than the maximum specified in the constructor.
     *
     * @param string $value
     * @param int $truncateAt The length after which to truncate.
     * Note that this is unrelated to the max length we validate against.
     *
     * @return string
     */
    private function truncateValue( $value, $truncateAt = 32 ) {
        $length = call_user_func( $this->measure, $value );

        if ( $length > $truncateAt ) {
            $value = substr( $value, 0, max( 1, $truncateAt - 3 ) ) . '...';
        }

        return $value;
    }

}