You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
diff --git a/.drone.yml b/.drone.yml
index d5f2fae702d6..ea8a71e873ae 100644
--- a/.drone.yml+++ b/.drone.yml@@ -217,7 +217,7 @@ steps:
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysql+ - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysql mysqli mysql jos_
- name: phpmax-api-mysql
depends_on:
@@ -226,7 +226,7 @@ steps:
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysqlphpmax+ - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysqlphpmax mysqli mysql phpmax_
# - name: phpnext-api-mysql
# depends_on:
@@ -236,7 +236,7 @@ steps:
# environment:
# JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
# commands:
-# - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysqlphpnext+# - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysqlphpnext mysqli mysql8 phpmax_
- name: phpmin-api-postgres
depends_on:
@@ -245,7 +245,7 @@ steps:
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgres+ - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgres pgsql postgres jos_
- name: phpmax-api-postgres
depends_on:
@@ -254,7 +254,7 @@ steps:
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgresphpmax+ - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgresphpmax pgsql postgres phpmax_
# - name: phpnext-api-postgres
# depends_on:
@@ -264,7 +264,7 @@ steps:
# environment:
# JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
# commands:
-# - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgresphpnext+# - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgresphpnext pgsql postgres
- name: phpmin-system-mysql
depends_on:
@@ -524,6 +524,6 @@ trigger:
---
kind: signature
-hmac: f496f213481b3afcec73da651fc838af21f76950954daac599e665ceb382cc2d+hmac: 35f71c2c3f977f0da835b27f18cea8f07419c3dd14aae4bc8da11fdb624983c5
...
diff --git a/installation/INSTALL b/installation/INSTALL
index 1badcf67b1b9..57bb0fa85889 100644
--- a/installation/INSTALL+++ b/installation/INSTALL@@ -109,20 +109,31 @@ INSTALLATION
and then enter 'exit' or 'quit' to exit MySQL.
-3. WEB INSTALLER+3. INSTALLATION+ The main method of installation is via the web browser. You can start that+ installation by simply pointing your web browser to http://www.example.org+ where the Joomla! web based installer will guide you through the rest of+ the installation.++ An alternative method of installation is from the command line. On the command line of your+ server, in the root folder of Joomla, you can run the following command++ php installation/joomla.php install++ You will be guided through the rest of the installation and ou can get further help by running++ php installation/joomla.php help install-Finally point your web browser to http://www.example.org where the Joomla! web-based installer will guide you through the rest of the installation.
4. CONFIGURE Joomla
-You can now launch your browser and point it to your Joomla! site eg+ You can now launch your browser and point it to your Joomla! site eg- http://www.example.org -> Main Site- http://www.example.org/administrator -> Admin+ http://www.example.org -> Main Site+ http://www.example.org/administrator -> Admin-You can log into Admin using the username and password that you chose-during the web based install.+ You can log into Admin using the username and password that you chose+ during the install.
Joomla! ADMINISTRATION
diff --git a/installation/forms/setup.xml b/installation/forms/setup.xml
index 1903910c5b92..f8a162b43265 100644
--- a/installation/forms/setup.xml+++ b/installation/forms/setup.xml@@ -15,14 +15,6 @@
class="form-control"
required="true"
/>
- <field- name="admin_email"- type="email"- label="INSTL_ADMIN_EMAIL_DESC"- class="form-control"- validate="email"- required="true"- />
<field
name="admin_user"
type="text"
@@ -53,12 +45,20 @@
force="on"
filter="raw"
/>
+ <field+ name="admin_email"+ type="email"+ label="INSTL_ADMIN_EMAIL_DESC"+ class="form-control"+ validate="email"+ required="true"+ />
<field
name="db_type"
type="databaseconnection"
label="INSTL_DATABASE_TYPE_DESC"
class="form-select"
- supported="mysql,mysqli,pgsql,postgresql"+ supported="mysql,mysqli,pgsql"
required="true"
default="mysqli"
filter="string"
diff --git a/installation/includes/cli.php b/installation/includes/cli.php
new file mode 100644
index 000000000000..da809ba19e1f
--- /dev/null+++ b/installation/includes/cli.php@@ -0,0 +1,63 @@+<?php++/**+ * @package Joomla.Installation+ * @subpackage Application+ *+ * @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>+ * @license GNU General Public License version 2 or later; see LICENSE.txt+ */++defined('_JEXEC') or die;++// Define the base path and require the other defines+define('JPATH_BASE', dirname(__DIR__));++require_once __DIR__ . '/defines.php';++// Check for presence of vendor dependencies not included in the git repository+if (!file_exists(JPATH_LIBRARIES . '/vendor/autoload.php') || !is_dir(JPATH_ROOT . '/media/vendor')) {+ echo 'It looks like you are trying to run Joomla! from our git repository.' . PHP_EOL;+ echo 'To do so requires you complete a couple of extra steps first.' . PHP_EOL;+ echo 'Please see https://docs.joomla.org/Special:MyLanguage/J4.x:Setting_Up_Your_Local_Environment for further details.' . PHP_EOL;++ exit;+}++// Get the framework.+require_once __DIR__ . '/framework.php';++// Check if the default log directory can be written to, add a logger for errors to use it+if (is_writable(JPATH_ADMINISTRATOR . '/logs')) {+ \Joomla\CMS\Log\Log::addLogger(+ [+ 'format' => '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}',+ 'text_file' => 'error.php'+ ],+ \Joomla\CMS\Log\Log::ALL,+ ['error']+ );+}++// Register the Installation application+JLoader::registerNamespace('Joomla\\CMS\\Installation', JPATH_INSTALLATION . '/src', false, false);++// Get the dependency injection container+$container = \Joomla\CMS\Factory::getContainer();+$container->registerServiceProvider(new \Joomla\CMS\Installation\Service\Provider\Application());++/*+ * Alias the session service keys to the CLI session service as that is the primary session backend for this application+ *+ * In addition to aliasing "common" service keys, we also create aliases for the PHP classes to ensure autowiring objects+ * is supported. This includes aliases for aliased class names, and the keys for aliased class names should be considered+ * deprecated to be removed when the class name alias is removed as well.+ */+$container->alias('session', 'session.cli')+ ->alias('JSession', 'session.cli')+ ->alias(\Joomla\CMS\Session\Session::class, 'session.cli')+ ->alias(\Joomla\Session\Session::class, 'session.cli')+ ->alias(\Joomla\Session\SessionInterface::class, 'session.cli');++// Instantiate and execute the application+$container->get(\Joomla\CMS\Installation\Application\CliInstallationApplication::class)->execute();diff --git a/installation/joomla.php b/installation/joomla.php
new file mode 100644
index 000000000000..08893f79d0b3
--- /dev/null+++ b/installation/joomla.php@@ -0,0 +1,39 @@+<?php++/**+ * @package Joomla.Installation+ *+ * @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>+ * @license GNU General Public License version 2 or later; see LICENSE.txt+ */++/**+ * NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message+ */++/**+ * Define the application's minimum supported PHP version as a constant so it can be referenced within the application.+ */+define('JOOMLA_MINIMUM_PHP', '7.2.5');++if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<')) {+ echo 'Sorry, your PHP version is not supported.' . PHP_EOL;+ echo 'Your command line php needs to be version ' . JOOMLA_MINIMUM_PHP . ' or newer to run the Joomla! CLI Tools' . PHP_EOL;+ echo 'The version of PHP currently running this code, at the command line, is PHP version ' . PHP_VERSION . '.' . PHP_EOL;+ echo 'Please note, the version of PHP running your commands here, may be different to the version that is used by ';+ echo 'your web server to run the Joomla! Web Application' . PHP_EOL;++ exit;+}++/**+ * Constant that is checked in included files to prevent direct access.+ * define() is used rather than "const" to not error for PHP 5.2 and lower+ */+define('_JEXEC', 1);++// Constant to identify the CLI installation+define('_JCLI_INSTALLATION', 1);++// Run the application - All executable code should be triggered through this file+require_once dirname(__FILE__) . '/includes/cli.php';diff --git a/installation/language/en-GB/joomla.cli.ini b/installation/language/en-GB/joomla.cli.ini
new file mode 100644
index 000000000000..fe7db95f4d9a
--- /dev/null+++ b/installation/language/en-GB/joomla.cli.ini@@ -0,0 +1,35 @@+INSTL_ADMIN_EMAIL_DESC="Enter the email address of the website Super User"+INSTL_ADMIN_EMAIL_DESC_SHORT="Email address of the website's Super User account"+INSTL_ADMIN_PASSWORD_DESC="Set the password for your Super User account"+INSTL_ADMIN_PASSWORD_DESC_SHORT="Password of your Super User account"+INSTL_ADMIN_USERNAME_DESC="Set the username for your Super User account"+INSTL_ADMIN_USERNAME_DESC_SHORT="Username of your Super User account"+INSTL_ADMIN_USER_DESC="Enter the real name of your Super User"+INSTL_ADMIN_USER_DESC_SHORT="Real name of the Super User account"+INSTL_DATABASE_COULD_NOT_CONNECT="%s"+INSTL_DATABASE_ENCRYPTION_CA_LABEL="Path to CA file to verify encryption against"+INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Path to CA file to verify encryption against"+INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Path to the SSL certificate for the database connection. Requires encryption to be set to 2"+INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Path to the SSL certificate for the database connection. Requires encryption to be set to 2"+INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Supported Cipher Suite (optional)"+INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Supported Cipher Suite (optional)"+INSTL_DATABASE_ENCRYPTION_KEY_LABEL="SSL key for the database connection. Requires encryption to be set to 2"+INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="SSL key for the database connection. Requires encryption to be set to 2"+INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Encryption for the database connection. Values: 0=None, 1=One way, 2=Two way"+INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Encryption for the database connection. Values: 0=None, 1=One way, 2=Two way"+INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Verify SSL certificate for database connection. Values: 0=No, 1=Yes. Requires encryption to be set to 1 or 2"+INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="Verify SSL certificate for database connection. Values: 0=No, 1=Yes. Requires encryption to be set to 1 or 2"+INSTL_DATABASE_HOST_DESC="Database host"+INSTL_DATABASE_HOST_DESC_SHORT="Database host"+INSTL_DATABASE_NAME_DESC="Database name"+INSTL_DATABASE_NAME_DESC_SHORT="Database name"+INSTL_DATABASE_PASSWORD_DESC="Database password"+INSTL_DATABASE_PASSWORD_DESC_SHORT="Database password"+INSTL_DATABASE_PREFIX_DESC="Prefix for the database tables"+INSTL_DATABASE_PREFIX_DESC_SHORT="Prefix for the database tables"+INSTL_DATABASE_TYPE_DESC="Database type. Supported: mysql, mysqli, pgsql"+INSTL_DATABASE_TYPE_DESC_SHORT="Database type. Supported by Joomla: mysql (=MySQL (PDO)), mysqli (=MySQLi), pgsql (=PostgreSQL (PDO))"+INSTL_DATABASE_USER_DESC="Database username"+INSTL_DATABASE_USER_DESC_SHORT="Database username"+INSTL_SITE_NAME_DESC="Enter the name of your Joomla site"+INSTL_SITE_NAME_DESC_SHORT="Name of the website"diff --git a/installation/src/Application/CliInstallationApplication.php b/installation/src/Application/CliInstallationApplication.php
new file mode 100644
index 000000000000..872ed10fb8d6
--- /dev/null+++ b/installation/src/Application/CliInstallationApplication.php@@ -0,0 +1,322 @@+<?php++/**+ * @package Joomla.Installation+ * @subpackage Application+ *+ * @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>+ * @license GNU General Public License version 2 or later; see LICENSE.txt+ */++namespace Joomla\CMS\Installation\Application;++use Joomla\Application\Web\WebClient;+use Joomla\CMS\Application\CMSApplicationInterface;+use Joomla\CMS\Application\EventAware;+use Joomla\CMS\Application\ExtensionNamespaceMapper;+use Joomla\CMS\Application\IdentityAware;+use Joomla\CMS\Extension\ExtensionManagerTrait;+use Joomla\CMS\Factory;+use Joomla\CMS\Installation\Console\InstallCommand;+use Joomla\CMS\Language\Language;+use Joomla\CMS\Language\LanguageHelper;+use Joomla\CMS\Language\Text;+use Joomla\CMS\MVC\Factory\MVCFactory;+use Joomla\CMS\Version;+use Joomla\Console\Application;+use Joomla\Database\DatabaseInterface;+use Joomla\DI\Container;+use Joomla\DI\ContainerAwareTrait;+use Joomla\Filesystem\Folder;+use Joomla\Input\Input;+use Joomla\Registry\Registry;+use Joomla\Session\SessionInterface;+use Symfony\Component\Console\Input\InputInterface;+use Symfony\Component\Console\Output\OutputInterface;++/**+ * Joomla! Installation Application class.+ *+ * @since __DEPLOY_VERSION__+ */+final class CliInstallationApplication extends Application implements CMSApplicationInterface+{+ use ExtensionNamespaceMapper;+ use IdentityAware;+ use ContainerAwareTrait;+ use EventAware;+ use ExtensionManagerTrait;++ /**+ * The application input object.+ *+ * @var Input+ * @since __DEPLOY_VERSION__+ */+ public $input;++ /**+ * The application language object.+ *+ * @var Language+ * @since __DEPLOY_VERSION__+ */+ protected $language;++ /**+ * @var MVCFactory+ * @since __DEPLOY_VERSION__+ */+ protected $mvcFactory;++ /**+ * Object to imitate the session object+ *+ * @var Registry+ * @since __DEPLOY_VERSION__+ */+ protected $session;++ /**+ * Class constructor.+ *+ * @param Input|null $input An optional argument to provide dependency injection for the application's input+ * object. If the argument is a JInput object that object will become the+ * application's input object, otherwise a default input object is created.+ * @param Registry|null $config An optional argument to provide dependency injection for the application's+ * config object. If the argument is a Registry object that object will become+ * the application's config object, otherwise a default config object is created.+ * @param WebClient|null $client An optional argument to provide dependency injection for the application's+ * client object. If the argument is a WebClient object that object will become the+ * application's client object, otherwise a default client object is created.+ * @param Container|null $container Dependency injection container.+ *+ * @since __DEPLOY_VERSION__+ */+ public function __construct(+ ?InputInterface $input = null,+ ?OutputInterface $output = null,+ ?Registry $config = null,+ ?Language $language = null+ ) {+ // Register the application name.+ $this->setName('Joomla CLI installation');+ $version = new Version();+ $this->setVersion($version->getShortVersion());++ // Register the client ID.+ $this->clientId = 2;+ $this->language = $language;++ // Run the parent constructor.+ parent::__construct($input, $output, $config);++ // Store the debug value to config based on the JDEBUG flag.+ $this->config->set('debug', JDEBUG);++ \define('JPATH_COMPONENT', JPATH_BASE);+ \define('JPATH_COMPONENT_SITE', JPATH_SITE);+ \define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR);++ // Register the config to Factory.+ Factory::$config = $this->config;+ Factory::$language = $language;+ }++ /**+ * Enqueue a system message.+ *+ * @param string $msg The message to enqueue.+ * @param string $type The message type. Default is message.+ *+ * @return void+ *+ * @since __DEPLOY_VERSION__+ */+ public function enqueueMessage($msg, $type = 'info')+ {+ throw new \Exception($msg);+ }++ /**+ * Retrieve the application configuration object.+ *+ * @return Registry+ *+ * @since __DEPLOY_VERSION__+ */+ public function getConfig()+ {+ return new Registry();+ }++ /**+ * Get the commands which should be registered by default to the application.+ *+ * @return \Joomla\Console\Command\AbstractCommand[]+ *+ * @since __DEPLOY_VERSION__+ */+ protected function getDefaultCommands(): array+ {+ return array_merge(+ parent::getDefaultCommands(),+ [+ new InstallCommand(),+ ]+ );+ }++ /**+ * Method to get the application input object.+ *+ * @return \Joomla\Input\Input+ *+ * @since 4.0.0+ */+ public function getInput(): Input+ {+ return new Input();+ }++ /**+ * Method to get the application language object.+ *+ * @return Language The language object+ *+ * @since __DEPLOY_VERSION__+ */+ public function getLanguage()+ {+ return $this->language;+ }++ /**+ * This is a dummy method, forcing to en-GB on CLI installation+ *+ * @return boolean False on failure, array on success.+ *+ * @since __DEPLOY_VERSION__+ */+ public function getLocalise()+ {+ return false;+ }++ /**+ * Returns the installed language files in the administrative and frontend area.+ *+ * @param DatabaseInterface|null $db Database driver.+ *+ * @return array Array with installed language packs in admin and site area.+ *+ * @since __DEPLOY_VERSION__+ */+ public function getLocaliseAdmin(DatabaseInterface $db = null)+ {+ $langfiles = array();++ // If db connection, fetch them from the database.+ if ($db) {+ foreach (LanguageHelper::getInstalledLanguages() as $clientId => $language) {+ $clientName = $clientId === 0 ? 'site' : 'admin';++ foreach ($language as $languageCode => $lang) {+ $langfiles[$clientName][] = $lang->element;+ }+ }+ } else {+ // Read the folder names in the site and admin area.+ $langfiles['site'] = Folder::folders(LanguageHelper::getLanguagePath(JPATH_SITE));+ $langfiles['admin'] = Folder::folders(LanguageHelper::getLanguagePath(JPATH_ADMINISTRATOR));+ }++ return $langfiles;+ }++ /**+ * Get the system message queue. This is a mock+ * to fullfill the interface requirements and is not functional.+ *+ * @return array The system message queue.+ *+ * @since __DEPLOY_VERSION__+ */+ public function getMessageQueue()+ {+ return [];+ }++ /**+ * Get the MVC factory for the installation application+ *+ * @return MVCFactory MVC Factory of the installation application+ *+ * @since __DEPLOY_VERSION__+ */+ public function getMVCFactory()+ {+ if (!$this->mvcFactory) {+ $this->mvcFactory = new MVCFactory('Joomla\\CMS', $this);+ }++ return $this->mvcFactory;+ }++ /**+ * We need to imitate the session object+ *+ * @return SessionInterface Object imitating the session object+ *+ * @since __DEPLOY_VERSION__+ */+ public function getSession()+ {+ return $this->session;+ }++ /**+ * Sets the session for the application to use, if required.+ *+ * @param SessionInterface $session A session object.+ *+ * @return $this+ *+ * @since __DEPLOY_VERSION__+ */+ public function setSession(SessionInterface $session): self+ {+ $this->session = $session;++ return $this;+ }++ /**+ * Check the client interface by name.+ *+ * @param string $identifier String identifier for the application interface+ *+ * @return boolean True if this application is of the given type client interface.+ *+ * @since __DEPLOY_VERSION__+ */+ public function isClient($identifier)+ {+ return 'cli_installation' === $identifier;+ }++ /**+ * Flag if the application instance is a CLI or web based application.+ *+ * Helper function, you should use the native PHP functions to detect if it is a CLI application.+ *+ * @return boolean+ *+ * @since __DEPLOY_VERSION__+ * @deprecated 5.0 Will be removed without replacements+ */+ public function isCli()+ {+ return $this->isClient('cli_installation');+ }+}diff --git a/installation/src/Console/InstallCommand.php b/installation/src/Console/InstallCommand.php
new file mode 100644
index 000000000000..cf3097d07b2a
--- /dev/null+++ b/installation/src/Console/InstallCommand.php@@ -0,0 +1,390 @@+<?php++/**+ * Joomla! Content Management System+ *+ * @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>+ * @license GNU General Public License version 2 or later; see LICENSE.txt+ */++namespace Joomla\CMS\Installation\Console;++use Joomla\CMS\Factory;+use Joomla\CMS\Form\FormField;+use Joomla\CMS\Form\FormHelper;+use Joomla\CMS\Installation\Model\ChecksModel;+use Joomla\CMS\Installation\Model\CleanupModel;+use Joomla\CMS\Installation\Model\DatabaseModel;+use Joomla\CMS\Installation\Model\SetupModel;+use Joomla\CMS\Installation\Application\CliInstallationApplication;+use Joomla\CMS\Language\Text;+use Joomla\CMS\Version;+use Joomla\Console\Command\AbstractCommand;+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;++/**+ * Console command for installing Joomla+ *+ * @since __DEPLOY_VERSION__+ */+class InstallCommand extends AbstractCommand+{+ /**+ * The default command name+ *+ * @var string+ * @since __DEPLOY_VERSION__+ */+ protected static $defaultName = 'install';++ /**+ * @var SymfonyStyle+ * @since __DEPLOY_VERSION__+ */+ protected $ioStyle;++ /**+ * @var InputInterface+ * @since __DEPLOY_VERSION__+ */+ protected $cliInput;++ /**+ * Internal function to execute the command.+ *+ * @param InputInterface $input The input to inject into the command.+ * @param OutputInterface $output The output to inject into the command.+ *+ * @return integer The command exit code+ *+ * @since __DEPLOY_VERSION__+ */+ protected function doExecute(InputInterface $input, OutputInterface $output): int+ {+ $this->cliInput = $input;+ $this->ioStyle = new SymfonyStyle($input, $output);++ $this->ioStyle->title('Install Joomla');++ if (file_exists(JPATH_ROOT . '/configuration.php')) {+ $this->ioStyle->error('configuration.php already present! Nothing to install, exiting.');+ return Command::FAILURE;+ }++ /* @var CliInstallationApplication $app */+ $app = $this->getApplication();++ /** @var ChecksModel $checkModel */+ $checkModel = $app->getMVCFactory()->createModel('Checks', 'Installation');+ $this->ioStyle->write('Checking system requirements...');++ if (!$checkModel->getPhpOptionsSufficient()) {+ $options = $checkModel->getPhpOptions();++ foreach ($options as $option) {+ if (!$option->state) {+ $this->ioStyle->error($option->notice);++ return Command::FAILURE;+ }+ }+ }++ $this->ioStyle->writeln('OK');++ // Collect the configuration+ $this->ioStyle->write('Collecting configuration...');+ $cfg = $this->getCLIOptions();+ $cfg['db_pass_plain'] = $cfg['db_pass'];+ $cfg['admin_password_plain'] = $cfg['admin_password'];+ $cfg['language'] = 'en-GB';+ $cfg['helpurl'] = 'https://help.joomla.org/proxy?keyref=Help{major}{minor}:{keyref}&lang={langcode}';+ $this->ioStyle->writeln('OK');++ /** @var SetupModel $setupModel */+ $setupModel = $app->getMVCFactory()->createModel('Setup', 'Installation');++ // Validate DB connection+ $this->ioStyle->write('Validating DB connection...');++ try {+ $setupModel->storeOptions($cfg);+ $setupModel->validateDbConnection();+ } catch (\Exception $e) {+ $this->ioStyle->error($e->getMessage());++ return Command::FAILURE;+ }+ $this->ioStyle->writeln('OK');++ /** @var DatabaseModel $databaseModel */+ $databaseModel = $app->getMVCFactory()->createModel('Database', 'Installation');++ // Create and populate database+ $this->ioStyle->write('Creating and populating the database...');+ $databaseModel->createDatabase();+ $db = $databaseModel->initialise();++ // Set the character set to UTF-8 for pre-existing databases.+ try {+ $db->alterDbCharacterSet($cfg['db_name']);+ } catch (\RuntimeException $e) {+ // Continue Anyhow+ }++ // Backup any old database.+ if (!$databaseModel->backupDatabase($db, $cfg['db_prefix'])) {+ return Command::FAILURE;+ }++ $files = [+ 'populate1' => 'base',+ 'populate2' => 'supports',+ 'populate3' => 'extensions',+ 'custom1' => 'localise',+ 'custom2' => 'custom',+ ];++ foreach ($files as $step => $schema) {+ $serverType = $db->getServerType();++ if (\in_array($step, ['custom1', 'custom2']) && !is_file('sql/' . $serverType . '/' . $schema . '.sql')) {+ continue;+ }++ $databaseModel->createTables($schema);+ }++ $this->ioStyle->writeln('OK');++ /** @var \Joomla\CMS\Installation\Model\ConfigurationModel $configurationModel */+ $configurationModel = $app->getMVCFactory()->createModel('Configuration', 'Installation');++ // Attempt to setup the configuration.+ $this->ioStyle->write('Writing configuration.php and additional setup ...');+ $configurationModel->setup($cfg);+ $this->ioStyle->writeln('OK');++ if (!(new Version())->isInDevelopmentState()) {+ $this->ioStyle->write('Deleting /installation folder...');++ /** @var CleanupModel $cleanupModel */+ $cleanupModel = $app->getMVCFactory()->createModel('Cleanup', 'Installation');++ if (!$cleanupModel->deleteInstallationFolder()) {+ return Command::FAILURE;+ }++ $this->ioStyle->writeln('OK');+ }++ $this->ioStyle->success('Joomla has been installed');++ return Command::SUCCESS;+ }++ /**+ * Retrieve all necessary options either from CLI options+ * or from interactive mode.+ *+ * @return array Array of configuration options+ *+ * @throws \Exception+ * @since __DEPLOY_VERSION__+ */+ protected function getCLIOptions()+ {+ /* @var CliInstallationApplication $app */+ $app = $this->getApplication();++ /* @var SetupModel $setupmodel */+ $setupmodel = $app->getMVCFactory()->createModel('Setup', 'Installation');+ $form = $setupmodel->getForm('setup');+ $cfg = [];++ foreach ($form->getFieldset() as $field) {+ if (\in_array($field->fieldname, ['language', 'db_old'])) {+ continue;+ }++ if ($field->showon) {+ $conditions = FormHelper::parseShowOnConditions($field->showon, $field->formControl, $field->group);+ $show = false;++ foreach ($conditions as $cond) {+ // remove jform[] from the name+ $f = rtrim(substr($cond['field'], 6), ']');+ $temp = false;++ if ($cond['sign'] == '=' && \in_array($cfg[$f], $cond['values'])) {+ $temp = true;+ } elseif ($cond['sign'] == '!=' && !\in_array($cfg[$f], $cond['values'])) {+ $temp = true;+ }++ if ($cond['op'] == '' || $cond['op'] == 'OR') {+ $show |= $temp;+ } else {+ $show &= $temp;+ }+ }++ if ($show) {+ $cfg[$field->fieldname] = $this->getStringFromOption(+ str_replace('_', '-', $field->fieldname),+ Text::_((string)$field->getAttribute('label')),+ $field+ );+ } else {+ $cfg[$field->fieldname] = $field->filter($field->default);+ }+ } else {+ $cfg[$field->fieldname] = $field->filter(+ $this->getStringFromOption(+ str_replace('_', '-', $field->fieldname),+ Text::_((string)$field->getAttribute('label')),+ $field+ )+ );+ }+ }++ return $cfg;+ }++ /**+ * Configure the command.+ *+ * @return void+ *+ * @since __DEPLOY_VERSION__+ */+ protected function configure(): void+ {+ /* @var CliInstallationApplication $app */+ $app = Factory::getApplication();++ $app->getLanguage()->load('joomla.cli');+ $help = "<info>%command.name%</info> will install Joomla+ \nUsage: <info>php %command.full_name%</info>";++ /* @var SetupModel $setupmodel */+ $setupmodel = $app->getMVCFactory()->createModel('Setup', 'Installation');+ $form = $setupmodel->getForm('setup');++ $this->setDescription('Install the Joomla CMS');++ foreach ($form->getFieldset() as $field) {+ if (\in_array($field->fieldname, ['language', 'db_old'])) {+ continue;+ }++ $default = $field->getAttribute('default');++ if ($field->fieldname == 'db_prefix') {+ // Create the random prefix.+ $prefix = '';+ $size = 5;+ $chars = range('a', 'z');+ $numbers = range(0, 9);++ // We want the fist character to be a random letter.+ shuffle($chars);+ $prefix .= $chars[0];++ // Next we combine the numbers and characters to get the other characters.+ $symbols = array_merge($numbers, $chars);+ shuffle($symbols);++ for ($i = 0, $j = $size - 1; $i < $j; ++$i) {+ $prefix .= $symbols[$i];+ }++ // Add in the underscore.+ $prefix .= '_';+ $default = $prefix;+ }++ $this->addOption(+ str_replace('_', '-', $field->fieldname),+ null,+ $field->required ? InputOption::VALUE_REQUIRED : InputOption::VALUE_OPTIONAL,+ Text::_(((string)$field->getAttribute('label')) . '_SHORT'),+ $default+ );+ }++ $this->setHelp($help);+ }++ /**+ * Method to get a value from option+ *+ * @param string $option set the option name+ * @param string $question set the question if user enters no value to option+ * @param FormField $field Field to validate against+ *+ * @return string+ *+ * @throws \Exception+ * @since __DEPLOY_VERSION__+ */+ protected function getStringFromOption($option, $question, FormField $field): string+ {+ // The symfony console unfortunately does not allow to check for parameters given by CLI without the defaults+ $givenOption = false;+ $answer = null;++ foreach ($_SERVER['argv'] as $arg) {+ if ($arg == '--' . $option || strpos($arg, $option . '=')) {+ $givenOption = true;+ }+ }++ // If an option is given via CLI, we validate that value and return it.+ if ($givenOption || !$this->cliInput->isInteractive()) {+ $answer = $this->getApplication()->getConsoleInput()->getOption($option);++ if (!is_string($answer)) {+ throw new \Exception($option . ' has been declared, but has not been given!');+ }++ $valid = $field->validate($answer);++ if ($valid instanceof \Exception) {+ throw new \Exception('Value for ' . $option . ' is wrong: ' . $valid->getMessage());+ }++ return (string) $answer;+ }++ // We don't have a CLI option and now interactively get that from the user.+ while (\is_null($answer) || $answer === false) {+ if (in_array($option, ['admin-password', 'db-pass'])) {+ $answer = $this->ioStyle->askHidden($question);+ } else {+ $answer = $this->ioStyle->ask(+ $question,+ $this->getApplication()->getConsoleInput()->getOption($option)+ );+ }++ $valid = $field->validate($answer);++ if ($valid instanceof \Exception) {+ $this->ioStyle->warning('Value for ' . $option . ' is incorrect: ' . $valid->getMessage());+ $answer = false;+ }++ if ($option == 'db-pass' && $valid && $answer == null) {+ return '';+ }+ }++ return $answer;+ }+}diff --git a/installation/src/Form/Field/Installation/LanguageField.php b/installation/src/Form/Field/Installation/LanguageField.php
index c2da30066d39..4a22cc2c2e70 100644
--- a/installation/src/Form/Field/Installation/LanguageField.php+++ b/installation/src/Form/Field/Installation/LanguageField.php@@ -119,6 +119,12 @@ protected function getNativeLanguage()
$app = Factory::getApplication();
+ if ($app->isClient('cli_installation')) {+ $native = 'en-GB';++ return $native;+ }+
// Detect the native language.
$native = LanguageHelper::detectLanguage();
diff --git a/installation/src/Helper/DatabaseHelper.php b/installation/src/Helper/DatabaseHelper.php
index 820750cac4a3..3f8920f3e886 100644
--- a/installation/src/Helper/DatabaseHelper.php+++ b/installation/src/Helper/DatabaseHelper.php@@ -335,8 +335,9 @@ public static function validateConnectionParameters($options)
*/
public static function checkRemoteDbHost($options)
{
- // Security check for remote db hosts: Check env var if disabled- $shouldCheckLocalhost = getenv('JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK') !== '1';+ // Security check for remote db hosts: Check env var if disabled. Also disable in CLI.+ $shouldCheckLocalhost = getenv('JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK') !== '1'+ && !defined('_JCLI_INSTALLATION');
// Per default allowed DB hosts: localhost / 127.0.0.1 / ::1 (optionally with port)
$localhost = '/^(((localhost|127\.0\.0\.1|\[\:\:1\])(\:[1-9]{1}[0-9]{0,4})?)|(\:\:1))$/';
diff --git a/installation/src/Model/DatabaseModel.php b/installation/src/Model/DatabaseModel.php
index bd64f3175997..287f3bba160c 100644
--- a/installation/src/Model/DatabaseModel.php+++ b/installation/src/Model/DatabaseModel.php@@ -314,7 +314,7 @@ public function createTables($schema)
$serverType = $db->getServerType();
// Set the appropriate schema script based on UTF-8 support.
- $schemaFile = 'sql/' . $serverType . '/' . $schema . '.sql';+ $schemaFile = JPATH_INSTALLATION . '/sql/' . $serverType . '/' . $schema . '.sql';
// Check if the schema is a valid file
if (!is_file($schemaFile)) {
diff --git a/installation/src/Service/Provider/Application.php b/installation/src/Service/Provider/Application.php
index 37bd21f4b9d2..ed6473badaf1 100644
--- a/installation/src/Service/Provider/Application.php+++ b/installation/src/Service/Provider/Application.php@@ -12,9 +12,13 @@
use Joomla\CMS\Error\Renderer\JsonRenderer;
use Joomla\CMS\Factory;
+use Joomla\CMS\Installation\Application\CliInstallationApplication;
use Joomla\CMS\Installation\Application\InstallationApplication;
+use Joomla\CMS\Language\Language;+use Joomla\CMS\Language\LanguageFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
+use Joomla\Session\SessionInterface;
use Psr\Log\LoggerInterface;
// phpcs:disable PSR1.Files.SideEffects
@@ -58,6 +62,27 @@ function (Container $container) {
true
);
+ $container->share(+ CliInstallationApplication::class,+ function (Container $container) {+ $lang = $container->get(LanguageFactoryInterface::class)->createLanguage('en-GB', false);++ $app = new CliInstallationApplication(null, null, $container->get('config'), $lang);++ // The session service provider needs Factory::$application, set it if still null+ if (Factory::$application === null) {+ Factory::$application = $app;+ }++ $app->setDispatcher($container->get('Joomla\Event\DispatcherInterface'));+ $app->setLogger($container->get(LoggerInterface::class));+ $app->setSession($container->get(SessionInterface::class));++ return $app;+ },+ true+ );+
// Inject a custom JSON error renderer
$container->share(
JsonRenderer::class,
diff --git a/libraries/src/Form/Field/PasswordField.php b/libraries/src/Form/Field/PasswordField.php
index 15dea10732b8..90184aa2a204 100644
--- a/libraries/src/Form/Field/PasswordField.php+++ b/libraries/src/Form/Field/PasswordField.php@@ -175,7 +175,7 @@ public function setup(\SimpleXMLElement $element, $value, $group = null)
$this->minUppercase = 0;
$this->minLowercase = 0;
- if (Factory::getApplication()->get('db') != '') {+ if (Factory::getApplication()->get('db') != '' && !Factory::getApplication()->isClient('cli_installation')) {
$this->minLength = (int) ComponentHelper::getParams('com_users')->get('minimum_length', 12);
$this->minIntegers = (int) ComponentHelper::getParams('com_users')->get('minimum_integers', 0);
$this->minSymbols = (int) ComponentHelper::getParams('com_users')->get('minimum_symbols', 0);
diff --git a/libraries/src/Form/Rule/PasswordRule.php b/libraries/src/Form/Rule/PasswordRule.php
index 3e17996d24a2..f744cdbfa216 100644
--- a/libraries/src/Form/Rule/PasswordRule.php+++ b/libraries/src/Form/Rule/PasswordRule.php@@ -58,7 +58,10 @@ public function test(\SimpleXMLElement $element, $value, $group = null, Registry
// In the installer we don't have any access to the
// database yet so use the hard coded default settings
- if (!Factory::getApplication()->isClient('installation')) {+ if (+ !Factory::getApplication()->isClient('installation')+ && !Factory::getApplication()->isClient('cli_installation')+ ) {
// If we have parameters from com_users, use those instead.
// Some of these may be empty for legacy reasons.
$params = ComponentHelper::getParams('com_users');
diff --git a/ruleset.xml b/ruleset.xml
index ee01c19c05dc..aab60ebefbbd 100644
--- a/ruleset.xml+++ b/ruleset.xml@@ -272,8 +272,10 @@
<exclude-pattern type="relative">includes/defines\.php</exclude-pattern>
<exclude-pattern type="relative">includes/framework\.php</exclude-pattern>
<exclude-pattern type="relative">installation/includes/app\.php</exclude-pattern>
+ <exclude-pattern type="relative">installation/includes/cli\.php</exclude-pattern>
<exclude-pattern type="relative">installation/includes/defines\.php</exclude-pattern>
<exclude-pattern type="relative">installation/index\.php</exclude-pattern>
+ <exclude-pattern type="relative">installation/joomla\.php</exclude-pattern>
<exclude-pattern type="relative">libraries/cms\.php</exclude-pattern>
<exclude-pattern type="relative">libraries/bootstrap\.php</exclude-pattern>
<exclude-pattern type="relative">libraries/import\.php</exclude-pattern>
diff --git a/tests/Codeception/drone-api-run.sh b/tests/Codeception/drone-api-run.sh
index a16d2489d918..d8862c8006af 100644
--- a/tests/Codeception/drone-api-run.sh+++ b/tests/Codeception/drone-api-run.sh@@ -1,7 +1,11 @@
#!/usr/bin/env bash
set -e
JOOMLA_BASE=$1
-DB_ENGINE=$2+TEST_SUITE=$2+DB_ENGINE=$3+DB_HOST=$4+DB_PREFIX=$5+
echo "[RUNNER] Prepare test environment"
@@ -9,15 +13,15 @@ echo "[RUNNER] Prepare test environment"
cd $JOOMLA_BASE
echo "[RUNNER] Copy files to test installation"
-rsync -a --exclude-from=tests/Codeception/exclude.txt $JOOMLA_BASE/ /tests/www/$DB_ENGINE/-chown -R www-data /tests/www/$DB_ENGINE/+rsync -a --exclude-from=tests/Codeception/exclude.txt $JOOMLA_BASE/ /tests/www/$TEST_SUITE/+chown -R www-data /tests/www/$TEST_SUITE/
echo "[RUNNER] Start Apache & Chrome"
apache2ctl -D FOREGROUND &
google-chrome --version
echo "[RUNNER] Start Selenium"
-selenium-standalone start > selenium.api.$DB_ENGINE.log 2>&1 &+selenium-standalone start > selenium.api.$TEST_SUITE.log 2>&1 &
echo -n "Waiting until Selenium is ready"
until $(curl --output /dev/null --silent --head --fail http://localhost:4444/wd/hub/status); do
printf '.'
@@ -25,13 +29,14 @@ until $(curl --output /dev/null --silent --head --fail http://localhost:4444/wd/
done
echo .
-echo "[RUNNER] Run Codeception"-cd /tests/www/$DB_ENGINE-php libraries/vendor/bin/codecept run --fail-fast --steps --debug --env $DB_ENGINE tests/Codeception/acceptance/01-install/+echo "[RUNNER] Install Joomla"+cd /tests/www/$TEST_SUITE+php installation/joomla.php install --verbose --site-name="Joomla CMS test" --admin-email=admin@example.org --admin-username=ci-admin --admin-user="jane doe" --admin-password=joomla-17082005 --db-type=$DB_ENGINE --db-host=$DB_HOST --db-name=test_joomla --db-pass=joomla_ut --db-user=root --db-encryption=0 --db-prefix=$DB_PREFIX
# If you have found this line failing on OSX you need to brew install gnu-sed like we mentioned in the codeception readme!
# This replaces the site secret in configuration.php so we can guarantee a consistent API token for our super user.
-sed -i "/\$secret/c\ public \$secret = 'tEstValue';" /tests/www/$DB_ENGINE/configuration.php+sed -i "/\$secret/c\ public \$secret = 'tEstValue';" /tests/www/$TEST_SUITE/configuration.php+echo "[RUNNER] Run Codeception"
# Executing API tests
-php libraries/vendor/bin/codecept run api --fail-fast --steps --debug --env $DB_ENGINE+php libraries/vendor/bin/codecept run api --fail-fast --steps --debug --env $TEST_SUITE
The text was updated successfully, but these errors were encountered:
PR w związku ze zmianą oryginału joomla/joomla-cms#38325 Poniżej zmiany w oryginale:
Click to expand the diff!
The text was updated successfully, but these errors were encountered: