From 2cd081ac1513e568699faebbd680d9591ee27ac5 Mon Sep 17 00:00:00 2001 From: Arman <407448+armanist@users.noreply.github.com> Date: Wed, 24 Dec 2025 16:00:44 +0400 Subject: [PATCH 1/4] Adding new project dependency `symfony/process` --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d555933..077ff36 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "doctrine/annotations": "^2.0", "voku/html-min": "^4.5", "league/commonmark": "^1.6", - "ezyang/htmlpurifier": "^4.18" + "ezyang/htmlpurifier": "^4.18", + "symfony/process": "^5.4" }, "require-dev": { "phpunit/phpunit": "^9.0", From bec78e43494e0f2e8ab6f4b3235a107aa013fc8b Mon Sep 17 00:00:00 2001 From: Arman <407448+armanist@users.noreply.github.com> Date: Wed, 24 Dec 2025 16:02:23 +0400 Subject: [PATCH 2/4] Correcting DemoCommand issue by introducing new `runCommandExternally()` method and applying overall refactoring --- shared/Commands/DemoCommand.php | 114 ++++++++++++++++++++++------ shared/resources/lang/en/common.php | 3 +- shared/resources/lang/es/common.php | 3 +- 3 files changed, 93 insertions(+), 27 deletions(-) diff --git a/shared/Commands/DemoCommand.php b/shared/Commands/DemoCommand.php index ce2ff42..eb995c0 100644 --- a/shared/Commands/DemoCommand.php +++ b/shared/Commands/DemoCommand.php @@ -26,6 +26,7 @@ use Quantum\Libraries\Database\Database; use Bluemmb\Faker\PicsumPhotosProvider; use Quantum\Di\Exceptions\DiException; +use Symfony\Component\Process\Process; use Quantum\Console\QtCommand; use Ottaviano\Faker\Gravatar; use ReflectionException; @@ -33,7 +34,6 @@ use Faker\Generator; use ErrorException; use Faker\Factory; -use Exception; /** * Class DemoCommand @@ -146,6 +146,7 @@ public function exec() foreach ($steps as $step) { $this->updateProgress($progress, $step['message']); $step['action'](); + $progress->advance(); } $progress->finish(); @@ -219,17 +220,15 @@ private function initProgressBar(int $steps): ProgressBar * @param string $moduleName * @param string $template * @param bool $withAssets - * @return void - * @throws ExceptionInterface */ private function createModule(string $moduleName, string $template, bool $withAssets): void { - $this->runExternalCommand(self::COMMANDS['module_generate'], [ + $this->runCommandExternally(self::COMMANDS['module_generate'], [ 'module' => $moduleName, '--yes' => true, '--template' => $template, '--with-assets' => $withAssets - ]); + ], true); } /** @@ -248,7 +247,7 @@ private function generateUsers(): array $users = []; for ($i = 0; $i < self::COUNTS['users']; $i++) { $user = $this->generateUserData(); - $this->runExternalCommand(self::COMMANDS['user_create'], $user); + $this->runCommandInternally(self::COMMANDS['user_create'], $user); $users[] = $user; } return $users; @@ -273,7 +272,7 @@ private function generatePosts(array $users): array foreach ($users as $user) { for ($i = 0; $i < self::COUNTS['posts_per_user']; $i++) { $post = $this->generatePostData($user); - $this->runExternalCommand(self::COMMANDS['post_create'], $post); + $this->runCommandInternally(self::COMMANDS['post_create'], $post); $posts[] = $post; } } @@ -294,7 +293,7 @@ private function generateComments(array $users, array $posts): void for ($i = 0; $i < self::COUNTS['comments_per_post']; $i++) { $commentUser = $this->getRandomUserExcept($users, $post['user_uuid']); - $this->runExternalCommand(self::COMMANDS['comment_create'], [ + $this->runCommandInternally(self::COMMANDS['comment_create'], [ 'post_uuid' => $post['uuid'], 'user_uuid' => $commentUser['uuid'], 'content' => textCleanUp($this->faker->realText(rand(20, 100))), @@ -316,7 +315,7 @@ private function generateComments(array $users, array $posts): void private function generateUserData(): array { $userUuid = $this->faker->uuid(); - $email = textCleanUp($this->faker->email()); + $email = $this->faker->safeEmail(); create_user_directory($userUuid); @@ -327,19 +326,19 @@ private function generateUserData(): array ); return [ - 'uuid' => $userUuid, + 'email' => $email, + 'password' => self::DEFAULT_PASSWORD, 'firstname' => $this->faker->name(), 'lastname' => $this->faker->lastName(), + 'uuid' => $userUuid, 'role' => Role::EDITOR, - 'email' => $email, - 'password' => self::DEFAULT_PASSWORD, 'image' => $imageName ]; } /** * Generates data for post - * @param $user + * @param array $user * @return array * @throws BaseException * @throws ConfigException @@ -348,7 +347,7 @@ private function generateUserData(): array * @throws HttpClientException * @throws ReflectionException */ - private function generatePostData($user): array + private function generatePostData(array $user): array { $postUuid = $this->faker->uuid(); $title = textCleanUp($this->faker->realText(50)); @@ -360,11 +359,11 @@ private function generatePostData($user): array ); return [ - 'uuid' => $postUuid, 'title' => $title, 'description' => textCleanUp($this->faker->realText(1000)), - 'image' => $imageName, 'user_uuid' => $user['uuid'], + 'uuid' => $postUuid, + 'image' => $imageName, ]; } @@ -393,25 +392,25 @@ private function updateProgress(ProgressBar $progress, string $message): void { $progress->setMessage($message, 'item'); $progress->display(); - $progress->advance(); } /** * Rebuilds the database + * @return void * @throws ExceptionInterface */ private function rebuildDatabase(): void { switch (Database::getInstance()->getConfigs()['driver']) { case 'mysql': - $this->runExternalCommand(self::COMMANDS['migrate'], ['direction' => 'down']); - $this->runExternalCommand(self::COMMANDS['migrate'], ['direction' => 'up']); + $this->runCommandInternally(self::COMMANDS['migrate'], ['direction' => 'down']); + $this->runCommandInternally(self::COMMANDS['migrate'], ['direction' => 'up']); break; case 'sleekdb': - $this->runExternalCommand(self::COMMANDS['comment_delete'], ['--yes' => true]); - $this->runExternalCommand(self::COMMANDS['post_delete'], ['--yes' => true]); - $this->runExternalCommand(self::COMMANDS['user_delete'], ['--yes' => true]); + $this->runCommandInternally(self::COMMANDS['comment_delete'], ['--yes' => true]); + $this->runCommandInternally(self::COMMANDS['post_delete'], ['--yes' => true]); + $this->runCommandInternally(self::COMMANDS['user_delete'], ['--yes' => true]); break; } } @@ -452,13 +451,78 @@ private function resetDatabase(): void } /** - * Runs an external command - * @throws Exception + * @param string $commandName + * @param array $arguments * @throws ExceptionInterface */ - private function runExternalCommand(string $commandName, ?array $arguments = []) + private function runCommandInternally(string $commandName, array $arguments = []) { $command = $this->getApplication()->find($commandName); $command->run(new ArrayInput($arguments), new NullOutput); } + + /** + * @param string $commandName + * @param array $arguments + */ + private function runCommandExternally(string $commandName, array $arguments = []) + { + $command = $this->buildCommand($commandName, $arguments); + $this->runExternalProcess($command); + } + + /** + * Runs separate process + * @param array $command + * @return void + */ + private function runExternalProcess(array $command): void + { + $process = new Process($command, base_dir()); + $process->setTimeout(null); + + $process->mustRun(); + } + + /** + * Builds command string + * @param string $commandName + * @param array $arguments + * @return string[] + */ + private function buildCommand(string $commandName, array $arguments): array + { + $command = ['php', 'qt', $commandName]; + + foreach ($arguments as $key => $value) { + + if (!is_int($key) && !str_starts_with($key, '--')) { + $command[] = (string)$value; + continue; + } + + if (is_bool($value)) { + if ($value) $command[] = $key; + continue; + } + + if (is_array($value)) { + foreach ($value as $item) { + $command[] = $key; + $command[] = (string)$item; + } + continue; + } + + $command[] = $key; + + if ($value === null) { + continue; + } + + $command[] = (string)$value; + } + + return $command; + } } \ No newline at end of file diff --git a/shared/resources/lang/en/common.php b/shared/resources/lang/en/common.php index ddd785d..1c71665 100644 --- a/shared/resources/lang/en/common.php +++ b/shared/resources/lang/en/common.php @@ -4,9 +4,10 @@ // ───── About framework ─────────────────────────────────── 'description' => 'Very fast and extremely simple, next generation PHP MVC framework with modular structure.', - 'about_framework' => 'Quantum is a free, open-source PHP web framework under MIT license...', + 'about_framework' => 'Quantum is a free, open-source PHP web framework under MIT license, specially designed to develop very fast web applications with modular structure. With Quantum it’s easy to start any kind of project immediately, whether it\'s regular websites or complex API based service, at the same time it allows to keep the code clean, organized through all the development process.', 'version' => 'Version', 'current_version' => 'Current version is: {%1}', + 'cli_commands' => 'Quantum CLI Commands', // ───── Navigation ───────────────────────────────────────── 'home' => 'Home', diff --git a/shared/resources/lang/es/common.php b/shared/resources/lang/es/common.php index 90998b9..e473b93 100644 --- a/shared/resources/lang/es/common.php +++ b/shared/resources/lang/es/common.php @@ -4,9 +4,10 @@ // ───── About framework ─────────────────────────────────── 'description' => 'Framework MVC en PHP de nueva generación, muy rápido y extremadamente simple, con una estructura modular.', - 'about_framework' => 'Quantum es un framework web en PHP gratuito y de código abierto bajo la licencia MIT...', + 'about_framework' => 'Quantum es un framework web PHP gratuito y de código abierto bajo la licencia MIT, diseñado especialmente para desarrollar aplicaciones web muy rápidas con una estructura modular. Con Quantum es fácil iniciar de inmediato cualquier tipo de proyecto, ya sean sitios web tradicionales o servicios complejos basados en API, y al mismo tiempo permite mantener el código limpio y organizado durante todo el proceso de desarrollo.', 'version' => 'Versión', 'current_version' => 'La versión actual es: {%1}', + 'cli_commands' => 'Comandos CLI de Quantum', // ───── Navigation ───────────────────────────────────────── 'home' => 'Inicio', From 64a992a31402cb435d659c2d393afa237ebca711 Mon Sep 17 00:00:00 2001 From: Arman <407448+armanist@users.noreply.github.com> Date: Wed, 24 Dec 2025 16:13:22 +0400 Subject: [PATCH 3/4] Removing outdated argument --- shared/Commands/DemoCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/Commands/DemoCommand.php b/shared/Commands/DemoCommand.php index eb995c0..ef27077 100644 --- a/shared/Commands/DemoCommand.php +++ b/shared/Commands/DemoCommand.php @@ -228,7 +228,7 @@ private function createModule(string $moduleName, string $template, bool $withAs '--yes' => true, '--template' => $template, '--with-assets' => $withAssets - ], true); + ]); } /** From 2bf2c23037b017e7c235b5746da2c29231bf85d2 Mon Sep 17 00:00:00 2001 From: Arman <407448+armanist@users.noreply.github.com> Date: Wed, 24 Dec 2025 16:25:48 +0400 Subject: [PATCH 4/4] Using php 7.3 compliant version of `str_starts_with` --- shared/Commands/DemoCommand.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shared/Commands/DemoCommand.php b/shared/Commands/DemoCommand.php index ef27077..c1232c3 100644 --- a/shared/Commands/DemoCommand.php +++ b/shared/Commands/DemoCommand.php @@ -495,8 +495,7 @@ private function buildCommand(string $commandName, array $arguments): array $command = ['php', 'qt', $commandName]; foreach ($arguments as $key => $value) { - - if (!is_int($key) && !str_starts_with($key, '--')) { + if (!is_int($key) && substr($key, 0, 2) !== '--') { $command[] = (string)$value; continue; }