Файловый менеджер - Редактировать - /home/wuectly/www/03cbe/CliCommands.tar
Назад
ProfileCopy.php 0000604 00000010001 15245606736 0007512 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Exception; use FOF40\Container\Container; use FOF40\Model\DataModel\Exception\RecordNotLoaded; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:profile:copy * * Creates a copy of an Akeeba Backup profile * * @since 7.5.0 */ class ProfileCopy extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:profile:copy'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $format = (string) $this->cliInput->getOption('format') ?? 'text'; $format = in_array($format, ['text', 'json']) ? $format : 'text'; $id = (int) $this->cliInput->getArgument('id') ?? 0; $withFilters = (bool) $this->cliInput->getArgument('filters') ?? false; $container = Container::getInstance('com_akeeba'); /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); try { $source = $model->findOrFail($id); } catch (RecordNotLoaded $e) { $this->ioStyle->error(sprintf("Cannot copy profile %s; profile not found.", $id)); return 1; } $profileData = $source->getData(); unset($profileData['id']); if (!$withFilters) { $profileData['filters'] = ''; } $description = (string) $this->cliInput->getArgument('description') ?? 0; if (!is_null($description)) { $profileData['description'] = trim($description); } $profileData['quickicon'] = (bool) $this->cliInput->getArgument('quickicon') ?? $profileData['quickicon']; try { $newProfile = $model->create($profileData); } catch (Exception $e) { $this->ioStyle->error(sprintf("Cannot copy profile #%s: %s", $id, $e->getMessage())); return 2; } if ($format == 'json') { echo json_encode($newProfile->getId()); return 0; } $this->ioStyle->success(sprintf("Copy successful. Created new profile with ID %s.", $newProfile->getId())); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will create a copy of an Akeeba Backup profile. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to copy'); $this->addOption('filters', null, InputOption::VALUE_NONE, 'Include filters in the copy.', false); $this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Description for the new backup profile. Uses the old profile\'s description if not specified.', null); $this->addOption('quickicon', null, InputOption::VALUE_OPTIONAL, 'Should the new backup profile have a one-click backup icon? Copies the old profile\'s setting if not specified.', null); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'The format for the response. Use JSON to get a JSON-parseable numeric ID of the new backup profile. Values: text, json', 'text'); $this->setDescription('Creates a copy of an Akeeba Backup profile'); $this->setHelp($help); } } FilterList.php 0000604 00000015154 15245606736 0007356 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\DatabaseFilters; use Akeeba\Backup\Admin\Model\FileFilters; use Akeeba\Backup\Admin\Model\IncludeFolders; use Akeeba\Backup\Admin\Model\MultipleDatabases; use Akeeba\Backup\Admin\Model\RegExDatabaseFilters; use Akeeba\Backup\Admin\Model\RegExFileFilters; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\FilterRoots; use Akeeba\Backup\Admin\CliCommands\MixIt\IsPro; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:filter:list * * Get the filter values known to Akeeba Backup. * * @since 7.5.0 */ class FilterList extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray, IsPro, FilterRoots; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:filter:list'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $profileId = (int) ($this->cliInput->getOption('profile') ?? 1); define('AKEEBA_PROFILE', $profileId); $root = (string) ($this->cliInput->getOption('root') ?? ''); $target = (string) ($this->cliInput->getOption('target') ?? 'fs'); $type = (string) ($this->cliInput->getOption('type') ?? 'exclude'); $format = (string) ($this->cliInput->getOption('format') ?? 'table'); if (!in_array($target, ['fs', 'db'])) { $target = 'fs'; } if (!in_array($type, ['include', 'exclude', 'regex'])) { $type = 'exclude'; } if (!$this->isPro()) { $type = 'exclude'; } $roots = $this->getRoots($target); if (empty($root)) { $root = ($target == 'fs') ? '[SITEROOT]' : '[SITEDB]'; } $output = []; if (!in_array($root, $roots)) { $this->ioStyle->error(sprintf("Unknown %s root '%s'.", $target, $root)); return 1; } if ($format === 'table') { $this->ioStyle->title('List of Akeeba Backup filters matching your criteria'); } $container = Container::getInstance('com_akeeba', [], 'admin'); switch ("$target.$type") { case "fs.exclude": /** @var FileFilters $model */ $model = $container->factory->model('FileFilters')->tmpInstance(); $allFilters = $model->get_filters($root); foreach ($allFilters as $item) { $output[] = [ 'filter' => $item['node'], 'type' => $item['type'], ]; } break; case "fs.regex": /** @var RegExFileFilters $model */ $model = $container->factory->model('RegExFileFilters')->tmpInstance(); $allFilters = $model->get_regex_filters($root); foreach ($allFilters as $item) { $output[] = [ 'filter' => $item['item'], 'type' => $item['type'], ]; } break; case "fs.include": /** @var IncludeFolders $model */ $model = $container->factory->model('IncludeFolders')->tmpInstance(); $allFilters = $model->get_directories(); foreach ($allFilters as $uuid => $item) { $output[] = [ 'filter' => $uuid, 'type' => 'extradirs', 'filesystem_directory' => $item[0], 'virtual_directory' => $item[1], ]; } break; case "db.exclude": /** @var DatabaseFilters $model */ $model = $container->factory->model('DatabaseFilters')->tmpInstance(); $allFilters = $model->get_filters($root); foreach ($allFilters as $item) { $output[] = [ 'filter' => $item['node'], 'type' => $item['type'], ]; } break; case "db.regex": /** @var RegExDatabaseFilters $model */ $model = $container->factory->model('RegExDatabaseFilters')->tmpInstance(); $allFilters = $model->get_regex_filters($root); foreach ($allFilters as $item) { $output[] = [ 'filter' => $item['item'], 'type' => $item['type'], ]; } break; case "db.include": /** @var MultipleDatabases $model */ $model = $container->factory->model('MultipleDatabases')->tmpInstance(); $allFilters = $model->get_databases(); foreach ($allFilters as $uuid => $item) { $output[] = [ 'filter' => $uuid, 'type' => 'multidb', 'host' => $item['host'], 'driver' => $item['driver'], 'port' => $item['port'], 'username' => $item['username'], 'password' => $item['password'], 'database' => $item['database'], 'prefix' => $item['prefix'], 'dumpFile' => $item['dumpFile'], ]; } break; } return $this->printFormattedAndReturn($output, $format); } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will list filter values for an Akeeba Backup profile. \nUsage: <info>php %command.full_name%</info>"; $this->addOption('root', null, InputOption::VALUE_OPTIONAL, 'Which filter root to use. Defaults to [SITEROOT] or [SITEDB] depending on the --target option. Ignored for --type=include. Tip: the filesystem and database roots are the "filter" column for --type=include. There are two special roots, [SITEROOT] (the filesystem root of the Joomla site) and [SITEDB] (the main database of the Joomla site).', ''); $this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1); $this->addOption('target', null, InputOption::VALUE_OPTIONAL, 'The target of filters you want to list: fs (files and folders) or db (database)', 'fs'); $this->addOption('type', null, InputOption::VALUE_OPTIONAL, 'The type of filters you want to list: exclude, include or regex', 'exclude'); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table'); $this->setDescription('Get the filter values known to Akeeba Backup.'); $this->setHelp($help); } } BackupDownload.php 0000604 00000012564 15245606736 0010174 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Statistics; use Akeeba\Engine\Factory; use Akeeba\Engine\Platform; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:backup:download * * Returns a backup archive part for a backup record known to Akeeba Backup * * @since 7.5.0 */ class BackupDownload extends AbstractCommand { use ConfigureIO, ArgumentUtilities; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:backup:download'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $container = Container::getInstance('com_akeeba', [], 'admin'); $id = (int) $this->cliInput->getArgument('id') ?? 0; $part = (int) $this->cliInput->getArgument('part') ?? 0; $outFile = $this->cliInput->getOption('file'); if (!empty($outFile)) { $this->ioStyle->title(sprintf('Retrieving part #%d of Akeeba Backup record #%d', $part, $id)); } if ($id <= 0) { $this->ioStyle->error('Invalid backup record'); return 1; } /** @var Statistics $model */ $model = $container->factory->model('Statistics')->tmpInstance(); $model->setState('id', $id); $stat = Platform::getInstance()->get_statistics($id); $allFileNames = Factory::getStatistics()->get_all_filenames($stat); if (empty($allFileNames)) { $this->ioStyle->error(sprintf("Backup record '%s' does not have any files available for download. Have you already deleted them?", $id)); return 1; } if (is_null($allFileNames)) { $this->ioStyle->error(sprintf("Backup record '%s' does not have any files available for download on the server. If they are stored remotely you may need to use the fetch command first.", $id)); return 2; } if (($part >= (is_array($allFileNames) || $allFileNames instanceof \Countable ? count($allFileNames) : 0)) || !isset($allFileNames[$part])) { $this->ioStyle->error(sprintf("There is no part '%s' of backup record '%s'.", $part, $id)); return 3; } $fileName = $allFileNames[$part]; if (!@file_exists($fileName)) { $this->ioStyle->error(sprintf("Can not find part '%s' of backup record '%s' on the server.", $part, $id)); return 4; } $basename = @basename($fileName); $fileSize = @filesize($fileName); $extension = strtolower(str_replace(".", "", strrchr($fileName, "."))); if (empty($outFile)) { readfile($fileName); return 0; } if (is_dir($outFile)) { $outFile = rtrim($outFile, '//\\') . DIRECTORY_SEPARATOR . $basename; } else { $dotPos = strrpos($outFile, '.'); $outFile = ($dotPos === false) ? $outFile : (substr($outFile, 0, $dotPos) . '.' . $extension); } // Read in 1M chunks $blocksize = 1048576; $handle = @fopen($fileName, "r"); if ($handle === false) { $this->ioStyle->error(sprintf("Cannot open '%s' for reading. Check the permissions / ACLs of the file.", $fileName)); return 5; } $fp = @fopen($outFile, 'w'); if ($fp === false) { fclose($handle); $this->ioStyle->error(sprintf("Cannot open '%s' for writing. Check whether the folder exists and the permissions / ACLs of both the enclosing folder and the file.", $outFile)); return 6; } $progress = $this->ioStyle->createProgressBar($fileSize); $runningSize = 0; $progress->display(); while (!@feof($handle)) { $data = @fread($handle, $blocksize); $readLength = strlen($data); $runningSize += $readLength; fwrite($fp, $data); $progress->setProgress($readLength); } $progress->finish(); $this->ioStyle->newLine(2); @fclose($handle); @fclose($fp); $this->ioStyle->success(sprintf('Downloaded part %d of backup record #%d into file %s', $part, $id, $outFile)); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will output or write a file with a backup archive part of a backup record known to Akeeba Backup \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('id', InputArgument::REQUIRED, 'The id of the backup record to retrieve archives for'); $this->addArgument('part', InputArgument::OPTIONAL, 'The part number of the backup archive to retrieve'); $this->addOption('file', null, InputOption::VALUE_OPTIONAL, 'File path to write to. Will output to STDOUT if not defined.'); $this->setDescription('Returns a backup archive part for a backup record known to Akeeba Backup'); $this->setHelp($help); } } ProfileImport.php 0000604 00000007760 15245606736 0010074 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Exception; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:profile:import * * Imports an Akeeba Backup profile from a JSON string. * * @since 7.5.0 */ class ProfileImport extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:profile:import'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $filename = (string) $this->cliInput->getArgument('fileOrJSON') ?? ''; $json = $this->getJSON($filename); try { $decoded = @json_decode($json, true); } catch (Exception $e) { $decoded = ''; } if (empty($decoded)) { $this->ioStyle->error("Cannot process input; invalid JSON string or file not found."); return 1; } // We must never pass an ID, forcing the model to create a new record if (isset($decoded['id'])) { unset($decoded['id']); } $container = Container::getInstance('com_akeeba'); /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); try { $newProfile = $model->create($decoded); } catch (Exception $e) { $this->ioStyle->error(sprintf("Cannot import profile: %s", $e->getMessage())); return 2; } $id = $newProfile->getId(); $format = (string) $this->cliInput->getOption('format') ?? 'text'; if ($format == 'json') { echo json_encode($id); return 0; } $this->ioStyle->success(sprintf("Successfully imported JSON as profile #%s", $id)); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will import an Akeeba Backup profile from a JSON string. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('fileOrJSON', InputOption::VALUE_OPTIONAL, 'A path to an Akeeba Backup profile export JSON file or a literal JSON string. Uses STDIN if omitted.'); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'The format for the response. Use json to get a JSON-parseable numeric ID of the new backup profile. Values: json, text', 'text'); $this->setDescription('Imports an Akeeba Backup profile from a JSON string'); $this->setHelp($help); } /** * Get the JSON input * * @param string|null $filename The filename to read from, raw JSON data or an empty string * * @return string The JSON data * * @since 7.5.0 */ private function getJSON(?string $filename): string { // No filename or JSON string passed to script; use STDIN if (empty($filename)) { $json = ''; while (!feof(STDIN)) { $json .= fgets(STDIN) . "\n"; } return rtrim($json); } // An existing file path was passed. Return the contents of the file. if (@file_exists($filename)) { $ret = @file_get_contents($filename); if ($ret === false) { return ''; } } // Otherwise assume raw JSON was passed back to us. return $filename; } } SysconfigGet.php 0000604 00000005331 15245606736 0007675 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ComponentOptions; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:sysconfig:get * * Gets the value of an Akeeba Backup component-wide option * * @since 7.5.0 */ class SysconfigGet extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray, ComponentOptions; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:sysconfig:get'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $key = (string) $this->cliInput->getArgument('key') ?? ''; $format = (string) $this->cliInput->getOption('format') ?? 'table'; $options = $this->getComponentOptions(); if (!array_key_exists($key, $options)) { $this->ioStyle->error(sprintf('Cannot find option “%s”.', $key)); return 1; } $value = $options[$key] ?? ''; switch ($format) { case 'text': default: echo $value; break; case 'json': echo json_encode($value); break; case 'print_r': print_r($value); break; case 'var_dump': var_dump($value); break; case 'var_export': var_export($value); break; } return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will get the value of an Akeeba Backup component-wide option. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('key', null, InputOption::VALUE_REQUIRED, 'The option key to retrieve'); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: text, json, print_r, var_dunp, var_export.', 'text'); $this->setDescription('Gets the value of an Akeeba Backup component-wide option'); $this->setHelp($help); } } BackupInfo.php 0000604 00000004565 15245606736 0007322 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Engine\Platform; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:backup:info * * Lists a backup record known to Akeeba Backup * * @since 7.5.0 */ class BackupInfo extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:backup:info'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $id = (int) $this->cliInput->getArgument('id') ?? 0; $format = (string) ($this->cliInput->getOption('format') ?? 'table'); if ($format === 'table') { $this->ioStyle->title(sprintf('Information for Akeeba Backup record #%d', $id)); } $record = Platform::getInstance()->get_statistics($id); return $this->printFormattedAndReturn($record, $format); } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will list a backup record known to Akeeba Backup \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('id', InputArgument::REQUIRED, 'The id of the backup record to list'); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table'); $this->setDescription('Lists a backup record known to Akeeba Backup'); $this->setHelp($help); } } ProfileDelete.php 0000604 00000005342 15245606736 0010016 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Exception; use FOF40\Container\Container; use FOF40\Model\DataModel\Exception\RecordNotLoaded; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:profile:delete * * Delete an Akeeba Backup profile * * @since 7.5.0 */ class ProfileDelete extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:profile:delete'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $id = (int) $this->cliInput->getArgument('id') ?? 0; if ($id === 1) { $this->ioStyle->error('You cannot delete the default backup profile (#1)'); } $container = Container::getInstance('com_akeeba'); /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); try { $profile = $model->findOrFail($id); } catch (RecordNotLoaded $e) { $this->ioStyle->error(sprintf("Cannot delete profile %s; profile not found.", $id)); return 2; } try { $newProfile = $model->forceDelete($profile->getId()); } catch (Exception $e) { $this->ioStyle->error(sprintf("Cannot delete profile #%s: %s", $id, $e->getMessage())); return 3; } $this->ioStyle->success(sprintf("Profile #%d has been deleted.", $newProfile->getId())); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will delete an Akeeba Backup profile. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to delete'); $this->setDescription('Delete an Akeeba Backup profile'); $this->setHelp($help); } } SysconfigSet.php 0000604 00000006056 15245606736 0007716 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Helper\SecretWord; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ComponentOptions; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:sysconfig:set * * Sets the value of an Akeeba Backup component-wide option * * @since 7.5.0 */ class SysconfigSet extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray, ComponentOptions; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:sysconfig:set'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $key = (string) $this->cliInput->getArgument('key') ?? ''; $value = (string) $this->cliInput->getArgument('value') ?? ''; $format = (string) $this->cliInput->getOption('format') ?? 'table'; $options = $this->getComponentOptions(); if (!array_key_exists($key, $options)) { $this->ioStyle->error(sprintf('Cannot find option “%s”.', $key)); return 1; } if ((string) $options[$key] === $value) { return 0; } $container = Container::getInstance('com_akeeba'); $container->params->set($key, $value); $container->params->save(); // Make sure the front-end backup Secret Word is stored encrypted $params = $container->params; SecretWord::enforceEncryption($params, 'frontend_secret_word'); $this->ioStyle->success(sprintf('Set component option “%s” to “%s”', $key, $value)); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will set the value of an Akeeba Backup component-wide option. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('key', null, InputOption::VALUE_REQUIRED, 'The option key to set'); $this->addArgument('value', null, InputOption::VALUE_REQUIRED, 'The option value to set'); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: text, json, print_r, var_dunp, var_export.', 'text'); $this->setDescription('Sets the value of an Akeeba Backup component-wide option'); $this->setHelp($help); } } ProfileReset.php 0000604 00000006527 15245606736 0007704 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Akeeba\Engine\Platform; use Exception; use FOF40\Container\Container; use FOF40\Model\DataModel\Exception\RecordNotLoaded; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:profile:reset * * Resets an Akeeba Backup profile * * @since 7.5.0 */ class ProfileReset extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:profile:reset'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $id = (int) $this->cliInput->getArgument('id') ?? 0; $filters = (bool) $this->cliInput->getOption('filters') ?? false; $configuration = (bool) $this->cliInput->getOption('configuration') ?? false; $container = Container::getInstance('com_akeeba'); /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); try { $profile = $model->findOrFail($id); } catch (RecordNotLoaded $e) { $this->ioStyle->error(sprintf("Cannot modify profile %s; profile not found.", $id)); return 1; } if ($filters) { $profile->filters = ''; } if ($configuration) { $profile->configuration = ''; } try { $newProfile = $profile->save(); } catch (Exception $e) { $this->ioStyle->error(sprintf("Cannot reset profile #%s: %s", $id, $e->getMessage())); return 2; } /** * Loading the new profile's empty configuration causes the Platform code to revert to the default options and * save them automatically to the database. */ if ($configuration) { Platform::getInstance()->load_configuration($id); } $this->ioStyle->success(sprintf("Profile #%s reset successfully.", $newProfile->getId())); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will resets an Akeeba Backup profile. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to modify'); $this->addOption('filters', null, InputOption::VALUE_NONE, 'Reset the filters?', false); $this->addOption('configuration', null, InputOption::VALUE_NONE, 'Reset the configuration?', false); $this->setDescription('Resets an Akeeba Backup profile'); $this->setHelp($help); } } FilterDelete.php 0000604 00000010531 15245606736 0007637 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Engine\Factory; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\FilterRoots; use Akeeba\Backup\Admin\CliCommands\MixIt\IsPro; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:filter:delete * * Delete a filter value known to Akeeba Backup. * * @since 7.5.0 */ class FilterDelete extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray, IsPro, FilterRoots; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:filter:delete'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $profileId = (int) ($this->cliInput->getOption('profile') ?? 1); define('AKEEBA_PROFILE', $profileId); $filterType = (string) ($this->cliInput->getOption('filterType') ?? 'files'); $target = (in_array($filterType, [ 'tables', 'tabledata', 'regextables', 'regextabledata', 'multidb', ])) ? 'db' : 'fs'; $root = (string) ($this->cliInput->getOption('root') ?? (($target == 'fs') ? '[SITEROOT]' : '[SITEDB]')); if (!in_array($root, $this->getRoots($target))) { $this->ioStyle->error(sprintf("Unknown %s root '%s'.", $target, $root)); return 1; } $filter = (string) $this->cliInput->getArgument('filter') ?? ''; $this->ioStyle->title(sprintf( 'Deleting %s filter “%s” of type %s from profile #%d', $target === 'db' ? 'database' : 'filesystem', $filter, $filterType, $profileId )); // Delete the filter $filterObject = Factory::getFilterObject($filterType); if ((stripos($filterType, 'regex') !== false) && !$this->isPro()) { $this->ioStyle->error(sprintf("Filters of the '%s' type are only available with Akeeba Backup Professional.", $filterType)); return 2; } switch ($filterType) { case 'extradirs': case 'multidb': if (!$this->isPro()) { $this->ioStyle->error(sprintf("Filters of the '%s' type are only available with Akeeba Backup Professional.", $filterType)); return 2; } $success = $filterObject->remove($filter); break; default: $success = $filterObject->remove($root, $filter); break; } if (!$success) { $this->ioStyle->error(sprintf("Could not delete filter '%s' of type '%s'.", $filter, $filterType)); return 3; } Factory::getFilters()->save(); $this->ioStyle->success(sprintf("Deleted filter '%s' of type '%s'.", $filter, $filterType)); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will delete a filter value known to Akeeba Backup. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('filter', InputArgument::REQUIRED, 'The filter name to delete'); $this->addOption('root', null, InputOption::VALUE_OPTIONAL, 'Which filter root to use. Defaults to [SITEROOT] or [SITEDB] depending on the fitler type.', ''); $this->addOption('filterType', null, InputOption::VALUE_REQUIRED, 'The type of filter you want to delete: files, directories, skipdirs, skipfiles, regexfiles, regexdirectories, regexskipdirs, regexskipfiles, tables, tabledata, regextables, regextabledata, extradirs, multidb', 'files'); $this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1); $this->setDescription('Delete a filter value known to Akeeba Backup.'); $this->setHelp($help); } } MixIt/IsPro.php 0000604 00000001477 15245606736 0007366 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands\MixIt; defined('_JEXEC') || die; /** * Is this Akeeba Backup Pro? * * @since 7.5.0 */ trait IsPro { /** * Caches whether this is the Pro version of the software. * * @var null|bool * @since 7.5.0 */ private $isPro = null; /** * is this the Professional version of the software? * * @return bool * @since 7.5.0 */ private function isPro(): bool { if (!is_null($this->isPro)) { return $this->isPro; } $componentFolder = JPATH_ADMINISTRATOR . '/components/com_akeeba'; $this->isPro = is_dir($componentFolder . '/AliceEngine'); return $this->isPro; } } MixIt/FilterRoots.php 0000604 00000002115 15245606736 0010574 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands\MixIt; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\DatabaseFilters; use Akeeba\Engine\Factory; use FOF40\Container\Container; trait FilterRoots { /** * @param string $target * * @return array * * @since 7.5.0 */ private function getRoots(string $target): array { $container = Container::getInstance('com_akeeba', [], 'admin'); $filters = Factory::getFilters(); $output = []; switch ($target) { case 'fs': $rootInfo = $filters->getInclusions('dir'); foreach ($rootInfo as $item) { $output[] = $item[0]; } break; case 'db': /** @var DatabaseFilters $model */ $model = $container->factory->model('DatabaseFilters')->tmpInstance(); $rootInfo = $model->get_roots(); foreach ($rootInfo as $item) { $output[] = $item->value; } break; } return $output; } } MixIt/JsonGuiDataParser.php 0000604 00000010626 15245606736 0011653 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands\MixIt; defined('_JEXEC') || die; use Akeeba\Engine\Factory; trait JsonGuiDataParser { /** * Parse the JSON GUI definition returned by Akeeba Engine into something I can use to provide information about * the options. * * @return array * * @since 7.5.0 */ private function parseJsonGuiData(): array { $jsonGUIData = Factory::getEngineParamsProvider()->getJsonGuiDefinition(); $guiData = json_decode($jsonGUIData, true); $ret = [ 'engines' => [], 'installers' => [], 'options' => [], ]; // Parse engines foreach ($guiData['engines'] as $engineType => $engineRecords) { if (!isset($ret['engines'][$engineType])) { $ret['engines'][$engineType] = []; } foreach ($engineRecords as $engineName => $record) { $ret['engines'][$engineType][$engineName] = [ 'title' => $record['information']['title'], 'description' => $record['information']['description'], ]; foreach ($record['parameters'] as $key => $optionRecord) { $ret['options'][$key] = array_merge($optionRecord, [ 'section' => $record['information']['title'], ]); } } } // Parse installers foreach ($guiData['installers'] as $installerName => $installerInfo) { $ret['installers'][$installerName] = $installerInfo['name']; } // Parse GUI sections foreach ($guiData['gui'] as $section => $options) { foreach ($options as $key => $optionRecord) { $ret['options'][$key] = array_merge($optionRecord, [ 'section' => $section, ]); } } return $ret; } /** * Flattens the option tree returned by exportToJson into an array with dotted notation for each option. * * @param array $rawOptions The option tree * @param string $prefix Current prefix, used for recursion * * @return array * @since 7.5.0 */ private function flattenOptions(array $rawOptions, string $prefix = ''): array { $ret = []; foreach ($rawOptions as $k => $v) { if (is_array($v)) { $ret = array_merge($ret, $this->flattenOptions($v, $prefix . $k . '.')); continue; } $ret[$prefix . $k] = $v; } return $ret; } /** * Get the information for an option record. * * @param string $key The option key * @param array $info The array returned by parseJsonGuiData * * @return array * * @since 7.5.0 */ private function getOptionInfo(string $key, array &$info): array { $ret = []; if (!isset($info['options'][$key])) { return $ret; } $keyInfo = $info['options'][$key]; $ret = [ 'title' => $keyInfo['title'], 'description' => $keyInfo['description'], 'section' => $keyInfo['section'], 'type' => $keyInfo['type'], 'default' => $keyInfo['default'], 'options' => [], 'optionTitles' => [], 'limits' => [], ]; switch ($keyInfo['type']) { case 'integer': if (isset($keyInfo['shortcuts'])) { $ret['options'] = explode('|', $keyInfo['shortcuts']); } $ret['limits'] = [ 'min' => $keyInfo['min'], 'max' => $keyInfo['max'], ]; break; case 'bool': $ret['type'] = 'integer'; $ret['options'] = [0, 1]; $ret['limits'] = [ 'min' => 0, 'max' => 1, ]; break; case 'engine': $ret['type'] = 'enum'; $ret['type'] = 'string'; $ret['options'] = array_keys($info['engines'][$keyInfo['subtype']]); $ret['optionTitles'] = []; foreach ($info['engines'][$keyInfo['subtype']] as $k => $details) { $ret['optionTitles'][$k] = $details['title']; } break; case 'installer': $ret['type'] = 'enum'; $ret['type'] = 'string'; $ret['options'] = array_keys($info['installers']); $ret['optionTitles'] = $info['installers']; break; case 'enum': $ret['type'] = 'string'; $ret['options'] = explode('|', $keyInfo['enumvalues']); $ret['optionTitles'] = explode('|', $keyInfo['enumkeys']); break; case 'hidden': case 'button': case 'separator': $ret['type'] = 'hidden'; break; case 'string': case 'browsedir': case 'password': default: $ret['type'] = 'string'; break; } return $ret; } } MixIt/PrintFormattedArray.php 0000604 00000005441 15245606736 0012266 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands\MixIt; trait PrintFormattedArray { /** * Prints the array formatted with the specific format and returns an integer result * * @param array $data The data to format and print * @param string $format One of table, json, yaml, csv, count * * @return int * @since 7.5.0 */ private function printFormattedAndReturn(?array $data, string $format): int { if (empty($data) && ($format != 'count')) { return 0; } elseif (empty($data)) { $data = []; } if (!empty($data)) { $keys = array_keys($data); $firstKey = array_shift($keys); $row = $data[$firstKey]; if (is_array($row)) { $headers = array_keys($row); } else { $headers = array_keys($data); if (!in_array($format, ['json', 'yaml'])) { $data = [$data]; } } } switch ($format) { default: case 'table': $this->ioStyle->table($headers, $data); break; case 'json': $this->ioStyle->writeln(json_encode($data, JSON_PRETTY_PRINT)); break; case 'yaml': if (!function_exists('yaml_emit')) { $this->ioStyle->error(<<< ERROR Cannot generate YAML Your PHP installation does not have the PHP YAML extension installed or enabled. ERROR ); return 1; } $this->ioStyle->writeln(yaml_emit($data)); break; case 'csv': $this->ioStyle->writeln($this->toCsv($data)); break; case 'count': $this->ioStyle->writeln(count($data)); break; } return 0; } /** * Converts an array to its CSV representation * * @param array $data The array data to convert to CSV * @param bool $csvHeader Should I print a CSV header row? * * @return string * @since 7.5.0 */ private function toCsv(array $data, bool $csvHeader = true): string { $output = ''; $item = array_pop($data); $data[] = $item; $keys = array_keys($item); if ($csvHeader) { $csv = []; foreach ($keys as $k) { $k = str_replace('"', '""', $k); $k = str_replace("\r", '\\r', $k); $k = str_replace("\n", '\\n', $k); $k = '"' . $k . '"'; $csv[] = $k; } $output .= implode(",", $csv) . "\r\n"; } foreach ($data as $item) { $csv = []; foreach ($keys as $k) { $v = $item[$k]; if (is_array($v)) { $v = 'Array'; } elseif (is_object($v)) { $v = 'Object'; } $v = str_replace('"', '""', $v); $v = str_replace("\r", '\\r', $v); $v = str_replace("\n", '\\n', $v); $v = '"' . $v . '"'; $csv[] = $v; } $output .= implode(",", $csv) . "\r\n"; } return $output; } } MixIt/ComponentOptions.php 0000604 00000002505 15245606736 0011641 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands\MixIt; defined('_JEXEC') || die; use Akeeba\Engine\Platform; use Joomla\CMS\Form\Form; use Joomla\CMS\Form\FormField; trait ComponentOptions { private function getComponentOptions(bool $defaultValuesOnly = false): array { $output = []; $fieldNames = []; $form = new Form('config'); $form->loadFile(JPATH_ADMINISTRATOR . '/components/com_akeeba/config.xml', true, '//config'); foreach ($form->getFieldsets() as $group => $fieldSetInfo) { $fields = $form->getFieldset($group); if (empty($fields)) { continue; } foreach ($fields as $fieldName => $v) { if (!is_object($v) || !($v instanceof FormField)) { continue; } if (substr((string) $v->type, -5) === 'Rules') { continue; } if (in_array(strtolower((string) $v->type), ['hidden', 'rules', 'spacer'])) { continue; } $fieldNames[$fieldName] = $v->value ?? null; } } if (!$defaultValuesOnly) { foreach ($fieldNames as $k => $default) { $output[$k] = Platform::getInstance()->get_platform_configuration_option($k, $default); } } return $output; } } MixIt/ConfigureIO.php 0000604 00000002036 15245606736 0010473 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands\MixIt; defined('_JEXEC') || die; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; /** * Set up the Symfony I/O objects * * @since 7.5.0 */ trait ConfigureIO { /** * @var SymfonyStyle * @since 7.5.0 */ private $ioStyle; /** * @var InputInterface * @since 7.5.0 */ private $cliInput; /** * Configure the IO. * * @param InputInterface $input The input to inject into the command. * @param OutputInterface $output The output to inject into the command. * * @return void * * @since 7.5.0 */ private function configureSymfonyIO(InputInterface $input, OutputInterface $output) { $this->cliInput = $input; $this->ioStyle = new SymfonyStyle($input, $output); } } MixIt/TimeInfo.php 0000604 00000004257 15245606736 0010043 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands\MixIt; defined('_JEXEC') || die; /** * Utility methods to get time information * * @since 7.5.0 */ trait TimeInfo { /** * Returns a fancy formatted time lapse code * * @param integer $referenceDateTime Timestamp of the reference date/time * @param int|null $currentDateTime Timestamp of the current date/time * @param string $measureBy One of s, m, h, d, or y (time unit) * @param boolean $autoText Append text automatically? * * @return string * * @since 7.5.0 */ private function timeAgo(int $referenceDateTime = 0, ?int $currentDateTime = null, string $measureBy = '', bool $autoText = true): string { if (is_null($currentDateTime)) { $currentDateTime = time(); } // Raw time difference $raw = $currentDateTime - $referenceDateTime; $clean = abs($raw); $calcNum = [ ['s', 60], ['m', 60 * 60], ['h', 60 * 60 * 60], ['d', 60 * 60 * 60 * 24], ['y', 60 * 60 * 60 * 24 * 365], ]; $calc = [ 's' => [1, 'second'], 'm' => [60, 'minute'], 'h' => [60 * 60, 'hour'], 'd' => [60 * 60 * 24, 'day'], 'y' => [60 * 60 * 24 * 365, 'year'], ]; if ($measureBy == '') { $usemeasure = 's'; for ($i = 0; $i < count($calcNum); $i++) { if ($clean <= $calcNum[$i][1]) { $usemeasure = $calcNum[$i][0]; $i = count($calcNum); } } } else { $usemeasure = $measureBy; } $datedifference = floor($clean / $calc[$usemeasure][0]); if ($autoText == true && ($currentDateTime == time())) { if ($raw < 0) { $prospect = ' from now'; } else { $prospect = ' ago'; } } else { $prospect = ''; } if ($referenceDateTime != 0) { if ($datedifference == 1) { return $datedifference . ' ' . $calc[$usemeasure][1] . ' ' . $prospect; } else { return $datedifference . ' ' . $calc[$usemeasure][1] . 's ' . $prospect; } } else { return 'No input time referenced.'; } } } MixIt/ArgumentUtilities.php 0000604 00000002173 15245606736 0012002 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands\MixIt; defined('_JEXEC') || die; /** * Utility methods to manage command arguments * * @since 7.5.0 */ trait ArgumentUtilities { /** * Parse the overrides provided in the command line. * * Input: "key1=value1, key2= value2, key3 = value3" * Output: ['key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'] * * @param string $rawString The raw string * * @return array The parsed overrides * * @since 7.5.0 */ private function commaListToMap(string $rawString): array { if (empty($rawString) || (trim($rawString) == '')) { return []; } $rawString = trim($rawString); $ret = []; $lines = explode($rawString, ","); foreach ($lines as $line) { if (strpos($line, '=') === false) { continue; } [$key, $value] = explode('=', $line); $key = trim($key); $value = trim($value); $ret[$key] = $value; } return $ret; } } MixIt/MemoryInfo.php 0000604 00000002175 15245606736 0010412 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands\MixIt; defined('_JEXEC') || die; /** * Utility methods to get memory information * * @since 7.5.0 */ trait MemoryInfo { /** * Returns the current memory usage * * @return string * * @since 7.5.0 */ private function memUsage(): string { if (function_exists('memory_get_usage')) { $size = memory_get_usage(); $unit = ['b', 'KB', 'MB', 'GB', 'TB', 'PB']; return @round($size / 1024 ** ($i = floor(log($size, 1024))), 2) . ' ' . $unit[$i]; } else { return "(unknown)"; } } /** * Returns the peak memory usage * * @return string * * @since 7.5.0 */ private function peakMemUsage(): string { if (function_exists('memory_get_peak_usage')) { $size = memory_get_peak_usage(); $unit = ['b', 'KB', 'MB', 'GB', 'TB', 'PB']; return @round($size / 1024 ** ($i = floor(log($size, 1024))), 2) . ' ' . $unit[$i]; } else { return "(unknown)"; } } } SysconfigList.php 0000604 00000004447 15245606736 0010100 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ComponentOptions; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:sysconfig:list * * Lists the Akeeba Backup component-wide options * * @since 7.5.0 */ class SysconfigList extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray, ComponentOptions; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:sysconfig:list'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $format = (string) $this->cliInput->getOption('format') ?? 'table'; $output = $this->getComponentOptions(); if (in_array($format, ['table', 'csv'])) { $temp = []; foreach ($output as $k => $v) { $temp[] = [ 'key' => $k, 'value' => $v, ]; } $output = $temp; } return $this->printFormattedAndReturn($output, $format); } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will list the Akeeba Backup component-wide options. \nUsage: <info>php %command.full_name%</info>"; $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table'); $this->setDescription('Lists the Akeeba Backup component-wide options'); $this->setHelp($help); } } BackupModify.php 0000604 00000006237 15245606736 0007654 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Engine\Platform; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:backup:modify * * Modifies a backup record known to Akeeba Backup * * @since 7.5.0 */ class BackupModify extends AbstractCommand { use ConfigureIO, ArgumentUtilities; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:backup:modify'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $id = (int) $this->cliInput->getArgument('id') ?? 0; $description = $this->cliInput->getOption('description'); $comment = $this->cliInput->getOption('comment'); $this->ioStyle->title(sprintf('Modifying Akeeba Backup record #%d', $id)); if ($id <= 0) { $this->ioStyle->error('Invalid backup record'); return 1; } if (is_null($description) && is_null($comment)) { $this->ioStyle->error('You must specify one or both of --description and --comment'); return 2; } $record = Platform::getInstance()->get_statistics($id); if (empty($record)) { $this->ioStyle->error('Invalid backup record'); return 1; } if (!is_null($description)) { $record['description'] = (string) $description; } if (!is_null($comment)) { $record['comment'] = (string) $comment; } $result = Platform::getInstance()->set_or_update_statistics($id, $record); if ($result === false) { $this->ioStyle->error(sprintf('Cannot modify backup record #%d', $id)); return 3; } $this->ioStyle->success(sprintf('Backup record #%d has been modified.', $id)); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will modify a backup record known to Akeeba Backup \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('id', InputArgument::REQUIRED, 'The id of the backup record to modify'); $this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Change the short description to this value.'); $this->addOption('comment', null, InputOption::VALUE_OPTIONAL, 'Change the backup comment to this value (accepts HTML).'); $this->setDescription('Modifies a backup record known to Akeeba Backup'); $this->setHelp($help); } } ProfileCreate.php 0000604 00000007327 15245606736 0010024 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Akeeba\Engine\Platform; use Exception; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:profile:create * * Creates a new Akeeba Backup profile * * @since 7.5.0 */ class ProfileCreate extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:profile:create'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $format = (string) $this->cliInput->getOption('format') ?? 'text'; $format = in_array($format, ['text', 'json']) ? $format : 'text'; $container = Container::getInstance('com_akeeba'); /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); // Set up the new profile data $profileData = [ 'description' => 'New backup profile', 'quickicon' => '1', 'configuration' => '', 'filters' => '', ]; $description = (string) $this->cliInput->getArgument('description') ?? 0; if (!is_null($description)) { $profileData['description'] = trim($description); } $profileData['quickicon'] = ((bool) $this->cliInput->getArgument('quickicon') ?? true) ? 1 : 0; try { $newProfile = $model->create($profileData); } catch (Exception $e) { $this->ioStyle->error(sprintf("Cannot create profile: %s", $e->getMessage())); return 2; } /** * Create a new profile configuration. * * Loading the new profile's empty configuration causes the Platform code to revert to the default options and * save them automatically to the database. */ $profileId = $newProfile->getId(); Platform::getInstance()->load_configuration($profileId); if ($format == 'json') { echo json_encode($newProfile->getId()); return 0; } $this->ioStyle->success(sprintf("Created new profile with ID %s.", $newProfile->getId())); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will create a new Akeeba Backup profile. \nUsage: <info>php %command.full_name%</info>"; $this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Description for the new backup profile. Default: "New backup profile".', 'New backup profile'); $this->addOption('quickicon', null, InputOption::VALUE_OPTIONAL, 'Should the new backup profile have a one-click backup icon? Default: 1', 1); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'The format for the response. Use JSON to get a JSON-parseable numeric ID of the new backup profile. Values: text, json', 'text'); $this->setDescription('Creates a new Akeeba Backup profile'); $this->setHelp($help); } } OptionsList.php 0000604 00000012350 15245606736 0007557 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Akeeba\Engine\Factory; use Akeeba\Engine\Platform; use FOF40\Container\Container; use FOF40\Model\DataModel\Exception\RecordNotLoaded; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\JsonGuiDataParser; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:option:list * * Lists the configuration options for an Akeeba Backup profile, including their titles * * @since 7.5.0 */ class OptionsList extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray, JsonGuiDataParser; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:option:list'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $container = Container::getInstance('com_akeeba'); $profileId = (int) ($this->cliInput->getOption('profile') ?? 1); define('AKEEBA_PROFILE', $profileId); $format = (string) $this->cliInput->getOption('format') ?? 'table'; /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); try { $model->findOrFail($profileId); } catch (RecordNotLoaded $e) { $this->ioStyle->error(sprintf("Could not find profile #%s.", $profileId)); return 1; } unset($model); // Get the profile's configuration Platform::getInstance()->load_configuration($profileId); $config = Factory::getConfiguration(); $rawJson = $config->exportAsJSON(); unset($config); // Get the key information from the GUI data $info = $this->parseJsonGuiData(); // Convert the INI data we got into an array we can print $rawValues = json_decode($rawJson, true); unset($rawJson); $output = []; $rawValues = $this->flattenOptions($rawValues); foreach ($rawValues as $key => $v) { $output[$key] = array_merge([ 'key' => $key, 'value' => $v, 'title' => '', 'description' => '', 'type' => '', 'default' => '', 'section' => '', 'options' => [], 'optionTitles' => [], 'limits' => [], ], $this->getOptionInfo($key, $info)); } // Filter the returned options $filter = (string) $this->cliInput->getOption('filter') ?? ''; $output = array_filter($output, function ($item) use ($filter) { if (!empty($filter) && strpos($item['key'], $filter) === false) { return false; } return $item['type'] != 'hidden'; }); // Sort the results $sort = (string) $this->cliInput->getOption('sort-by') ?? 'none'; $order = (string) $this->cliInput->getOption('sort-order') ?? 'asc'; if ($sort != 'none') { usort($output, function ($a, $b) use ($sort, $order) { if ($a[$sort] == $b[$sort]) { return 0; } $signChange = ($order == 'asc') ? 1 : -1; $isGreater = $a[$sort] > $b[$sort] ? 1 : -1; return $signChange * $isGreater; }); } // Output the list if (empty($output)) { $this->ioStyle->error("No options found matching your criteria."); return 2; } if ($format === 'table') { $output = array_map(function (array $optionDef) { return array_map(function ($value) { return is_array($value) ? implode(', ', $value) : $value; }, $optionDef); }, $output); } return $this->printFormattedAndReturn($output, $format); } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will list the configuration options for an Akeeba Backup profile, including their titles. \nUsage: <info>php %command.full_name%</info>"; $this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1); $this->addOption('filter', null, InputOption::VALUE_OPTIONAL, 'Only return records whose keys begin with the given filter.', ''); $this->addOption('sort-by', null, InputOption::VALUE_OPTIONAL, 'Sort the output by the given column: none, key, value, type, default, title, description, section', 'none'); $this->addOption('sort-order', null, InputOption::VALUE_OPTIONAL, 'Sort order: asc, desc.', 'desc'); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table'); $this->setDescription('Lists the configuration options for an Akeeba Backup profile, including their titles'); $this->setHelp($help); } } BackupList.php 0000604 00000012426 15245606736 0007335 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Statistics; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:backup:list * * Lists backup records known to Akeeba Backup * * @since 7.5.0 */ class BackupList extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:backup:list'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $from = (int) ($this->cliInput->getOption('from') ?? 0); $limit = (int) ($this->cliInput->getOption('limit') ?? 0); $format = (string) ($this->cliInput->getOption('format') ?? 'table'); $filters = $this->getFilters(); $order = $this->getOrdering(); if ($format === 'table') { $this->ioStyle->title('List of Akeeba Backup records matching your criteria'); } $container = Container::getInstance('com_akeeba', [], 'admin'); /** @var Statistics $model */ $model = $container->factory->model('Statistics')->tmpInstance(); $model->setState('limitstart', $from); $model->setState('limit', $limit); $output = $model->getStatisticsListWithMeta(false, $filters, $order); return $this->printFormattedAndReturn($output, $format); } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will list backup records known to Akeeba Backup \nUsage: <info>php %command.full_name%</info>"; $this->addOption('from', null, InputOption::VALUE_OPTIONAL, 'How many backup records to skip before starting the output.', 0); $this->addOption('limit', null, InputOption::VALUE_OPTIONAL, 'Maximum number of backup records to display.', 50); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table'); $this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Listed backup records must match this (partial) description.'); $this->addOption('after', null, InputOption::VALUE_OPTIONAL, 'List backup records taken after this date.'); $this->addOption('before', null, InputOption::VALUE_OPTIONAL, 'List backup records taken before this date.'); $this->addOption('origin', null, InputOption::VALUE_OPTIONAL, 'List backups from this origin only: backend, frontend, json, cli.'); $this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'List backups taken with this profile. Give the numeric profile ID.'); $this->addOption('sort-by', null, InputOption::VALUE_OPTIONAL, 'Sort the output by the given column: id, description, profile_id, backupstart', 'id'); $this->addOption('sort-order', null, InputOption::VALUE_OPTIONAL, 'Sort order: asc, desc.', 'desc'); $this->setDescription('Lists backup records known to Akeeba Backup'); $this->setHelp($help); } private function getFilters(): ?array { $filters = []; $description = $this->cliInput->getOption('description') ?? ''; if ($description) { $filters[] = [ 'field' => 'description', 'operand' => 'LIKE', 'value' => $description, ]; } $after = $this->cliInput->getOption('after') ?? ''; $before = $this->cliInput->getOption('before') ?? ''; if (!empty($after) && !empty($before)) { $filters[] = [ 'field' => 'backupstart', 'operand' => 'BETWEEN', 'value' => $after, 'value2' => $before, ]; } elseif (!empty($after)) { $filters[] = [ 'field' => 'backupstart', 'operand' => '>=', 'value' => $after, ]; } elseif (!empty($before)) { $filters[] = [ 'field' => 'backupstart', 'operand' => '<=', 'value' => $before, ]; } $origin = $this->cliInput->getOption('origin') ?? ''; if (!empty($origin)) { $filters[] = [ 'field' => 'origin', 'operand' => '=', 'value' => $origin, ]; } $profile = (int) ($this->cliInput->getOption('profile') ?? 0); if ($profile > 0) { $filters[] = [ 'field' => 'profile_id', 'operand' => '=', 'value' => $profile, ]; } return !empty($filters) ? $filters : null; } private function getOrdering(): array { $order = strtolower($this->cliInput->getOption('sort-order') ?? 'desc'); $order = in_array($order, ['asc', 'desc']) ?: 'desc'; return [ 'by' => $this->cliInput->getOption('sort-by') ?? 'id', 'order' => $order, ]; } } FilterExclude.php 0000604 00000010135 15245606736 0010026 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Engine\Factory; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\FilterRoots; use Akeeba\Backup\Admin\CliCommands\MixIt\IsPro; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:filter:exclude * * Set an exclusion filter to Akeeba Backup. * * @since 7.5.0 */ class FilterExclude extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray, IsPro, FilterRoots; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:filter:exclude'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $profileId = (int) ($this->cliInput->getOption('profile') ?? 1); define('AKEEBA_PROFILE', $profileId); $filterType = (string) ($this->cliInput->getOption('filterType') ?? 'files'); $target = (in_array($filterType, [ 'tables', 'tabledata', 'regextables', 'regextabledata', 'multidb', ])) ? 'db' : 'fs'; $root = (string) ($this->cliInput->getOption('root') ?? (($target == 'fs') ? '[SITEROOT]' : '[SITEDB]')); if (!in_array($root, $this->getRoots($target))) { $this->ioStyle->error(sprintf("Unknown %s root '%s'.", $target, $root)); return 1; } $filter = (string) $this->cliInput->getArgument('filter') ?? ''; $this->ioStyle->title(sprintf( 'Adding %s filter “%s” of type %s to profile #%d', $target === 'db' ? 'database' : 'filesystem', $filter, $filterType, $profileId )); // Delete the filter $filterObject = Factory::getFilterObject($filterType); if ((stripos($filterType, 'regex') !== false) && !$this->isPro()) { $this->ioStyle->error(sprintf("Filters of the '%s' type are only available with Akeeba Backup Professional.", $filterType)); return 1; } $success = $filterObject->set($root, $filter); if (!$success) { $this->ioStyle->error(sprintf("Could not add filter '%s' of type '%s'.", $filter, $filterType)); return 2; } Factory::getFilters()->save(); $this->ioStyle->success(sprintf("Added filter '%s' of type '%s'.", $filter, $filterType)); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will set a file, folder or table exclusion filter to Akeeba Backup. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('filter', InputArgument::REQUIRED, 'The filter target to add. This is the full path to a file/directory, a table name or a regular expression, depending on the filter type.'); $this->addOption('root', null, InputOption::VALUE_OPTIONAL, 'Which filter root to use. Defaults to [SITEROOT] or [SITEDB] depending on the filter type.', ''); $this->addOption('filterType', null, InputOption::VALUE_REQUIRED, 'The type of filter you want to add: files, directories, skipdirs, skipfiles, regexfiles, regexdirectories, regexskipdirs, regexskipfiles, tables, tabledata, regextables, regextabledata', 'files'); $this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1); $this->setDescription('Set an exclusion filter to Akeeba Backup.'); $this->setHelp($help); } } ProfileModify.php 0000604 00000006325 15245606736 0010045 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Exception; use FOF40\Container\Container; use FOF40\Model\DataModel\Exception\RecordNotLoaded; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:profile:modify * * Modifies an Akeeba Backup profile * * @since 7.5.0 */ class ProfileModify extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:profile:modify'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $id = (int) $this->cliInput->getArgument('id') ?? 0; $container = Container::getInstance('com_akeeba'); /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); try { $profile = $model->findOrFail($id); } catch (RecordNotLoaded $e) { $this->ioStyle->error(sprintf("Cannot modify profile %s; profile not found.", $id)); return 1; } $description = (string) $this->cliInput->getArgument('description') ?? 0; if (!is_null($description)) { $profile->description = $description; } $profile->quickicon = (bool) $this->cliInput->getArgument('quickicon') ?? $profile->quickicon; try { $newProfile = $profile->save(); } catch (Exception $e) { $this->ioStyle->error(sprintf("Cannot modify profile #%s: %s", $id, $e->getMessage())); return 2; } $this->ioStyle->success(sprintf("Profile #%s modified successfully.", $newProfile->getId())); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will modify an Akeeba Backup profile. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to modify'); $this->addOption('description', null, InputOption::VALUE_OPTIONAL, 'Description for the new backup profile. Uses the old profile\'s description if not specified.', null); $this->addOption('quickicon', null, InputOption::VALUE_OPTIONAL, 'Should the new backup profile have a one-click backup icon? Copies the old profile\'s setting if not specified.', null); $this->setDescription('Modifies an Akeeba Backup profile'); $this->setHelp($help); } } ProfileExport.php 0000604 00000006004 15245606736 0010071 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Akeeba\Engine\Factory; use FOF40\Container\Container; use FOF40\Model\DataModel\Exception\RecordNotLoaded; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:profile:export * * Exports an Akeeba Backup profile as a JSON string. * * @since 7.5.0 */ class ProfileExport extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:profile:export'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $id = (int) $this->cliInput->getArgument('id') ?? 0; $filters = (bool) $this->cliInput->getOption('filters') ?? false; $container = Container::getInstance('com_akeeba'); /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); try { $profile = $model->findOrFail($id); } catch (RecordNotLoaded $e) { $this->ioStyle->error(sprintf("Cannot export profile %s; profile not found.", $id)); return 1; } $data = $profile->toArray(); if (!$filters) { unset($data['filters']); } unset($data['id']); // Decrypt configuration data if necessary if (substr($data['configuration'], 0, 12) == '###AES128###') { // Load the server key file if necessary $key = Factory::getSecureSettings()->getKey(); $data['configuration'] = Factory::getSecureSettings()->decryptSettings($data['configuration'], $key); } echo json_encode($data); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will exports an Akeeba Backup profile as a JSON string. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('id', InputOption::VALUE_REQUIRED, 'The numeric ID of the profile to modify'); $this->addOption('filters', null, InputOption::VALUE_NONE, 'Include the filter settings?', false); $this->setDescription('Exports an Akeeba Backup profile as a JSON string'); $this->setHelp($help); } } LogList.php 0000604 00000007204 15245606736 0006647 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Log; use Akeeba\Engine\Factory; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:log:list * * Lists log files known to Akeeba Backup * * @since 7.5.0 */ class LogList extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:log:list'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $profile_id = max(1, (int) $this->cliInput->getArgument('profile_id') ?? 1); $format = (string) ($this->cliInput->getOption('format') ?? 'table'); define('AKEEBA_PROFILE', $profile_id); $configuration = Factory::getConfiguration(); $outputDirectory = $configuration->get('akeeba.basic.output_directory'); if ($format === 'table') { $this->ioStyle->title(sprintf('List of Akeeba Backup log files for output directory %s', $outputDirectory)); } $container = Container::getInstance('com_akeeba', [], 'admin'); /** @var Log $model */ $model = $container->factory->model('Log')->tmpInstance(); $output = array_map(function ($tag) use ($outputDirectory) { $possibilities = [ $outputDirectory . '/akeeba.' . $tag . '.log', $outputDirectory . '/akeeba.' . $tag . '.log.php', $outputDirectory . '/akeeba' . $tag . '.log', $outputDirectory . '/akeeba' . $tag . '.log.php', ]; $path = null; foreach ($possibilities as $possiblePath) { if (@is_file($possiblePath)) { $path = $possiblePath; break; } } if (empty($path)) { return null; } return [ 'tag' => $tag, 'absolute_path' => $path, ]; }, $model->getLogFiles()); $output = array_filter($output, function ($x) { return !is_null($x); }); return $this->printFormattedAndReturn(array_values($output), $format); } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will list all log files in the output directory of the Akeeba Backup profile specified. Note: log files from other backup profiles or Akeeba Backup installations sharing the same output directory will also be listed. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('profile_id', InputArgument::OPTIONAL, 'Log files in the output directory of this Akeeba Backup profile will be listed', 1); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table'); $this->setDescription('Lists log files known to Akeeba Backup'); $this->setHelp($help); } } ProfileList.php 0000604 00000004665 15245606736 0007536 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:profile:list * * Lists the Akeeba Backup backup profiles * * @since 7.5.0 */ class ProfileList extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:profile:list'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $format = (string) $this->cliInput->getOption('format') ?? 'table'; $container = Container::getInstance('com_akeeba'); /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); $profiles = $model->get(true); $output = array_map(function (array $profile) { return [ 'id' => $profile['id'], 'description' => $profile['description'], 'quickicon' => $profile['quickicon'], ]; }, $profiles->toArray()); return $this->printFormattedAndReturn($output, $format); } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will list the Akeeba Backup backup profiles. \nUsage: <info>php %command.full_name%</info>"; $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: table, json, yaml, csv, count.', 'table'); $this->setDescription('Lists the Akeeba Backup backup profiles'); $this->setHelp($help); } } OptionsGet.php 0000604 00000007665 15245606736 0007400 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Akeeba\Engine\Factory; use Akeeba\Engine\Platform; use FOF40\Container\Container; use FOF40\Model\DataModel\Exception\RecordNotLoaded; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\JsonGuiDataParser; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:option:get * * Gets the value of a configuration option for an Akeeba Backup profile * * @since 7.5.0 */ class OptionsGet extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray, JsonGuiDataParser; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:option:get'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $container = Container::getInstance('com_akeeba'); $profileId = (int) ($this->cliInput->getOption('profile') ?? 1); define('AKEEBA_PROFILE', $profileId); $format = (string) $this->cliInput->getOption('format') ?? 'text'; /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); try { $model->findOrFail($profileId); } catch (RecordNotLoaded $e) { $this->ioStyle->error(sprintf("Could not find profile #%s.", $profileId)); return 1; } unset($model); // Get the profile's configuration Platform::getInstance()->load_configuration($profileId); $config = Factory::getConfiguration(); $key = (string) $this->cliInput->getArgument('key') ?? ''; $value = $config->get($key, null, false); if (!is_null($value) && !is_scalar($value)) { $this->ioStyle->error(sprintf("This command cannot return multiple values given the partial key prefix “%s”. Please supply they exact key name you want to retrieve. Use the akeeba:option:list command to see the available keys with the prefix %s.", $key, $key)); return 2; } if (is_null($value)) { $this->ioStyle->error(sprintf("Invalid key “%s”.", $key)); return 3; } switch ($format) { case 'text': default: echo $value . PHP_EOL; break; case 'json': echo json_encode($value) . PHP_EOL; break; case 'print_r': print_r($value); echo PHP_EOL; break; case 'var_dump': var_dump($value); echo PHP_EOL; break; case 'var_export': var_export($value); break; } return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will get the value of a configuration option for an Akeeba Backup profile. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('key', InputOption::VALUE_REQUIRED, 'The option key to retrieve'); $this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1); $this->addOption('format', null, InputOption::VALUE_OPTIONAL, 'Output format: text, json, print_r, var_dump, var_export.', 'text'); $this->setDescription('Gets the value of a configuration option for an Akeeba Backup profile'); $this->setHelp($help); } } BackupDelete.php 0000604 00000006207 15245606736 0007624 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Statistics; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:backup:delete * * Deletes a backup record known to Akeeba Backup, or just its files * * @since 7.5.0 */ class BackupDelete extends AbstractCommand { use ConfigureIO, ArgumentUtilities; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:backup:delete'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $id = (int) $this->cliInput->getArgument('id') ?? 0; $onlyFiles = $this->cliInput->getOption('only-files'); $this->ioStyle->title(sprintf('Deleting Akeeba Backup record #%d', $id)); if ($id <= 0) { $this->ioStyle->error('Invalid backup record'); return 1; } $container = Container::getInstance('com_akeeba', [], 'admin'); /** @var Statistics $model */ $model = $container->factory->model('Statistics')->tmpInstance(); $model->setState('id', $id); try { if ($onlyFiles) { $model->deleteFile(); $this->ioStyle->success(sprintf('The files of backup record #%d have been deleted.', $id)); return 0; } $model->delete(); $this->ioStyle->success(sprintf('The backup record #%d has been deleted.', $id)); } catch (\RuntimeException $e) { if ($onlyFiles) { $this->ioStyle->error(sprintf('Cannot delete the files of backup record #%d: %s', $id, $e->getMessage())); } else { $this->ioStyle->error(sprintf('Cannot delete backup record #%d: %s', $id, $e->getMessage())); } return 1; } return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will delete a backup record known to Akeeba Backup, or just its files \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('id', InputArgument::REQUIRED, 'The id of the backup record to delete'); $this->addOption('only-files', null, InputOption::VALUE_NONE, 'Only delete the backup files stored on the site\'s server, not the record itself.'); $this->setDescription('Deletes a backup record known to Akeeba Backup, or just its files'); $this->setHelp($help); } } LogGet.php 0000604 00000005131 15245606736 0006450 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Log; use FOF40\Container\Container; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:log:get * * Retrieves log files known to Akeeba Backup * * @since 7.5.0 */ class LogGet extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:log:get'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $profile_id = max(1, (int) $this->cliInput->getArgument('profile_id') ?? 1); $log_tag = (string) $this->cliInput->getArgument('log_tag') ?? 1; define('AKEEBA_PROFILE', $profile_id); $container = Container::getInstance('com_akeeba', [], 'admin'); /** @var Log $model */ $model = $container->factory->model('Log')->tmpInstance(); $model->setState('tag', $log_tag); $model->echoRawLog(true); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will retrieve a log file from the output directory of the Akeeba Backup profile specified. Note: log files from other backup profiles or Akeeba Backup installations sharing the same output directory can also be retrieved. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('profile_id', InputArgument::REQUIRED, 'Log files in the output directory of this Akeeba Backup profile will be retrieved'); $this->addArgument('log_tag', InputArgument::REQUIRED, 'The tag of the log file to retrieve'); $this->setDescription('Retrieve a log file known to Akeeba Backup'); $this->setHelp($help); } } OptionsSet.php 0000604 00000013423 15245606736 0007401 0 ustar 00 <?php /** * @package akeebabackup * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\Backup\Admin\CliCommands; defined('_JEXEC') || die; use Akeeba\Backup\Admin\Model\Profiles; use Akeeba\Engine\Factory; use Akeeba\Engine\Platform; use FOF40\Container\Container; use FOF40\Model\DataModel\Exception\RecordNotLoaded; use Joomla\Console\Command\AbstractCommand; use Akeeba\Backup\Admin\CliCommands\MixIt\ArgumentUtilities; use Akeeba\Backup\Admin\CliCommands\MixIt\ConfigureIO; use Akeeba\Backup\Admin\CliCommands\MixIt\JsonGuiDataParser; use Akeeba\Backup\Admin\CliCommands\MixIt\PrintFormattedArray; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * akeeba:option:set * * Sets the value of a configuration option for an Akeeba Backup profile * * @since 7.5.0 */ class OptionsSet extends AbstractCommand { use ConfigureIO, ArgumentUtilities, PrintFormattedArray, JsonGuiDataParser; /** * The default command name * * @var string * @since 7.5.0 */ protected static $defaultName = 'akeeba:option:set'; /** * 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 7.5.0 */ protected function doExecute(InputInterface $input, OutputInterface $output): int { $this->configureSymfonyIO($input, $output); $container = Container::getInstance('com_akeeba'); $profileId = (int) ($this->cliInput->getOption('profile') ?? 1); define('AKEEBA_PROFILE', $profileId); $format = (string) $this->cliInput->getOption('format') ?? 'text'; /** @var Profiles $model */ $model = $container->factory->model('Profiles')->tmpInstance(); try { $model->findOrFail($profileId); } catch (RecordNotLoaded $e) { $this->ioStyle->error(sprintf("Could not find profile #%s.", $profileId)); return 1; } unset($model); // Get the profile's configuration Platform::getInstance()->load_configuration($profileId); $config = Factory::getConfiguration(); $key = (string) $this->cliInput->getArgument('key') ?? ''; $value = (string) $this->cliInput->getArgument('value') ?? ''; // Get the key information from the GUI data $info = $this->parseJsonGuiData(); // Does the key exist? if (!array_key_exists($key, $info['options'])) { $this->ioStyle->error(sprintf("Invalid option key '%s'.", $key)); return 2; } // Validate / sanitize the value $optionInfo = $this->getOptionInfo($key, $info); switch ($optionInfo['type']) { case 'integer': $value = (int) $value; if (($value < $optionInfo['limits']['min']) || ($value > $optionInfo['limits']['max'])) { $this->ioStyle->error(sprintf("Invalid value '%s': out of bounds.", $value)); return 3; } break; case 'bool': if (is_numeric($value)) { $value = (int) $value; } elseif (is_string($value)) { $value = strtolower($value); } if (in_array($value, [false, 0, '0', 'false', 'no', 'off'], true)) { $value = 0; } elseif (in_array($value, [true, 1, '1', 'true', 'yes', 'on'], true)) { $value = 1; } else { $this->ioStyle->error(sprintf("Invalid boolean value '%s': use one of 0, false, no, off, 1, true, yes or on.'", $value)); return 3; } break; case 'enum': if (!in_array($value, $optionInfo['options'])) { $options = array_map(function ($v) { return "'$v'"; }, $optionInfo['options']); $options = implode(', ', $options); $this->ioStyle->error(sprintf("Invalid enumerated value '%s'. Must be one of %s.", $value, $options)); return 3; } break; case 'hidden': $this->ioStyle->error(sprintf("Setting hidden option '%s' is not allowed.", $key)); return 3; break; case 'string': break; default: $this->ioStyle->error(sprintf("Unknown type %s for option '%s'. Have you manually tampered with the option JSON files?", $optionInfo['type'], $key)); return 3; break; } $protected = $config->getProtectedKeys(); $force = isset($assoc_args['force']) && $assoc_args['force']; if (in_array($key, $protected) && !$force) { $this->ioStyle->error(sprintf("Cannot set protected option '%s'. Please use the --force option to override the protection.", $key)); return 4; } if (in_array($key, $protected) && $force) { $config->setKeyProtection($key, false); } $result = $config->set($key, $value, false); if ($result === false) { $this->ioStyle->error(sprintf("Could not set option '%s'.", $key)); return 5; } Platform::getInstance()->save_configuration($profileId); $this->ioStyle->success(sprintf("Successfully set option '%s' to '%s'", $key, $value)); return 0; } /** * Configure the command. * * @return void * * @since 7.5.0 */ protected function configure(): void { $help = "<info>%command.name%</info> will set the value of a configuration option for an Akeeba Backup profile. \nUsage: <info>php %command.full_name%</info>"; $this->addArgument('key', InputOption::VALUE_REQUIRED, 'The option key to set'); $this->addArgument('value', InputOption::VALUE_REQUIRED, 'The value to set'); $this->addOption('profile', null, InputOption::VALUE_OPTIONAL, 'The backup profile to use. Default: 1.', 1); $this->addOption('force', null, InputOption::VALUE_NONE, 'Allow setting the value of protected options.', false); $this->setDescription('Sets the value of a configuration option for an Akeeba Backup profile'); $this->setHelp($help); } }
| ver. 1.4 |
Github
|
.
| PHP 8.1.34 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка