Add system task type to logintasks - these are always run
authorMichael M Slusarz <slusarz@curecanti.org>
Sun, 26 Jul 2009 22:24:17 +0000 (16:24 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Sun, 26 Jul 2009 22:36:38 +0000 (16:36 -0600)
framework/Core/lib/Horde/Registry.php
framework/LoginTasks/lib/Horde/LoginTasks.php
framework/LoginTasks/lib/Horde/LoginTasks/SystemTask.php [new file with mode: 0644]
framework/LoginTasks/lib/Horde/LoginTasks/Tasklist.php
framework/LoginTasks/package.xml

index 7ad033e..665cde8 100644 (file)
@@ -777,7 +777,8 @@ class Horde_Registry
      *                 DEFAULT: true
      * <pre>
      * 'logintasks' - (boolean) Perform login tasks? Only performed if
-     *                'check_perms' is also true.
+     *                'check_perms' is also true. System tasks are always
+     *                peformed if the user is authorized.
      *                DEFAULT: false
      * </pre>
      *
@@ -798,7 +799,7 @@ class Horde_Registry
         if (!isset($this->applications[$app]) ||
             $this->applications[$app]['status'] == 'inactive' ||
             ($this->applications[$app]['status'] == 'admin' && !Horde_Auth::isAdmin())) {
-            throw new Horde_Exception($app . ' is not activated.', 'not_active');
+            throw new Horde_Exception($app . ' is not activated.', self::NOT_ACTIVE);
         }
 
         $checkPerms = !isset($options['check_perms']) || !empty($options['check_perms']);
@@ -809,15 +810,13 @@ class Horde_Registry
          *  - To all admins.
          *  - To all authenticated users if no permission is set on $app.
          *  - To anyone who is allowed by an explicit ACL on $app. */
-        if ($checkPerms) {
-            if (!$this->hasPermission($app, PERMS_READ)) {
-                if (!Horde_Auth::isAuthenticated(array('app' => $app))) {
-                    throw new Horde_Exception('User is not authorized', self::AUTH_FAILURE);
-                }
-
-                Horde::logMessage(sprintf('%s does not have READ permission for %s', Horde_Auth::getAuth() ? 'User ' . Horde_Auth::getAuth() : 'Guest user', $app), __FILE__, __LINE__, PEAR_LOG_DEBUG);
-                throw new Horde_Exception(sprintf(_('%s is not authorized for %s.'), Horde_Auth::getAuth() ? 'User ' . Horde_Auth::getAuth() : 'Guest user', $this->applications[$app]['name']), 'permission_denied');
+        if ($checkPerms && !$this->hasPermission($app, PERMS_READ)) {
+            if (!Horde_Auth::isAuthenticated(array('app' => $app))) {
+                throw new Horde_Exception('User is not authorized', self::AUTH_FAILURE);
             }
+
+            Horde::logMessage(sprintf('%s does not have READ permission for %s', Horde_Auth::getAuth() ? 'User ' . Horde_Auth::getAuth() : 'Guest user', $app), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+            throw new Horde_Exception(sprintf(_('%s is not authorized for %s.'), Horde_Auth::getAuth() ? 'User ' . Horde_Auth::getAuth() : 'Guest user', $this->applications[$app]['name']), self::PERMISSION_DENIED);
         }
 
         /* Set up autoload paths for the current application. This needs to
@@ -860,9 +859,9 @@ class Horde_Registry
         Horde::callHook('_horde_hook_post_pushapp', array($app), 'horde');
 
         /* Do login tasks. */
-        if ($checkPerms && Horde_Auth::getAuth() && !empty($options['logintasks'])) {
+        if (Horde_Auth::getAuth()) {
             $tasks = Horde_LoginTasks::singleton($app, Horde::selfUrl(true, true, true));
-            $tasks->runTasks();
+            $tasks->runTasks(array('runtasks' => $checkPerms && !empty($options['logintasks'])));
         }
 
         return true;
index 49789ab..33b0626 100644 (file)
@@ -67,7 +67,7 @@ class Horde_LoginTasks
      * if no instance with the same parameters currently exists.
      *
      * This method must be invoked as:
-     *   $var = &Horde_LoginTasks::singleton($app[, $params]);
+     *   $var = Horde_LoginTasks::singleton($app[, $params]);
      *
      * @param string $app  See self::__construct().
      * @param string $url  The URL to redirect to when finished.
@@ -102,7 +102,7 @@ class Horde_LoginTasks
             $this->_tasklist = @unserialize($_SESSION['horde_logintasks'][$app]);
         }
 
-        if (is_null($this->_tasklist) || ($this->_tasklist === false)) {
+        if (empty($this->_tasklist)) {
             $this->_createTaskList($url);
             $this->_init = true;
         }
@@ -129,34 +129,39 @@ class Horde_LoginTasks
         /* Create a new Horde_LoginTasks_Tasklist object. */
         $this->_tasklist = new Horde_LoginTasks_Tasklist($url);
 
-        /* Get last task run date(s). */
-        $old_error = error_reporting();
-        $last_logintasks = unserialize($GLOBALS['prefs']->getValue('last_logintasks'));
-        error_reporting($old_error);
-        if (!is_array($last_logintasks)) {
-            $last_logintasks = array();
+        /* Get last task run date(s). Array keys are app names, values are
+         * last run timestamps. Special key '_once' contains list of
+         * ONCE tasks previously run. */
+        $lasttask_pref = @unserialize($GLOBALS['prefs']->getValue('last_logintasks'));
+        if (!is_array($lasttask_pref)) {
+            $lasttask_pref = array();
         }
 
-        /* If this application handles Horde auth, need to add Horde tasks
-         * here. */
+        /* Add Horde tasks here if not yet run. */
         $app_list = array($this->_app);
         if (($this->_app != 'horde') &&
             !isset($_SESSION['horde_logintasks']['horde'])) {
             array_unshift($app_list, 'horde');
         }
 
+        $lasttasks = $tasks = array();
+
         foreach ($app_list as $app) {
             $fileroot = $GLOBALS['registry']->get('fileroot', $app);
-            if (!is_null($fileroot) &&
-                is_dir($fileroot . '/lib/LoginTasks/Task')) {
-                foreach (scandir($fileroot . '/lib/LoginTasks/Task') as $file) {
-                    $classname = $app . '_LoginTasks_Task_' . basename($file, '.php');
-                    if (class_exists($classname)) {
-                        $tasks[$classname] = $app;
-                        if (!isset($lasttasks[$app])) {
-                            $lasttasks[$app] = empty($last_logintasks[$app])
-                                ? 0
-                                : getdate($last_logintasks[$app]);
+            if (!is_null($fileroot)) {
+                foreach (array('SystemTask', 'Task') as $val) {
+                    if (is_dir($fileroot . '/lib/LoginTasks/' . $val)) {
+                        foreach (scandir($fileroot . '/lib/LoginTasks/' . $val) as $file) {
+                            $classname = $app . '_LoginTasks_' . $val . '_' . basename($file, '.php');
+                            if (class_exists($classname)) {
+                                $tasks[$classname] = $app;
+
+                                if (!isset($lasttasks[$app])) {
+                                    $lasttasks[$app] = empty($lasttask_pref[$app])
+                                        ? 0
+                                        : getdate($lasttask_pref[$app]);
+                                }
+                            }
                         }
                     }
                 }
@@ -208,9 +213,9 @@ class Horde_LoginTasks
                     break;
 
                 case self::ONCE:
-                    $addtask = empty($lasttasks['_once']) || !in_array($classname, $lasttasks['_once']);
-                    $lasttasks['_once'][] = $classname;
-                    $GLOBALS['prefs']->setValue('last_logintasks', serialize($lasttasks));
+                    $addtask = empty($lasttask_pref['_once']) || !in_array($classname, $lasttask_pref['_once']);
+                    $lasttask_pref['_once'][] = $classname;
+                    $GLOBALS['prefs']->setValue('last_logintasks', serialize($lasttask_pref));
                     break;
                 }
             }
@@ -228,19 +233,27 @@ class Horde_LoginTasks
      * login and will redirect to the login tasks page if necessary.  This is
      * the function that should be called from the application upon login.
      *
-     * @param boolean $confirmed  If true, indicates that any pending actions
-     *                            have been confirmed by the user.
+     * @param array $options  Options:
+     * <pre>
+     * 'confirmed' - (boolean) If true, indicates that any pending actions
+     *                         have been confirmed by the user.
+     * 'runtasks' - (boolean) If true, run all tasks. If false, only run
+     *                        system tasks.
+     * </pre>
      */
-    public function runTasks($confirmed = false)
+    public function runTasks($options = array())
     {
         if (!isset($this->_tasklist) ||
             ($this->_tasklist === true)) {
             return;
         }
 
+        $options['advance'] = $this->_init || !empty($options['confirmed']);
+
         /* Perform ready tasks now. */
-        foreach ($this->_tasklist->ready($this->_init || $confirmed) as $key => $val) {
-            if (in_array($val->display, array(self::DISPLAY_AGREE, self::DISPLAY_NOTICE, self::DISPLAY_NONE)) ||
+        foreach ($this->_tasklist->ready($options) as $key => $val) {
+            if ($val instanceof Horde_LoginTasks_SystemTask ||
+                in_array($val->display, array(self::DISPLAY_AGREE, self::DISPLAY_NOTICE, self::DISPLAY_NONE)) ||
                 Horde_Util::getFormData('logintasks_confirm_' . $key)) {
                 $val->execute();
             }
@@ -251,7 +264,7 @@ class Horde_LoginTasks
 
         /* If we've successfully completed every task in the list (or skipped
          * it), record now as the last time login tasks was run. */
-        if (empty($need_display)) {
+        if ($this->_tasklist->isDone()) {
             $lasttasks = unserialize($GLOBALS['prefs']->getValue('last_logintasks'));
             $lasttasks[$this->_app] = time();
             if (($this->_app != 'horde') &&
diff --git a/framework/LoginTasks/lib/Horde/LoginTasks/SystemTask.php b/framework/LoginTasks/lib/Horde/LoginTasks/SystemTask.php
new file mode 100644 (file)
index 0000000..671fb3f
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Abstract class to allow for modularization of specific system login tasks
+ * that are always run on login.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Horde_LoginTasks
+ */
+abstract class Horde_LoginTasks_SystemTask
+{
+    /**
+     * Should the task be run?
+     *
+     * @var boolean
+     */
+    public $active = true;
+
+    /**
+     * The interval at which to run the task.
+     *
+     * @var integer
+     */
+    public $interval = Horde_LoginTasks::EVERY;
+
+    /**
+     * Do login task (if it has been confirmed).
+     *
+     * @return boolean  Whether the login task was successful.
+     */
+    abstract public function execute();
+
+}
index c342613..9949df8 100644 (file)
@@ -69,6 +69,10 @@ class Horde_LoginTasks_Tasklist
             'task' => $task
         );
 
+        if ($task instanceof Horde_LoginTasks_SystemTask) {
+            return;
+        }
+
         if (($task->display == Horde_LoginTasks::DISPLAY_AGREE) ||
             ($task->display == Horde_LoginTasks::DISPLAY_NOTICE)) {
             $tmp['display'] = true;
@@ -93,23 +97,32 @@ class Horde_LoginTasks_Tasklist
     /**
      * Returns the list of tasks to perform.
      *
+     * @param array $options  Options:
+     * <pre>
+     * 'advance' - (boolean) If true, mark ready tasks a completed.
+     * 'runtasks' - (boolean) If true, run all tasks. If false, only run
+     *              system tasks.
+     * </pre>
+     *
      * @param boolean $complete  Mark ready tasks as completed?
      *
      * @return array  The list of tasks to perform.
      */
-    public function ready($advance = false)
+    public function ready($options = array())
     {
         $tmp = array();
 
         reset($this->_tasks);
         while (list($k, $v) = each($this->_tasks)) {
-            if ($v['display'] && ($k > $this->_ptr)) {
+            if ((empty($options['runtasks']) &&
+                 ($v['task'] instanceof Horde_LoginTasks_Task)) ||
+                ($v['display'] && ($k > $this->_ptr))) {
                 break;
             }
             $tmp[] = $v['task'];
         }
 
-        if ($advance) {
+        if (!empty($options['advance'])) {
             $this->_tasks = array_slice($this->_tasks, $this->_ptr);
             $this->_ptr = 0;
         }
@@ -146,4 +159,14 @@ class Horde_LoginTasks_Tasklist
         return $tmp;
     }
 
+    /**
+     * Are all tasks complete?
+     *
+     * @return boolean  True if all tasks are complete.
+     */
+    public function isDone()
+    {
+        return ($this->_ptr == count($this->_tasks));
+    }
+
 }
index dd1514b..ce91f47 100644 (file)
@@ -24,13 +24,16 @@ http://pear.php.net/dtd/package-2.0.xsd">
   <api>beta</api>
  </stability>
  <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
- <notes>* Renamed Maintenance:: -> Horde_LoginTasks::.
+ <notes>* Added system tasks.
+ * Added ONCE interval.
+ * Renamed Maintenance:: -> Horde_LoginTasks::.
  * Initial Horde 4 package.</notes>
  <contents>
   <dir name="/">
    <dir name="lib">
     <dir name="Horde">
      <dir name="LoginTasks">
+     <file name="SystemTask.php" role="php" />
      <file name="Task.php" role="php" />
      <file name="Tasklist.php" role="php" />
      </dir> <!-- /lib/Horde/LoginTasks -->
@@ -55,6 +58,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
  </dependencies>
  <phprelease>
   <filelist>
+   <install name="lib/Horde/LoginTasks/SystemTask.php" as="Horde/LoginTasks/SystemTask.php" />
    <install name="lib/Horde/LoginTasks/Task.php" as="Horde/LoginTasks/Task.php" />
    <install name="lib/Horde/LoginTasks/Tasklist.php" as="Horde/LoginTasks/Tasklist.php" />
    <install name="lib/Horde/LoginTasks.php" as="Horde/LoginTasks.php" />