wikimedia/mediawiki-extensions-Wikibase

View on GitHub
repo/rest-api/src/Application/Validation/DescriptionsSyntaxValidator.php

Summary

Maintainability
D
1 day
Test Coverage
<?php declare( strict_types=1 );

namespace Wikibase\Repo\RestApi\Application\Validation;

use Wikibase\Repo\RestApi\Application\Serialization\DescriptionsDeserializer;
use Wikibase\Repo\RestApi\Application\Serialization\Exceptions\EmptyDescriptionException;
use Wikibase\Repo\RestApi\Application\Serialization\Exceptions\InvalidDescriptionException;

/**
 * @license GPL-2.0-or-later
 */
class DescriptionsSyntaxValidator {
    public const CODE_DESCRIPTIONS_NOT_ASSOCIATIVE = 'descriptions-syntax-validator-code-descriptions-not-associative';
    public const CODE_EMPTY_DESCRIPTION = 'descriptions-syntax-validator-code-description-empty';
    public const CODE_INVALID_DESCRIPTION_TYPE = 'descriptions-syntax-validator-code-invalid-description-type';

    public const CONTEXT_FIELD = 'descriptions-syntax-validator-context-field';
    public const CONTEXT_VALUE = 'descriptions-syntax-validator-context-value';
    public const CONTEXT_DESCRIPTION = 'descriptions-syntax-validator-context-description';
    public const CONTEXT_LANGUAGE = 'descriptions-syntax-validator-context-language';

    private DescriptionsDeserializer $deserializer;
    private DescriptionLanguageCodeValidator $languageCodeValidator;
    private PartiallyValidatedDescriptions $deserializedDescriptions;

    public function __construct( DescriptionsDeserializer $deserializer, DescriptionLanguageCodeValidator $languageCodeValidator ) {
        $this->deserializer = $deserializer;
        $this->languageCodeValidator = $languageCodeValidator;
    }

    public function validate( array $serialization, string $basePath = '' ): ?ValidationError {
        if ( count( $serialization ) && array_is_list( $serialization ) ) {
            return new ValidationError( self::CODE_DESCRIPTIONS_NOT_ASSOCIATIVE, [ self::CONTEXT_VALUE => $serialization ] );
        }

        return $this->validateLanguageCodes( array_keys( $serialization ), $basePath )
            ?: $this->validateSerialization( $serialization );
    }

    private function validateLanguageCodes( array $languageCodes, string $basePath ): ?ValidationError {
        foreach ( $languageCodes as $languageCode ) {
            $languageValidationError = $this->languageCodeValidator->validate( (string)$languageCode, $basePath );
            if ( $languageValidationError ) {
                return $languageValidationError;
            }
        }

        return null;
    }

    private function validateSerialization( array $serialization ): ?ValidationError {
        try {
            $this->deserializedDescriptions = new PartiallyValidatedDescriptions( $this->deserializer->deserialize( $serialization ) );
        } catch ( EmptyDescriptionException $e ) {
            return new ValidationError(
                self::CODE_EMPTY_DESCRIPTION,
                [ self::CONTEXT_LANGUAGE => $e->getField() ]
            );
        } catch ( InvalidDescriptionException $e ) {
            return new ValidationError(
                self::CODE_INVALID_DESCRIPTION_TYPE,
                [ self::CONTEXT_LANGUAGE => $e->getField(), self::CONTEXT_DESCRIPTION => $e->getValue() ]
            );
        }

        return null;
    }

    public function getPartiallyValidatedDescriptions(): PartiallyValidatedDescriptions {
        return $this->deserializedDescriptions;
    }
}