#!/usr/bin/env php * @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