307067580c
Every non-interactive backup trigger used a slightly different path, so final status and notification gating behaved inconsistently depending on what started the backup (this is why pre-update backups did not gate notifications the way "Backup Now" does). Add src/Service/BackupRunner.php as the single synchronous entry point. It delegates to BackupEngine (which already sends notifications gated by the profile's notify_on_success/notify_on_failure and applies retention — so there is exactly ONE notification layer), and normalises the result, including the real complete/warning/fail status the engine records but did not return. BackupRunner self-loads BackupEngine so callers require one file. Routed through BackupRunner: - plg_system runPreActionBackup() (preaction) + web-cron handler (webcron) - plg_content triggerAutoBackup() (pre-install) - plg_task scheduled task run - plg_console RunCommand (cli) The dashboard AJAX/stepped "Backup Now" flow is unchanged (it is the interactive equivalent). The installer progress popup is deferred — the installer request cannot drive the AJAX modal (TODO(#196) noted in code). php -l clean on all changed files. Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
68 lines
1.9 KiB
PHP
68 lines
1.9 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @package MokoSuiteBackup
|
|
* @subpackage plg_console_mokosuitebackup
|
|
* @author Moko Consulting <hello@mokoconsulting.tech>
|
|
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
|
* @license GNU General Public License version 3 or later; see LICENSE
|
|
*/
|
|
|
|
namespace Joomla\Plugin\Console\MokoSuiteBackup\Command;
|
|
|
|
defined('_JEXEC') or die;
|
|
|
|
use Joomla\CMS\Factory;
|
|
use Joomla\Component\MokoSuiteBackup\Administrator\Service\BackupRunner;
|
|
use Joomla\Console\Command\AbstractCommand;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
|
|
class RunCommand extends AbstractCommand
|
|
{
|
|
protected static $defaultName = 'mokosuitebackup:run';
|
|
|
|
protected function configure(): void
|
|
{
|
|
$this->setDescription('Run a backup using a specified profile');
|
|
$this->addOption('profile', 'p', InputOption::VALUE_REQUIRED, 'Profile ID to use', '1');
|
|
$this->addOption('description', 'd', InputOption::VALUE_OPTIONAL, 'Backup description', '');
|
|
}
|
|
|
|
protected function doExecute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
$profileId = (int) $input->getOption('profile');
|
|
$desc = $input->getOption('description') ?: '';
|
|
|
|
$io->title('MokoSuiteBackup — Run Backup');
|
|
$io->text('Profile ID: ' . $profileId);
|
|
|
|
$runnerFile = JPATH_ADMINISTRATOR . '/components/com_mokosuitebackup/src/Service/BackupRunner.php';
|
|
|
|
if (!file_exists($runnerFile)) {
|
|
$io->error('MokoSuiteBackup component not installed.');
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (!class_exists(BackupRunner::class)) {
|
|
require_once $runnerFile;
|
|
}
|
|
|
|
$result = (new BackupRunner())->run($profileId, $desc ?: 'CLI backup', 'cli');
|
|
|
|
if ($result['success']) {
|
|
$io->success($result['message']);
|
|
|
|
return 0;
|
|
}
|
|
|
|
$io->error($result['message']);
|
|
|
|
return 1;
|
|
}
|
|
}
|