summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/scheduler/controllers/admin_schedule.php105
-rw-r--r--modules/scheduler/helpers/scheduler.php133
-rw-r--r--modules/scheduler/helpers/scheduler_event.php64
-rw-r--r--modules/scheduler/helpers/scheduler_installer.php42
-rw-r--r--modules/scheduler/models/schedule.php33
-rw-r--r--modules/scheduler/module.info3
-rw-r--r--modules/scheduler/views/admin_schedule.html.php11
-rw-r--r--modules/scheduler/views/admin_schedule_confirm.html.php4
-rw-r--r--modules/scheduler/views/scheduler_definitions.html.php49
9 files changed, 444 insertions, 0 deletions
diff --git a/modules/scheduler/controllers/admin_schedule.php b/modules/scheduler/controllers/admin_schedule.php
new file mode 100644
index 00000000..6911cf86
--- /dev/null
+++ b/modules/scheduler/controllers/admin_schedule.php
@@ -0,0 +1,105 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * 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 (at
+ * your option) 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Admin_Schedule_Controller extends Admin_Controller {
+ public function form_add($task_callback) {
+ access::verify_csrf();
+
+ $schedule = ORM::factory("schedule");
+ $schedule->task_callback = $task_callback;
+ $schedule->next_run_datetime = time();
+ $v = new View("admin_schedule.html");
+ $v->form = scheduler::get_form("define", $schedule);
+ $v->method = "define";
+ print $v;
+ }
+
+ public function update_form($id) {
+ access::verify_csrf();
+
+
+ $schedule = ORM::factory("schedule", $id);
+ $v = new View("admin_schedule.html");
+ $v->form = scheduler::get_form("update", $schedule);
+ $v->method = "update";
+ print $v;
+ }
+
+ public function remove_form($id) {
+ access::verify_csrf();
+
+ $schedule = ORM::factory("schedule", $id);
+
+ $v = new View("admin_schedule_confirm.html");
+ $v->name = $schedule->name;
+ $v->form = new Forge("admin/schedule/remove/{$id}", "", "post",
+ array("id" => "g-remove-schedule"));
+ $group = $v->form->group("remove");
+ $group->submit("")->value(t("Continue"));
+ print $v;
+ }
+
+ public function remove($id) {
+ access::verify_csrf();
+ $schedule = ORM::factory("schedule", $id);
+ $schedule->delete();
+
+ message::success(t("Removed scheduled task: %name", array("name" => $schedule->name)));
+ print json_encode(array("result" => "success", "reload" => 1));
+ }
+
+ public function define() {
+ $this->_handle_request("define");
+ }
+
+ public function update($id=null) {
+ $this->_handle_request("update", $id);
+ }
+
+ private function _handle_request($method, $id=null) {
+ $schedule = ORM::factory("schedule", $id);
+ $form = scheduler::get_form($method, $schedule);
+ $valid = $form->validate();
+ if ($valid) {
+ $schedule->name = $form->schedule_group->schedule_name->value;
+ $schedule->interval = $form->schedule_group->interval->value;
+ $schedule->next_run_datetime =
+ $this->_start_date($form->schedule_group->run_date->dow->selected,
+ $form->schedule_group->run_date->time->value);
+ $schedule->task_callback = $form->schedule_group->callback->value;
+ $schedule->save();
+ if ($method == "define") {
+ message::success(t("Added scheduled task: %name", array("name" => $schedule->name)));
+ } else {
+ message::success(t("Updated scheduled task: %name", array("name" => $schedule->name)));
+ }
+ print json_encode(array("result" => "success", "reload" => 1));
+ } else {
+ print json_encode(array("result" => "error", "form" => (string) $form));
+ }
+ }
+
+ private function _start_date($dow, $time) {
+ list ($hour, $minutes) = explode(":", $time);
+ $local_time = localtime();
+ $days = ($dow < $local_time[6] ? 7 : 0) + $dow - $local_time[6];
+ return
+ mktime($hour, $minutes, 0, $local_time[4] + 1, $local_time[3] + $days, 1900 + $local_time[5]);
+ }
+}
diff --git a/modules/scheduler/helpers/scheduler.php b/modules/scheduler/helpers/scheduler.php
new file mode 100644
index 00000000..987b1b32
--- /dev/null
+++ b/modules/scheduler/helpers/scheduler.php
@@ -0,0 +1,133 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * 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 (at
+ * your option) 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class scheduler_Core {
+
+ static function intervals() {
+ static $intervals;
+ if (empty($intervals)) {
+ $intervals = array("3600" => t("Hourly"), "86400" => t("Daily"),
+ "604800" => t("Weekly"), "2419200" => t("Monthly"));
+ }
+ return $intervals;
+ }
+
+ static function get_form($method, $schedule) {
+ if ($method == "define") {
+ $title = t("Create a scheduled event");
+ $button_text = t("Create");
+ } else {
+ $title = t("Update a scheduled event");
+ $button_text = t("Update");
+ }
+
+ $id = empty($schedule->id) ? "" : "/$schedule->id";
+ $form = new Forge("admin/schedule/$method{$id}", "", "post",
+ array("id" => "g-{$method}-schedule"));
+ $group = $form->group("schedule_group")->label($title);
+ $group->input("schedule_name")
+ ->label(t("Description"))
+ ->id("g-schedule-name")
+ ->rules("required|length[0, 128]")
+ ->error_messages("required", t("You must provide a description"))
+ ->error_messages("length", t("Your description is too long"))
+ ->value(!empty($schedule->name) ? $schedule->name : "");
+
+ list ($dow, $display_time) = scheduler::format_time($schedule->next_run_datetime);
+ $next = $group->group("run_date")->label(t("Scheduled Date"));
+ $next->dropdown("dow")
+ ->label(t("Day"))
+ ->id("g-schedule-day")
+ ->rules("required")
+ ->options(array(t("Sunday"), t("Monday"), t("Tuesday"), t("Wednesday"),
+ t("Thursday"), t("Friday"), t("Saturday")))
+ ->selected($dow);
+
+ $next->input("time")
+ ->label(t("Hour"))
+ ->id("g-schedule-time")
+ ->rules("required")
+ ->error_messages("required", t("You must provide a time"))
+ ->error_messages("time_invalid", t("Invalid time"))
+ ->callback("scheduler::valid_time")
+ ->value($display_time);
+
+ // need to set the top padding to zero on g-define-schedule li.g-error
+ $group->dropdown("interval")->label(t("How often"))->id("g-schedule-frequency")
+ ->options(scheduler::intervals())
+ ->rules("required")
+ ->error_messages("required", t("You must provide an interval"))
+ ->selected(!empty($schedule->interval) ? $schedule->interval : "2419200");
+ $group->hidden("callback")->value($schedule->task_callback);
+ $group->submit("")->value($button_text);
+
+ return $form;
+ }
+
+ static function format_time($time) {
+ $local_time = localtime($time);
+ $display_time = str_pad($local_time[2], 2, "0", STR_PAD_LEFT) . ":" .
+ str_pad($local_time[1], 2, "0", STR_PAD_LEFT);
+ return array($local_time[6], $display_time);
+ }
+
+ static function valid_time($field) {
+ if (preg_match("/([0-9]{1,2}):([0-9]{2})/", $field->value, $matches)) {
+ $hour = (int)$matches[1];
+ $minutes = (int)$matches[2];
+ if (!(0 <= $hour && $hour<= 23 || 0 <= $minutes && $minutes <= 59)) {
+ $field->add_error("time_invalid", 1);
+ }
+ } else {
+ $field->add_error("time_invalid", 1);
+ }
+ }
+
+ static function get_definitions() {
+ $v = "";
+ $events = ORM::factory("schedule")
+ ->order_by("next_run_datetime", "asc")
+ ->find_all();
+ if ($events->count()) {
+ $v = new View("scheduler_definitions.html");
+ $v->schedule_definitions = array();
+ foreach ($events as $schedule) {
+ $entry[] = $schedule->id;
+ $entry[] = $schedule->name;
+ $run_date = strftime("%A, %b %e, %Y %H:%M ", $schedule->next_run_datetime);
+ $intervals = scheduler::intervals();
+ $interval = $intervals[$schedule->interval];
+ if (!empty($schedule->task_id)) {
+ $status = t("Running");
+ } else if ($schedule->next_run_datetime < time()) {
+ $status = t("Overdue");
+ } else {
+ $status = t("Scheduled");
+ }
+
+ $v->schedule_definitions[] = (object)array("id" => $schedule->id,
+ "name" => $schedule->name,
+ "run_date" => $run_date,
+ "interval" => $interval,
+ "status" => $status);
+ }
+ }
+ return $v;
+ }
+} \ No newline at end of file
diff --git a/modules/scheduler/helpers/scheduler_event.php b/modules/scheduler/helpers/scheduler_event.php
new file mode 100644
index 00000000..365b1df1
--- /dev/null
+++ b/modules/scheduler/helpers/scheduler_event.php
@@ -0,0 +1,64 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * 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 (at
+ * your option) 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+class scheduler_event_Core {
+ /**
+ * At this point, the output has been sent to the browser, so we can take some time
+ * to run a schedule task.
+ */
+ static function gallery_shutdown() {
+ try {
+ $schedule = ORM::factory("schedule")
+ ->where("next_run_datetime", "<=", time())
+ ->where("busy", "!=", 1)
+ ->order_by("next_run_datetime")
+ ->find_all(1);
+
+ if ($schedule->count()) {
+ $schedule = $schedule->current();
+ $schedule->busy = true;
+ $schedule->save();
+
+ try {
+ if (empty($schedule->task_id)) {
+ $task = task::start($schedule->task_callback);
+ $schedule->task_id = $task->id;
+ }
+
+ $task = task::run($schedule->task_id);
+
+ if ($task->done) {
+ $schedule->next_run_datetime += $schedule->interval;
+ $schedule->task_id = null;
+ }
+
+ $schedule->busy = false;
+ $schedule->save();
+ } catch (Exception $e) {
+ $schedule->busy = false;
+ $schedule->save();
+ throw $e;
+ }
+ }
+ } catch (Exception $e) {
+ Kohana_Log::add("error", (string)$e);
+ }
+ }
+}
diff --git a/modules/scheduler/helpers/scheduler_installer.php b/modules/scheduler/helpers/scheduler_installer.php
new file mode 100644
index 00000000..46be4a81
--- /dev/null
+++ b/modules/scheduler/helpers/scheduler_installer.php
@@ -0,0 +1,42 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * 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 (at
+ * your option) 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class scheduler_installer {
+ static function install() {
+ $db = Database::instance();
+ $db->query("CREATE TABLE {schedules} (
+ `id` int(9) NOT NULL auto_increment,
+ `name` varchar(128) NOT NULL,
+ `task_callback` varchar(128) NOT NULL,
+ `task_id` int(9) NULL,
+ `next_run_datetime` int(9) NOT NULL,
+ `interval` int(9) NOT NULL,
+ `busy` bool NOT NULL DEFAULT 0,
+ PRIMARY KEY (`id`),
+ KEY `run_date` (`next_run_datetime`, `busy`),
+ UNIQUE KEY (`name`))
+ DEFAULT CHARSET=utf8;");
+ module::set_version("scheduler", $version = 1);
+ }
+
+ static function uninstall() {
+ $db = Database::instance();
+ $db->query("DROP TABLE IF EXISTS {schedules}");
+ }
+}
diff --git a/modules/scheduler/models/schedule.php b/modules/scheduler/models/schedule.php
new file mode 100644
index 00000000..b83b5738
--- /dev/null
+++ b/modules/scheduler/models/schedule.php
@@ -0,0 +1,33 @@
+<?php defined("SYSPATH") or die("No direct script access.");
+/**
+ * Gallery - a web based photo album viewer and editor
+ * Copyright (C) 2000-2009 Bharat Mediratta
+ *
+ * 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 (at
+ * your option) 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+class Schedule_Model extends ORM {
+ public function tasks() {
+ return ORM::factory("task")
+ ->join("schedules_tasks", "task.id", "schedules_tasks.task_id")
+ ->where("schedule_id", "=", $this->id)
+ ->find_all();
+ }
+
+ public function add_task($task) {
+ db::build()
+ ->insert("schedules_tasks", array("schedule_id" => $this->id,"task_id" => $task->id))
+ ->execute();
+ }
+}
diff --git a/modules/scheduler/module.info b/modules/scheduler/module.info
new file mode 100644
index 00000000..15355dfb
--- /dev/null
+++ b/modules/scheduler/module.info
@@ -0,0 +1,3 @@
+name = "Scheduler"
+description = "Schedule tasks to run at specific times and intervals"
+version = 1
diff --git a/modules/scheduler/views/admin_schedule.html.php b/modules/scheduler/views/admin_schedule.html.php
new file mode 100644
index 00000000..3d45dc53
--- /dev/null
+++ b/modules/scheduler/views/admin_schedule.html.php
@@ -0,0 +1,11 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<style>
+#g-define-schedule fieldset fieldset li {
+ margin-right: .5em;
+}
+
+#g-schedule-time {
+ width: 40px !important;
+}
+</style>
+<?= $form ?>
diff --git a/modules/scheduler/views/admin_schedule_confirm.html.php b/modules/scheduler/views/admin_schedule_confirm.html.php
new file mode 100644
index 00000000..5d09654d
--- /dev/null
+++ b/modules/scheduler/views/admin_schedule_confirm.html.php
@@ -0,0 +1,4 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<h1 style="display:none"><?= t("Confirm task removal") ?></h1>
+<p class="g-warning"><?= t("Really remove the task: %name", array("name" => $name)) ?></p>
+<?= $form ?>
diff --git a/modules/scheduler/views/scheduler_definitions.html.php b/modules/scheduler/views/scheduler_definitions.html.php
new file mode 100644
index 00000000..0ab46f2b
--- /dev/null
+++ b/modules/scheduler/views/scheduler_definitions.html.php
@@ -0,0 +1,49 @@
+<?php defined("SYSPATH") or die("No direct script access.") ?>
+<div id="g-sheduled-tasks">
+ <h2> <?= t("Scheduled tasks") ?> </h2>
+ <table>
+ <tr>
+ <th>
+ <?= t("Name") ?>
+ </th>
+ <th>
+ <?= t("Next run") ?>
+ </th>
+ <th>
+ <?= t("Interval") ?>
+ </th>
+ <th>
+ <?= t("Status") ?>
+ </th>
+ <th>
+ <?= t("Action") ?>
+ </th>
+ </tr>
+ <? foreach ($schedule_definitions as $entry): ?>
+ <tr class="<?= text::alternate("g-odd", "g-even") ?>">
+ <td>
+ <?= html::clean($entry->name) ?>
+ </td>
+ <td>
+ <?= html::clean($entry->run_date) ?>
+ </td>
+ <td>
+ <?= html::clean($entry->interval) ?>
+ </td>
+ <td>
+ <?= html::clean($entry->status) ?>
+ </td>
+ <td>
+ <a href="<?= url::site("admin/schedule/update_form/$entry->id?csrf=$csrf") ?>"
+ class="g-dialog-link g-button ui-icon-left ui-state-default ui-corner-all">
+ <?= t("edit") ?>
+ </a>
+ <a href="<?= url::site("admin/schedule/remove_form/$entry->id?csrf=$csrf") ?>"
+ class="g-dialog-link g-button ui-icon-left ui-state-default ui-corner-all">
+ <?= t("remove") ?>
+ </a>
+ </td>
+ </tr>
+ <? endforeach ?>
+ </table>
+</div>