Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 7 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
"description": "Ibexa DXP and Open Source core. Provides the Content Repository, its APIs, and the application's Symfony framework integration.",
"homepage": "https://ibexa.co",
"license": "(GPL-2.0-only or proprietary)",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/ibexa/doctrine-migrations.git"
}
],
"suggest": {
"php-64bit": "For support of more than 30 languages, a 64bit php installation on all involved prod/dev machines is required"
},
Expand Down Expand Up @@ -39,6 +45,7 @@
"symfony/validator": "^5.3.0",
"symfony/var-dumper": "^5.3.0",
"ibexa/doctrine-schema": "~4.6.0@dev",
"ibexa/doctrine-migrations": "dev-feat/doctrine-migrations",
"symfony-cmf/routing": "^2.3",
"nelmio/cors-bundle": "^2.0",
"pagerfanta/pagerfanta": "^2.1",
Expand Down
72 changes: 0 additions & 72 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5550,84 +5550,12 @@ parameters:
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Call to method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:checkParameters\(\) on a separate line has no effect\.$#'
identifier: method.resultUnused
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:__construct\(\) has parameter \$installers with no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:cacheClear\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:checkCreateDatabase\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:checkParameters\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:checkPermissions\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:configure\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:executeCommand\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:getInstaller\(\) has parameter \$type with no type specified\.$#'
identifier: missingType.parameter
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:getInstaller\(\) should return Ibexa\\Bundle\\RepositoryInstaller\\Installer\\Installer but returns false\.$#'
identifier: return.type
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\InstallPlatformCommand\:\:indexData\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Strict comparison using \=\=\= between bool and 1 will always evaluate to false\.$#'
identifier: identical.alwaysFalse
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Unreachable statement \- code above always terminates\.$#'
identifier: deadCode.unreachable
count: 1
path: src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php

-
message: '#^Method Ibexa\\Bundle\\RepositoryInstaller\\Command\\ValidatePasswordHashesCommand\:\:configure\(\) has no return type specified\.$#'
identifier: missingType.return
Expand Down
39 changes: 39 additions & 0 deletions src/bundle/Core/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public function getConfigTreeBuilder()
$this->addUrlWildcardsSection($rootNode);
$this->addOrmSection($rootNode);
$this->addUITranslationsSection($rootNode);
$this->addInstallerSection($rootNode);

// Delegate SiteAccess config to configuration parsers
$this->mainSiteAccessConfigParser->addSemanticConfig($this->generateScopeBaseNode($rootNode));
Expand Down Expand Up @@ -563,6 +564,44 @@ private function addUITranslationsSection($rootNode): ArrayNodeDefinition
->end()
->end();
}

/**
* Defines configuration for the "ibexa:install" installer.
*
* The configuration is available at:
* <code>
* ibexa:
* installer:
* schema_builder_event:
* enabled: true
* </code>
*
* @param \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition $rootNode
*/
private function addInstallerSection(ArrayNodeDefinition $rootNode): ArrayNodeDefinition
{
return $rootNode
->children()
->arrayNode('installer')
->children()
->arrayNode('schema_builder_event')
->info('Configuration of the legacy, event-driven database schema building mechanism used by the "ibexa:install" command')
->children()
->booleanNode('enabled')
->defaultTrue()
->info(
'Whether "ibexa:install" dispatches Ibexa\Contracts\DoctrineSchema\Event\SchemaBuilderEvent ' .
'to let packages contribute their database schema via an event subscriber, as opposed to ' .
'the schema being installed from static SQL migrations. ' .
'Disable once all installed packages have migrated away from the event-driven mechanism.'
)
->end()
->end()
->end()
->end()
->end()
->end();
}
}

class_alias(Configuration::class, 'eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration');
12 changes: 12 additions & 0 deletions src/bundle/Core/DependencyInjection/IbexaCoreExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ public function load(array $configs, ContainerBuilder $container)
$this->registerUrlWildcardsConfiguration($config, $container);
$this->registerOrmConfiguration($config, $container);
$this->registerUITranslationsConfiguration($config, $container);
$this->registerInstallerConfiguration($config, $container);

// Routing
$this->handleRouting($config, $container, $loader);
Expand Down Expand Up @@ -331,6 +332,17 @@ private function registerUITranslationsConfiguration(array $config, ContainerBui
$container->setParameter('ibexa.ui.translations.enabled', $config['ui']['translations']['enabled'] ?? false);
}

/**
* @param array<string, mixed> $config
*/
private function registerInstallerConfiguration(array $config, ContainerBuilder $container): void
{
$container->setParameter(
'ibexa.installer.schema_builder_event.enabled',
$config['installer']['schema_builder_event']['enabled'] ?? true
);
}

/**
* Handle routing parameters.
*
Expand Down
85 changes: 30 additions & 55 deletions src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Doctrine\DBAL\Connection;
use Ibexa\Bundle\Core\ApiLoader\RepositoryConfigurationProvider;
use Ibexa\Bundle\Core\Command\BackwardCompatibleCommand;
use Ibexa\Bundle\RepositoryInstaller\Installer\Installer;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -17,28 +18,25 @@
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;

final class InstallPlatformCommand extends Command implements BackwardCompatibleCommand
{
/** @var \Doctrine\DBAL\Connection */
private $connection;
protected static $defaultName = 'ibexa:install';

/** @var \Symfony\Component\Console\Output\OutputInterface */
private $output;
private Connection $connection;

/** @var \Psr\Cache\CacheItemPoolInterface */
private $cachePool;
private OutputInterface $output;

