Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
SchemaMigrator
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 3
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 convertDataToVersion
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 doConvertDataToVersion
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace MediaWiki\Extension\CommunityConfiguration\Schema;
4
5use LogicException;
6use MediaWiki\Extension\CommunityConfiguration\Provider\IConfigurationProvider;
7use MediaWiki\Extension\CommunityConfiguration\Validation\IValidator;
8use StatusValue;
9use stdClass;
10
11/**
12 * Generic class to convert data to a specified target version (by repetatively constructing an
13 * ISchemaConverter).
14 */
15class SchemaMigrator {
16
17    private SchemaConverterFactory $schemaConverterFactory;
18
19    public function __construct( SchemaConverterFactory $schemaConverterFactory ) {
20        $this->schemaConverterFactory = $schemaConverterFactory;
21    }
22
23    /**
24     * Convert data from a provider to a particular target version
25     *
26     * @param IConfigurationProvider $provider
27     * @param string $targetVersion
28     * @throws LogicException when not convertable due to missing version data/support
29     * @return StatusValue
30     */
31    public function convertDataToVersion(
32        IConfigurationProvider $provider,
33        string $targetVersion
34    ): StatusValue {
35        $status = $provider->loadValidConfiguration();
36        if ( !$status->isOK() ) {
37            return $status;
38        }
39
40        $currentVersion = $provider->getStore()->getVersion();
41        if ( $currentVersion === null ) {
42            throw new LogicException( __METHOD__ . ' lacks version data' );
43        }
44
45        return StatusValue::newGood( $this->doConvertDataToVersion(
46            $provider->getValidator(),
47            $status->getValue(),
48            $currentVersion,
49            $targetVersion
50        ) );
51    }
52
53    /**
54     * Recursively convert data to the target version
55     *
56     * @param IValidator $validator
57     * @param stdClass $data
58     * @param string $currentVersion
59     * @param string $targetVersion
60     * @return stdClass
61     */
62    private function doConvertDataToVersion(
63        IValidator $validator,
64        stdClass $data,
65        string $currentVersion,
66        string $targetVersion
67    ): stdClass {
68        $versionComparsion = version_compare( $currentVersion, $targetVersion );
69        if ( $versionComparsion === 0 ) {
70            // Nothing to convert
71            return $data;
72        }
73
74        $schemaBuilder = $validator->getSchemaBuilder();
75        $currentSchemaReader = $schemaBuilder->getVersionManager()->getVersionForSchema( $currentVersion );
76        if ( $versionComparsion < 0 ) {
77            // current version is lower than $targetVersion, we need to upgrade
78            $nextVersion = $currentSchemaReader->getNextVersion();
79        } else {
80            // current version is lower than $targetVersion, we need to downgrade
81            $nextVersion = $currentSchemaReader->getPreviousVersion();
82        }
83
84        if ( $nextVersion === null ) {
85            throw new LogicException(
86                $currentSchemaReader->getSchemaId()
87                . ' does not have a next/previous version linked.'
88            );
89        }
90
91        $converter = $this->schemaConverterFactory->getConverterFromVersion( $schemaBuilder, $nextVersion );
92        if ( $versionComparsion < 0 ) {
93            // current version is lower than $targetVersion, we need to upgrade
94            $newData = $converter->upgradeFromOlder( $data );
95        } else {
96            // current version is lower than $targetVersion, we need to downgrade
97            $newData = $converter->downgradeFromNewer( $data );
98        }
99
100        return $this->doConvertDataToVersion(
101            $validator,
102            $newData,
103            $nextVersion,
104            $targetVersion
105        );
106    }
107}