| Current Path : /home/wuectly/www/03cbe/ |
| Current File : /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);
}
}