3
/** @constant MAINTENANCE_YEARLY Do task yearly (First login after/on January 1). */
4
define('MAINTENANCE_YEARLY', 1);
6
/** @constant MAINTENANCE_MONTHLY Do task monthly (First login after/on first of month). */
7
define('MAINTENANCE_MONTHLY', 2);
9
/** @constant MAINTENANCE_WEEKLY Do task weekly (First login after/on a Sunday). */
10
define('MAINTENANCE_WEEKLY', 3);
12
/** @constant MAINTENANCE_DAILY Do task daily (First login of the day). */
13
define('MAINTENANCE_DAILY', 4);
15
/** @constant MAINTENANCE_EVERY Do task every login. */
16
define('MAINTENANCE_EVERY', 5);
18
/** @constant MAINTENANCE_FIRST_LOGIN Do task on first login only. */
19
define('MAINTENANCE_FIRST_LOGIN', 6);
21
/** @constant MAINTENANCE_OUTPUT_CONFIRM Confirmation-style output for maintenance page. */
22
define('MAINTENANCE_OUTPUT_CONFIRM', 7);
24
/** @constant MAINTENANCE_OUTPUT_AGREE Agreement-style output for maintenance page. */
25
define('MAINTENANCE_OUTPUT_AGREE', 8);
27
/** @constant MAINTENANCE_OUTPUT_NOTICE Notice-style output for maintenance page. */
28
define('MAINTENANCE_OUTPUT_NOTICE', 9);
30
/** @constant MAINTENANCE_DONE_PARAM The name of the URL parameter that indicates that the maintenance tasks are completed. */
31
define('MAINTENANCE_DONE_PARAM', 'maintenance_done');
33
/* Intervals hash - used to build select tables in preferences menu. */
35
$intervals[MAINTENANCE_YEARLY] = _("Yearly");
36
$intervals[MAINTENANCE_MONTHLY] = _("Monthly");
37
$intervals[MAINTENANCE_WEEKLY] = _("Weekly");
38
$intervals[MAINTENANCE_DAILY] = _("Daily");
39
$intervals[MAINTENANCE_EVERY] = _("Every Login");
40
$GLOBALS['intervals'] = &$intervals;
43
* The Maintenance:: class provides a set of methods for dealing with
44
* maintenance operations run upon login to Horde applications.
46
* $Horde: framework/Maintenance/Maintenance.php,v 1.52.10.2 2005/01/03 12:19:06 jan Exp $
48
* Copyright 2001-2005 Michael Slusarz <slusarz@bigworm.colorado.edu>
50
* See the enclosed file COPYING for license information (LGPL). If you
51
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
53
* @author Michael Slusarz <slusarz@bigworm.colorado.edu>
54
* @version $Revision: 1.52.10.2 $
56
* @package Horde_Maintenance
61
* Hash holding maintenance preference names.
62
* Syntax: PREFNAME => interval
63
* Valid intervals are: MAINTENANCE_YEARLY, MAINTENANCE_MONTHLY,
64
* MAINTENANCE_WEEKLY, MAINTENANCE_DAILY,
65
* MAINTENANCE_EVERY, MAINTENANCE_FIRST_LOGIN
66
* Operations will be run in the order they appear in the array -
67
* MAKE SURE FUNCTIONS ARE IN THE CORRECT ORDER!
68
* Operations can appear more than once - they will only be run once per
69
* login though (the operation will run the first time it is seen in
72
* This array should be filled in for each Horde module that extends
73
* the Maintenance class.
75
* @var array $maint_tasks
77
var $maint_tasks = array();
80
* UNIX timestamp of the last maintenance run for user.
82
* @var integer $_lastRun
87
* The Maintenance_Tasklist object for this login.
89
* @var object Maintenance_Tasklist $_tasklist
94
* Array to store Maintenance_Task objects.
96
* @var array $_modulesCache
98
var $_taskCache = array();
101
* Attempts to return a concrete Maintenance_* object based on the
102
* module name passed into it.
106
* @param string $module The name of the Horde module.
107
* @param optional array $params A hash containing additional data
108
* needed by the constructor.
110
* @return object Maintenance The Maintenance object.
111
* Returns false on error.
113
function &factory($module, $params = array())
117
/* Spawn the relevant driver, and return it (or false on failure). */
118
include_once $registry->get('fileroot', $module) . '/lib/Maintenance/' . $module . '.php';
119
$class = 'Maintenance_' . $module;
120
if (class_exists($class)) {
121
return $ret = &new $class($params);
132
* @param array $params A hash containing the following entries:
133
* 'last_maintenance' => The last time maintenance was run (unix timestamp).
135
function Maintenance($params = array())
137
/* Set the class variable $_lastRun. */
138
if (isset($params['last_maintenance'])) {
139
$this->_lastRun = $params['last_maintenance'];
142
$this->_retrieveTasklist();
147
* Do maintenance operations needed for this login. This function
148
* will generate the list of tasks to perform during this login
149
* and will redirect to the maintenance page if necessary. This
150
* is the function that should be called from the application upon
155
function runMaintenance()
157
/* Check to see if we are finished with maintenance
159
if (!Util::getFormData(MAINTENANCE_DONE_PARAM)) {
160
/* Determine if we should redirect to the maintenance page. */
161
if ($this->_needMaintenancePage() !== null) {
162
header('Location: ' . $this->_getMaintenanceURL(), true);
167
/* Finally, run any tasks that need to be executed. */
168
$this->_doMaintenanceTasks();
172
* Do the necessary maintenance tasks for this loading of the
173
* maintenance page. This is the function that is called from the
174
* maintenance page every time it is loaded.
178
* @return integer The display required for the maintenance page.
180
function runMaintenancePage()
182
/* Should we run any tasks? */
183
$this->_doMaintenanceTasks();
185
/* Get the list of tasks we need to display to the user. */
186
$task_no = $this->_needMaintenancePage();
187
$tasks = $this->_tasklist->getList();
189
/* Remove 'newflag' from first task. */
190
if (!$this->_tasklist->processed(true)) {
193
$this->_tasklist->unsetNewPage(key($tasks));
197
if (!is_null($task_no)) {
198
$tasks = array_slice($tasks, 0, $task_no + 1);
203
$action = $tasks[key($tasks)]['display'];
208
return array($action, array_keys($tasks));
212
* Returns the informational text message on what the operation is
213
* about to do. Also indicates whether the box should be checked
214
* by default or not. Operations that have been locked by the
215
* admin will return null.
219
* @param string $pref Name of the operation to get information for.
221
* @return array 1st element - Description of what the operation is about
222
* to do during this login.
223
* 2nd element - Whether the preference is set to on or not.
225
function infoMaintenance($pref)
229
/* If the preference has been locked by the admin, do not show
231
if ($prefs->isLocked($pref)) {
235
$mod = &$this->_loadModule($pref);
236
return array($mod->describeMaintenance(), $prefs->getValue($pref));
240
* Export variable names to use for creating select tables in the
245
* @return array An array of variable names to be imported into the
246
* prefs.php namespace.
248
function exportIntervalPrefs()
252
$return_array = array();
254
foreach (array_keys($this->maint_tasks) as $val) {
255
if (!$prefs->isLocked($val . '_interval')) {
256
$return_array[] = $val . '_interval_options';
260
return $return_array;
264
* Output hidden for elements for the POST form to ensure the
265
* calling script has the same POST elements as when the
266
* maintenance operations first run.
270
* @return string The form data.
272
function getPostData()
276
if (($data = $this->_tasklist->getPostData())) {
277
foreach ($data as $name => $val) {
278
$text .= '<input type="hidden" name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars($val) . '" />' . "\n";
286
* Return the URL needed for the maintenance form.
290
* @return string The URL to redirect to.
292
function getMaintenanceFormURL()
294
if ($this->_needMaintenancePage() !== null) {
295
return $this->_getMaintenanceURL();
297
return $this->_getInitialPageURL();
302
* Creates the list of maintenance operations that are available
303
* for this session (stored in a Maintenance_Tasklist object).
307
* @return boolean Returns true if list was created.
308
* False if not (e.g. list already exists).
310
function _createTaskList()
314
/* Create a new Maintenance_Tasklist object. */
315
$this->_tasklist = &new Maintenance_Tasklist();
317
/* Create time objects for today's date and last login date. */
318
$last_date = getdate($this->_lastRun);
319
$cur_date = getdate();
321
/* Go through each item in $maint_tasks and determine if we need to
322
run it during this maintenance run. */
323
foreach ($this->maint_tasks as $key => $val) {
324
/* Skip item if it already appears in the tasks list. */
325
if ($this->_tasklist->inList($key)) {
329
/* Determine the correct interval for the item. */
330
if (($interval = $prefs->getValue($key . '_interval'))) {
336
/* FIRST LOGIN OPERATIONS */
337
/* If $_lastRun is empty (= 0), this is the first time the user
338
has logged in. Don't run any other maintenance operations on
340
if (empty($this->_lastRun)) {
341
if ($val == MAINTENANCE_FIRST_LOGIN) {
346
/* YEARLY_OPERATIONS */
347
elseif (($val == MAINTENANCE_YEARLY) &&
348
($cur_date['year'] > $last_date['year'])) {
352
/* MONTHLY OPERATIONS */
353
elseif (($val == MAINTENANCE_MONTHLY) &&
354
(($cur_date['year'] > $last_date['year']) || ($cur_date['mon'] > $last_date['mon']))) {
358
/* WEEKLY OPERATIONS */
359
elseif (($val == MAINTENANCE_WEEKLY) &&
360
(($cur_date['wday'] < $last_date['wday']) || ((time() - 604800) > $this->_lastRun))) {
364
/* DAILY OPERATIONS */
365
elseif (($val == MAINTENANCE_DAILY) &&
366
(($cur_date['year'] > $last_date['year']) || ($cur_date['yday'] > $last_date['yday']))) {
370
/* EVERY LOGIN OPERATIONS */
371
elseif ($val == MAINTENANCE_EVERY) {
374
/* Skip the task if any of the following:
375
+ This task does not need to be run in this login
376
+ This task is not set in the preferences */
377
if (!$addTask || !$prefs->getValue($key)) continue;
379
/* Load the task module now. */
380
$mod = &$this->_loadModule($key);
382
/* Determine if this task has already been confirmed/set via some
383
sort of admin setting. Also, if the user/admin has set the
384
'confirm_maintenance' flag, skip confirmation. */
386
if ($prefs->isLocked($key) ||
387
!$prefs->getValue('confirm_maintenance')) {
391
/* Add the task to the tasklist. */
392
$this->_tasklist->addTask($key, $confirmed, $mod->getDisplayType());
397
* Load module (if not already loaded).
401
* @param string $modname Name of the module to load.
403
* @return object Maintenance_Task A reference to the requested module.
405
function &_loadModule($modname)
409
if (!isset($this->_taskCache[$modname])) {
410
include_once $registry->get('fileroot', $this->_tasklist->getModule()) . '/lib/Maintenance/Task/' . $modname . '.php';
411
$class = 'Maintenance_Task_' . $modname;
412
if (class_exists($class)) {
413
$this->_taskCache[$modname] = &new $class;
415
Horde::fatal(PEAR::raiseError(sprintf(_("Could not open Maintenance_Task module %s"), $class)), __FILE__, __LINE__);
419
return $this->_taskCache[$modname];
423
* Get the URL for the initial page.
427
* @return string The URL for the initial page.
429
function _getInitialPageURL()
431
return Util::addParameter($this->_tasklist->getTarget(), MAINTENANCE_DONE_PARAM, 1);
435
* Get the URL for the maintenance page.
439
* @return string The URL for the maintenance page.
441
function _getMaintenanceURL()
445
/* We need to pass the cache ID and 'module' parameters. */
446
$url = Horde::url($registry->get('webroot', 'horde') . '/services/maintenance.php', true);
447
$url = Util::addParameter($url, 'module', $this->_tasklist->getModule(), false);
453
* Register the shutdown function for storing the maintenance
460
register_shutdown_function(array(&$this, '_cacheTasklist'));
464
* Cache the maintenance tasklist between page requests.
468
function _cacheTasklist()
470
$_SESSION['horde_maintenance_tasklist'] = serialize($this->_tasklist);
474
* Retrieves a cached maintenance tasklist or makes sure one is
479
function _retrieveTasklist()
481
if (isset($_SESSION['horde_maintenance_tasklist'])) {
482
$this->_tasklist = unserialize($_SESSION['horde_maintenance_tasklist']);
484
$this->_createTasklist();
489
* Execute all confirmed tasks.
493
function _doMaintenanceTasks()
495
$tasks = $this->_tasklist->getList();
497
foreach ($tasks as $key => $val) {
498
if ($val['newpage']) {
499
if ($this->_tasklist->processed()) {
500
$this->_tasklist->unsetNewPage($key);
503
} elseif ($val['confirmed'] ||
504
Util::getFormData($key . '_confirm')) {
505
/* Perform maintenance if confirmed. */
506
$mod = &$this->_loadModule($key);
507
$mod->doMaintenance();
509
$this->_tasklist->removeTask($key);
512
/* If we've successfully completed every task in the list (or
513
* skipped it), record now as the last time maintenance was
515
if (!count($this->_tasklist->getList())) {
516
$GLOBALS['prefs']->setValue('last_maintenance', time());
521
* Do any of the tasks require the maintenance page?
525
* @return integer The key of the task that requires the maintenance
526
* page. Returns null if the maintenance page is no
529
function _needMaintenancePage()
532
foreach ($this->_tasklist->getList() as $val) {
533
if ($val['newpage']) {
545
* The Maintenance_Tasklist:: class is used to store the list of maintenance
546
* tasks that need to be run during this login.
548
* Copyright 2002-2005 Michael Slusarz <slusarz@bigworm.colorado.edu>
550
* See the enclosed file COPYING for license information (LGPL). If you
551
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
553
* @author Michael Slusarz <slusarz@bigworm.colorado.edu>
554
* @version $Revision: 1.52.10.2 $
556
* @package Horde_Maintenance
558
class Maintenance_Tasklist {
561
* The Horde module running the maintenance tasks.
563
* @var string $_module
568
* The URL of the web page to load after maintenance is complete.
570
* @var string $_target
575
* POST data for the calling script.
577
* @var array $_postdata
582
* The list of tasks to run during this login.
586
* 'confirmed' => boolean,
587
* 'display' => integer,
588
* 'newpage' => boolean
593
var $_tasks = array();
596
* Internal flag for addTask().
598
* @var boolean $_addFlag
600
var $_addFlag = false;
603
* Has the tasklist been processed yet?
605
* @var boolean $_processed
607
var $_processed = false;
614
function Maintenance_Tasklist()
618
$this->_module = $registry->getApp();
619
$this->_target = Horde::selfURL(true);
623
* Adds a task to the tasklist.
627
* @param string $key The name of the task to perform.
628
* @param boolean $confirmed Has the task been confirmed?
629
* @param integer $display The display type of the task.
631
function addTask($key, $confirmed, $display)
633
$this->_tasks[$key] = array();
634
$this->_tasks[$key]['confirmed'] = $confirmed;
635
$this->_tasks[$key]['display'] = $display;
637
if (($display == MAINTENANCE_OUTPUT_AGREE) ||
638
($display == MAINTENANCE_OUTPUT_NOTICE)) {
639
$this->_tasks[$key]['newpage'] = true;
640
$this->_addFlag = false;
641
} elseif (($confirmed == false) && (!$this->_addFlag)) {
642
$this->_tasks[$key]['newpage'] = true;
643
$this->_addFlag = true;
645
$this->_tasks[$key]['newpage'] = false;
650
* Unsets the newpage flag for a task.
654
* @param string $task The name of the task to alter.
656
function unsetNewPage($task)
658
if ($this->inList($task)) {
659
$this->_tasks[$task]['newpage'] = false;
664
* Removes the task from the tasklist.
668
* @param string $task The name of the task to alter.
670
function removeTask($task)
672
if ($this->inList($task)) {
673
unset($this->_tasks[$task]);
678
* Is this task already in the tasklist?
682
* @param string $task The name of the task.
684
* @return boolean Whether the task is already in the tasklist.
686
function inList($task)
688
return isset($this->_tasks[$task]);
692
* Return the list of tasks.
696
* @return array The list of tasks that still need to be done.
700
return $this->_tasks;
704
* Return the Horde module the tasks are running under.
708
* @return string The Horde module name.
712
return $this->_module;
716
* Return the POST data.
720
* @return array The POST data from the initial URL.
722
function getPostData()
724
return $this->_postdata;
728
* Return the URL of the web page to load after maintenance is complete.
732
* @return string The target URL.
736
return $this->_target;
740
* Sets/displays the flag to show that tasklist has been processed at
745
* @param optional boolean $set Set the flag?
747
* @return boolean Has the tasklist been processed before?
749
function processed($set = false)
751
$retvalue = $this->_processed;
753
$this->_processed = true;
761
* Abstract class to allow for modularization of specific maintenace tasks.
763
* For this explanation, the specific Horde application you want to create
764
* maintenance actions for will be labeled HORDEAPP.
766
* To add a new maintenance task, you need to do the following:
767
* [1] Add preference to "HORDEAPP/config/prefs.php" file.
768
* (The name of this preference will be referred to as PREFNAME)
769
* This preference should be of type 'checkbox' (i.e. 1 = on; 0 = off).
770
* [Optional:] Add a preference in prefs.php of the name
771
* 'PREFNAME_interval' to allow the user to set the interval.
772
* 'default' value should be set to the values of the interval
774
* If this preference doesn't exist, the default interval
775
* used will be the one that appears in $maint_tasks.
776
* [2] Create a directory named "HORDEAPP/lib/Maintenance".
777
* [3] Create a class entitled Maintenance_HORDEAPP that extends the
779
* This class should contain only the application specific definitions of
780
* $maint_tasks (see above for description).
781
* Save this file as "HORDEAPP/lib/Maintenance/HORDEAPP.php".
782
* [4] Create a directory titled "HORDEAPP/lib/Maintenance/Task".
783
* [5] Create modules in HORDEAPP/lib/Maintenance/Task named 'PREFNAME.php'
784
* that extend the Maintenance_Task class.
785
* The class should be named Maintenance_Task_PREFNAME.
786
* The class should declare the following two methods:
787
* 'doMaintenance' - This is the function that is run to do the
788
* specified maintenance operation.
789
* 'describeMaintenance' - This function sets the preference text
790
* and text to be used on the confirmation
791
* page. Should return a description of what
792
* your 'doMaintenance' function is about to do.
793
* Neither function requires any parameters passed in.
795
* There are 3 different types of maintenance (set via $_display_type):
796
* [1] MAINTENANCE_OUTPUT_CONFIRM
797
* Each output from describeMaintenance() will have a checkbox associated
798
* with it. For each checkbox selected, doMaintenance() for that task will
799
* be run. More than 1 confirmation message can be displayed on the
800
* maintenance page at once.
802
* [2] MAINTENANCE_OUTPUT_AGREE
803
* The output from describeMaintenance() should be text asking the user to
804
* agree/disagree to specified terms. If 'yes' is selected, the POST
805
* variable 'agree' will be set. If 'no' is selected, the POST variable
806
* 'not_agree' will be set. In either case, doMaintenance() will ALWAYS be
808
* * This style will be displayed on its own, separate maintenance page. *
810
* [3] MAINTENANCE_OUTPUT_NOTICE
811
* The output from describeMaintenance() should be any non-interactive text
812
* desired. There will be a single 'Click to Continue' button below this
813
* text. doMaintenance() will ALWAYS be run.
814
* * This style will be displayed on its own, separate maintenance page. *
816
* Copyright 2001-2005 Michael Slusarz <slusarz@bigworm.colorado.edu>
818
* See the enclosed file COPYING for license information (LGPL). If you
819
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
821
* @author Michael Slusarz <slusarz@bigworm.colorado.edu>
822
* @version $Revision: 1.52.10.2 $
824
* @package Horde_Maintenance
826
class Maintenance_Task {
829
* The style of the maintenance page output.
830
* Possible values: MAINTENANCE_OUTPUT_CONFIRM,
831
* MAINTENANCE_OUTPUT_AGREE,
832
* MAINTENANCE_OUTPUT_NOTICE
834
* @var integer $_display_type
836
var $_display_type = MAINTENANCE_OUTPUT_CONFIRM;
843
function Maintenance_Task()
848
* Do maintenance operation (if it has been confirmed).
852
* @return boolean Whether the maintenance operation was successful or
855
function doMaintenance()
861
* Return description information for the maintenance page.
865
* @return string Description that will be displayed on the maintenance
868
function describeMaintenance()
874
* Returns the desired output type for the maintenance page.
878
* @return integer Desired output type for the maintenance confirmation
881
function getDisplayType()
883
return $this->_display_type;