diff --git a/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php b/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php
index b1452e9..41e1bbf 100644
--- a/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php
+++ b/src/app/CliTools/Console/Command/Mysql/AbstractCommand.php
@@ -21,6 +21,7 @@
* along with this program. If not, see .
*/
+use CliTools\Console\Command\Traits\ClisyncConfigTrait;
use CliTools\Database\DatabaseConnection;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -28,6 +29,7 @@
abstract class AbstractCommand extends \CliTools\Console\Command\AbstractCommand
{
+ use ClisyncConfigTrait;
/**
* Configure command
@@ -85,6 +87,9 @@ protected function initialize(InputInterface $input, OutputInterface $output)
{
parent::initialize($input, $output);
+ // Try to read credentials from clisync.yml if present
+ $this->initDatabaseConfigurationFromClisync();
+
$dsn = null;
$user = null;
$password = null;
diff --git a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php
index 89272c6..00b3740 100644
--- a/src/app/CliTools/Console/Command/Sync/AbstractCommand.php
+++ b/src/app/CliTools/Console/Command/Sync/AbstractCommand.php
@@ -21,6 +21,7 @@
* along with this program. If not, see .
*/
+use CliTools\Console\Command\Traits\ClisyncConfigTrait;
use CliTools\Database\DatabaseConnection;
use CliTools\Reader\ConfigReader;
use CliTools\Shell\CommandBuilder\CommandBuilder;
@@ -29,7 +30,6 @@
use CliTools\Shell\CommandBuilder\RemoteCommandBuilder;
use CliTools\Shell\CommandBuilder\SelfCommandBuilder;
use CliTools\Utility\ConsoleUtility;
-use CliTools\Utility\DockerUtility;
use CliTools\Utility\FilterUtility;
use CliTools\Utility\PhpUtility;
use CliTools\Utility\UnixUtility;
@@ -43,6 +43,7 @@
abstract class AbstractCommand extends \CliTools\Console\Command\AbstractDockerCommand
{
+ use ClisyncConfigTrait;
const CONFIG_FILE = 'clisync.yml';
const GLOBAL_KEY = 'GLOBAL';
@@ -155,64 +156,8 @@ protected function initializeConfiguration()
// Read configuration
$this->readConfiguration();
- $this->initDatabaseConfiguration();
- $this->initDockerContainer();
- }
-
- /**
- * Init database configuration (for local one)
- */
- protected function initDatabaseConfiguration()
- {
- $hostname = DatabaseConnection::getDbHostname();
- $port = DatabaseConnection::getDbPort();
- $username = DatabaseConnection::getDbUsername();
- $password = DatabaseConnection::getDbPassword();
-
- if ($this->config->exists('LOCAL.mysql.hostname')) {
- $hostname = $this->config->get('LOCAL.mysql.hostname');
- }
-
- if ($this->config->exists('LOCAL.mysql.port')) {
- $port = $this->config->get('LOCAL.mysql.port');
- }
-
- if ($this->config->exists('LOCAL.mysql.username')) {
- $username = $this->config->get('LOCAL.mysql.username');
- }
-
- if ($this->config->exists('LOCAL.mysql.password')) {
- $password = $this->config->get('LOCAL.mysql.password');
- }
-
- $dsn = 'mysql:host=' . urlencode($hostname) . ';port=' . (int)$port;
-
- DatabaseConnection::setDsn($dsn, $username, $password);
- }
-
- /**
- * Init docker container setting
- */
- protected function initDockerContainer()
- {
- $useDockerMysql = false;
-
- if ($this->config->exists('LOCAL.mysql.docker')) {
- $this->setLocalDockerContainer(\CliTools\Console\Command\AbstractDockerCommand::DOCKER_ALIAS_MYSQL , $this->config->get('LOCAL.mysql.docker'));
- $useDockerMysql = true;
- } elseif ($this->config->exists('LOCAL.mysql.docker-compose')) {
- $this->setLocalDockerContainer(\CliTools\Console\Command\AbstractDockerCommand::DOCKER_ALIAS_MYSQL , $this->config->get('LOCAL.mysql.docker-compose'), true);
- $useDockerMysql = true;
- }
-
- if ($useDockerMysql) {
- $container = $this->getLocalDockerContainer(\CliTools\Console\Command\AbstractDockerCommand::DOCKER_ALIAS_MYSQL);
- $password = DockerUtility::getDockerContainerEnv($container, 'MYSQL_ROOT_PASSWORD');
- if (empty($password)) {
- $password = DockerUtility::getDockerContainerEnv($container, 'MARIADB_ROOT_PASSWORD');
- }
- DatabaseConnection::setDsn('mysql:host=localhost', 'root', $password);
- }
+ // Init database and Docker configuration using trait (pass already loaded config)
+ $this->initDatabaseConfigurationFromClisync($this->config);
}
/**
diff --git a/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php b/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php
index 1bc0d83..ccb81d1 100644
--- a/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php
+++ b/src/app/CliTools/Console/Command/TYPO3/BeUserCommand.php
@@ -58,7 +58,7 @@ protected function configure()
->addArgument(
'hash',
InputArgument::OPTIONAL,
- 'Choose the hashing algorithm for saving the password: md5, md5_salted, bcrypt, argon2i, argon2id'
+ 'Choose the hashing algorithm for saving the password: bcrypt, argon2i, argon2id'
);
}
@@ -207,10 +207,11 @@ protected function setTypo3UserForDatabase($database, $username, $password)
$beUserId = reset($beUserId);
// Insert or update user in TYPO3 database
+ $uidValue = $beUserId ? $this->mysqlQuote($beUserId) : 'NULL';
$query = 'INSERT INTO ' . DatabaseConnection::sanitizeSqlDatabase($database) . '.be_users
(uid, tstamp, crdate, realName, username, password, TSconfig, admin, disable, starttime, endtime)
VALUES(
- ' . $this->mysqlQuote($beUserId) . ',
+ ' . $uidValue . ',
UNIX_TIMESTAMP(),
UNIX_TIMESTAMP(),
' . $this->mysqlQuote('DEVELOPMENT') . ',
diff --git a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php b/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php
deleted file mode 100644
index 380a2ec..0000000
--- a/src/app/CliTools/Console/Command/TYPO3/ClearCacheCommand.php
+++ /dev/null
@@ -1,102 +0,0 @@
-
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-use CliTools\Shell\CommandBuilder\CommandBuilder;
-use CliTools\Utility\Typo3Utility;
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-
-class ClearCacheCommand extends \CliTools\Console\Command\AbstractCommand
-{
-
- /**
- * Configure command
- */
- protected function configure()
- {
- $this->setName('typo3:clearcache')
- ->setDescription(
- 'Clear cache on all (or one specific) TYPO3 instances'
- )
- ->addArgument(
- 'path',
- InputArgument::OPTIONAL,
- 'Path to TYPO3 instance'
- );
- }
-
- /**
- * Execute command
- *
- * @param InputInterface $input Input instance
- * @param OutputInterface $output Output instance
- *
- * @return int|null|void
- */
- public function execute(InputInterface $input, OutputInterface $output): int
- {
- // ####################
- // Init
- // ####################
- $basePath = $this->getApplication()
- ->getConfigValue('config', 'www_base_path', '/var/www/');
- $maxDepth = 3;
-
- $output->writeln('
Clear TYPO3 cache
');
-
- if ($input->getArgument('path')) {
- $basePath = $input->getArgument('path');
- }
-
- // ####################
- // Find and loop through TYPO3 instances
- // ####################
- foreach (Typo3Utility::getTypo3InstancePathList($basePath, $maxDepth) as $dirPath) {
-
- // Check if coreapi is installed
- if (!is_dir($dirPath . '/typo3conf/ext/coreapi/')) {
- $output->writeln('EXT:coreapi is missing on ' . $dirPath . ', skipping
');
- continue;
- }
-
- $params = array(
- $dirPath . '/typo3/cli_dispatch.phpsh',
- 'coreapi',
- 'cache:clearallcaches'
- );
-
- $output->writeln('Running clearcache command on ' . $dirPath . '
');
- try {
-
- $command = new CommandBuilder('php');
- $command->setArgumentList($params)
- ->executeInteractive();
- } catch (\Exception $e) {
- $output->writeln(' Failed with exception: ' . $e->getMessage() . '');
- }
- }
-
- return 0;
- }
-}
diff --git a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php b/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php
deleted file mode 100644
index 7ed1b9f..0000000
--- a/src/app/CliTools/Console/Command/TYPO3/DomainCommand.php
+++ /dev/null
@@ -1,296 +0,0 @@
-
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Output\OutputInterface;
-
-class DomainCommand extends \CliTools\Console\Command\Mysql\AbstractCommand
-{
-
- /**
- * Configure command
- */
- protected function configure()
- {
- parent::configure();
-
- $this->setName('typo3:domain')
- ->setDescription('Add common development domains to database')
- ->addArgument(
- 'db',
- InputArgument::OPTIONAL,
- 'Database name'
- )
- ->addOption(
- 'baseurl',
- null,
- InputOption::VALUE_NONE,
- 'Also set config.baseURL setting'
- )
- ->addOption(
- 'list',
- null,
- InputOption::VALUE_NONE,
- 'List only databases'
- )
- ->addOption(
- 'remove',
- null,
- InputOption::VALUE_REQUIRED,
- 'Remove domain (with wildcard support)'
- )
- ->addOption(
- 'duplicate',
- null,
- InputOption::VALUE_REQUIRED,
- 'Add duplication domains (will duplicate all domains in system, eg. for vagrant share)'
- )
- ->addOption(
- 'suffix',
- null,
- InputOption::VALUE_REQUIRED,
- 'Domain suffix'
- );
- }
-
- /**
- * Execute command
- *
- * @param InputInterface $input Input instance
- * @param OutputInterface $output Output instance
- *
- * @return int|null|void
- */
- public function execute(InputInterface $input, OutputInterface $output): int
- {
- // ##################
- // Init
- // ##################
- $dbName = $input->getArgument('db');
-
- $output->writeln('Updating TYPO3 domain entries
');
-
- // ##############
- // Loop through databases
- // ##############
-
- if (empty($dbName)) {
- // ##############
- // All databases
- // ##############
- $databaseList = $this->mysqlDatabaseList();
-
- foreach ($databaseList as $dbName) {
- // Check if database is TYPO3 instance
- $query = 'SELECT COUNT(*) as count
- FROM information_schema.tables
- WHERE table_schema = ' . $this->mysqlQuote($dbName) . '
- AND table_name = \'sys_domain\'';
- $isTypo3Database = $this->execSqlCommand($query);
- $isTypo3Database = reset($isTypo3Database);
-
- if ($isTypo3Database) {
- $this->runTaskForDomain($dbName);
- }
- }
- } else {
- // ##############
- // One databases
- // ##############
- $this->runTaskForDomain($dbName);
- }
-
- return 0;
- }
-
- /**
- * Run tasks for one domain
- */
- protected function runTaskForDomain($dbName)
- {
- if ($this->input->getOption('list')) {
- // Show domain list (and skip all other tasks)
- $this->showDomainList($dbName);
- } else {
- // Remove domains (eg. for cleanup)
- if ($this->input->getOption('remove')) {
- $this->removeDomains($dbName, $this->input->getOption('remove'));
- }
-
- // Set development domains
- $this->manipulateDomains($dbName);
-
- // Add sharing domains
- if ($this->input->getOption('baseurl')) {
- $this->updateBaseUrlConfig($dbName);
- }
-
- // Add sharing domains
- if ($this->input->getOption('duplicate')) {
- $this->addDuplicateDomains($dbName, $this->input->getOption('duplicate'));
- }
-
- // Show domain list
- $this->showDomainList($dbName);
- }
- }
-
- /**
- * Remove domains
- */
- protected function removeDomains($dbName, $pattern)
- {
- $pattern = str_replace('*', '%', $pattern);
-
- $query = 'DELETE FROM ' . $dbName . '.sys_domain WHERE domainName LIKE %s';
- $query = sprintf($query, $this->mysqlQuote($pattern));
- $this->execSqlCommand($query);
- }
-
- /**
- * Update baseURL config
- */
- protected function updateBaseUrlConfig($dbName)
- {
- $query = 'SELECT st.uid as template_id,
- st.config as template_config,
- (SELECT sd.domainName
- FROM sys_domain sd
- WHERE sd.pid = st.pid
- AND sd.hidden = 0
- ORDER BY sd.forced DESC,
- sd.sorting ASC
- LIMIT 1) as domain_name
- FROM ' . $dbName . '.sys_template st
- WHERE st.root = 1
- AND st.deleted = 0
- HAVING domain_name IS NOT NULL';
- $templateIdList = $this->execSqlQuery($query);
-
- foreach ($templateIdList as $row) {
- $templateId = $row['template_id'];
- $domainName = $row['domain_name'];
- $templateConf = $row['template_config'];
-
- // Remove old baseURL entries (no duplciates)
- $templateConf = preg_replace('/^config.baseURL = .*$/m', '', $templateConf);
- $templateConf = trim($templateConf);
-
- // Add new baseURL
- $templateConf .= "\n" . 'config.baseURL = http://' . $domainName . '/';
-
- $query = 'UPDATE ' . $dbName . '.sys_template SET config = %s WHERE uid = %s';
- $query = sprintf($query, $this->mysqlQuote($templateConf), (int)$templateId);
- $this->execSqlCommand($query);
- }
- }
-
- /**
- * Add share domains (eg. for vagrantshare)
- *
- * @param string $suffix Domain suffix
- */
- protected function addDuplicateDomains($dbName, $suffix)
- {
- $devDomain = '.' . $this->getApplication()
- ->getConfigValue('config', 'domain_dev');
-
- $query = 'SELECT * FROM ' . $dbName . '.sys_domain';
- $domainList = $this->execSqlQuery($query);
-
- foreach ($domainList as $domain) {
- unset($domain['uid']);
-
- $domainName = $domain['domainName'];
-
- // remove development suffix
- $domainName = preg_replace('/' . preg_quote($devDomain) . '$/', '', $domainName);
-
- // add share domain
- $domainName .= '.' . ltrim($suffix, '.');
-
- $domain['domainName'] = $domainName;
-
- // create insert
- $table = 'sys_domain';
- $fieldList = array_keys($domain);
-
- $valueList = array();
- foreach ($domain as $value) {
- $valueList[] = $this->mysqlQuote($value);
- }
-
- $query = 'INSERT INTO %s (%s) VALUES (%s)';
- $query = sprintf($query, $table, implode(',', $fieldList), implode(',', $valueList));
- $this->execSqlCommand($query);
- }
- }
-
- /**
- * Show list of domains
- *
- * @param string $dbName Domain name
- */
- protected function showDomainList($dbName)
- {
- $query = 'SELECT domainName
- FROM ' . $dbName . '.sys_domain
- WHERE hidden = 0
- ORDER BY domainName ASC';
- $domainList = $this->execSqlQuery($query);
-
- $this->output->writeln('Domain list of "' . $dbName . '":
');
-
- foreach ($domainList as $domain) {
- $this->output->writeln(' ' . reset($domain) . '
');
- }
- $this->output->writeln('');
- }
-
- /**
- * Set development domains for TYPO3 database
- *
- * @return void
- */
- protected function manipulateDomains($dbName)
- {
- $devDomain = '.' . $this->getApplication()
- ->getConfigValue('config', 'domain_dev');
-
- if ($this->input->getOption('suffix')) {
- $devDomain = $this->input->getOption('suffix');
- }
-
- $domainLength = strlen($devDomain);
-
- // ##################
- // Fix domains
- // ##################
- $query = 'UPDATE ' . $dbName . '.sys_domain
- SET domainName = CONCAT(domainName, ' . $this->mysqlQuote($devDomain) . ')
- WHERE RIGHT(domainName, ' . $domainLength . ') <> ' . $this->mysqlQuote($devDomain);
- $this->execSqlCommand($query);
- }
-}
diff --git a/src/app/CliTools/Console/Command/TYPO3/ListCommand.php b/src/app/CliTools/Console/Command/TYPO3/ListCommand.php
index 50a0ec9..2ec2953 100644
--- a/src/app/CliTools/Console/Command/TYPO3/ListCommand.php
+++ b/src/app/CliTools/Console/Command/TYPO3/ListCommand.php
@@ -63,48 +63,22 @@ public function execute(InputInterface $input, OutputInterface $output): int
$basePath = Typo3Utility::guessBestTypo3BasePath($basePath, $input, 'path');
- $versionFileList = array(
- // 6.x version
- '/typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php' => '/define\(\'TYPO3_version\',[\s]*\'([^\']+)\'\)/i',
- // 4.x version
- '/t3lib/config_default.php' => '/\$TYPO_VERSION[\s]*=[\s]*\'([^\']+)\'/i',
- );
-
// ####################
// Find and loop through TYPO3 instances
// ####################
$typo3List = array();
foreach (Typo3Utility::getTypo3InstancePathList($basePath, $maxDepth) as $dirPath) {
- $typo3Version = null;
- $typo3Path = $dirPath;
-
- // Detect version (dirty way...)
- foreach ($versionFileList as $versionFile => $versionRegExp) {
- $versionFile = $dirPath . $versionFile;
-
- if (file_exists($versionFile)) {
- $tmp = file_get_contents($versionFile);
- if (preg_match($versionRegExp, $tmp, $matches)) {
- $typo3Version = $matches[1];
- break;
- }
- }
- }
+ $typo3Version = $this->detectTypo3Version($dirPath);
- if (strpos($typo3Version, '6') === 0) {
- // TYPO3 6.x
+ if ($typo3Version !== null) {
$typo3Version = '' . $typo3Version . '';
- } elseif (!empty($typo3Version)) {
- // TYPO3 4.x
- $typo3Version = '' . $typo3Version . '';
} else {
- // Unknown
$typo3Version = 'unknown';
}
$typo3List[] = array(
- $typo3Path,
+ $dirPath,
$typo3Version,
);
}
@@ -119,4 +93,46 @@ public function execute(InputInterface $input, OutputInterface $output): int
return 0;
}
+
+ /**
+ * Detect TYPO3 version from installation path
+ *
+ * @param string $dirPath Path to TYPO3 installation
+ * @return string|null
+ */
+ protected function detectTypo3Version(string $dirPath): ?string
+ {
+ // Try composer.json in vendor (Composer mode)
+ $composerFile = $dirPath . '/vendor/typo3/cms-core/composer.json';
+ if (file_exists($composerFile)) {
+ $composerData = json_decode(file_get_contents($composerFile), true);
+ if (isset($composerData['version'])) {
+ return $composerData['version'];
+ }
+ }
+
+ // Try composer.lock in project root
+ $composerLock = $dirPath . '/composer.lock';
+ if (file_exists($composerLock)) {
+ $lockData = json_decode(file_get_contents($composerLock), true);
+ if (isset($lockData['packages'])) {
+ foreach ($lockData['packages'] as $package) {
+ if ($package['name'] === 'typo3/cms-core') {
+ return $package['version'];
+ }
+ }
+ }
+ }
+
+ // Try ext_emconf.php (classic mode)
+ $extEmconfFile = $dirPath . '/typo3/sysext/core/ext_emconf.php';
+ if (file_exists($extEmconfFile)) {
+ $content = file_get_contents($extEmconfFile);
+ if (preg_match('/[\'"]version[\'"]\s*=>\s*[\'"]([^\'"]+)[\'"]/', $content, $matches)) {
+ return $matches[1];
+ }
+ }
+
+ return null;
+ }
}
diff --git a/src/app/CliTools/Console/Command/Traits/ClisyncConfigTrait.php b/src/app/CliTools/Console/Command/Traits/ClisyncConfigTrait.php
new file mode 100644
index 0000000..00de846
--- /dev/null
+++ b/src/app/CliTools/Console/Command/Traits/ClisyncConfigTrait.php
@@ -0,0 +1,148 @@
+
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+use CliTools\Console\Command\AbstractDockerCommand;
+use CliTools\Database\DatabaseConnection;
+use CliTools\Reader\ConfigReader;
+use CliTools\Utility\DockerUtility;
+use CliTools\Utility\PhpUtility;
+use CliTools\Utility\UnixUtility;
+use Symfony\Component\Yaml\Yaml;
+
+trait ClisyncConfigTrait
+{
+ /**
+ * Init database configuration from clisync.yml if present
+ *
+ * @param ConfigReader|null $config Optional config reader (if already loaded)
+ */
+ protected function initDatabaseConfigurationFromClisync(?ConfigReader $config = null)
+ {
+ if ($config === null) {
+ $config = $this->loadClisyncConfig();
+ if ($config === null) {
+ return;
+ }
+ }
+
+ // Handle Docker container configuration first (takes precedence)
+ if ($this->initDockerContainerFromConfig($config)) {
+ return;
+ }
+
+ // Apply standard MySQL credentials
+ $this->applyMysqlCredentialsFromConfig($config);
+ }
+
+ /**
+ * Load clisync.yml configuration
+ *
+ * @return ConfigReader|null
+ */
+ protected function loadClisyncConfig(): ?ConfigReader
+ {
+ $confFileList = array(
+ 'clisync.yml',
+ '.clisync.yml',
+ );
+
+ $confFilePath = UnixUtility::findFileInDirectortyTree($confFileList);
+ if (empty($confFilePath) || !file_exists($confFilePath)) {
+ return null;
+ }
+
+ $conf = Yaml::parse(PhpUtility::fileGetContents($confFilePath));
+ if (empty($conf)) {
+ return null;
+ }
+
+ $config = new ConfigReader();
+ $config->setData($conf);
+
+ return $config;
+ }
+
+ /**
+ * Apply MySQL credentials from config to DatabaseConnection
+ *
+ * @param ConfigReader $config
+ */
+ protected function applyMysqlCredentialsFromConfig(ConfigReader $config)
+ {
+ $hostname = DatabaseConnection::getDbHostname();
+ $port = DatabaseConnection::getDbPort();
+ $username = DatabaseConnection::getDbUsername();
+ $password = DatabaseConnection::getDbPassword();
+
+ if ($config->exists('LOCAL.mysql.hostname')) {
+ $hostname = $config->get('LOCAL.mysql.hostname');
+ }
+
+ if ($config->exists('LOCAL.mysql.port')) {
+ $port = $config->get('LOCAL.mysql.port');
+ }
+
+ if ($config->exists('LOCAL.mysql.username')) {
+ $username = $config->get('LOCAL.mysql.username');
+ }
+
+ if ($config->exists('LOCAL.mysql.password')) {
+ $password = $config->get('LOCAL.mysql.password');
+ }
+
+ $dsn = 'mysql:host=' . urlencode($hostname) . ';port=' . (int)$port;
+
+ DatabaseConnection::setDsn($dsn, $username, $password);
+ }
+
+ /**
+ * Init Docker container from config
+ *
+ * @param ConfigReader $config
+ * @return bool True if Docker was configured
+ */
+ protected function initDockerContainerFromConfig(ConfigReader $config): bool
+ {
+ $useDockerMysql = false;
+
+ if ($config->exists('LOCAL.mysql.docker')) {
+ $this->setLocalDockerContainer(AbstractDockerCommand::DOCKER_ALIAS_MYSQL, $config->get('LOCAL.mysql.docker'));
+ $useDockerMysql = true;
+ } elseif ($config->exists('LOCAL.mysql.docker-compose')) {
+ $this->setLocalDockerContainer(AbstractDockerCommand::DOCKER_ALIAS_MYSQL, $config->get('LOCAL.mysql.docker-compose'), true);
+ $useDockerMysql = true;
+ }
+
+ if ($useDockerMysql) {
+ $container = $this->getLocalDockerContainer(AbstractDockerCommand::DOCKER_ALIAS_MYSQL);
+ $password = DockerUtility::getDockerContainerEnv($container, 'MYSQL_ROOT_PASSWORD');
+ if (empty($password)) {
+ $password = DockerUtility::getDockerContainerEnv($container, 'MARIADB_ROOT_PASSWORD');
+ }
+ DatabaseConnection::setDsn('mysql:host=localhost', 'root', $password);
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/src/app/CliTools/Iterator/Filter/Typo3RecursiveDirectoryFilter.php b/src/app/CliTools/Iterator/Filter/Typo3RecursiveDirectoryFilter.php
index 938444a..04c569f 100644
--- a/src/app/CliTools/Iterator/Filter/Typo3RecursiveDirectoryFilter.php
+++ b/src/app/CliTools/Iterator/Filter/Typo3RecursiveDirectoryFilter.php
@@ -52,7 +52,7 @@ class Typo3RecursiveDirectoryFilter extends \CliTools\Iterator\Filter\RecursiveD
*
* @return bool
*/
- public function accept()
+ public function accept(): bool
{
if (!parent::accept()) {
return false;
diff --git a/src/app/CliTools/Utility/Typo3Utility.php b/src/app/CliTools/Utility/Typo3Utility.php
index e6ae507..8423a65 100644
--- a/src/app/CliTools/Utility/Typo3Utility.php
+++ b/src/app/CliTools/Utility/Typo3Utility.php
@@ -27,11 +27,9 @@
class Typo3Utility
{
- const PASSWORD_TYPE_MD5 = 'md5';
- const PASSWORD_TYPE_MD5_SALTED = 'md5_salted';
- const PASSWORD_TYPE_BCRYPT = 'bcrypt';
- const PASSWORD_TYPE_ARGON2I = 'argon2i';
- const PASSWORD_TYPE_ARGON2ID = 'argon2id';
+ const PASSWORD_TYPE_BCRYPT = 'bcrypt';
+ const PASSWORD_TYPE_ARGON2I = 'argon2i';
+ const PASSWORD_TYPE_ARGON2ID = 'argon2id';
/**
* Generate TYPO3 password
@@ -39,25 +37,13 @@ class Typo3Utility
* @param string $password Password
* @param ?string $type Type of password (see constants)
*
- * @return null|string
+ * @return array [hash, algorithm_name]
*/
public static function generatePassword($password, ?string $type = null)
{
$ret = null;
switch ($type) {
-
- case self::PASSWORD_TYPE_MD5:
- $ret = md5($password);
- break;
-
- case self::PASSWORD_TYPE_MD5_SALTED:
- // Salted md5
- $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
- $salt = '$1$' . substr(str_shuffle($chars), 0, 6) . '$';
- $ret = crypt($password, $salt);
- break;
-
case self::PASSWORD_TYPE_BCRYPT:
$ret = password_hash($password, PASSWORD_BCRYPT);
break;
@@ -72,8 +58,7 @@ public static function generatePassword($password, ?string $type = null)
default:
$possibleAlgorithms = [];
- # Commented out since TYPO3 9.5 doesn't support argon2id yet
- #defined('PASSWORD_ARGON2ID') && $possibleAlgorithms[PASSWORD_ARGON2ID] = self::PASSWORD_TYPE_ARGON2ID;
+ defined('PASSWORD_ARGON2ID') && $possibleAlgorithms[PASSWORD_ARGON2ID] = self::PASSWORD_TYPE_ARGON2ID;
defined('PASSWORD_ARGON2I') && $possibleAlgorithms[PASSWORD_ARGON2I] = self::PASSWORD_TYPE_ARGON2I;
defined('PASSWORD_BCRYPT') && $possibleAlgorithms[PASSWORD_BCRYPT] = self::PASSWORD_TYPE_BCRYPT;