Skip to content

Commit 0475f8e

Browse files
dgrammatikoHLeithnerbrianteeman
authored
[5.0] Introduce a CLI UI for creating a public folder (#41446)
* Public folder * CS Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * Use a helper to reduce duplicate code -cli install * $folder -> destinationPath * CLI Installation * one helper Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * consistent error text Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * wrong expected default value Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * text Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * Draw the rest of the horse (kinda) Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * update * CS * cs * Update InstallCommand.php * cleanup Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * Simplify * entropy * useless * typehint * simplify more * move the unset * oops * code docs * well that path doesn't resolve * Update SetupModel.php * Fix the paths Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * Fix the installation cli skipping images Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * cs Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * Fix the defines path Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * Use full paths * Make the public folder input optional Signed-off-by: Dimitris Grammatikogiannis <[email protected]> * No reason to limit this to cli. * Allow public folder creation to use relative path * cs * cs * allow empty value for public folder input * Some typos * Update installation/src/Model/SetupModel.php Co-authored-by: Brian Teeman <[email protected]> * Update libraries/src/Helper/PublicFolderGeneratorHelper.php Co-authored-by: Brian Teeman <[email protected]> * Update libraries/src/Helper/PublicFolderGeneratorHelper.php Co-authored-by: Brian Teeman <[email protected]> * Update installation/language/en-GB/joomla.ini Co-authored-by: Brian Teeman <[email protected]> * Update installation/language/en-GB/joomla.cli.ini Co-authored-by: Brian Teeman <[email protected]> --------- Signed-off-by: Dimitris Grammatikogiannis <[email protected]> Co-authored-by: Harald Leithner <[email protected]> Co-authored-by: Brian Teeman <[email protected]>
1 parent b0064dc commit 0475f8e

File tree

9 files changed

+406
-7
lines changed

9 files changed

+406
-7
lines changed

includes/app.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@
1919

2020
require_once __DIR__ . '/defines.php';
2121

22-
if (!defined('JPATH_PUBLIC')) {
23-
define('JPATH_PUBLIC', JPATH_ROOT);
24-
}
25-
2622
// Check for presence of vendor dependencies not included in the git repository
2723
if (!file_exists(JPATH_LIBRARIES . '/vendor/autoload.php') || !is_dir(JPATH_PUBLIC . '/media/vendor')) {
2824
echo file_get_contents(JPATH_ROOT . '/templates/system/build_incomplete.html');

installation/forms/setup.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,15 @@
176176
/>
177177

178178
</fieldset>
179+
180+
<fieldset name="expert">
181+
<field
182+
name="public_folder"
183+
type="text"
184+
label="INSTL_PUBLIC_FOLDER_LABEL"
185+
description="INSTL_PUBLIC_FOLDER_DESCRIPTION"
186+
default=""
187+
filter="string"
188+
/>
189+
</fieldset>
179190
</form>

installation/language/en-GB/joomla.cli.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,7 @@ INSTL_DATABASE_TYPE_DESC="Database type. Supported: mysql, mysqli, pgsql"
3131
INSTL_DATABASE_TYPE_DESC_SHORT="Database type. Supported by Joomla: mysql (=MySQL (PDO)), mysqli (=MySQLi), pgsql (=PostgreSQL (PDO))"
3232
INSTL_DATABASE_USER_DESC="Database username"
3333
INSTL_DATABASE_USER_DESC_SHORT="Database username"
34+
INSTL_PUBLIC_FOLDER_DESC_SHORT="Relative or absolute path to the public folder"
35+
INSTL_PUBLIC_FOLDER_LABEL="Relative or absolute path to the public folder"
3436
INSTL_SITE_NAME_DESC="Enter the name of your Joomla site"
3537
INSTL_SITE_NAME_DESC_SHORT="Name of the website"

installation/language/en-GB/joomla.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ INSTL_SITE="Main Configuration"
114114
INSTL_SITE_DEVMODE_LABEL="We detected development mode"
115115
INSTL_SITE_NAME_DESC="Enter the name of your Joomla site."
116116

117+
; Expert View
118+
INSTL_PUBLIC_FOLDER_DESC_SHORT="Relative or absolute path to the public folder"
119+
INSTL_PUBLIC_FOLDER_LABEL="Relative or absolute path to the public folder"
120+
117121
; Complete view
118122
INSTL_COMPLETE_ERROR_FOLDER_DELETE="The \"%s\" folder could not be deleted. Please manually delete the folder."
119123
INSTL_COMPLETE_REMOVE_FOLDER="Remove \"%s\" folder"

installation/src/Console/InstallCommand.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use Joomla\CMS\Factory;
1313
use Joomla\CMS\Form\FormField;
1414
use Joomla\CMS\Form\FormHelper;
15-
use Joomla\CMS\Installation\Application\CliInstallationApplication;
15+
use Joomla\CMS\Helper\PublicFolderGeneratorHelper;
1616
use Joomla\CMS\Installation\Model\ChecksModel;
1717
use Joomla\CMS\Installation\Model\CleanupModel;
1818
use Joomla\CMS\Installation\Model\DatabaseModel;
@@ -181,6 +181,16 @@ protected function doExecute(InputInterface $input, OutputInterface $output): in
181181
$this->ioStyle->writeln('OK');
182182
}
183183

184+
if (!empty($cfg['public_folder'])) {
185+
$this->ioStyle->write('Creating the public folder...');
186+
187+
if (!(new PublicFolderGeneratorHelper())->createPublicFolder($cfg['public_folder'])) {
188+
return Command::FAILURE;
189+
}
190+
191+
$this->ioStyle->writeln('OK');
192+
}
193+
184194
$this->ioStyle->success('Joomla has been installed');
185195

186196
return Command::SUCCESS;
@@ -363,7 +373,7 @@ protected function getStringFromOption($option, $question, FormField $field): st
363373

364374
// We don't have a CLI option and now interactively get that from the user.
365375
while (\is_null($answer) || $answer === false) {
366-
if (in_array($option, ['admin-password', 'db-pass'])) {
376+
if (in_array($option, ['admin-password', 'db-pass', 'public_folder'])) {
367377
$answer = $this->ioStyle->askHidden($question);
368378
} else {
369379
$answer = $this->ioStyle->ask(
@@ -379,7 +389,7 @@ protected function getStringFromOption($option, $question, FormField $field): st
379389
$answer = false;
380390
}
381391

382-
if ($option == 'db-pass' && $valid && $answer == null) {
392+
if (($option == 'db-pass' || $option == 'public_folder') && $valid && $answer == null) {
383393
return '';
384394
}
385395
}

installation/src/Model/SetupModel.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ public function getForm($view = null)
109109
return false;
110110
}
111111

112+
/** @todo make this available in web installer too */
113+
if (!Factory::getApplication()->isClient('cli_installation')) {
114+
$form->removeField('public_folder');
115+
}
116+
112117
// Check the session for previously entered form data.
113118
$data = (array) $this->getOptions();
114119

libraries/src/Application/ConsoleApplication.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ protected function getDefaultCommands(): array
310310
new Console\DeleteUserCommand($this->getDatabase()),
311311
new Console\ChangeUserPasswordCommand(),
312312
new Console\ListUserCommand($this->getDatabase()),
313+
new Console\SiteCreatePublicFolderCommand(),
313314
]
314315
);
315316
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
<?php
2+
3+
/**
4+
* Joomla! Content Management System
5+
*
6+
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
7+
* @license GNU General Public License version 2 or later; see LICENSE.txt
8+
*/
9+
10+
namespace Joomla\CMS\Console;
11+
12+
use Joomla\CMS\Helper\PublicFolderGeneratorHelper;
13+
use Joomla\Console\Command\AbstractCommand;
14+
use Joomla\Filter\InputFilter;
15+
use Symfony\Component\Console\Command\Command;
16+
use Symfony\Component\Console\Input\InputInterface;
17+
use Symfony\Component\Console\Input\InputOption;
18+
use Symfony\Component\Console\Output\OutputInterface;
19+
use Symfony\Component\Console\Style\SymfonyStyle;
20+
21+
// phpcs:disable PSR1.Files.SideEffects
22+
\defined('_JEXEC') or die;
23+
// phpcs:enable PSR1.Files.SideEffects
24+
25+
/**
26+
* Console command for creating a public folder
27+
*
28+
* @since __DEPLOY_VERSION__
29+
*/
30+
class SiteCreatePublicFolderCommand extends AbstractCommand
31+
{
32+
/**
33+
* The default command name
34+
*
35+
* @var string
36+
* @since __DEPLOY_VERSION__
37+
*/
38+
protected static $defaultName = 'site:create-public-folder';
39+
40+
/**
41+
* SymfonyStyle Object
42+
* @var object
43+
* @since __DEPLOY_VERSION__
44+
*/
45+
private $ioStyle;
46+
47+
/**
48+
* Stores the Input Object
49+
* @var object
50+
* @since __DEPLOY_VERSION__
51+
*/
52+
private $cliInput;
53+
54+
/**
55+
* The public folder path (absolute)
56+
*
57+
* @var string
58+
*
59+
* @since __DEPLOY_VERSION__
60+
*/
61+
private $publicFolder;
62+
63+
/**
64+
* Internal function to execute the command.
65+
*
66+
* @param InputInterface $input The input to inject into the command.
67+
* @param OutputInterface $output The output to inject into the command.
68+
*
69+
* @return integer The command exit code
70+
*
71+
* @since __DEPLOY_VERSION__
72+
*/
73+
protected function doExecute(InputInterface $input, OutputInterface $output): int
74+
{
75+
$this->configureIO($input, $output);
76+
$this->ioStyle->title('Create a public folder');
77+
78+
$this->publicFolder = $this->getStringFromOption('public-folder', 'Please enter the absolute path to the public folder', true);
79+
80+
// Remove the last (Windows || NIX) slash
81+
$this->publicFolder = rtrim((new InputFilter())->clean($this->publicFolder, 'PATH'), '/');
82+
$this->publicFolder = rtrim($this->publicFolder, '\\');
83+
84+
if (!((new PublicFolderGeneratorHelper())->createPublicFolder($this->publicFolder))) {
85+
return Command::FAILURE;
86+
}
87+
88+
$this->ioStyle->success("Public folder created! \nAdjust your server configuration to serve from the public folder.");
89+
90+
return Command::SUCCESS;
91+
}
92+
93+
/**
94+
* Method to get a value from option
95+
*
96+
* @param string $option set the option name
97+
* @param string $question set the question if user enters no value to option
98+
* @param bool $required is it required
99+
*
100+
* @return string
101+
*
102+
* @since __DEPLOY_VERSION__
103+
*/
104+
public function getStringFromOption($option, $question, $required = true): string
105+
{
106+
$answer = (string) $this->cliInput->getOption($option);
107+
108+
while (!$answer && $required) {
109+
$answer = (string) $this->ioStyle->ask($question);
110+
}
111+
112+
if (!$required) {
113+
$answer = (string) $this->ioStyle->ask($question);
114+
}
115+
116+
return $answer;
117+
}
118+
119+
/**
120+
* Configure the IO.
121+
*
122+
* @param InputInterface $input The input to inject into the command.
123+
* @param OutputInterface $output The output to inject into the command.
124+
*
125+
* @return void
126+
*
127+
* @since __DEPLOY_VERSION__
128+
*/
129+
private function configureIO(InputInterface $input, OutputInterface $output)
130+
{
131+
$this->cliInput = $input;
132+
$this->ioStyle = new SymfonyStyle($input, $output);
133+
}
134+
135+
/**
136+
* Configure the command.
137+
*
138+
* @return void
139+
*
140+
* @since __DEPLOY_VERSION__
141+
*/
142+
protected function configure(): void
143+
{
144+
$help = "<info>%command.name%</info> will create a public folder
145+
\nUsage: <info>php %command.full_name%</info>";
146+
147+
$this->addOption('public-folder', null, InputOption::VALUE_REQUIRED, 'public folder absolute path');
148+
$this->setDescription('Create a public folder');
149+
$this->setHelp($help);
150+
}
151+
}

0 commit comments

Comments
 (0)