Convert Maintenance:: (from CVS HEAD) to Horde_LoginTasks::.
authorMichael M Slusarz <slusarz@curecanti.org>
Wed, 24 Jun 2009 06:20:58 +0000 (00:20 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Wed, 24 Jun 2009 21:08:47 +0000 (15:08 -0600)
framework/LoginTasks/lib/Horde/LoginTasks.php [new file with mode: 0644]
framework/LoginTasks/lib/Horde/LoginTasks/Task.php [new file with mode: 0644]
framework/LoginTasks/lib/Horde/LoginTasks/Tasklist.php [new file with mode: 0644]
framework/LoginTasks/package.xml [new file with mode: 0644]

diff --git a/framework/LoginTasks/lib/Horde/LoginTasks.php b/framework/LoginTasks/lib/Horde/LoginTasks.php
new file mode 100644 (file)
index 0000000..88865f3
--- /dev/null
@@ -0,0 +1,282 @@
+<?php
+/**
+ * The Horde_LoginTasks:: class provides a set of methods for dealing with
+ * login tasks to run upon login to Horde applications.
+ *
+ * Copyright 2001-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
+ */
+class Horde_LoginTasks
+{
+    /* Interval settings. */
+    // Do task yearly (First login after/on January 1).
+    const YEARLY = 1;
+    // Do task monthly (First login after/on first of month).
+    const MONTHLY = 2;
+    // Do task weekly (First login after/on a Sunday).
+    const WEEKLY = 3;
+    // Do task daily (First login of the day).
+    const DAILY = 4;
+    // Do task every login.
+    const EVERY = 5;
+    // Do task on first login only.
+    const FIRST_LOGIN = 6;
+
+    /* Display styles. */
+    const DISPLAY_CONFIRM_NO = 1;
+    const DISPLAY_CONFIRM_YES = 2;
+    const DISPLAY_AGREE = 3;
+    const DISPLAY_NOTICE = 4;
+    const DISPLAY_NONE = 5;
+
+    /* Priority settings */
+    const PRIORITY_HIGH = 1;
+    const PRIORITY_NORMAL = 2;
+
+    /**
+     * Singleton instance.
+     *
+     * @var array
+     */
+    static protected $_instances = array();
+
+    /**
+     * The Horde_LoginTasks_Tasklist object for this login.
+     *
+     * @var Horde_LoginTasks_Tasklist
+     */
+    protected $_tasklist;
+
+    /**
+     * Was the tasklist init'd in this access?
+     *
+     * @var boolean
+     */
+    protected $_init = false;
+
+    /**
+     * Attempts to return a reference to a concrete Horde_LoginTasks
+     * instance based on $app. It will only create a new instance
+     * if no instance with the same parameters currently exists.
+     *
+     * This method must be invoked as:
+     *   $var = &Horde_LoginTasks::singleton($app[, $params]);
+     *
+     * @param string $app  See self::__construct().
+     * @param string $url  The URL to redirect to when finished.
+     *
+     * @return Horde_LoginTasks  The singleton instance.
+     */
+    static public function singleton($app, $url = null)
+    {
+        if (empty(self::$_instances[$app])) {
+            self::$_instances[$app] = new Horde_LoginTasks($app, $url);
+        }
+
+        return self::$_instances[$app];
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param string $app  The name of the Horde application.
+     * @param string $url  The URL to redirect to when finished.
+     */
+    protected function __construct($app, $url)
+    {
+        $this->_app = $app;
+
+        /* Retrieves a cached tasklist or make sure one is created. */
+        if (isset($_SESSION['horde_logintasks'][$app])) {
+            $this->_tasklist = unserialize($_SESSION['horde_logintasks'][$app]);
+        } else {
+            $this->_createTaskList($url);
+            $this->_init = true;
+        }
+    }
+
+    /**
+     * Destructor.
+     */
+    public function __destruct()
+    {
+        $_SESSION['horde_logintasks'][$this->_app] = serialize($this->_tasklist);
+    }
+
+    /**
+     * Creates the list of login tasks that are available for this session
+     * (stored in a Horde_LoginTasks_Tasklist object).
+     *
+     * @param string $url  The URL to redirect to when finished.
+     */
+    protected function _createTaskList($url)
+    {
+        /* 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();
+        }
+
+        /* If this application handles Horde auth, need to add Horde tasks
+         * here. */
+        $app_list = array($this->_app);
+        if (strnatcasecmp($this->_app, Auth::getProvider()) === 0) {
+            array_unshift($app_list, 'horde');
+        }
+
+        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) {
+                    if (stripos($file, '.php') !== false) {
+                        $classname = $app . '_LoginTasks_Task_' . substr($file, 0, -4);
+                        if (class_exists($classname)) {
+                            $tasks[$classname] = $app;
+                            if (!isset($lasttasks[$app])) {
+                                $lasttasks[$app] = empty($last_logintasks[$app])
+                                    ? 0
+                                    : getdate($last_logintasks[$app]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (empty($tasks)) {
+            return;
+        }
+
+        /* Create time objects for today's date and last task run date. */
+        $cur_date = getdate();
+
+        foreach ($tasks as $classname => $app) {
+            $ob = new $classname();
+
+            /* If marked inactive, skip the task. */
+            if (!$ob->active) {
+                continue;
+            }
+
+            $addtask = false;
+
+            if (empty($lasttasks[$app])) {
+                /* If timestamp is empty (= 0), this is the first time the
+                   user has logged in. Don't run any other login task
+                   operations on the first login. */
+                $addtask = ($ob->interval == self::FIRST_LOGIN);
+            } else {
+                switch ($ob->interval) {
+                case self::YEARLY:
+                    $addtask = ($cur_date['year'] > $lasttasks[$app]['year']);
+                    break;
+
+                case self::MONTHLY:
+                    $addtask = (($cur_date['year'] > $lasttasks[$app]['year']) || ($cur_date['mon'] > $lasttasks[$app]['mon']));
+                    break;
+
+                case self::WEEKLY:
+                    $addtask = (($cur_date['wday'] < $lasttasks[$app]['wday']) || ((time() - 604800) > $this->_lastRun));
+                    break;
+
+                case self::DAILY:
+                    $addtask = (($cur_date['year'] > $lasttasks[$app]['year']) || ($cur_date['yday'] > $lasttasks[$app]['yday']));
+                    break;
+
+                case self::EVERY:
+                    $addtask = true;
+                    break;
+                }
+            }
+
+            if ($addtask) {
+                $this->_tasklist->addTask($ob);
+            }
+        }
+    }
+
+    /**
+     * Do operations needed for this login.
+     *
+     * This function will generate the list of tasks to perform during this
+     * login and will redirect to the login tasks page if necessary.  This is
+     * the function that should be called from the application upon login.
+     */
+    public function runTasks()
+    {
+        if ($this->_tasklist === true) {
+            return;
+        }
+
+        /* Perform ready tasks now. */
+        foreach ($this->_tasklist->ready() as $key => $val) {
+            if (($val->display == self::DISPLAY_AGREE) ||
+                ($val->display == self::DISPLAY_NOTICE) ||
+                Horde_Util::getFormData('logintasks_confirm_' . $key)) {
+                $val->execute();
+            }
+        }
+
+        $need_display = $this->_tasklist->needDisplay();
+        $tasklist_target = $this->_tasklist->target;
+
+        /* 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)) {
+            $lasttasks = unserialize($GLOBALS['prefs']->getValue('last_logintasks'));
+            $lasttasks[$this->_app] = time();
+            if (strnatcasecmp($this->_app, Auth::getProvider()) === 0) {
+                $lasttasks['horde'] = time();
+            }
+            $GLOBALS['prefs']->setValue('last_logintasks', serialize($lasttasks));
+
+            /* This will prevent us from having to store the entire tasklist
+             * object in the session, while still indicating we have
+             * completed the login tasks for this application. */
+            $this->_tasklist = true;
+        }
+
+        if ($this->_init && $need_display) {
+            header('Location: ' . $this->getLoginTasksUrl());
+            exit;
+        } elseif (!$this->_init && !$need_display) {
+            header('Location: ' . $tasklist_target);
+            exit;
+        }
+    }
+
+    /**
+     * Generate the list of tasks that need to be displayed.
+     *
+     * This is the function called from the login tasks page every time it
+     * is loaded.
+     *
+     * @return array  The list of tasks that need to be displayed.
+     */
+    public function displayTasks()
+    {
+        return $this->_tasklist->needDisplay(true);
+    }
+
+    /**
+     * Generated the login tasks URL.
+     *
+     * @return string  The login tasks URL.
+     */
+    public function getLoginTasksUrl()
+    {
+        return Horde_Util::addParameter(Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/logintasks.php', true), array('app' => $this->_app));
+    }
+
+}
diff --git a/framework/LoginTasks/lib/Horde/LoginTasks/Task.php b/framework/LoginTasks/lib/Horde/LoginTasks/Task.php
new file mode 100644 (file)
index 0000000..1fc7552
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Abstract class to allow for modularization of specific login tasks.
+ *
+ * Copyright 2001-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_Task
+{
+    /**
+     * Should the task be run?
+     *
+     * @var boolean
+     */
+    public $active = true;
+
+    /**
+     * The interval at which to run the task.
+     *
+     * @var integer
+     */
+    public $interval = Horde_LoginTasks::MONTHLY;
+
+    /**
+     * The style of the page output.
+     *
+     * [1] Horde_LoginTasks::DISPLAY_CONFIRM_NO
+     *     Horde_LoginTasks::DISPLAY_CONFIRM_YES
+     *     Each output from describe() will have a checkbox associated
+     *     with it. For each checkbox selected, execute() for that task will
+     *     be run. More than 1 confirmation message can be displayed on the
+     *     confirmation page at once.
+     *
+     *     DISPLAY_CONFIRM_YES will be checked by default, DISPLAY_CONFIRM_NO
+     *     will be unchecked by default.
+     *
+     * [2] Horde_LoginTasks::DISPLAY_AGREE
+     *     The output from describe() should be text asking the user to
+     *     agree/disagree to specified terms. If 'yes' is selected, the POST
+     *     variable 'agree' will be set. If 'no' is selected, the POST variable
+     *     'not_agree' will be set. In either case, execute() will ALWAYS be
+     *     run.
+     *     This style will be displayed on its own confirmation page.
+     *
+     * [3] Horde_LoginTasks::DISPLAY_NOTICE
+     *     The output from describe() should be any non-interactive text
+     *     desired. There will be a single 'Click to Continue' button below
+     *     this text. execute() will ALWAYS be run.
+     *     This style will be displayed on its own confirmation page.
+     *
+     * [4] Horde_LoginTasks::DISPLAY_NONE
+     *     Don't display any confirmation to the user.
+     *
+     * @var integer
+     */
+    public $display = Horde_LoginTasks::DISPLAY_CONFIRM_YES;
+
+    /**
+     * The priority of the task.
+     *
+     * @var integer
+     */
+    public $priority = Horde_LoginTasks::PRIORITY_NORMAL;
+
+    /**
+     * Do login task (if it has been confirmed).
+     *
+     * @return boolean  Whether the login task was successful.
+     */
+    abstract public function execute();
+
+    /**
+     * Return description information for the login task.
+     *
+     * @return string  Description that will be displayed on the login task
+     *                 confirmation page.
+     */
+    abstract public function describe();
+
+}
diff --git a/framework/LoginTasks/lib/Horde/LoginTasks/Tasklist.php b/framework/LoginTasks/lib/Horde/LoginTasks/Tasklist.php
new file mode 100644 (file)
index 0000000..af5dc05
--- /dev/null
@@ -0,0 +1,148 @@
+<?php
+/**
+ * The Horde_LoginTasks_Tasklist:: class is used to store the list of
+ * login tasks that need to be run during this login.
+ *
+ * Copyright 2002-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
+ */
+class Horde_LoginTasks_Tasklist
+{
+    /**
+     * The URL of the web page to load after login tasks are complete.
+     *
+     * @var string
+     */
+    public $target;
+
+    /**
+     * The list of tasks to run during this login.
+     *
+     * KEY: Task name
+     * VALUE: array => (
+     *   'display' => boolean,
+     *   'task' => integer
+     * )
+     *
+     * @var array
+     */
+    protected $_tasks = array();
+
+    /**
+     * Internal flag for addTask().
+     *
+     * @var boolean
+     */
+    protected $_addFlag = false;
+
+    /**
+     * Current task location pointer.
+     *
+     * @var integer
+     */
+    protected $_ptr = null;
+
+    /**
+     * Constructor.
+     *
+     * @param string $url  The target URL to redirect to when finished.
+     */
+    public function __construct($url)
+    {
+        $this->target = $url;
+    }
+
+    /**
+     * Adds a task to the tasklist.
+     *
+     * @param Horde_LoginTasks_Task $task  The task to execute.
+     */
+    public function addTask($task)
+    {
+        $tmp = array(
+            'display' => false,
+            'task' => $task
+        );
+
+        if (($task->display == Horde_LoginTasks::DISPLAY_AGREE) ||
+            ($task->display == Horde_LoginTasks::DISPLAY_NOTICE)) {
+            $tmp['display'] = true;
+            $this->_addFlag = false;
+        } elseif (($task->display != Horde_LoginTasks::DISPLAY_NONE) &&
+                  !$this->_addFlag) {
+            $tmp['display'] = true;
+            $this->_addFlag = true;
+        }
+
+        switch ($task->priority) {
+        case Horde_LoginTasks::PRIORITY_HIGH:
+            array_unshift($this->_tasks, $tmp);
+            break;
+
+        case Horde_LoginTasks::PRIORITY_NORMAL:
+            $this->_tasks[] = $tmp;
+            break;
+        }
+    }
+
+    /**
+     * Returns the list of tasks to perform.
+     *
+     * @return array  The list of tasks to perform.
+     */
+    public function ready()
+    {
+        $tmp = array();
+
+        reset($this->_tasks);
+        while (list($k, $v) = each($this->_tasks)) {
+            if ($v['display'] &&
+                (is_null($this->_ptr) || ($k > $this->_ptr))) {
+                break;
+            }
+            $tmp[] = $v['task'];
+        }
+
+        if (!is_null($this->_ptr)) {
+            $this->_tasks = array_slice($this->_tasks, $this->_ptr);
+            $this->_ptr = 0;
+        }
+
+        return $tmp;
+    }
+
+    /**
+     * Returns the next batch of tasks that need display.
+     *
+     * @param boolean $advance  If true, advance the internal pointer.
+     *
+     * @return array  The list of tasks to display.
+     */
+    public function needDisplay($advance = false)
+    {
+        $tmp = array();
+        $display = null;
+
+        reset($this->_tasks);
+        while (list($k, $v) = each($this->_tasks)) {
+            if (!$v['display'] ||
+                (!is_null($display) && ($v['task']->display != $display))) {
+                break;
+            }
+            $tmp[] = $v['task'];
+            $display = $v['task']->display;
+        }
+
+        if ($advance) {
+            $this->_ptr = count($tmp);
+        }
+
+        return $tmp;
+    }
+
+}
diff --git a/framework/LoginTasks/package.xml b/framework/LoginTasks/package.xml
new file mode 100644 (file)
index 0000000..dd1514b
--- /dev/null
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>LoginTasks</name>
+ <channel>pear.horde.org</channel>
+ <summary>Horde Login Tasks System</summary>
+ <description>The Horde_LoginTasks:: class provides a set of methods for dealing with tasks run upon login to Horde applications.
+ </description>
+ <lead>
+  <name>Michael Slusarz</name>
+  <user>slusarz</user>
+  <email>slusarz@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <date>2009-06-23</date>
+ <version>
+  <release>0.1.0</release>
+  <api>0.1.0</api>
+ </version>
+ <stability>
+  <release>beta</release>
+  <api>beta</api>
+ </stability>
+ <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+ <notes>* Renamed Maintenance:: -> Horde_LoginTasks::.
+ * Initial Horde 4 package.</notes>
+ <contents>
+  <dir name="/">
+   <dir name="lib">
+    <dir name="Horde">
+     <dir name="LoginTasks">
+     <file name="Task.php" role="php" />
+     <file name="Tasklist.php" role="php" />
+     </dir> <!-- /lib/Horde/LoginTasks -->
+     <file name="LoginTasks.php" role="php" />
+    </dir> <!-- /lib/Horde -->
+   </dir> <!-- /lib -->
+  </dir> <!-- / -->
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.2.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.5.4</min>
+   </pearinstaller>
+   <package>
+    <name>Util</name>
+    <channel>pear.horde.org</channel>
+   </package>
+  </required>
+ </dependencies>
+ <phprelease>
+  <filelist>
+   <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" />
+  </filelist>
+ </phprelease>
+ <changelog>
+  <release>
+   <date>2006-05-08</date>
+   <time>22:26:53</time>
+   <version>
+    <release>0.0.2</release>
+    <api>0.0.2</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Converted to package.xml 2.0 for pear.horde.org</notes>
+  </release>
+  <release>
+   <date>2003-07-05</date>
+   <version>
+    <release>0.0.1</release>
+    <api>0.0.1</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Initial release as a PEAR package
+   </notes>
+  </release>
+ </changelog>
+</package>
+