ModCfg/bin/d3maintenance

417 lines
14 KiB
PHP

#!/usr/bin/env php
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
*
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link https://www.oxidmodule.com
*/
use D3\ModCfg\Application\Model\d3bitmask;
use D3\ModCfg\Application\Model\d3cliutils;
use D3\ModCfg\Application\Model\d3database;
use D3\ModCfg\Application\Model\Log\d3log;
use D3\ModCfg\Application\Model\Log\d3LogLevel;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\DateIntervalUnit;
use Exception as ExceptionAlias;
use OxidEsales\ComposerPlugin\Installer\Package\ShopPackageInstaller;
use OxidEsales\Eshop\Core\Config;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\Eshop\Core\Session;
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\Bridge\ShopConfigurationDaoBridgeInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Exception;
use splitbrain\phpcli\Options;
// @codeCoverageIgnoreStart
require_once(__DIR__.'/../../../../../vendor/autoload.php');
$bootstrapFileName = getenv('ESHOP_BOOTSTRAP_PATH');
if (!empty($bootstrapFileName)) {
$bootstrapFileName = realpath(trim(getenv('ESHOP_BOOTSTRAP_PATH')));
} else {
$count = 0;
$bootstrapFileName = '../../../'. ShopPackageInstaller::SHOP_SOURCE_DIRECTORY .'/bootstrap.php';
$currentDirectory = __DIR__ . '/';
while ($count < 5) {
$count++;
if (file_exists($currentDirectory . $bootstrapFileName)) {
$bootstrapFileName = $currentDirectory . $bootstrapFileName;
break;
}
$bootstrapFileName = '../' . $bootstrapFileName;
}
}
if (!(file_exists($bootstrapFileName) && !is_dir($bootstrapFileName))) {
$items = [
"Unable to find eShop bootstrap.php file.",
"You can override the path by using ESHOP_BOOTSTRAP_PATH environment variable.",
"\n"
];
$message = implode(" ", $items);
die($message);
}
if (false === defined('OXID_PHP_UNIT')) {
require_once($bootstrapFileName);
// required for recalculating order and generating pdf
define('OX_IS_ADMIN', true);
}
if (false == function_exists('isAdmin')) {
/**
* @return bool
*/
function isAdmin()
{
if (defined('OX_IS_ADMIN')) {
return OX_IS_ADMIN;
}
return true;
}
}
// set language
$langs = getopt(null, ["lang:"]);
$searchedValue = $langs['lang'] ?? '';
$languages = Registry::getLang()->getLanguageArray();
Registry::getLang()->setTplLanguage(
current(
array_merge(
array_filter( // selected
$languages,
function ($e) use (&$searchedValue) {
return $e->abbr == $searchedValue;
}
),
[reset($languages)] // first item, if no language is selected
)
)->id
);
// @codeCoverageIgnoreEnd
class d3maintenance extends CLI
{
const OPTION_VERSION = 'version';
const OPTION_QUIET = 'quiet';
const OPTION_LANG = 'lang';
const COMMAND_CLEANUPLOG = 'clearlog';
const COMMAND_LOGSTATUS = 'logstatus';
const ARGUMENT_CLEANUP_VALUE = 'value';
const ARGUMENT_CLEANUP_UNIT = 'unit';
public function __construct()
{
// there are argv setting in CLI mode only
if ($this->isCLI()) {
parent::__construct();
}
}
/**
* @return bool
*/
public function isCLI()
{
return 'cli' == php_sapi_name();
}
/**
* @param Options $options
* @throws \Exception
*/
protected function setup(Options $options)
{
$lang = Registry::getLang();
$sLangList = implode(
$lang->translateString('D3_LOG_CLI_ARGUMENT_ENCLOSER'),
array_map(
function ($e) {
return $e->abbr;
},
Registry::getLang()->getLanguageArray()
)
);
$sUnitList = implode(
$lang->translateString('D3_LOG_CLI_ARGUMENT_ENCLOSER'),
$this->getTimeUnitList()
);
$options->registerArgument(self::ARGUMENT_CLEANUP_VALUE, $lang->translateString('D3_LOG_CLI_ARGUMENT_VALUE'), false);
$options->registerArgument(self::ARGUMENT_CLEANUP_UNIT, sprintf($lang->translateString('D3_LOG_CLI_ARGUMENT_UNIT'), $sUnitList), false);
$options->setHelp($lang->translateString('D3_LOG_CLI_HELP'));
$options->registerOption(self::OPTION_VERSION, $lang->translateString('D3_LOG_CLI_OPTION_VERSION'), 'v');
$options->registerOption(self::OPTION_QUIET, $lang->translateString('D3_LOG_CLI_OPTION_QUIET'), 'q');
$options->registerOption(self::OPTION_LANG, sprintf($lang->translateString('D3_LOG_CLI_OPTION_LANG'), $sLangList), null, 'language');
$options->registerCommand(self::COMMAND_CLEANUPLOG, $lang->translateString('D3_LOG_CLI_COMMAND_CLEANUPLOG'));
$options->registerCommand(self::COMMAND_LOGSTATUS, $lang->translateString('D3_LOG_CLI_COMMAND_LOGSTATUS'));
}
/**
* retranslate default messages
*/
protected function parseOptions()
{
$lang = Registry::getLang();
parent::parseOptions();
$this->options->registerOption('help', $lang->translateString('D3_LOG_CLI_OPTION_HELP'), 'h');
$this->options->registerOption('no-colors', $lang->translateString('D3_LOG_CLI_OPTION_NOCOLORS'));
$this->options->registerOption('loglevel', $lang->translateString('D3_LOG_CLI_OPTION_LOGLEVELS'), null, 'level');
}
/**
* @param Options $options
* @throws \Exception
*/
protected function main(Options $options)
{
if ( $options->getOpt( self::OPTION_VERSION ) ) {
$container = ContainerFactory::getInstance()->getContainer();
$shopConfiguration = $container->get(ShopConfigurationDaoBridgeInterface::class)->get();
$moduleConfiguration = $shopConfiguration->getModuleConfiguration('d3modcfg_lib');
$this->info($moduleConfiguration->getVersion());
return;
}
if ( $options->getOpt( self::OPTION_QUIET ) ) {
d3GetOxidDIC()->get('d3ox.modcfg.'.Session::class)->setVariable( 'd3modcfg_quiet', true );
}
$arguments = $options->getArgs();
$aTranslation = [];
$aTranslation['value'] = isset( $arguments[0] ) ? trim($arguments[0]) : '';
$aTranslation['unit'] = isset( $arguments[1] ) ? trim($arguments[1]) : '';
$_GET = array_merge( $_GET, $aTranslation );
try {
$value = $aTranslation['value'];
$unit = $aTranslation['unit'];
if (((bool) strlen($value) || (bool) strlen($value)) &&
(
false === is_numeric($value) ||
false === in_array(strtoupper($unit), array_map('strtoupper', $this->getTimeUnitList()), true)
)
){
throw oxNew(RuntimeException::class, Registry::getLang()->translateString('D3_LOG_CLI_UNVALID_PARAMETERS'));
}
switch ( $options->getCmd() ) {
case self::COMMAND_CLEANUPLOG:
$this->clearlog( $value, $unit, $options );
break;
case self::COMMAND_LOGSTATUS:
$this->logstatus( $value, $unit );
break;
default:
echo $this->translateFixedStrings( $options->help() );
}
} catch ( \Exception $oEx ) {
if (!Registry::getSession()->getVariable('d3modcfg_quiet')) {
$this->error( $oEx->getMessage() );
}
} finally {
/** @var Config $config */
$config = d3GetOxidDIC()->get( 'd3ox.modcfg.' . Config::class );
// @codeCoverageIgnoreStart
if (false === defined('OXID_PHP_UNIT')) {
$config->pageClose();
}
// @codeCoverageIgnoreEnd
}
}
/**
* @param int $value
* @param string $unit
* @param Options $options
*
* @throws DatabaseConnectionException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
protected function clearlog($value, $unit, Options $options)
{
$lang = Registry::getLang();
if ( (bool) strlen( $value ) || (bool) strlen( $value ) ) {
$queryBuilder = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$queryBuilder->delete( d3GetOxidDIC()->get( 'd3.modcfg.log_get' )->getCoreTableName() )
->where( 'oxtime < DATE_SUB(NOW(), INTERVAL ' . $queryBuilder->createNamedParameter( $value, ParameterType::INTEGER ) . ' ' . $unit . ')' );
$this->debug( d3database::getInstance()->getPreparedStatementQuery( $queryBuilder->getSQL(), $queryBuilder->getParameters() ) );
$affected = $queryBuilder->execute()->columnCount();
if ( ! $options->getOpt( self::OPTION_QUIET ) ) {
$this->info( sprintf( $lang->translateString( 'D3_LOG_CLI_FINISHED_AFFECTED' ), $affected ) );
$this->success( $lang->translateString( 'D3_LOG_CLI_FINISHED_SUCCFESSFULLY' ) );
}
} else {
throw oxNew( RuntimeException::class, $lang->translateString( 'D3_LOG_CLI_UNVALID_PARAMETERS' ) );
}
}
/**
* @param $value
* @param $unit
*
* @throws ContainerExceptionInterface
* @throws DatabaseConnectionException
* @throws NotFoundExceptionInterface
*/
protected function logstatus($value, $unit)
{
$lang = Registry::getLang();
$queryBuilder = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
$queryBuilder->select('count(*)', 'oxlogtype', 'DATE_FORMAT(OXTIME, \'%Y-%m\')')
->from(d3GetOxidDIC()->get('d3.modcfg.log_get')->getCoreTableName())
->groupBy('DATE_FORMAT(OXTIME, \'%Y-%m\')')
->addGroupBy('OXLOGTYPE')
->orderBy('DATE_FORMAT(OXTIME, \'%Y-%m\')', 'DESC')
->addOrderBy("FIELD(OXLOGTYPE, '".$this->getLogTypeListString()."')");
if ((bool) strlen($value) || (bool) strlen($value)) {
$queryBuilder->where(
'oxtime < DATE_SUB(NOW(), INTERVAL ' .
$queryBuilder->createNamedParameter( $value, ParameterType::INTEGER ) . ' ' . $unit . ')'
);
}
$this->debug(d3database::getInstance()->getPreparedStatementQuery($queryBuilder->getSQL(), $queryBuilder->getParameters()));
$result = array_merge(
['-1' => [
$lang->translateString('D3_LOG_CLI_COMMAND_LOGSTATUS_COUNT'),
$lang->translateString('D3_LOG_CLI_COMMAND_LOGSTATUS_TYPE'),
$lang->translateString('D3_LOG_CLI_COMMAND_LOGSTATUS_DATE')
]],
$queryBuilder->execute()->fetchAllNumeric()
);
/** @var d3cliutils $cliUtils */
$cliUtils = oxNew(d3cliutils::class);
$this->info(PHP_EOL.$cliUtils->table($result, [STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_RIGHT]));
}
/**
* prevent code exit while coverage check
*
* @codeCoverageIgnore
* @throws \Exception
*/
public function run()
{
if (false === $this->isCLI()) {
throw new Exception(Registry::getLang()->translateString('D3_LOG_CLI_COMMON_RUNFROMCLI'));
}
if (false === defined('OXID_PHP_UNIT')) {
parent::run();
} else {
$this->setup($this->options);
$this->registerDefaultOptions();
$this->parseOptions();
$this->handleDefaultOptions();
$this->setupLogging();
$this->checkArguments();
$this->execute();
}
}
/**
* @param $text
* @return string
*/
public function translateFixedStrings($text)
{
$search = [
'This tool accepts a command as first parameter as outlined below:'
];
$replace = [
Registry::getLang()->translateString('D3_LOG_CLI_COMMAND')
];
return str_replace($search, $replace, $text);
}
/**
* @return array
*/
public function getLogTypeList()
{
/** @var d3log $log */
$log = d3GetOxidDIC()->get('d3.modcfg.log_get');
$bitmask = oxNew( d3bitmask::class);
$range = $bitmask->removeBit(d3LogLevel::ERROR_AND_BELOW, d3LogLevel::EMPTY_AND_BELOW);
return $log->getLogTypeListByRange($range);
}
/**
* @return string
*/
public function getLogTypeListString()
{
return implode(
"', '", // don't use translation item for separator, because possible syntactical incorrect one
$this->getLogTypeList()
);
}
/**
* @return array
*/
public function getTimeUnitList()
{
return [ DateIntervalUnit::HOUR, DateIntervalUnit::DAY, DateIntervalUnit::MONTH, DateIntervalUnit::YEAR];
}
}
// @codeCoverageIgnoreStart
$cli = new d3maintenance();
if (false === defined('OXID_PHP_UNIT')) {
try {
$cli->run();
} catch ( ExceptionAlias $e) {
$cli->error($e->getMessage());
}
}
// @codeCoverageIgnoreEnd