Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix upgrade handling of extension install wizards #614

Merged
merged 1 commit into from
Dec 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 28 additions & 40 deletions Classes/Install/Upgrade/UpgradeHandling.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Helhum\Typo3Console\Service\Configuration\ConfigurationService;
use TYPO3\CMS\Core\Package\PackageManager;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Install\Updates\AbstractDownloadExtensionUpdate;
use TYPO3\CMS\Install\Updates\DatabaseCharsetUpdate;

/**
Expand Down Expand Up @@ -87,12 +88,7 @@ class UpgradeHandling
*
* @var array
*/
private static $wizardsWithArguments = [
'DbalAndAdodbExtractionUpdate' => [['name' => 'install', 'type' => 'bool', 'default' => '0']],
'compatibility6Extension' => [['name' => 'install', 'type' => 'bool', 'default' => '0']],
'compatibility7Extension' => [['name' => 'install', 'type' => 'bool', 'default' => '0']],
'rtehtmlareaExtension' => [['name' => 'install', 'type' => 'bool', 'default' => '0']],
];
private static $extensionWizardArguments = [['name' => 'install', 'type' => 'bool', 'default' => '0']];

/**
* @param UpgradeWizardFactory|null $factory
Expand Down Expand Up @@ -140,33 +136,25 @@ public function executeWizard($identifier, array $rawArguments = [], $force = fa

/**
* @param array $arguments
* @param ConsoleOutput|null $consoleOutput
* @param ConsoleOutput $consoleOutput
* @param array &$messages
* @return array
*/
public function executeAll(array $arguments, ConsoleOutput $consoleOutput = null, array &$messages = [])
public function executeAll(array $arguments, ConsoleOutput $consoleOutput, array &$messages = [])
{
if ($consoleOutput) {
$consoleOutput->progressStart(rand(6, 9));
$consoleOutput->progressAdvance();
}
$consoleOutput->progressStart(rand(6, 9));
$consoleOutput->progressAdvance();

$wizards = $this->executeInSubProcess('listWizards', [], $messages);

if ($consoleOutput) {
$consoleOutput->progressStart(count($wizards['scheduled']) + 2);
}
$consoleOutput->progressStart(count($wizards['scheduled']) + 2);

$results = [];
if (!empty($wizards['scheduled'])) {
foreach ($wizards['scheduled'] as $identifier => $_) {
if ($consoleOutput) {
$consoleOutput->progressAdvance();
}
$shortIdentifier = str_replace('TYPO3\\CMS\\Install\\Updates\\', '', $identifier);
if ($consoleOutput && isset(self::$wizardsWithArguments[$shortIdentifier])
) {
foreach (self::$wizardsWithArguments[$shortIdentifier] as $argumentDefinition) {
foreach ($wizards['scheduled'] as $shortIdentifier => $wizardOptions) {
$consoleOutput->progressAdvance();
if (is_subclass_of($wizardOptions['className'], AbstractDownloadExtensionUpdate::class)) {
foreach (self::$extensionWizardArguments as $argumentDefinition) {
$argumentName = $argumentDefinition['name'];
$argumentDefault = $argumentDefinition['default'];
if ($this->wizardHasArgument($shortIdentifier, $argumentName, $arguments)) {
Expand All @@ -175,10 +163,14 @@ public function executeAll(array $arguments, ConsoleOutput $consoleOutput = null
// In composer mode, skip all install extension wizards!
if (ConsoleBootstrap::usesComposerClassLoading()) {
$arguments[] = sprintf('%s[%s]=%s', $shortIdentifier, $argumentName, $argumentDefault);
$messages[] = '<warning>Wizard "' . $shortIdentifier . '" was not executed but only marked as executed due to composer mode.</warning>';
// We currently only handle one argument type
} elseif ($argumentDefinition['type'] === 'bool') {
$wizard = $this->factory->create($shortIdentifier);
$wizard = $this->factory->create($wizardOptions['className']);
$consoleOutput->outputLine(PHP_EOL . PHP_EOL . '<info>' . $wizard->getTitle() . '</info>' . PHP_EOL);
$consoleOutput->outputLine(implode(PHP_EOL, array_filter(array_map('trim', explode(chr(10), html_entity_decode(strip_tags($wizard->getUserInput(''))))))));
if (is_callable([$wizard, 'getUserInput'])) {
$consoleOutput->outputLine(implode(PHP_EOL, array_filter(array_map('trim', explode(chr(10), html_entity_decode(strip_tags($wizard->getUserInput(''))))))));
}
$consoleOutput->outputLine();
$arguments[] = sprintf(
'%s[%s]=%s',
Expand All @@ -189,19 +181,17 @@ public function executeAll(array $arguments, ConsoleOutput $consoleOutput = null
}
}
}
$results[$identifier] = $this->executeInSubProcess('executeWizard', [$identifier, $arguments], $messages);
$wizardMessages = [];
$results[$shortIdentifier] = $this->executeInSubProcess('executeWizard', [$shortIdentifier, $arguments], $wizardMessages);
$messages = array_merge($messages, $wizardMessages);
}
}

if ($consoleOutput) {
$consoleOutput->progressAdvance();
}
$consoleOutput->progressAdvance();

$this->commandDispatcher->executeCommand('database:updateschema');

if ($consoleOutput) {
$consoleOutput->progressFinish();
}
$consoleOutput->progressFinish();

return $results;
}
Expand All @@ -214,14 +204,12 @@ public function executeAll(array $arguments, ConsoleOutput $consoleOutput = null
*/
private function wizardHasArgument($identifier, $argumentName, array $arguments)
{
if (isset(self::$wizardsWithArguments[$identifier])) {
foreach ($arguments as $argument) {
if (strpos($argument, sprintf('%s[%s]', $identifier, $argumentName)) !== false) {
return true;
}
if (strpos($argument, '[') === false && strpos($argument, $argumentName) !== false) {
return true;
}
foreach ($arguments as $argument) {
if (strpos($argument, sprintf('%s[%s]', $identifier, $argumentName)) !== false) {
return true;
}
if (strpos($argument, '[') === false && strpos($argument, $argumentName) !== false) {
return true;
}
}
return false;
Expand Down
31 changes: 27 additions & 4 deletions Classes/Install/Upgrade/UpgradeWizardFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,40 @@ public function __construct(
* @return AbstractUpdate Newly instantiated upgrade wizard
*/
public function create($identifier)
{
/** @var AbstractUpdate $upgradeWizard */
$upgradeWizard = $this->objectManager->get($this->getClassNameFromIdentifier($identifier));
$upgradeWizard->setIdentifier($identifier);

return $upgradeWizard;
}

/**
* @param string $identifier
* @throws \RuntimeException
* @return string
*/
public function getClassNameFromIdentifier($identifier)
{
if (empty($className = $this->wizardRegistry[$identifier])
&& empty($className = $this->wizardRegistry['TYPO3\\CMS\\Install\\Updates\\' . $identifier])
&& !class_exists($className = $identifier)
) {
throw new \RuntimeException(sprintf('Upgrade wizard "%s" not found', $identifier), 1491914890);
}
/** @var AbstractUpdate $upgradeWizard */
$upgradeWizard = $this->objectManager->get($className);
$upgradeWizard->setIdentifier($identifier);
return $className;
}

return $upgradeWizard;
public function getShortIdentifier($classNameOrIdentifier)
{
if (!empty($className = $this->wizardRegistry[$classNameOrIdentifier])
|| !empty($className = $this->wizardRegistry['TYPO3\\CMS\\Install\\Updates\\' . $classNameOrIdentifier])
) {
$classNameOrIdentifier = $className;
}
if ($identifier = array_search($classNameOrIdentifier, $this->wizardRegistry, true)) {
return str_replace('TYPO3\\CMS\\Install\\Updates\\', '', $identifier);
}
throw new \RuntimeException(sprintf('Upgrade wizard "%s" not found', $classNameOrIdentifier), 1508495588);
}
}
8 changes: 5 additions & 3 deletions Classes/Install/Upgrade/UpgradeWizardList.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,19 @@ public function listWizards($includeDone = false)
$availableUpgradeWizards = [];
foreach ($this->wizardRegistry as $identifier => $className) {
$updateObject = $this->factory->create($identifier);
$availableUpgradeWizards[$identifier] = [
$shortIdentifier = $this->factory->getShortIdentifier($identifier);
$availableUpgradeWizards[$shortIdentifier] = [
'className' => $className,
'title' => $updateObject->getTitle(),
'done' => false,
];
$explanation = '';
if ($this->registry->get('installUpdate', $className, false)
|| !$updateObject->checkForUpdate($explanation)
) {
$availableUpgradeWizards[$identifier]['done'] = true;
$availableUpgradeWizards[$shortIdentifier]['done'] = true;
}
$availableUpgradeWizards[$identifier]['explanation'] = html_entity_decode(strip_tags($explanation));
$availableUpgradeWizards[$shortIdentifier]['explanation'] = html_entity_decode(strip_tags($explanation));
}
$this->listCache = $availableUpgradeWizards;
}
Expand Down
4 changes: 2 additions & 2 deletions Classes/Install/Upgrade/UpgradeWizardListRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ public function render(array $upgradeWizardList, ConsoleOutput $output, $verbose
$tableRows = [];
foreach ($upgradeWizardList as $identifier => $info) {
$row = [
str_replace('TYPO3\\CMS\\Install\\Updates\\', '', $identifier),
$identifier,
wordwrap($info['title'], 40),
];
if ($verbose) {
$row = [
str_replace('TYPO3\\CMS\\Install\\Updates\\', '', $identifier),
$identifier,
wordwrap($info['explanation'], 40),
];
}
Expand Down
9 changes: 4 additions & 5 deletions Classes/Install/Upgrade/UpgradeWizardResultRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,15 @@ class UpgradeWizardResultRenderer
/**
* Renders a table for upgrade wizards
*
* @param UpgradeWizardResult[] $upgradeWizardResult
* @param UpgradeWizardResult[] $upgradeWizardResults
* @param ConsoleOutput $output
*/
public function render(array $upgradeWizardResult, ConsoleOutput $output)
public function render(array $upgradeWizardResults, ConsoleOutput $output)
{
if (empty($upgradeWizardResult)) {
if (empty($upgradeWizardResults)) {
return;
}
foreach ($upgradeWizardResult as $identifier => $result) {
$identifier = str_replace('TYPO3\\CMS\\Install\\Updates\\', '', $identifier);
foreach ($upgradeWizardResults as $identifier => $result) {
$output->outputLine();
if (!$result->hasPerformed()) {
$output->outputLine('<warning>Skipped upgrade wizard "%s" because it was not scheduled for execution or marked as done.</warning>', [$identifier]);
Expand Down
57 changes: 57 additions & 0 deletions Tests/Unit/Install/Upgrade/UpgradeWizardFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,61 @@ public function throwsExceptionForInvalidIdentifier()
$subject = new UpgradeWizardFactory($objectManagerProphecy->reveal(), $registryFixture);
$subject->create('foo');
}

/**
* @expectedException \RuntimeException
* @expectedExceptionCode 1508495588
* @test
*/
public function throwsExceptionForInvalidIdentifierWhenFetchingShortIdentifier()
{
$registryFixture = [
'TYPO3\\CMS\\Install\\Updates\\FooUpgrade' => 'TYPO3\\CMS\\Install\\Updates\\FooUpgrade',
];
$objectManagerProphecy = $this->prophesize(ObjectManager::class);

$subject = new UpgradeWizardFactory($objectManagerProphecy->reveal(), $registryFixture);
$subject->getShortIdentifier('foo');
}

public function shortIdentifierCanBeDeterminedDataProvider()
{
return [
'Core class name' => [
'TYPO3\\CMS\\Install\\Updates\\FooUpgrade',
'FooUpgrade',
],
'Core short identifier' => [
'FooUpgrade',
'FooUpgrade',
],
'Other class name' => [
'Helhum\\Install\\Updates\\BarUpgrade',
'bar',
],
'Other class name not shortened' => [
'Helhum\\Install\\Updates\\FooUpgrade',
'Helhum\\Install\\Updates\\FooUpgrade',
],
];
}

/**
* @test
* @dataProvider shortIdentifierCanBeDeterminedDataProvider
* @param string $identifierOrClassName
* @param string $expectedIdentifier
*/
public function shortIdentifierCanBeDetermined($identifierOrClassName, $expectedIdentifier)
{
$registryFixture = [
'TYPO3\\CMS\\Install\\Updates\\FooUpgrade' => 'TYPO3\\CMS\\Install\\Updates\\FooUpgrade',
'bar' => 'Helhum\\Install\\Updates\\BarUpgrade',
'Helhum\\Install\\Updates\\FooUpgrade' => 'Helhum\\Install\\Updates\\FooUpgrade',
];
$objectManagerProphecy = $this->prophesize(ObjectManager::class);

$subject = new UpgradeWizardFactory($objectManagerProphecy->reveal(), $registryFixture);
$this->assertSame($expectedIdentifier, $subject->getShortIdentifier($identifierOrClassName));
}
}