From 59e78a5af07b8e9d113e60d18baa1e000b31b9b8 Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Sun, 26 Jul 2009 16:24:17 -0600 Subject: [PATCH] Add system task type to logintasks - these are always run --- framework/Core/lib/Horde/Registry.php | 23 ++++--- framework/LoginTasks/lib/Horde/LoginTasks.php | 71 +++++++++++++--------- .../LoginTasks/lib/Horde/LoginTasks/SystemTask.php | 37 +++++++++++ .../LoginTasks/lib/Horde/LoginTasks/Tasklist.php | 29 ++++++++- framework/LoginTasks/package.xml | 6 +- 5 files changed, 121 insertions(+), 45 deletions(-) create mode 100644 framework/LoginTasks/lib/Horde/LoginTasks/SystemTask.php diff --git a/framework/Core/lib/Horde/Registry.php b/framework/Core/lib/Horde/Registry.php index 7ad033ed7..665cde81a 100644 --- a/framework/Core/lib/Horde/Registry.php +++ b/framework/Core/lib/Horde/Registry.php @@ -777,7 +777,8 @@ class Horde_Registry * DEFAULT: true *
      * '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
      * 
* @@ -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; diff --git a/framework/LoginTasks/lib/Horde/LoginTasks.php b/framework/LoginTasks/lib/Horde/LoginTasks.php index 49789abd3..33b0626f7 100644 --- a/framework/LoginTasks/lib/Horde/LoginTasks.php +++ b/framework/LoginTasks/lib/Horde/LoginTasks.php @@ -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: + *
+     * '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.
+     * 
*/ - 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 index 000000000..671fb3f6c --- /dev/null +++ b/framework/LoginTasks/lib/Horde/LoginTasks/SystemTask.php @@ -0,0 +1,37 @@ + + * @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(); + +} diff --git a/framework/LoginTasks/lib/Horde/LoginTasks/Tasklist.php b/framework/LoginTasks/lib/Horde/LoginTasks/Tasklist.php index c3426131a..9949df84d 100644 --- a/framework/LoginTasks/lib/Horde/LoginTasks/Tasklist.php +++ b/framework/LoginTasks/lib/Horde/LoginTasks/Tasklist.php @@ -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: + *
+     * 'advance' - (boolean) If true, mark ready tasks a completed.
+     * 'runtasks' - (boolean) If true, run all tasks. If false, only run
+     *              system tasks.
+     * 
+ * * @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)); + } + } diff --git a/framework/LoginTasks/package.xml b/framework/LoginTasks/package.xml index dd1514bce..ce91f472d 100644 --- a/framework/LoginTasks/package.xml +++ b/framework/LoginTasks/package.xml @@ -24,13 +24,16 @@ http://pear.php.net/dtd/package-2.0.xsd"> beta LGPL - * Renamed Maintenance:: -> Horde_LoginTasks::. + * Added system tasks. + * Added ONCE interval. + * Renamed Maintenance:: -> Horde_LoginTasks::. * Initial Horde 4 package. + @@ -55,6 +58,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + -- 2.11.0