From d08668cdb8cfe09449fb6f459c0cd8acb64211e6 Mon Sep 17 00:00:00 2001 From: Yurii Date: Thu, 25 Jun 2026 14:38:38 +0300 Subject: [PATCH] App check command --- .../Espo/Classes/ConsoleCommands/AppCheck.php | 128 ++++++++++++++++++ .../Espo/Core/ApplicationRunners/Cron.php | 11 +- .../Espo/Core/Utils/Config/SystemConfig.php | 8 ++ .../metadata/app/consoleCommands.json | 5 + .../Espo/Tools/AdminNotifications/Manager.php | 2 +- .../Espo/Commands/AppCheckTest.php | 54 ++++++++ 6 files changed, 203 insertions(+), 5 deletions(-) create mode 100644 application/Espo/Classes/ConsoleCommands/AppCheck.php create mode 100644 tests/integration/Espo/Commands/AppCheckTest.php diff --git a/application/Espo/Classes/ConsoleCommands/AppCheck.php b/application/Espo/Classes/ConsoleCommands/AppCheck.php new file mode 100644 index 0000000000..b527507083 --- /dev/null +++ b/application/Espo/Classes/ConsoleCommands/AppCheck.php @@ -0,0 +1,128 @@ +. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace Espo\Classes\ConsoleCommands; + +use Espo\Core\Authentication\ConfigDataProvider as AuthenticationConfig; +use Espo\Core\Console\Command; +use Espo\Core\Console\Command\Params; +use Espo\Core\Console\IO; +use Espo\Core\Upgrades\Migration\VersionDataProvider; +use Espo\Core\Utils\Config\SystemConfig; +use Espo\Core\Utils\Database\Helper; +use Exception; + +/** + * @noinspection PhpUnused + */ +class AppCheck implements Command +{ + public function __construct( + private Helper $databaseHelper, + private SystemConfig $systemConfig, + private VersionDataProvider $versionDataProvider, + private AuthenticationConfig $authenticationConfig, + ) {} + + public function run(Params $params, IO $io): void + { + $this->versionMatch($io); + $this->checkDb($io); + $this->maintenanceIsOff($io); + $this->cronEnabled($io); + } + + private function versionMatch(IO $io): void + { + $io->write('Migration not needed: '); + + if ($this->systemConfig->getVersion() === $this->versionDataProvider->getTargetVersion()) { + $this->writeOK($io); + } else { + $this->writeFail($io); + $io->setExitStatus(1); + } + + $io->writeLine(''); + } + + private function checkDb(IO $io): void + { + $io->write('Database: '); + + try { + $this->databaseHelper->createPDO(); + + $this->writeOK($io); + } catch (Exception) { + $this->writeFail($io); + $io->setExitStatus(1); + } + + $io->writeLine(''); + } + + private function maintenanceIsOff(IO $io): void + { + $io->write('Not in maintenance mode: '); + + if (!$this->authenticationConfig->isMaintenanceMode()) { + $this->writeOK($io); + } else { + $this->writeFail($io); + $io->setExitStatus(1); + } + + $io->writeLine(''); + } + + private function cronEnabled(IO $io): void + { + $io->write('Cron is enabled: '); + + if ($this->systemConfig->isCronEnabled()) { + $this->writeOK($io); + } else { + $this->writeFail($io); + $io->setExitStatus(1); + } + + $io->writeLine(''); + } + + private function writeOK(IO $io): void + { + $io->write("\033[32mOK\033[0m"); + } + + private function writeFail(IO $io): void + { + $io->write("\033[31mFAIL\033[0m"); + } +} diff --git a/application/Espo/Core/ApplicationRunners/Cron.php b/application/Espo/Core/ApplicationRunners/Cron.php index acf7efd2df..c203f8f24e 100644 --- a/application/Espo/Core/ApplicationRunners/Cron.php +++ b/application/Espo/Core/ApplicationRunners/Cron.php @@ -31,7 +31,7 @@ namespace Espo\Core\ApplicationRunners; use Espo\Core\Application\Runner; use Espo\Core\Job\JobManager; -use Espo\Core\Utils\Config; +use Espo\Core\Utils\Config\SystemConfig; use Espo\Core\Utils\Log; /** @@ -42,12 +42,15 @@ class Cron implements Runner use Cli; use SetupSystemUser; - public function __construct(private JobManager $jobManager, private Config $config, private Log $log) - {} + public function __construct( + private JobManager $jobManager, + private SystemConfig $config, + private Log $log + ) {} public function run(): void { - if ($this->config->get('cronDisabled')) { + if (!$this->config->isCronEnabled()) { $this->log->warning("Cron is not run because it's disabled with 'cronDisabled' param."); return; diff --git a/application/Espo/Core/Utils/Config/SystemConfig.php b/application/Espo/Core/Utils/Config/SystemConfig.php index 67d4569c1c..d77cd671d0 100644 --- a/application/Espo/Core/Utils/Config/SystemConfig.php +++ b/application/Espo/Core/Utils/Config/SystemConfig.php @@ -60,4 +60,12 @@ class SystemConfig { return (bool) $this->config->get('restrictedMode'); } + + /** + * @since 10.0.0 + */ + public function isCronEnabled(): bool + { + return !$this->config->get('cronDisabled'); + } } diff --git a/application/Espo/Resources/metadata/app/consoleCommands.json b/application/Espo/Resources/metadata/app/consoleCommands.json index 9816b59723..38084c8c9f 100644 --- a/application/Espo/Resources/metadata/app/consoleCommands.json +++ b/application/Espo/Resources/metadata/app/consoleCommands.json @@ -81,6 +81,11 @@ "listed": true, "noSystemUser": true }, + "appCheck": { + "className": "Espo\\Classes\\ConsoleCommands\\AppCheck", + "listed": true, + "noSystemUser": true + }, "migrate": { "listed": true, "noSystemUser": true diff --git a/application/Espo/Tools/AdminNotifications/Manager.php b/application/Espo/Tools/AdminNotifications/Manager.php index 0794e3f002..b545097841 100644 --- a/application/Espo/Tools/AdminNotifications/Manager.php +++ b/application/Espo/Tools/AdminNotifications/Manager.php @@ -70,7 +70,7 @@ class Manager } if ($this->config->get('adminNotificationsCronIsNotConfigured')) { - if ($this->config->get('cronDisabled')) { + if (!$this->systemConfig->isCronEnabled()) { $notificationList[] = [ 'id' => 'cronIsDisabled', 'type' => 'cronIsDisabled', diff --git a/tests/integration/Espo/Commands/AppCheckTest.php b/tests/integration/Espo/Commands/AppCheckTest.php new file mode 100644 index 0000000000..ed2196eb3d --- /dev/null +++ b/tests/integration/Espo/Commands/AppCheckTest.php @@ -0,0 +1,54 @@ +. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace integration\Espo\Commands; + +use Espo\Classes\ConsoleCommands\AppCheck; +use Espo\Core\Console\Command\Params; +use Espo\Core\Console\IO; +use tests\integration\Core\BaseTestCase; + +class AppCheckTest extends BaseTestCase +{ + public function testNotFailed(): void + { + $command = $this->getInjectableFactory()->create(AppCheck::class); + + $params = $this->createMock(Params::class); + $io = $this->createMock(IO::class); + + $io->expects($this->never()) + ->method('setExitStatus') + ->with(1); + + $command->run($params, $io); + + $this->assertEquals(0, $io->getExitStatus()); + } +}