PDF rausgenommen
This commit is contained in:
56
msd2/tracking/piwik/core/Scheduler/Schedule/Daily.php
Normal file
56
msd2/tracking/piwik/core/Scheduler/Schedule/Daily.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler\Schedule;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Daily class is used to schedule tasks every day.
|
||||
*
|
||||
* @see \Piwik\Scheduler\Task
|
||||
*/
|
||||
class Daily extends Schedule
|
||||
{
|
||||
/**
|
||||
* @see ScheduledTime::getRescheduledTime
|
||||
* @return int
|
||||
*
|
||||
*/
|
||||
public function getRescheduledTime()
|
||||
{
|
||||
$currentTime = $this->getTime();
|
||||
|
||||
// Add one day
|
||||
$rescheduledTime = mktime(date('H', $currentTime),
|
||||
date('i', $currentTime),
|
||||
date('s', $currentTime),
|
||||
date('n', $currentTime),
|
||||
date('j', $currentTime) + 1,
|
||||
date('Y', $currentTime)
|
||||
);
|
||||
|
||||
// Adjusts the scheduled hour
|
||||
$rescheduledTime = $this->adjustHour($rescheduledTime);
|
||||
$rescheduledTime = $this->adjustTimezone($rescheduledTime);
|
||||
|
||||
return $rescheduledTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ScheduledTime::setDay
|
||||
* @param int $_day
|
||||
* @throws \Exception
|
||||
* @ignore
|
||||
*/
|
||||
public function setDay($_day)
|
||||
{
|
||||
throw new Exception("Method not supported");
|
||||
}
|
||||
}
|
61
msd2/tracking/piwik/core/Scheduler/Schedule/Hourly.php
Normal file
61
msd2/tracking/piwik/core/Scheduler/Schedule/Hourly.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler\Schedule;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Hourly class is used to schedule tasks every hour.
|
||||
*
|
||||
* @see \Piwik\Scheduler\Task
|
||||
*/
|
||||
class Hourly extends Schedule
|
||||
{
|
||||
/**
|
||||
* @see ScheduledTime::getRescheduledTime
|
||||
* @return int
|
||||
*/
|
||||
public function getRescheduledTime()
|
||||
{
|
||||
$currentTime = $this->getTime();
|
||||
|
||||
// Adds one hour and reset the number of minutes
|
||||
$rescheduledTime = mktime(date('H', $currentTime) + 1,
|
||||
0,
|
||||
date('s', $currentTime),
|
||||
date('n', $currentTime),
|
||||
date('j', $currentTime),
|
||||
date('Y', $currentTime)
|
||||
);
|
||||
return $rescheduledTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ScheduledTime::setHour
|
||||
* @param int $_hour
|
||||
* @throws \Exception
|
||||
* @return int
|
||||
*/
|
||||
public function setHour($_hour)
|
||||
{
|
||||
throw new Exception("Method not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ScheduledTime::setDay
|
||||
* @param int $_day
|
||||
* @throws \Exception
|
||||
* @return int
|
||||
*/
|
||||
public function setDay($_day)
|
||||
{
|
||||
throw new Exception("Method not supported");
|
||||
}
|
||||
}
|
144
msd2/tracking/piwik/core/Scheduler/Schedule/Monthly.php
Normal file
144
msd2/tracking/piwik/core/Scheduler/Schedule/Monthly.php
Normal file
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler\Schedule;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Monthly class is used to schedule tasks every month.
|
||||
*
|
||||
* @see \Piwik\Scheduler\Task
|
||||
*/
|
||||
class Monthly extends Schedule
|
||||
{
|
||||
/**
|
||||
* List of available week number strings used in setDayOfWeekFromString.
|
||||
*/
|
||||
private static $weekNumberStringToInt = array('first' => 0, 'second' => 1, 'third' => 2, 'fourth' => 3);
|
||||
|
||||
/**
|
||||
* Day of the week for scheduled time.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $dayOfWeek = null;
|
||||
|
||||
/**
|
||||
* Week number for scheduled time.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $week = null;
|
||||
|
||||
public function setDayOfWeekFromString($day)
|
||||
{
|
||||
@list($weekNumberString, $dayNumberString) = explode(' ', $day);
|
||||
|
||||
// get day number
|
||||
$day = Weekly::getDayIntFromString($dayNumberString) % 7;
|
||||
|
||||
// get week number
|
||||
$weekNumberString = strtolower($weekNumberString);
|
||||
if (isset(self::$weekNumberStringToInt[$weekNumberString])) {
|
||||
$week = self::$weekNumberStringToInt[$weekNumberString];
|
||||
} else {
|
||||
throw new Exception("Invalid week describer in Schedule\\Monthly::setDayOfWeekFromString: '$weekNumberString'. "
|
||||
. "Supported values are 'first', 'second', 'third', 'fourth'.");
|
||||
}
|
||||
|
||||
$this->setDayOfWeek($day, $week);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getRescheduledTime()
|
||||
{
|
||||
$currentTime = $this->getTime();
|
||||
|
||||
// Adds one month
|
||||
$rescheduledTime = mktime(date('H', $currentTime),
|
||||
date('i', $currentTime),
|
||||
date('s', $currentTime),
|
||||
date('n', $currentTime) + 1,
|
||||
1,
|
||||
date('Y', $currentTime)
|
||||
);
|
||||
|
||||
$nextMonthLength = date('t', $rescheduledTime);
|
||||
|
||||
// Sets scheduled day
|
||||
$scheduledDay = date('j', $currentTime);
|
||||
|
||||
if ($this->day !== null) {
|
||||
$scheduledDay = $this->day;
|
||||
}
|
||||
|
||||
if ($this->dayOfWeek !== null
|
||||
&& $this->week !== null
|
||||
) {
|
||||
$newTime = $rescheduledTime + $this->week * 7 * 86400;
|
||||
while (date("w", $newTime) != $this->dayOfWeek % 7) {
|
||||
// modulus for sanity check
|
||||
|
||||
$newTime += 86400;
|
||||
}
|
||||
$scheduledDay = ($newTime - $rescheduledTime) / 86400 + 1;
|
||||
}
|
||||
|
||||
// Caps scheduled day
|
||||
if ($scheduledDay > $nextMonthLength) {
|
||||
$scheduledDay = $nextMonthLength;
|
||||
}
|
||||
|
||||
// Adjusts the scheduled day
|
||||
$rescheduledTime += ($scheduledDay - 1) * 86400;
|
||||
|
||||
// Adjusts the scheduled hour
|
||||
$rescheduledTime = $this->adjustHour($rescheduledTime);
|
||||
$rescheduledTime = $this->adjustTimezone($rescheduledTime);
|
||||
|
||||
return $rescheduledTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $_day the day to set, has to be >= 1 and < 32
|
||||
* @throws Exception if parameter _day is invalid
|
||||
*/
|
||||
public function setDay($_day)
|
||||
{
|
||||
if (!($_day >= 1 && $_day < 32)) {
|
||||
throw new Exception("Invalid day parameter, must be >=1 and < 32");
|
||||
}
|
||||
|
||||
$this->day = $_day;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes this scheduled time execute on a particular day of the week on each month.
|
||||
*
|
||||
* @param int $_day the day of the week to use, between 0-6 (inclusive). 0 -> Sunday
|
||||
* @param int $_week the week to use, between 0-3 (inclusive)
|
||||
* @throws Exception if either parameter is invalid
|
||||
*/
|
||||
public function setDayOfWeek($_day, $_week)
|
||||
{
|
||||
if (!($_day >= 0 && $_day < 7)) {
|
||||
throw new Exception("Invalid day of week parameter, must be >= 0 & < 7");
|
||||
}
|
||||
|
||||
if (!($_week >= 0 && $_week < 4)) {
|
||||
throw new Exception("Invalid week number, must be >= 1 & < 4");
|
||||
}
|
||||
|
||||
$this->dayOfWeek = $_day;
|
||||
$this->week = $_week;
|
||||
}
|
||||
}
|
224
msd2/tracking/piwik/core/Scheduler/Schedule/Schedule.php
Normal file
224
msd2/tracking/piwik/core/Scheduler/Schedule/Schedule.php
Normal file
@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler\Schedule;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Date;
|
||||
|
||||
/**
|
||||
* Describes the interval on which a scheduled task is executed. Use the {@link factory()} method
|
||||
* to create Schedule instances.
|
||||
*
|
||||
* @see \Piwik\Scheduler\Task
|
||||
*/
|
||||
abstract class Schedule
|
||||
{
|
||||
const PERIOD_NEVER = 'never';
|
||||
const PERIOD_DAY = 'day';
|
||||
const PERIOD_WEEK = 'week';
|
||||
const PERIOD_MONTH = 'month';
|
||||
const PERIOD_HOUR = 'hour';
|
||||
const PERIOD_YEAR = 'year';
|
||||
const PERIOD_RANGE = 'range';
|
||||
|
||||
/**
|
||||
* @link http://php.net/manual/en/function.date.php, format string : 'G'
|
||||
* Defaults to midnight
|
||||
* @var integer
|
||||
*/
|
||||
protected $hour = 0;
|
||||
|
||||
/**
|
||||
* For weekly scheduling : http://php.net/manual/en/function.date.php, format string : 'N', defaults to Monday
|
||||
* For monthly scheduling : day of the month (1 to 31) (note: will be capped at the latest day available the
|
||||
* month), defaults to first day of the month
|
||||
* @var integer
|
||||
*/
|
||||
protected $day = 1;
|
||||
|
||||
protected $timezone = null;
|
||||
|
||||
/**
|
||||
* @param $period
|
||||
* @return Daily|Monthly|Weekly
|
||||
* @throws \Exception
|
||||
* @ignore
|
||||
*/
|
||||
public static function getScheduledTimeForPeriod($period)
|
||||
{
|
||||
switch ($period) {
|
||||
case self::PERIOD_MONTH:
|
||||
return new Monthly();
|
||||
case self::PERIOD_WEEK:
|
||||
return new Weekly();
|
||||
case self::PERIOD_DAY:
|
||||
return new Daily();
|
||||
case self::PERIOD_HOUR:
|
||||
return new Hourly();
|
||||
|
||||
default:
|
||||
throw new Exception('period ' . $period . 'is undefined.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the system time used by subclasses to compute schedulings.
|
||||
* This method has been introduced so unit tests can override the current system time.
|
||||
* @return int
|
||||
*/
|
||||
protected function getTime()
|
||||
{
|
||||
return time();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the next scheduled time based on the system time at which the method has been called and
|
||||
* the underlying scheduling interval.
|
||||
*
|
||||
* @abstract
|
||||
* @return integer Returns the rescheduled time measured in the number of seconds since the Unix Epoch
|
||||
* @ignore
|
||||
*/
|
||||
abstract public function getRescheduledTime();
|
||||
|
||||
/**
|
||||
* Sets the day of the period to execute the scheduled task. Not a valid operation for all period types.
|
||||
*
|
||||
* @abstract
|
||||
* @param int $_day a number describing the day to set. Its meaning depends on the Schedule's period type.
|
||||
* @throws Exception if method not supported by subclass or parameter _day is invalid
|
||||
*/
|
||||
abstract public function setDay($_day);
|
||||
|
||||
/**
|
||||
* Sets the hour of the day on which the task should be executed.
|
||||
*
|
||||
* @param int $hour Must be `>= 0` and `< 24`.
|
||||
* @throws Exception If the current scheduled period is **hourly** or if `$hour` is invalid.
|
||||
* @api
|
||||
*/
|
||||
public function setHour($hour)
|
||||
{
|
||||
if (!($hour >= 0 && $hour < 24)) {
|
||||
throw new Exception("Invalid hour parameter, must be >=0 and < 24");
|
||||
}
|
||||
|
||||
$this->hour = $hour;
|
||||
}
|
||||
|
||||
/**
|
||||
* By setting a timezone you make sure the scheduled task will be run at the requested time in the
|
||||
* given timezone. This is useful for instance in case you want to make sure a task runs at midnight in a website's
|
||||
* timezone.
|
||||
*
|
||||
* @param string $timezone
|
||||
*/
|
||||
public function setTimezone($timezone)
|
||||
{
|
||||
$this->timezone = $timezone;
|
||||
}
|
||||
|
||||
protected function adjustTimezone($rescheduledTime)
|
||||
{
|
||||
if (is_null($this->timezone)) {
|
||||
return $rescheduledTime;
|
||||
}
|
||||
|
||||
$arbitraryDateInUTC = Date::factory('2011-01-01');
|
||||
$dateInTimezone = Date::factory($arbitraryDateInUTC, $this->timezone);
|
||||
|
||||
$midnightInTimezone = date('H', $dateInTimezone->getTimestamp());
|
||||
|
||||
if ($arbitraryDateInUTC->isEarlier($dateInTimezone)) {
|
||||
$hoursDifference = 0 - $midnightInTimezone;
|
||||
} else {
|
||||
$hoursDifference = 24 - $midnightInTimezone;
|
||||
}
|
||||
|
||||
$hoursDifference = $hoursDifference % 24;
|
||||
|
||||
$rescheduledTime += (3600 * $hoursDifference);
|
||||
|
||||
if ($this->getTime() > $rescheduledTime) {
|
||||
// make sure the rescheduled date is in the future
|
||||
$rescheduledTime = (24 * 3600) + $rescheduledTime;
|
||||
}
|
||||
|
||||
return $rescheduledTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the delta in seconds needed to adjust the rescheduled time to the required hour.
|
||||
*
|
||||
* @param int $rescheduledTime The rescheduled time to be adjusted
|
||||
* @return int adjusted rescheduled time
|
||||
*/
|
||||
protected function adjustHour($rescheduledTime)
|
||||
{
|
||||
if ($this->hour !== null) {
|
||||
// Reset the number of minutes and set the scheduled hour to the one specified with setHour()
|
||||
$rescheduledTime = mktime($this->hour,
|
||||
0,
|
||||
date('s', $rescheduledTime),
|
||||
date('n', $rescheduledTime),
|
||||
date('j', $rescheduledTime),
|
||||
date('Y', $rescheduledTime)
|
||||
);
|
||||
}
|
||||
return $rescheduledTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Schedule instance using a string description of the scheduled period type
|
||||
* and a string description of the day within the period to execute the task on.
|
||||
*
|
||||
* @param string $periodType The scheduled period type. Can be `'hourly'`, `'daily'`, `'weekly'`, or `'monthly'`.
|
||||
* @param bool|false|int|string $periodDay A string describing the day within the scheduled period to execute
|
||||
* the task on. Only valid for week and month periods.
|
||||
*
|
||||
* If `'weekly'` is supplied for `$periodType`, this should be a day
|
||||
* of the week, for example, `'monday'` or `'tuesday'`.
|
||||
*
|
||||
* If `'monthly'` is supplied for `$periodType`, this can be a numeric
|
||||
* day in the month or a day in one week of the month. For example,
|
||||
* `12`, `23`, `'first sunday'` or `'fourth tuesday'`.
|
||||
* @return Hourly|Daily|Weekly|Monthly
|
||||
* @throws Exception
|
||||
* @api
|
||||
*/
|
||||
public static function factory($periodType, $periodDay = false)
|
||||
{
|
||||
switch ($periodType) {
|
||||
case 'hourly':
|
||||
return new Hourly();
|
||||
case 'daily':
|
||||
return new Daily();
|
||||
case 'weekly':
|
||||
$result = new Weekly();
|
||||
if ($periodDay !== false) {
|
||||
$result->setDay($periodDay);
|
||||
}
|
||||
return $result;
|
||||
case 'monthly':
|
||||
$result = new Monthly($periodDay);
|
||||
if ($periodDay !== false) {
|
||||
if (is_int($periodDay)) {
|
||||
$result->setDay($periodDay);
|
||||
} else {
|
||||
$result->setDayOfWeekFromString($periodDay);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
default:
|
||||
throw new Exception("Unsupported scheduled period type: '$periodType'. Supported values are"
|
||||
. " 'hourly', 'daily', 'weekly' or 'monthly'.");
|
||||
}
|
||||
}
|
||||
}
|
33
msd2/tracking/piwik/core/Scheduler/Schedule/SpecificTime.php
Normal file
33
msd2/tracking/piwik/core/Scheduler/Schedule/SpecificTime.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler\Schedule;
|
||||
|
||||
class SpecificTime extends Schedule
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $scheduledTime;
|
||||
|
||||
public function __construct($scheduledTime)
|
||||
{
|
||||
$this->scheduledTime = $scheduledTime;
|
||||
}
|
||||
|
||||
public function getRescheduledTime()
|
||||
{
|
||||
return $this->scheduledTime;
|
||||
}
|
||||
|
||||
public function setDay($_day)
|
||||
{
|
||||
throw new \Exception('not supported');
|
||||
}
|
||||
}
|
82
msd2/tracking/piwik/core/Scheduler/Schedule/Weekly.php
Normal file
82
msd2/tracking/piwik/core/Scheduler/Schedule/Weekly.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler\Schedule;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Weekly class is used to schedule tasks every week.
|
||||
*
|
||||
* @see \Piwik\Scheduler\Task
|
||||
*/
|
||||
class Weekly extends Schedule
|
||||
{
|
||||
/**
|
||||
* @see ScheduledTime::getRescheduledTime
|
||||
* @return int
|
||||
*/
|
||||
public function getRescheduledTime()
|
||||
{
|
||||
$currentTime = $this->getTime();
|
||||
|
||||
$daysFromNow = 7;
|
||||
|
||||
// Adjusts the scheduled day
|
||||
if ($this->day !== null) {
|
||||
$daysFromNow = ($this->day - date('N', $currentTime) + 7) % 7;
|
||||
|
||||
if ($daysFromNow == 0) {
|
||||
$daysFromNow = 7;
|
||||
}
|
||||
}
|
||||
|
||||
// Adds correct number of days
|
||||
$rescheduledTime = mktime(date('H', $currentTime),
|
||||
date('i', $currentTime),
|
||||
date('s', $currentTime),
|
||||
date('n', $currentTime),
|
||||
date('j', $currentTime) + $daysFromNow,
|
||||
date('Y', $currentTime)
|
||||
);
|
||||
|
||||
// Adjusts the scheduled hour
|
||||
$rescheduledTime = $this->adjustHour($rescheduledTime);
|
||||
$rescheduledTime = $this->adjustTimezone($rescheduledTime);
|
||||
|
||||
return $rescheduledTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $day the day to set, has to be >= 1 and < 8
|
||||
* @throws Exception if parameter _day is invalid
|
||||
*/
|
||||
public function setDay($day)
|
||||
{
|
||||
if (!is_int($day)) {
|
||||
$day = self::getDayIntFromString($day);
|
||||
}
|
||||
|
||||
if (!($day >= 1 && $day < 8)) {
|
||||
throw new Exception("Invalid day parameter, must be >=1 and < 8");
|
||||
}
|
||||
|
||||
$this->day = $day;
|
||||
}
|
||||
|
||||
public static function getDayIntFromString($dayString)
|
||||
{
|
||||
$time = strtotime($dayString);
|
||||
if ($time === false) {
|
||||
throw new Exception("Invalid day string '$dayString'. Must be 'monday', 'tuesday', etc.");
|
||||
}
|
||||
|
||||
return date("N", $time);
|
||||
}
|
||||
}
|
288
msd2/tracking/piwik/core/Scheduler/Scheduler.php
Normal file
288
msd2/tracking/piwik/core/Scheduler/Scheduler.php
Normal file
@ -0,0 +1,288 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Timer;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Schedules task execution.
|
||||
*
|
||||
* A scheduled task is a callback that should be executed every so often (such as daily,
|
||||
* weekly, monthly, etc.). They are registered by extending {@link \Piwik\Plugin\Tasks}.
|
||||
*
|
||||
* Tasks are executed when the `core:archive` command is executed.
|
||||
*
|
||||
* ### Examples
|
||||
*
|
||||
* **Scheduling a task**
|
||||
*
|
||||
* class Tasks extends \Piwik\Plugin\Tasks
|
||||
* {
|
||||
* public function schedule()
|
||||
* {
|
||||
* $this->hourly('myTask'); // myTask() will be executed once every hour
|
||||
* }
|
||||
* public function myTask()
|
||||
* {
|
||||
* // do something
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* **Executing all pending tasks**
|
||||
*
|
||||
* $results = $scheduler->run();
|
||||
* $task1Result = $results[0];
|
||||
* $task1Name = $task1Result['task'];
|
||||
* $task1Output = $task1Result['output'];
|
||||
*
|
||||
* echo "Executed task '$task1Name'. Task output:\n$task1Output";
|
||||
*/
|
||||
class Scheduler
|
||||
{
|
||||
/**
|
||||
* Is the scheduler running any task.
|
||||
* @var bool
|
||||
*/
|
||||
private $isRunningTask = false;
|
||||
|
||||
/**
|
||||
* @var Timetable
|
||||
*/
|
||||
private $timetable;
|
||||
|
||||
/**
|
||||
* @var TaskLoader
|
||||
*/
|
||||
private $loader;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
public function __construct(TaskLoader $loader, LoggerInterface $logger)
|
||||
{
|
||||
$this->timetable = new Timetable();
|
||||
$this->loader = $loader;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes tasks that are scheduled to run, then reschedules them.
|
||||
*
|
||||
* @return array An array describing the results of scheduled task execution. Each element
|
||||
* in the array will have the following format:
|
||||
*
|
||||
* ```
|
||||
* array(
|
||||
* 'task' => 'task name',
|
||||
* 'output' => '... task output ...'
|
||||
* )
|
||||
* ```
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$tasks = $this->loader->loadTasks();
|
||||
|
||||
$this->logger->debug('{count} scheduled tasks loaded', array('count' => count($tasks)));
|
||||
|
||||
// remove from timetable tasks that are not active anymore
|
||||
$this->timetable->removeInactiveTasks($tasks);
|
||||
|
||||
$this->logger->info("Starting Scheduled tasks... ");
|
||||
|
||||
// for every priority level, starting with the highest and concluding with the lowest
|
||||
$executionResults = array();
|
||||
for ($priority = Task::HIGHEST_PRIORITY; $priority <= Task::LOWEST_PRIORITY; ++$priority) {
|
||||
$this->logger->debug("Executing tasks with priority {priority}:", array('priority' => $priority));
|
||||
|
||||
// loop through each task
|
||||
foreach ($tasks as $task) {
|
||||
// if the task does not have the current priority level, don't execute it yet
|
||||
if ($task->getPriority() != $priority) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$taskName = $task->getName();
|
||||
$shouldExecuteTask = $this->timetable->shouldExecuteTask($taskName);
|
||||
|
||||
if ($this->timetable->taskShouldBeRescheduled($taskName)) {
|
||||
$rescheduledDate = $this->timetable->rescheduleTask($task);
|
||||
|
||||
$this->logger->debug("Task {task} is scheduled to run again for {date}.", array('task' => $taskName, 'date' => $rescheduledDate));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered before a task is executed.
|
||||
*
|
||||
* A plugin can listen to it and modify whether a specific task should be executed or not. This way
|
||||
* you can force certain tasks to be executed more often or for example to be never executed.
|
||||
*
|
||||
* @param bool &$shouldExecuteTask Decides whether the task will be executed.
|
||||
* @param Task $task The task that is about to be executed.
|
||||
*/
|
||||
Piwik::postEvent('ScheduledTasks.shouldExecuteTask', array(&$shouldExecuteTask, $task));
|
||||
|
||||
if ($shouldExecuteTask) {
|
||||
$message = $this->executeTask($task);
|
||||
|
||||
$executionResults[] = array('task' => $taskName, 'output' => $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->info("done");
|
||||
|
||||
return $executionResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a specific task now. Will ignore the schedule completely.
|
||||
*
|
||||
* @param string $taskName
|
||||
* @return string Task output.
|
||||
*/
|
||||
public function runTaskNow($taskName)
|
||||
{
|
||||
$tasks = $this->loader->loadTasks();
|
||||
|
||||
foreach ($tasks as $task) {
|
||||
if ($task->getName() === $taskName) {
|
||||
return $this->executeTask($task);
|
||||
}
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Task ' . $taskName . ' not found');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines a task's scheduled time and persists it, overwriting the previous scheduled time.
|
||||
*
|
||||
* Call this method if your task's scheduled time has changed due to, for example, an option that
|
||||
* was changed.
|
||||
*
|
||||
* @param Task $task Describes the scheduled task being rescheduled.
|
||||
* @api
|
||||
*/
|
||||
public function rescheduleTask(Task $task)
|
||||
{
|
||||
$this->logger->debug('Rescheduling task {task}', array('task' => $task->getName()));
|
||||
|
||||
$this->timetable->rescheduleTask($task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines a task's scheduled time and persists it, overwriting the previous scheduled time.
|
||||
*
|
||||
* Call this method if your task's scheduled time has changed due to, for example, an option that
|
||||
* was changed.
|
||||
*
|
||||
* The task will be run the first time tomorrow.
|
||||
*
|
||||
* @param Task $task Describes the scheduled task being rescheduled.
|
||||
* @api
|
||||
*/
|
||||
public function rescheduleTaskAndRunTomorrow(Task $task)
|
||||
{
|
||||
$this->logger->debug('Rescheduling task and setting first run for tomorrow {task}', array('task' => $task->getName()));
|
||||
|
||||
$this->timetable->rescheduleTaskAndRunTomorrow($task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the scheduler is currently running a task.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRunningTask()
|
||||
{
|
||||
return $this->isRunningTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the next scheduled time given the class and method names of a scheduled task.
|
||||
*
|
||||
* @param string $className The name of the class that contains the scheduled task method.
|
||||
* @param string $methodName The name of the scheduled task method.
|
||||
* @param string|null $methodParameter Optional method parameter.
|
||||
* @return mixed int|bool The time in miliseconds when the scheduled task will be executed
|
||||
* next or false if it is not scheduled to run.
|
||||
*/
|
||||
public function getScheduledTimeForMethod($className, $methodName, $methodParameter = null)
|
||||
{
|
||||
return $this->timetable->getScheduledTimeForMethod($className, $methodName, $methodParameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of the task names.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getTaskList()
|
||||
{
|
||||
$tasks = $this->loader->loadTasks();
|
||||
|
||||
return array_map(function (Task $task) {
|
||||
return $task->getName();
|
||||
}, $tasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given task
|
||||
*
|
||||
* @param Task $task
|
||||
* @return string
|
||||
*/
|
||||
private function executeTask($task)
|
||||
{
|
||||
$this->logger->info("Scheduler: executing task {taskName}...", array(
|
||||
'taskName' => $task->getName(),
|
||||
));
|
||||
|
||||
$this->isRunningTask = true;
|
||||
|
||||
$timer = new Timer();
|
||||
|
||||
/**
|
||||
* Triggered directly before a scheduled task is executed
|
||||
*
|
||||
* @param Task $task The task that is about to be executed
|
||||
*/
|
||||
Piwik::postEvent('ScheduledTasks.execute', array(&$task));
|
||||
|
||||
try {
|
||||
$callable = array($task->getObjectInstance(), $task->getMethodName());
|
||||
call_user_func($callable, $task->getMethodParameter());
|
||||
$message = $timer->__toString();
|
||||
} catch (Exception $e) {
|
||||
$message = 'ERROR: ' . $e->getMessage();
|
||||
}
|
||||
|
||||
$this->isRunningTask = false;
|
||||
|
||||
/**
|
||||
* Triggered after a scheduled task is successfully executed.
|
||||
*
|
||||
* You can use the event to execute for example another task whenever a specific task is executed or to clean up
|
||||
* certain resources.
|
||||
*
|
||||
* @param Task $task The task that was just executed
|
||||
*/
|
||||
Piwik::postEvent('ScheduledTasks.execute.end', array(&$task));
|
||||
|
||||
$this->logger->info("Scheduler: finished. {timeElapsed}", array(
|
||||
'timeElapsed' => $timer,
|
||||
));
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
200
msd2/tracking/piwik/core/Scheduler/Task.php
Normal file
200
msd2/tracking/piwik/core/Scheduler/Task.php
Normal file
@ -0,0 +1,200 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Scheduler\Schedule\Schedule;
|
||||
|
||||
/**
|
||||
* Describes a task that should be executed on a given time.
|
||||
*
|
||||
* See the {@link TaskScheduler} docs to learn more about scheduled tasks.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Task
|
||||
{
|
||||
const LOWEST_PRIORITY = 12;
|
||||
const LOW_PRIORITY = 9;
|
||||
const NORMAL_PRIORITY = 6;
|
||||
const HIGH_PRIORITY = 3;
|
||||
const HIGHEST_PRIORITY = 0;
|
||||
|
||||
/**
|
||||
* Object instance on which the method will be executed by the task scheduler
|
||||
* @var string
|
||||
*/
|
||||
private $objectInstance;
|
||||
|
||||
/**
|
||||
* Class name where the specified method is located
|
||||
* @var string
|
||||
*/
|
||||
private $className;
|
||||
|
||||
/**
|
||||
* Class method to run when task is scheduled
|
||||
* @var string
|
||||
*/
|
||||
private $methodName;
|
||||
|
||||
/**
|
||||
* Parameter to pass to the executed method
|
||||
* @var string
|
||||
*/
|
||||
private $methodParameter;
|
||||
|
||||
/**
|
||||
* The scheduled time policy
|
||||
* @var Schedule
|
||||
*/
|
||||
private $scheduledTime;
|
||||
|
||||
/**
|
||||
* The priority of a task. Affects the order in which this task will be run.
|
||||
* @var int
|
||||
*/
|
||||
private $priority;
|
||||
|
||||
/**
|
||||
* @param mixed $objectInstance The object or class that contains the method to execute regularly.
|
||||
* Usually this will be a {@link Plugin} instance.
|
||||
* @param string $methodName The name of the method that will be regularly executed.
|
||||
* @param mixed|null $methodParameter An optional parameter to pass to the method when executed.
|
||||
* Must be convertible to string.
|
||||
* @param Schedule|null $scheduledTime A {@link Schedule} instance that describes when the method
|
||||
* should be executed and how long before the next execution.
|
||||
* @param int $priority The priority of the task. Tasks with a higher priority will be executed first.
|
||||
* Tasks with low priority will be executed last.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($objectInstance, $methodName, $methodParameter, $scheduledTime,
|
||||
$priority = self::NORMAL_PRIORITY)
|
||||
{
|
||||
$this->className = $this->getClassNameFromInstance($objectInstance);
|
||||
|
||||
if ($priority < self::HIGHEST_PRIORITY || $priority > self::LOWEST_PRIORITY) {
|
||||
throw new Exception("Invalid priority for ScheduledTask '$this->className.$methodName': $priority");
|
||||
}
|
||||
|
||||
$this->objectInstance = $objectInstance;
|
||||
$this->methodName = $methodName;
|
||||
$this->scheduledTime = $scheduledTime;
|
||||
$this->methodParameter = $methodParameter;
|
||||
$this->priority = $priority;
|
||||
}
|
||||
|
||||
protected function getClassNameFromInstance($_objectInstance)
|
||||
{
|
||||
if (is_string($_objectInstance)) {
|
||||
return $_objectInstance;
|
||||
}
|
||||
|
||||
$namespaced = get_class($_objectInstance);
|
||||
|
||||
return $namespaced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object instance that contains the method to execute. Returns a class
|
||||
* name if the method is static.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getObjectInstance()
|
||||
{
|
||||
return $this->objectInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the class that contains the method to execute.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getClassName()
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the method that will be executed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMethodName()
|
||||
{
|
||||
return $this->methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value that will be passed to the method when executed, or `null` if
|
||||
* no value will be supplied.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getMethodParameter()
|
||||
{
|
||||
return $this->methodParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Schedule} instance that describes when the method should be executed
|
||||
* and how long before the next execution.
|
||||
*
|
||||
* @return \Piwik\Scheduler\Schedule\Schedule
|
||||
*/
|
||||
public function getScheduledTime()
|
||||
{
|
||||
return $this->scheduledTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time in milliseconds when this task will be executed next.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRescheduledTime()
|
||||
{
|
||||
return $this->getScheduledTime()->getRescheduledTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the task priority. The priority will be an integer whose value is
|
||||
* between {@link HIGH_PRIORITY} and {@link LOW_PRIORITY}.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPriority()
|
||||
{
|
||||
return $this->priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique name for this scheduled task. The name is stored in the DB and is used
|
||||
* to store a task's previous execution time. The name is created using:
|
||||
*
|
||||
* - the name of the class that contains the method to execute,
|
||||
* - the name of the method to regularly execute,
|
||||
* - and the value that is passed to the executed task.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return self::getTaskName($this->getClassName(), $this->getMethodName(), $this->getMethodParameter());
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public static function getTaskName($className, $methodName, $methodParameter = null)
|
||||
{
|
||||
return $className . '.' . $methodName . ($methodParameter == null ? '' : '_' . $methodParameter);
|
||||
}
|
||||
}
|
41
msd2/tracking/piwik/core/Scheduler/TaskLoader.php
Normal file
41
msd2/tracking/piwik/core/Scheduler/TaskLoader.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler;
|
||||
|
||||
use Piwik\Container\StaticContainer;
|
||||
use Piwik\Plugin\Manager as PluginManager;
|
||||
use Piwik\Plugin\Tasks;
|
||||
|
||||
/**
|
||||
* Loads scheduled tasks.
|
||||
*/
|
||||
class TaskLoader
|
||||
{
|
||||
/**
|
||||
* @return Task[]
|
||||
*/
|
||||
public function loadTasks()
|
||||
{
|
||||
$tasks = array();
|
||||
|
||||
/** @var Tasks[] $pluginTasks */
|
||||
$pluginTasks = PluginManager::getInstance()->findComponents('Tasks', 'Piwik\Plugin\Tasks');
|
||||
|
||||
foreach ($pluginTasks as $pluginTask) {
|
||||
$pluginTask = StaticContainer::get($pluginTask);
|
||||
$pluginTask->schedule();
|
||||
|
||||
foreach ($pluginTask->getScheduledTasks() as $task) {
|
||||
$tasks[] = $task;
|
||||
}
|
||||
}
|
||||
|
||||
return $tasks;
|
||||
}
|
||||
}
|
146
msd2/tracking/piwik/core/Scheduler/Timetable.php
Normal file
146
msd2/tracking/piwik/core/Scheduler/Timetable.php
Normal file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Scheduler;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Option;
|
||||
use Piwik\Date;
|
||||
|
||||
/**
|
||||
* This data structure holds the scheduled times for each active scheduled task.
|
||||
*/
|
||||
class Timetable
|
||||
{
|
||||
const TIMETABLE_OPTION_STRING = "TaskScheduler.timetable";
|
||||
|
||||
private $timetable;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$optionData = Option::get(self::TIMETABLE_OPTION_STRING);
|
||||
$unserializedTimetable = Common::safe_unserialize($optionData);
|
||||
|
||||
$this->timetable = $unserializedTimetable === false ? array() : $unserializedTimetable;
|
||||
}
|
||||
|
||||
public function getTimetable()
|
||||
{
|
||||
return $this->timetable;
|
||||
}
|
||||
|
||||
public function setTimetable($timetable)
|
||||
{
|
||||
$this->timetable = $timetable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Task[] $activeTasks
|
||||
*/
|
||||
public function removeInactiveTasks($activeTasks)
|
||||
{
|
||||
$activeTaskNames = array();
|
||||
foreach ($activeTasks as $task) {
|
||||
$activeTaskNames[] = $task->getName();
|
||||
}
|
||||
foreach (array_keys($this->timetable) as $taskName) {
|
||||
if (!in_array($taskName, $activeTaskNames)) {
|
||||
unset($this->timetable[$taskName]);
|
||||
}
|
||||
}
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function getScheduledTaskNames()
|
||||
{
|
||||
return array_keys($this->timetable);
|
||||
}
|
||||
|
||||
public function getScheduledTaskTime($taskName)
|
||||
{
|
||||
return isset($this->timetable[$taskName]) ? Date::factory($this->timetable[$taskName]) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the task should be executed
|
||||
*
|
||||
* Task has to be executed if :
|
||||
* - the task has already been scheduled once and the current system time is greater than the scheduled time.
|
||||
* - execution is forced, see $forceTaskExecution
|
||||
*
|
||||
* @param string $taskName
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function shouldExecuteTask($taskName)
|
||||
{
|
||||
$forceTaskExecution = (defined('DEBUG_FORCE_SCHEDULED_TASKS') && DEBUG_FORCE_SCHEDULED_TASKS);
|
||||
|
||||
if ($forceTaskExecution) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->taskHasBeenScheduledOnce($taskName) && time() >= $this->timetable[$taskName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a task should be rescheduled
|
||||
*
|
||||
* Task has to be rescheduled if :
|
||||
* - the task has to be executed
|
||||
* - the task has never been scheduled before
|
||||
*
|
||||
* @param string $taskName
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function taskShouldBeRescheduled($taskName)
|
||||
{
|
||||
return !$this->taskHasBeenScheduledOnce($taskName) || $this->shouldExecuteTask($taskName);
|
||||
}
|
||||
|
||||
public function rescheduleTask(Task $task)
|
||||
{
|
||||
$rescheduledTime = $task->getRescheduledTime();
|
||||
|
||||
// update the scheduled time
|
||||
$this->timetable[$task->getName()] = $rescheduledTime;
|
||||
$this->save();
|
||||
|
||||
return Date::factory($rescheduledTime);
|
||||
}
|
||||
|
||||
public function rescheduleTaskAndRunTomorrow(Task $task)
|
||||
{
|
||||
$tomorrow = Date::factory('tomorrow');
|
||||
|
||||
// update the scheduled time
|
||||
$this->timetable[$task->getName()] = $tomorrow->getTimestamp();
|
||||
$this->save();
|
||||
|
||||
return $tomorrow;
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
Option::set(self::TIMETABLE_OPTION_STRING, serialize($this->timetable));
|
||||
}
|
||||
|
||||
public function getScheduledTimeForMethod($className, $methodName, $methodParameter = null)
|
||||
{
|
||||
$taskName = Task::getTaskName($className, $methodName, $methodParameter);
|
||||
|
||||
return $this->taskHasBeenScheduledOnce($taskName) ? $this->timetable[$taskName] : false;
|
||||
}
|
||||
|
||||
public function taskHasBeenScheduledOnce($taskName)
|
||||
{
|
||||
return isset($this->timetable[$taskName]);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user