wikimedia/mediawiki-extensions-Wikibase

View on GitHub
lib/includes/Modules/DataTypesModule.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace Wikibase\Lib\Modules;

// phpcs:disable MediaWiki.Classes.FullQualifiedClassName -- T308814
use MediaWiki\ResourceLoader as RL;
use MediaWiki\ResourceLoader\ResourceLoader;
use RuntimeException;
use Wikibase\Lib\DataType;
use Wikibase\Lib\DataTypeFactory;

/**
 * Resource loader module for defining resources that will create a MW config var in JavaScript
 * holding information about all data types known to a given DataTypeFactory.
 *
 * The resource definition requires the following additional keys:
 * - (string) datatypesconfigvarname: Name of the "mw.config.get( '...' )" config variable.
 * - (Function|DataTypeFactory) datatypefactory: Provider for the data types. Can be a callback
 *   returning a DataTypeFactory instance.
 *
 * @license GPL-2.0-or-later
 * @author Daniel Werner < daniel.a.r.werner@gmail.com >
 */
class DataTypesModule extends RL\Module {

    /**
     * @var DataType[]
     */
    protected $dataTypes;

    /**
     * @var string
     */
    protected $dataTypesConfigVarName;

    /**
     * @var DataTypeFactory
     */
    protected $dataTypeFactory;

    /**
     * @since 0.1
     *
     * @param array $resourceDefinition
     */
    public function __construct( array $resourceDefinition ) {
        $this->dataTypesConfigVarName =
            static::extractDataTypesConfigVarNameFromResourceDefinition( $resourceDefinition );

        $this->dataTypeFactory =
            static::extractDataTypeFactoryFromResourceDefinition( $resourceDefinition );

        $dataTypeFactory = $this->getDataTypeFactory();
        $this->dataTypes = $dataTypeFactory->getTypes();
    }

    /**
     * @since 0.1
     * @param array $resourceDefinition
     * @return string
     */
    public static function extractDataTypesConfigVarNameFromResourceDefinition(
        array $resourceDefinition
    ) {
        $dataTypesConfigVarName = $resourceDefinition['datatypesconfigvarname'] ?? null;

        if ( !is_string( $dataTypesConfigVarName ) || $dataTypesConfigVarName === '' ) {
            throw new RuntimeException(
                'The "datatypesconfigvarname" value of the resource definition' .
                ' has to be a non-empty string value'
            );
        }

        return $dataTypesConfigVarName;
    }

    /**
     * @since 0.1
     * @param array $resourceDefinition
     * @return DataTypeFactory
     */
    public static function extractDataTypeFactoryFromResourceDefinition(
        array $resourceDefinition
    ) {
        $dataTypeFactory = $resourceDefinition['datatypefactory'] ?? null;

        if ( is_callable( $dataTypeFactory ) ) {
            $dataTypeFactory = call_user_func( $dataTypeFactory );
        }

        if ( !( $dataTypeFactory instanceof DataTypeFactory ) ) {
            throw new RuntimeException(
                'The "datatypefactory" value of the resource definition has' .
                ' to be an instance of DataTypeFactory or a callback returning one'
            );
        }

        return $dataTypeFactory;
    }

    /**
     * Returns the name of the config var key under which the data type definition will be available
     * in JavaScript using "mw.config.get( '...' )"
     *
     * @since 0.1
     *
     * @return string
     */
    public function getConfigVarName() {
        return $this->dataTypesConfigVarName;
    }

    /**
     * Returns the data types factory providing the data type information.
     *
     * @since 0.1
     *
     * @return DataTypeFactory
     */
    public function getDataTypeFactory() {
        return $this->dataTypeFactory;
    }

    /**
     * Used to propagate available data type ids to JavaScript.
     * Data type ids will be available in 'wbDataTypeIds' config var.
     * @see RL\Module::getScript
     *
     * @since 0.1
     *
     * @param RL\Context $context
     *
     * @return string
     */
    public function getScript( RL\Context $context ) {
        $configVarName = $this->getConfigVarName();
        $typesJson = [];

        foreach ( $this->dataTypes as $dataType ) {
            $typesJson[ $dataType->getId() ] = $dataType->toArray();
        }

        return ResourceLoader::makeConfigSetScript( [ $configVarName => $typesJson ] );
    }

    /**
     * @see RL\Module::getDefinitionSummary
     *
     * @param RL\Context $context
     *
     * @return array
     */
    public function getDefinitionSummary( RL\Context $context ) {
        $summary = parent::getDefinitionSummary( $context );

        $summary[] = [
            'dataHash' => sha1( json_encode( array_keys( $this->dataTypes ) ) ),
        ];

        return $summary;
    }

}