mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 19:18:44 +02:00
Abstract implementation for iScheduledProcess (#89)
* 📝 little PHPDoc in BackupExec * ♻️ Create a extendable implementation of iScheduledProcess * create AbstractWeeklyScheduledProcess * move schedule methods to the new abstract class * create ProcessInvalidConfigException * in cron.php skip abstract class
This commit is contained in:
@@ -56,8 +56,9 @@ interface iBackgroundProcess extends iProcess
|
|||||||
* interface iScheduledProcess
|
* interface iScheduledProcess
|
||||||
* A variant of process that must be called at specific times
|
* 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
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
|
* @copyright Copyright (C) 2013 Combodo SARL
|
||||||
*/
|
*/
|
||||||
interface iScheduledProcess extends iProcess
|
interface iScheduledProcess extends iProcess
|
||||||
{
|
{
|
||||||
@@ -67,14 +68,189 @@ interface iScheduledProcess extends iProcess
|
|||||||
public function GetNextOccurrence();
|
public function GetNextOccurrence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ProcessException
|
* Implementation of {@link iScheduledProcess}, using config parameters for module
|
||||||
* Exception for iProcess implementations.<br>
|
*
|
||||||
|
* 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.<br>
|
||||||
* An error happened during the processing but we can go on with the next implementations.
|
* An error happened during the processing but we can go on with the next implementations.
|
||||||
*/
|
*/
|
||||||
class ProcessException extends CoreException
|
class ProcessException extends CoreException
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.7.0
|
||||||
|
*/
|
||||||
|
class ProcessInvalidConfigException extends ProcessException
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,5 +260,4 @@ class ProcessException extends CoreException
|
|||||||
*/
|
*/
|
||||||
class ProcessFatalException extends CoreException
|
class ProcessFatalException extends CoreException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,16 +85,26 @@ class DBBackupScheduled extends DBBackup
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BackupExec implements iScheduledProcess
|
class BackupExec extends AbstractWeeklyScheduledProcess
|
||||||
{
|
{
|
||||||
protected $sBackupDir;
|
protected $sBackupDir;
|
||||||
protected $iRetentionCount;
|
protected $iRetentionCount;
|
||||||
|
|
||||||
|
protected function GetModuleName()
|
||||||
|
{
|
||||||
|
return 'itop-backup';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function GetDefaultModuleSettingTime()
|
||||||
|
{
|
||||||
|
return '23:30';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* @param string $sBackupDir Target directory, defaults to APPROOT/data/backups/auto
|
||||||
* @param sBackupDir string Target directory, defaults to APPROOT/data/backups/auto
|
* @param int $iRetentionCount default to the value given in the configuration file 'retentation_count'<br>
|
||||||
* @param iRetentionCount int Rotation (default to the value given in the configuration file 'retentation_count') set to 0 to disable this feature
|
* set to 0 to disable this feature
|
||||||
*/
|
*/
|
||||||
public function __construct($sBackupDir = null, $iRetentionCount = null)
|
public function __construct($sBackupDir = null, $iRetentionCount = null)
|
||||||
{
|
{
|
||||||
if (is_null($sBackupDir))
|
if (is_null($sBackupDir))
|
||||||
@@ -107,7 +117,7 @@ class BackupExec implements iScheduledProcess
|
|||||||
}
|
}
|
||||||
if (is_null($iRetentionCount))
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -151,9 +161,10 @@ class BackupExec implements iScheduledProcess
|
|||||||
|
|
||||||
// Do execute the backup
|
// Do execute the backup
|
||||||
//
|
//
|
||||||
$oBackup->SetMySQLBinDir(MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''));
|
$oBackup->SetMySQLBinDir(MetaModel::GetConfig()->GetModuleSetting($this->GetModuleName(), 'mysql_bindir', ''));
|
||||||
|
|
||||||
$sBackupFileFormat = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'file_name_format', '__DB__-%Y-%m-%d_%H_%M');
|
$sBackupFileFormat = MetaModel::GetConfig()->GetModuleSetting($this->GetModuleName(), 'file_name_format',
|
||||||
|
'__DB__-%Y-%m-%d_%H_%M');
|
||||||
$sName = $oBackup->MakeName($sBackupFileFormat);
|
$sName = $oBackup->MakeName($sBackupFileFormat);
|
||||||
if ($sName == '')
|
if ($sName == '')
|
||||||
{
|
{
|
||||||
@@ -179,101 +190,4 @@ class BackupExec implements iScheduledProcess
|
|||||||
return "Created the backup: $sBackupFile";
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -528,6 +528,10 @@ $aProcesses = array();
|
|||||||
foreach (get_declared_classes() as $sPHPClass)
|
foreach (get_declared_classes() as $sPHPClass)
|
||||||
{
|
{
|
||||||
$oRefClass = new ReflectionClass($sPHPClass);
|
$oRefClass = new ReflectionClass($sPHPClass);
|
||||||
|
if ($oRefClass->isAbstract())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$oExtensionInstance = null;
|
$oExtensionInstance = null;
|
||||||
if ($oRefClass->implementsInterface('iProcess'))
|
if ($oRefClass->implementsInterface('iProcess'))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user