/** @var string */
private $environment;
private CacheItemPoolInterface $cachePool;

/** @var \Ibexa\Bundle\RepositoryInstaller\Installer\Installer[] */
private $installers = [];
private string $environment;

/** @var \Ibexa\Bundle\Core\ApiLoader\RepositoryConfigurationProvider */
private $repositoryConfigurationProvider;
private ServiceLocator $installers;

private RepositoryConfigurationProvider $repositoryConfigurationProvider;

public const EXIT_GENERAL_DATABASE_ERROR = 4;
public const EXIT_PARAMETERS_NOT_FOUND = 5;
Expand All @@ -47,7 +45,7 @@ final class InstallPlatformCommand extends Command implements BackwardCompatible

public function __construct(
Connection $connection,
array $installers,
ServiceLocator $installers,
CacheItemPoolInterface $cachePool,
string $environment,
RepositoryConfigurationProvider $repositoryConfigurationProvider
Expand All @@ -60,14 +58,13 @@ public function __construct(
parent::__construct();
}

protected function configure()
protected function configure(): void
{
$this->setName('ibexa:install');
$this->setAliases($this->getDeprecatedAliases());
$this->addArgument(
'type',
InputArgument::OPTIONAL,
'The type of install. Available options: ' . implode(', ', array_keys($this->installers)),
'The type of install. Available options: ' . implode(', ', array_keys($this->installers->getProvidedServices())),
'ibexa-oss'
);
$this->addOption(
Expand All @@ -82,43 +79,35 @@ protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->output = $output;
$this->checkPermissions();
$this->checkParameters();
$this->checkCreateDatabase($output);

$schemaManager = $this->connection->getSchemaManager();
if (!empty($schemaManager->listTables())) {
$io = new SymfonyStyle($input, $output);
if (!$io->confirm('Running this command will delete data in all Ibexa generated tables. Continue?', )) {
return 0;
return self::SUCCESS;
}
}

$type = $input->getArgument('type');
$siteaccess = $input->getOption('siteaccess');
$installer = $this->getInstaller($type);
if ($installer === false) {
$output->writeln(
"Unknown install type '$type', available options in currently installed Ibexa package: " .
implode(', ', array_keys($this->installers))
);
exit(self::EXIT_UNKNOWN_INSTALL_TYPE);
}
$installer = $this->getInstaller($type, $output);

$installer->setOutput($output);

$installer->importSchema();
$installer->importData();
$installer->importBinaries();
$this->cacheClear($output);
$this->cacheClear();

if (!$input->getOption('skip-indexing')) {
$this->indexData($output, $siteaccess);
}

return 0;
return self::SUCCESS;
}

private function checkPermissions()
private function checkPermissions(): void
{
// @todo should take var-dir etc. from composer config or fallback to flex directory scheme
if (!is_writable('public') && !is_writable('public/var')) {
Expand All @@ -127,18 +116,7 @@ private function checkPermissions()
}
}

private function checkParameters()
{
// @todo doesn't make sense to check for parameters.yml in sf4 and flex
return;
$parametersFile = 'app/config/parameters.yml';
if (!is_file($parametersFile)) {
$this->output->writeln("Required configuration file '$parametersFile' not found");
exit(self::EXIT_PARAMETERS_NOT_FOUND);
}
}

private function checkCreateDatabase(OutputInterface $output)
private function checkCreateDatabase(OutputInterface $output): void
{
$output->writeln(
sprintf(
Expand Down Expand Up @@ -167,10 +145,8 @@ private function checkCreateDatabase(OutputInterface $output)

/**
* Clear all content related cache (persistence cache).
*
* @param \Symfony\Component\Console\Output\OutputInterface $output
*/
private function cacheClear(OutputInterface $output)
private function cacheClear(): void
{
$this->cachePool->clear();
}
Expand All @@ -183,11 +159,8 @@ private function cacheClear(OutputInterface $output)
* This is done after cache clearing to make sure no cached data from before sql import is used.
*
* IMPORTANT: This is done using a command because config has change, so container and all services are different.
*
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @param string|null $siteaccess
*/
private function indexData(OutputInterface $output, $siteaccess = null)
private function indexData(OutputInterface $output, ?string $siteaccess = null): void
{
$output->writeln(
sprintf('Search engine re-indexing, executing command ibexa:reindex')
Expand All @@ -202,17 +175,19 @@ private function indexData(OutputInterface $output, $siteaccess = null)
}

/**
* @param $type
*
* @return \Ibexa\Bundle\RepositoryInstaller\Installer\Installer
*/
private function getInstaller($type)
private function getInstaller(string $type, OutputInterface $output): Installer
{
if (!isset($this->installers[$type])) {
return false;
if (!$this->installers->has($type)) {
$output->writeln(
"Unknown install type '$type', available options in currently installed Ibexa package: " .
implode(', ', array_keys($this->installers->getProvidedServices()))
);
exit(self::EXIT_UNKNOWN_INSTALL_TYPE);
}

return $this->installers[$type];
return $this->installers->get($type);
}

/**
Expand All @@ -227,7 +202,7 @@ private function getInstaller($type)
* Escape any user provided arguments, like: 'assets:install '.escapeshellarg($webDir)
* @param int $timeout
*/
private function executeCommand(OutputInterface $output, $cmd, $timeout = 300)
private function executeCommand(OutputInterface $output, $cmd, $timeout = 300): void
{
$phpFinder = new PhpExecutableFinder();
if (!$phpPath = $phpFinder->find(false)) {
Expand Down
Loading
Loading