aboutsummaryrefslogtreecommitdiff
path: root/lib/models/CronjobSchedule.class.php
diff options
context:
space:
mode:
authorPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
committerPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
commit4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch)
tree5c07151ae61276d334e88f6309c30d439a85c12e /lib/models/CronjobSchedule.class.php
parentda0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff)
parent97a188592c679890a25c37ab78463add76a52ff7 (diff)
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/models/CronjobSchedule.class.php')
-rw-r--r--lib/models/CronjobSchedule.class.php324
1 files changed, 0 insertions, 324 deletions
diff --git a/lib/models/CronjobSchedule.class.php b/lib/models/CronjobSchedule.class.php
deleted file mode 100644
index 4304be1..0000000
--- a/lib/models/CronjobSchedule.class.php
+++ /dev/null
@@ -1,324 +0,0 @@
-<?php
-// +---------------------------------------------------------------------------+
-// This file is part of Stud.IP
-// CronjobSchedule.class.php
-//
-// Copyright (C) 2013 Jan-Hendrik Willms <tleilax+studip@gmail.com>
-// +---------------------------------------------------------------------------+
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or any later version.
-// +---------------------------------------------------------------------------+
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-// +---------------------------------------------------------------------------+
-
-/**
- * CronjobSchedule - Model for the database table "cronjobs_schedules"
- *
- * @author Jan-Hendrik Willms <tleilax+studip@gmail.com>
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @category Stud.IP
- * @since 2.4
- *
- * @property string $id alias column for schedule_id
- * @property string $schedule_id database column
- * @property string $task_id database column
- * @property int $active database column
- * @property string|null $title database column
- * @property string|null $description database column
- * @property string|null $parameters database column
- * @property string $priority database column
- * @property string $type database column
- * @property int|null $minute database column
- * @property int|null $hour database column
- * @property int|null $day database column
- * @property int|null $month database column
- * @property int|null $day_of_week database column
- * @property int $next_execution database column
- * @property int|null $last_execution database column
- * @property string|null $last_result database column
- * @property int $execution_count database column
- * @property int $mkdate database column
- * @property int $chdate database column
- * @property SimpleORMapCollection|CronjobLog[] $logs has_many CronjobLog
- * @property CronjobTask $task belongs_to CronjobTask
- */
-
-class CronjobSchedule extends SimpleORMap
-{
- const PRIORITY_LOW = 'low';
- const PRIORITY_NORMAL = 'normal';
- const PRIORITY_HIGH = 'high';
-
- protected static function configure($config = [])
- {
- $config['db_table'] = 'cronjobs_schedules';
-
- $config['belongs_to']['task'] = [
- 'class_name' => CronjobTask::class,
- 'foreign_key' => 'task_id',
- ];
- $config['has_many']['logs'] = [
- 'class_name' => CronjobLog::class,
- 'on_delete' => 'delete',
- 'on_store' => 'store',
- ];
-
- $config['registered_callbacks']['before_store'][] = 'cbJsonifyParameters';
- $config['registered_callbacks']['after_store'][] = 'cbJsonifyParameters';
- $config['registered_callbacks']['after_initialize'][] = 'cbJsonifyParameters';
-
- parent::configure($config);
- }
-
- /**
- * Returns a mapped version of the priorities (key = priority value,
- * value = localized priority label).
- *
- * @return Array The mapped priorities
- */
- public static function getPriorities()
- {
- $mapping = [];
- $mapping[self::PRIORITY_LOW] = _('niedrig');
- $mapping[self::PRIORITY_NORMAL] = _('normal');
- $mapping[self::PRIORITY_HIGH] = _('hoch');
-
- return $mapping;
- }
-
- /**
- * Maps a priority value to it's localized label.
- *
- * @param String $priority Priority value
- * @return String The localized label
- * @throws RuntimeException when an unknown priority value is passed
- */
- public static function describePriority($priority)
- {
- $priority = $priority ?? 'normal';
-
- $mapping = self::getPriorities();
- if (!isset($mapping[$priority])) {
- throw new RuntimeException('Access to unknown priority "' . $priority . '"');
- }
-
- return $mapping[$priority];
- }
-
- /**
- * replaces title with task name if title is empty.
- *
- * @return string the title or the task name
- */
- public function getTitle()
- {
- return $this->content['title'] ?: $this->task->name ?? '';
- }
-
- protected function cbJsonifyParameters($type)
- {
- if ($type === 'before_store' && !is_string($this->parameters)) {
- $this->parameters = json_encode($this->parameters ?: null);
- }
- if (in_array($type, ['after_initialize', 'after_store']) && is_string($this->parameters)) {
- $parameters = json_decode($this->parameters, true) ?: [];
- if ($this->task && $this->task->valid) {
- $default_parameters = $this->task->extractDefaultParameters();
- foreach ($default_parameters as $key => $value) {
- if (!isset($parameters[$key])) {
- $parameters[$key] = $value;
- }
- }
- }
- $this->parameters = $parameters;
- }
- }
-
- /**
- * Stores the schedule in database. Will bail out with an exception if
- * the provided task does not exists. Will also nullify the title if it
- * matches the task name (see CronjobSchedule::getTitle()).
- *
- * @return CronjobSchedule Returns itself to allow chaining
- */
- public function store()
- {
- if ($this->task === null) {
- $message = sprintf('A task with the id "%s" does not exist.', $this->task_id);
- throw new InvalidArgumentException($message);
- }
-
- // Remove title if it is the default (task's name)
- if ($this->title === $this->task->name) {
- $this->title = null;
- }
-
- parent::store();
-
- return $this;
- }
-
- /**
- * Activates this schedule.
- *
- * @return CronjobSchedule Returns itself to allow chaining
- */
- public function activate()
- {
- $this->active = 1;
- $this->next_execution = $this->calculateNextExecution();
- $this->store();
-
- return $this;
- }
-
- /**
- * Deactivates this schedule.
- *
- * @return CronjobSchedule Returns itself to allow chaining
- */
- public function deactivate()
- {
- $this->active = 0;
- $this->store();
-
- return $this;
- }
-
- /**
- * Executes this schedule.
- *
- * @param bool $force Pass true to force execution of the schedule even
- * if it's not activated
- * @return mixed The result of the execution
- * @throws RuntimeException When either the schedule or the according is
- * not activated
- */
- public function execute($force = false)
- {
- if (!$force && !$this->active) {
- throw new RuntimeException('Execution aborted. Schedule is not active');
- }
- if (!$this->task->active) {
- throw new RuntimeException('Execution aborted. Associated task is not active');
- }
-
- $this->last_execution = time();
- $this->execution_count += 1;
- $this->next_execution = $this->calculateNextExecution();
- $this->store();
-
- $this->task->execution_count += 1;
- $this->task->store();
-
- $result = $this->task->engage($this->last_result, $this->parameters);
-
- if ($this->type === 'once') {
- $this->active = 0;
- }
- $this->last_result = $result;
- $this->store();
-
- return $result;
- }
-
- /**
- * Determines whether the schedule should execute given the provided
- * timestamp.
- *
- * @param mixed $now Defines the temporal fix point
- * @return bool Whether the schedule should execute or not.
- */
- public function shouldExecute($now = null)
- {
- return ($now ?: time()) >= $this->next_execution;
- }
-
- /**
- * Calculates the next execution for this schedule.
- *
- * For schedules of type 'once' the check solely tests whether the
- * timestamp has already passed and will return false in that case.
- * Otherwise the defined timestamp will be returned.
- *
- * For schedules of type 'periodic' the next execution
- * is calculated by increasing the current timestamp and testing
- * whether all conditions match. This is not the best method to test
- * and should be optimized sooner or later.
- *
- * @param mixed $now Defines the temporal fix point
- * @return int Timestamp of calculated next execution
- * @throws RuntimeException When calculation takes too long (you should
- * check the conditions for validity in that case)
- */
- public function calculateNextExecution($now = null)
- {
- $now = $now ?: time();
-
- if ($this->type === 'once') {
- return $now <= $this->next_execution
- ? $this->next_execution
- : false;
- }
-
- $result = $now;
- $result -= $result % 60;
-
- $i = 366 * 24 * 60; // Maximum: A year
- $offset = 60;
-
- do {
- $result += $offset;
-
- // TODO: Performance - Adjust result according to conditions
- // See http://coderzone.org/library/PHP-PHP-Cron-Parser-Class_1084.htm
- $valid = $this->testTimestamp($result, $this->minute, 'i')
- && $this->testTimestamp($result, $this->hour, 'H')
- && $this->testTimestamp($result, $this->day, 'd')
- && $this->testTimestamp($result, $this->month, 'm')
- && $this->testTimestamp($result, $this->day_of_week, 'N');
-
- } while (!$valid && $i-- > 0);
-
- if ($i <= 0) {
- throw new RuntimeException('No result, current: ' . date('d.m.Y H:i', $result));
- }
-
- $this->next_execution = $result;
- return $result;
- }
-
- /**
- * Tests a timestamp against the passed condition.
- *
- * @param int $timestamp The timestamp to test
- * @param mixed $condition Can be either null for "don't care", a positive
- * number for an exact moment or a negative number
- * for a repeating moment
- * @param String $format Format for date() to extract a portion of the
- * timestamp
- */
- protected function testTimestamp($timestamp, $condition, $format)
- {
- if ($condition === null) {
- return true;
- }
-
- $probe = (int) date($format, $timestamp);
- $condition = (int) $condition;
-
- if ($condition < 0) {
- return ($probe % abs($condition)) === 0;
- }
-
- return $probe === $condition;
- }
-}