Commit 72dd0fdb authored by Oliver Bartsch's avatar Oliver Bartsch Committed by Thomas Löffler
Browse files

Add different use-cases, tests and extend command for skip option

parent fd4ebcdf
......@@ -19,6 +19,7 @@ namespace T3o\TerFe2\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use T3o\TerFe2\Utility\VersionUtility;
......@@ -32,33 +33,56 @@ class AddCompatibleTypo3Versions extends Command
{
protected function configure(): void
{
$this->setDescription('One-time-migration. Adds tx_terfe2_domain_model_version.compatible_typo3_versions from dependencies data.');
$this
->setDescription('One-time-migration. Adds tx_terfe2_domain_model_version.compatible_typo3_versions from dependencies data.')
->addOption(
'skipNonEmptyFields',
null,
InputOption::VALUE_OPTIONAL,
'If command is used a second time, skip already migrated fields.',
false
);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->section('Updating field \'compatible_typo3_versions\' of all \'tx_terfe2_domain_model_version\' rows now');
$skipNonEmptyFields = (bool)$input->getOption('skipNonEmptyFields');
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
$queryBuilder = $connectionPool->getQueryBuilderForTable('tx_terfe2_domain_model_version');
$io->section('Updating field \'compatible_typo3_versions\' of all \'tx_terfe2_domain_model_version\' rows now');
$queryBuilder->getRestrictions()->removeAll();
$statement = $queryBuilder
$queryBuilder
->select('uid', 'dependencies')
->from('tx_terfe2_domain_model_version')
->execute();
->from('tx_terfe2_domain_model_version');
if ($skipNonEmptyFields) {
$io->writeln('<info>Rows with non empty fields are skipped.</info>');
$queryBuilder->where(
$queryBuilder->expr()->isNull('compatible_typo3_versions')
);
}
$result = $queryBuilder->execute();
$itemsProcessed = 0;
while ($row = $statement->fetchAssociative()) {
while ($row = $result->fetchAssociative()) {
// @todo Once https://gitlab.typo3.org/t3o/ter/-/merge_requests/600 is merged,
// @todo we need to json_encode the dependencies instead of unserialize
$compatibleTypo3Versions = VersionUtility::getCompatibleTypo3Versions(
(array)(unserialize((string)($row['dependencies'] ?? ''), ['allowed_classes' => false]) ?: [])
);
// @todo we need to json_encode the dependencies instead of unserialize.
$dependencies = (array)(unserialize((string)($row['dependencies'] ?? ''), ['allowed_classes' => false]) ?: []);
if ($dependencies === []) {
continue;
}
$compatibleTypo3Versions = VersionUtility::getCompatibleTypo3Versions($dependencies);
if ($compatibleTypo3Versions === '') {
continue;
}
GeneralUtility::makeInstance(ConnectionPool::class)
$connectionPool
->getConnectionForTable('tx_terfe2_domain_model_version')
->update(
'tx_terfe2_domain_model_version',
......
......@@ -14,6 +14,9 @@ namespace T3o\TerFe2\Utility;
* The TYPO3 project - inspiring people to share!
*/
use T3o\TerFe2\Service\LTSVersionService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Utilities to manage versions
*/
......@@ -70,16 +73,111 @@ class VersionUtility
foreach ($dependencies as $relation) {
if ((string)($relation['kind'] ?? '') !== 'depends'
|| (string)($relation['extensionKey'] ?? '') !== 'typo3'
|| !in_array((string)($relation['extensionKey'] ?? ''), ['typo3', 'cms'], true)
) {
continue;
}
foreach (explode('-', (string)($relation['versionRange'] ?? '')) as $version) {
$parts = explode('.', $version);
$compatibleTypo3Versions[] = array_shift($parts);
$versionRange = (string)($relation['versionRange'] ?? '');
// Assume all LTS versions are supported
if ($versionRange === '*') {
$compatibleTypo3Versions = self::getAllLtsVersionAsMajorNumber();
continue;
}
// Extract all supported versions form minimal and maximal
if (strpos($versionRange, '-') !== false) {
[$min, $max] = explode('-', $versionRange);
if ($min === null || $min === '0' || $min === '0.0.0') {
// Skip if minimal version is not valid
continue;
}
$min = self::getMajorVersion($min);
if ($min <= 0 || $max === null) {
// Skip if major version could not be extracted or maximal version is not valid
continue;
}
if ($max === '0' || $max === '0.0.0') {
// Assume that all LTS versions between the minimal and the latest are compatible.
$compatibleTypo3Versions = self::getVersionRange($min);
// Also break the foreach as all information was gathered.
break;
}
$max = self::getMajorVersion($max);
if ($max <= 0) {
// Only add minimal since maximal could not be extracted
$compatibleTypo3Versions[] = $min;
continue;
}
// Add all major versions between min and max
$compatibleTypo3Versions = self::getVersionRange($min, $max);
// Also break the foreach as all information was gathered.
break;
}
// Assume only the minimal version is supported
if (strpos($versionRange, '.') !== false) {
$major = self::getMajorVersion($versionRange);
if ($major > 0) {
$compatibleTypo3Versions[] = $major;
}
}
}
return implode(',', array_unique($compatibleTypo3Versions));
}
/**
* Generates an array of LTS versions with only their major number
*
* @return array
*/
protected static function getAllLtsVersionAsMajorNumber(): array
{
$ltsVersions = GeneralUtility::makeInstance(LTSVersionService::class)->getAllLTSVersions();
asort($ltsVersions, SORT_NUMERIC);
foreach ($ltsVersions as &$ltsVersion) {
$ltsVersion = self::getMajorVersion(self::convertIntegerToVersionNumber($ltsVersion));
}
return $ltsVersions;
}
/**
* Generate range for min and max by removing invalid version numbers
*
* @param int $min
* @param null|int $max
* @return array
*/
protected static function getVersionRange(int $min, int $max = null): array
{
$allLtsVersions = self::getAllLtsVersionAsMajorNumber();
$max = (int)($max ?? end($allLtsVersions) ?: 0);
if ($max <= 0) {
return [];
}
$range = range($min, $max);
foreach ($range as $key => $version) {
if (!in_array($version, $allLtsVersions, true)) {
unset($range[$key]);
}
}
return $range;
}
/**
* Extract the major version from version string
*
* @param string $versionString
* @return int
*/
protected static function getMajorVersion(string $versionString): int
{
$parts = explode('.', $versionString) ?: [];
return (int)array_shift($parts);
}
}
<?php
declare(strict_types = 1);
namespace T3o\TerFe2\Tests\Unit\Utility;
/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
class VersionUtilityTest extends \Nimut\TestingFramework\TestCase\UnitTestCase
{
/**
* @param array $dependencies
* @param string $versionList
*
* @test
* @dataProvider getCompatibleTypo3VersionsDataProvider
*/
public function getCompatibleTypo3VersionsTest(array $dependencies, string $versionList): void
{
self::assertSame(
$versionList,
\T3o\TerFe2\Utility\VersionUtility::getCompatibleTypo3Versions($dependencies)
);
}
/**
* @return \Generator
*/
public function getCompatibleTypo3VersionsDataProvider(): \Generator
{
yield 'No range given' => [
[
[
'kind' => 'depends',
'extensionKey' => 'typo3'
]
],
''
];
yield 'Invalid range given' => [
[
[
'kind' => 'depends',
'extensionKey' => 'typo3',
'versionRange' => '0'
]
],
''
];
yield 'CMS wildcard' => [
[
[
'kind' => 'depends',
'extensionKey' => 'cms',
'versionRange' => '*'
]
],
'4,6,7,8,9,10'
];
yield 'Only minimal given' => [
[
[
'kind' => 'depends',
'extensionKey' => 'typo3',
'versionRange' => '10.4.99'
]
],
'10'
];
yield 'Only maximal given' => [
[
[
'kind' => 'depends',
'extensionKey' => 'typo3',
'versionRange' => '0-10.4.99'
]
],
''
];
yield 'Minimal with wildcard' => [
[
[
'kind' => 'depends',
'extensionKey' => 'typo3',
'versionRange' => '8.6.0-0'
]
],
'8,9,10'
];
yield 'Minimal with empty maximal' => [
[
[
'kind' => 'depends',
'extensionKey' => 'typo3',
'versionRange' => '8.6.0-'
]
],
'8'
];
yield 'Version "5" is omit on range' => [
[
[
'kind' => 'depends',
'extensionKey' => 'typo3',
'versionRange' => '4.5.0-0'
]
],
'4,6,7,8,9,10'
];
yield 'Two LTS versions' => [
[
[
'kind' => 'depends',
'extensionKey' => 'typo3',
'versionRange' => '9.5.0-10.4.99'
]
],
'9,10'
];
yield 'Range of versions' => [
[
[
'kind' => 'depends',
'extensionKey' => 'typo3',
'versionRange' => '4.5.0-10.4.10'
]
],
'4,6,7,8,9,10'
];
yield 'Both cms and TYPO3 defined' => [
[
[
'kind' => 'depends',
'extensionKey' => 'cms',
'versionRange' => '*'
],
[
'kind' => 'depends',
'extensionKey' => 'typo3',
'versionRange' => '9.5.0-10.4.10'
]
],
'9,10'
];
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment