diff --git a/core/backgroundprocess.inc.php b/core/backgroundprocess.inc.php index 625385f59..ba23b7030 100644 --- a/core/backgroundprocess.inc.php +++ b/core/backgroundprocess.inc.php @@ -56,8 +56,9 @@ interface iBackgroundProcess extends iProcess * interface iScheduledProcess * A variant of process that must be called at specific times * - * @copyright Copyright (C) 2013 Combodo SARL + * @see \AbstractWeeklyScheduledProcess for a bootstrap implementation * @license http://opensource.org/licenses/AGPL-3.0 + * @copyright Copyright (C) 2013 Combodo SARL */ interface iScheduledProcess extends iProcess { @@ -67,14 +68,189 @@ interface iScheduledProcess extends iProcess public function GetNextOccurrence(); } + /** - * Class ProcessException - * Exception for iProcess implementations.
+ * Implementation of {@link iScheduledProcess}, using config parameters for module + * + * Use these parameters : + * + * * enabled + * * week_days + * * time + * + * Param names and some of their default values are in constant that can be overriden. + * + * Other info (module name and time default value) should be provided using a method that needs to be implemented. + * + * @since 2.7.0 + */ +abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess +{ + // param have default names/values but can be overriden + const MODULE_SETTING_ENABLED = 'enabled'; + const DEFAULT_MODULE_SETTING_ENABLED = true; + const MODULE_SETTING_WEEKDAYS = 'week_days'; + const DEFAULT_MODULE_SETTING_WEEKDAYS = 'monday, tuesday, wednesday, thursday, friday, saturday, sunday'; + const MODULE_SETTING_TIME = 'time'; + + /** + * Module must be declared in each implementation + * + * @return string + */ + abstract protected function GetModuleName(); + + /** + * @return string default value for {@link MODULE_SETTING_TIME} config param. + * example '23:30' + */ + abstract protected function GetDefaultModuleSettingTime(); + + /** + * Interpret current setting for the week days + * + * @returns int[] (monday = 1) + * @throws ProcessInvalidConfigException + */ + public function InterpretWeekDays() + { + static $aWEEKDAYTON = array( + 'monday' => 1, + 'tuesday' => 2, + 'wednesday' => 3, + 'thursday' => 4, + 'friday' => 5, + 'saturday' => 6, + 'sunday' => 7, + ); + $aDays = array(); + $sWeekDays = MetaModel::GetConfig()->GetModuleSetting( + $this->GetModuleName(), + static::MODULE_SETTING_WEEKDAYS, + static::DEFAULT_MODULE_SETTING_WEEKDAYS + ); + + if ($sWeekDays !== '') + { + $aWeekDaysRaw = explode(',', $sWeekDays); + foreach ($aWeekDaysRaw as $sWeekDay) + { + $sWeekDay = strtolower(trim($sWeekDay)); + if (array_key_exists($sWeekDay, $aWEEKDAYTON)) + { + $aDays[] = $aWEEKDAYTON[$sWeekDay]; + } + else + { + throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_WEEKDAYS."' (found '$sWeekDay')"); + } + } + } + if (count($aDays) === 0) + { + throw new ProcessInvalidConfigException($this->GetModuleName().': missing setting \''.static::MODULE_SETTING_WEEKDAYS.'\''); + } + $aDays = array_unique($aDays); + sort($aDays); + + return $aDays; + } + + /** + * Gives the exact time at which the process must be run next time + * + * @return DateTime + * @throws Exception + */ + public function GetNextOccurrence() + { + $bEnabled = MetaModel::GetConfig()->GetModuleSetting( + $this->GetModuleName(), + static::MODULE_SETTING_ENABLED, + static::DEFAULT_MODULE_SETTING_ENABLED + ); + if (!$bEnabled) + { + return new DateTime('3000-01-01'); + } + + // 1st - Interpret the list of days as ordered numbers (monday = 1) + // + $aDays = $this->InterpretWeekDays(); + + // 2nd - Find the next active week day + // + $sProcessTime = MetaModel::GetConfig()->GetModuleSetting( + $this->GetModuleName(), + static::MODULE_SETTING_TIME, + static::DEFAULT_MODULE_SETTING_TIME + ); + if (!preg_match('/[0-2][0-9]:[0-5][0-9]/', $sProcessTime)) + { + throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_TIME."' (found '$sProcessTime')"); + } + $oNow = new DateTime(); + $iNextPos = false; + for ($iDay = $oNow->format('N'); $iDay <= 7; $iDay++) + { + $iNextPos = array_search($iDay, $aDays, true); + if ($iNextPos !== false) + { + if (($iDay > $oNow->format('N')) || ($oNow->format('H:i') < $sProcessTime)) + { + break; + } + $iNextPos = false; // necessary on sundays + } + } + + // 3rd - Compute the result + // + if ($iNextPos === false) + { + // Jump to the first day within the next week + $iFirstDayOfWeek = $aDays[0]; + $iDayMove = $oNow->format('N') - $iFirstDayOfWeek; + $oRet = clone $oNow; + $oRet->modify('-'.$iDayMove.' days'); + $oRet->modify('+1 weeks'); + } + else + { + $iNextDayOfWeek = $aDays[$iNextPos]; + $iMove = $iNextDayOfWeek - $oNow->format('N'); + $oRet = clone $oNow; + $oRet->modify('+'.$iMove.' days'); + } + list($sHours, $sMinutes) = explode(':', $sProcessTime); + $oRet->setTime((int)$sHours, (int)$sMinutes); + + return $oRet; + } + + /** + * @see \iProcess + * + * @param int $iUnixTimeLimit + * + * @return string + */ + abstract public function Process($iUnixTimeLimit); +} + +/** + * Exception for {@link iProcess} implementations.
* An error happened during the processing but we can go on with the next implementations. */ class ProcessException extends CoreException { +} +/** + * @since 2.7.0 + */ +class ProcessInvalidConfigException extends ProcessException +{ } /** @@ -84,5 +260,4 @@ class ProcessException extends CoreException */ class ProcessFatalException extends CoreException { - } diff --git a/datamodels/2.x/itop-backup/main.itop-backup.php b/datamodels/2.x/itop-backup/main.itop-backup.php index 698bfc70b..d53d37cbf 100644 --- a/datamodels/2.x/itop-backup/main.itop-backup.php +++ b/datamodels/2.x/itop-backup/main.itop-backup.php @@ -85,16 +85,26 @@ class DBBackupScheduled extends DBBackup } } -class BackupExec implements iScheduledProcess +class BackupExec extends AbstractWeeklyScheduledProcess { protected $sBackupDir; protected $iRetentionCount; + protected function GetModuleName() + { + return 'itop-backup'; + } + + protected function GetDefaultModuleSettingTime() + { + return '23:30'; + } + /** - * Constructor - * @param sBackupDir string Target directory, defaults to APPROOT/data/backups/auto - * @param iRetentionCount int Rotation (default to the value given in the configuration file 'retentation_count') set to 0 to disable this feature - */ + * @param string $sBackupDir Target directory, defaults to APPROOT/data/backups/auto + * @param int $iRetentionCount default to the value given in the configuration file 'retentation_count'
+ * set to 0 to disable this feature + */ public function __construct($sBackupDir = null, $iRetentionCount = null) { if (is_null($sBackupDir)) @@ -107,7 +117,7 @@ class BackupExec implements iScheduledProcess } if (is_null($iRetentionCount)) { - $this->iRetentionCount = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'retention_count', 5); + $this->iRetentionCount = MetaModel::GetConfig()->GetModuleSetting($this->GetModuleName(), 'retention_count', 5); } else { @@ -151,9 +161,10 @@ class BackupExec implements iScheduledProcess // Do execute the backup // - $oBackup->SetMySQLBinDir(MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', '')); - - $sBackupFileFormat = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'file_name_format', '__DB__-%Y-%m-%d_%H_%M'); + $oBackup->SetMySQLBinDir(MetaModel::GetConfig()->GetModuleSetting($this->GetModuleName(), 'mysql_bindir', '')); + + $sBackupFileFormat = MetaModel::GetConfig()->GetModuleSetting($this->GetModuleName(), 'file_name_format', + '__DB__-%Y-%m-%d_%H_%M'); $sName = $oBackup->MakeName($sBackupFileFormat); if ($sName == '') { @@ -179,101 +190,4 @@ class BackupExec implements iScheduledProcess return "Created the backup: $sBackupFile"; } - /** - * Interpret current setting for the week days - * @returns array of int (monday = 1) - * @throws Exception - */ - public function InterpretWeekDays() - { - static $aWEEKDAYTON = array('monday' => 1, 'tuesday' => 2, 'wednesday' => 3, 'thursday' => 4, 'friday' => 5, 'saturday' => 6, 'sunday' => 7); - $aDays = array(); - $sWeekDays = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'week_days', 'monday, tuesday, wednesday, thursday, friday'); - if ($sWeekDays != '') - { - $aWeekDaysRaw = explode(',', $sWeekDays); - foreach ($aWeekDaysRaw as $sWeekDay) - { - $sWeekDay = strtolower(trim($sWeekDay)); - if (array_key_exists($sWeekDay, $aWEEKDAYTON)) - { - $aDays[] = $aWEEKDAYTON[$sWeekDay]; - } - else - { - throw new Exception("'itop-backup: wrong format for setting 'week_days' (found '$sWeekDay')"); - } - } - } - if (count($aDays) == 0) - { - throw new Exception("'itop-backup: missing setting 'week_days'"); - } - $aDays = array_unique($aDays); - sort($aDays); - return $aDays; - } - - /** Gives the exact time at which the process must be run next time - * @return DateTime - * @throws Exception - */ - public function GetNextOccurrence() - { - $bEnabled = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'enabled', true); - if (!$bEnabled) - { - $oRet = new DateTime('3000-01-01'); - } - else - { - // 1st - Interpret the list of days as ordered numbers (monday = 1) - // - $aDays = $this->InterpretWeekDays(); - - // 2nd - Find the next active week day - // - $sBackupTime = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'time', '23:30'); - if (!preg_match('/[0-2][0-9]:[0-5][0-9]/', $sBackupTime)) - { - throw new Exception("'itop-backup: wrong format for setting 'time' (found '$sBackupTime')"); - } - $oNow = new DateTime(); - $iNextPos = false; - for ($iDay = $oNow->format('N') ; $iDay <= 7 ; $iDay++) - { - $iNextPos = array_search($iDay, $aDays); - if ($iNextPos !== false) - { - if (($iDay > $oNow->format('N')) || ($oNow->format('H:i') < $sBackupTime)) - { - break; - } - $iNextPos = false; // necessary on sundays - } - } - - // 3rd - Compute the result - // - if ($iNextPos === false) - { - // Jump to the first day within the next week - $iFirstDayOfWeek = $aDays[0]; - $iDayMove = $oNow->format('N') - $iFirstDayOfWeek; - $oRet = clone $oNow; - $oRet->modify('-'.$iDayMove.' days'); - $oRet->modify('+1 weeks'); - } - else - { - $iNextDayOfWeek = $aDays[$iNextPos]; - $iMove = $iNextDayOfWeek - $oNow->format('N'); - $oRet = clone $oNow; - $oRet->modify('+'.$iMove.' days'); - } - list($sHours, $sMinutes) = explode(':', $sBackupTime); - $oRet->setTime((int)$sHours, (int) $sMinutes); - } - return $oRet; - } } diff --git a/webservices/cron.php b/webservices/cron.php index dc4e866fc..e7544878d 100644 --- a/webservices/cron.php +++ b/webservices/cron.php @@ -528,6 +528,10 @@ $aProcesses = array(); foreach (get_declared_classes() as $sPHPClass) { $oRefClass = new ReflectionClass($sPHPClass); + if ($oRefClass->isAbstract()) + { + continue; + } $oExtensionInstance = null; if ($oRefClass->implementsInterface('iProcess')) {