Classes
Nag Storage
Subclasses


Nag's Storage API

<?php
// $Horde: hordeweb/papers/oscon2001-horde_tutorial/39_nagclass.xml.html,v 1.1 2001/12/05 16:48:06 chuck Exp $

// Return codes
/** @constant STORAGE_OK Operation succeeded. */
define('STORAGE_OK'0);

/** @constant STORAGE_ERROR Operation failed. */
define('STORAGE_ERROR', -1);

/** @constant STORAGE_ERROR_PARAMS Bad or missing parameters ($params). */
define('STORAGE_ERROR_PARAMS', -2);

/** @constant STORAGE_ERROR_CONNECT Connection failure. */
define('STORAGE_ERROR_CONNECT', -3);

/** @constant STORAGE_ERROR_AUTH Authentication failure. */
define('STORAGE_ERROR_AUTH', -4);

/** @constant STORAGE_ERROR_EMPTY Empty retrieval result. */
define('STORAGE_ERROR_EMPTY', -5);

// Internal status flags (for bitwise operations)
/** @constant TASK_ANY Task has any flag set. */
define('TASK_ANY'0);

/** @constant TASK_ADDED Task has just been added. */
define('TASK_ADDED'1);

/** @constant TASK_MODIFIED Task has been modified. */
define('TASK_MODIFIED'2);

/** @constant TASK_DELETED Task has been deleted. */
define('TASK_DELETED'4);

/**
* Nag_Storage:: defines an API for implementing storage backends for Nag.
*
* @author  Jon Parise <jon@horde.org>
* @version $Revision: 1.1 $
* @since   Nag 0.1
* @package nag
*/
class Nag_Storage {
    
    
/**
     * Array holding the current tast list.  Each array entry is a hash
     * describing a task.  The array is indexed numerically by task ID.
     * @var array $tasks
     */
    
var $tasks = array();

    
/**
     * String containing the current username.  This indicates the owner of
     * the current task list.
     * @var string $user
     */
    
var $user '';

    
/**
     * Attempts to return a concrete Nag_Storage instance based on $driver.
     *
     * @param string    $driver     The type of concrete Nag_Storage subclass
     *                              to return.  The is based on the storage
     *                              driver ($driver).  The code is dynamically
     *                              included.
     *
     * @param string    $user       The name of the user who owns these tasks.
     *
     * @param hash      $params     (optional) A hash containing any additional
     *                              configuration or connection parameters a
     *                              subclass might need.
     *
     * @return mixed    The newly created concrete Nag_Storage instance, or
     *                  false on an error.
     */
    
function &factory($driver$user$params = array())
    {
        
$driver strtolower($driver);
        @include_once 
dirname(__FILE__) . '/Storage/' $driver '.php';
        
$class 'Nag_Storage_' $driver;
        if (
class_exists($class)) {
            return new 
$class($user$params);
        } else {
            return 
false;
        }
    }

    
/**
     * Attempts to return a reference to a concrete Nag_Storage instance
     * based on $driver.  It wil only create a new instance if no
     * Nag_Storage instance with the same parameters currently exists.
     *
     * This should be used if multiple storage sources are required.
     *
     * This method must be invoked as: $var = &Nag_Storage::singleton()
     *
     * @param string    $driver     The type of concrete Nag_Storage subclass
     *                              to return.  The is based on the storage
     *                              driver ($driver).  The code is dynamically
     *                              included.
     *
     * @param string    $user       The name of the user who owns these tasks.
     *
     * @param hash      $params     (optional) A hash containing any additional
     *                              configuration or connection parameters a
     *                              subclass might need.
     *
     * @return mixed    The created concrete Nag_Storage instance, or false
     *                  on error.
     */
    
function &singleton($driver$user$params = array())
    {
        static 
$instances;

        if (!isset(
$instances)) $instances = array();

        
$signature md5(strtolower($driver) . '][' $user implode(']['$params));
        if (!isset(
$instances[$signature])) {
            
$instances[$signature] = Nag_Storage::factory($driver$user$params);
        }

        return 
$instances[$signature];
    }

    
/**
     * Lists tasks based on the given criteria.  All tasks will be returned
     * by default.
     *
     * @param int       $criteria   (optional) A set of flags specifying the
     *                              set of tasks to return.
     *
     * @return array    Returns a list of the requested tasks.
     */
    
function listTasks($criteria TASK_ANY)
    {
        
/* Return all of the tasks by default. */
        
if ($criteria == TASK_ANY) {
            return 
$this->tasks;
        }

        
/* Otherwise, return only the set of tasks that match $criteria. */
        
$return_set = array();
        foreach (
$this->tasks as $task_id => $task) {
            if (
$this->tasks[$task_id]['flags'] & $criteria) {
                
$return_set[$task_id] = $task;
            }
        }

        return 
$return_set;
    }

    
/**
     * Adds a new task to the $tasks list.
     *
     * @param string    $name       The name (short) of the task.
     * @param string    $desc       The description (long) of the task.
     * @param int       $due        (optional) The due date of the task.
     * @param int       $priority   (optional) The priority of the task.
     * @param int       $depends    (optional) The task ID of a dependency.
     *
     * @return integer  The numeric ID of the new task.
     */
    
function addTask($name$desc$due 0$priority 0$depends = -1)
    {
        
/* Create a new task task. */
        
$task = array();
        
$task['name'] = $name;
        
$task['desc'] = $desc;
        
$task['added'] = time();
        
$task['due'] = $due;
        
$task['priority'] = $priority;
        
$task['depends'] = $depends;
        
$task['flags'] = TASK_ADDED;

        
/* Add it to the $tasks list. */
        
$this->tasks[] = $task;

        
$keys array_keys($this->tasks);

        return 
$keys[(count($keys) - 1)];
    }

    
/**
     * Modifies an attribute of a task in the $tasks list.
     *
     * @param int       $id         The ID of the task to modify.
     * @param string    $attribute  The attribute of the task to modify.
     * @param mixed     $value      The new value for $attribute.
     *
     * @return boolean  True if the task was successfully marked as modified.
     */
    
function modifyTask($id$attribute$value)
    {
        if (isset(
$this->tasks[$id]) && isset($this->tasks[$id][$attribute])) {
            
$this->tasks[$id][strtolower($attribute)] = $value;
            
$this->tasks[$id]['flags'] |= TASK_MODIFIED;
            return (
$this->tasks[$id]['flags'] & TASK_MODIFIED);
        }

        return 
false;
    }

    
/**
     * Removes a task from the $tasks list.
     *
     * @param int       $id         The ID of the task to delete.
     *
     * @return boolean  True if the task was successfully marked as deleted.
     */
    
function deleteTask($id)
    {
        if (isset(
$this->tasks[$id])) {
            
$this->tasks[$id]['flags'] |= TASK_DELETED;
            return (
$this->tasks[$id]['flags'] & TASK_DELETED);
        }

        return 
false;
    }

    
/**
     * Sets the requested flag to the given value.
     *
     * @param int       $id         The ID of the task task to modify.
     * @param int       $flag       The flag to modify.
     * @param boolean   $state      The new state of the flag.
     */
    
function setFlag($id$flag$state)
    {
        if (isset(
$this->tasks[$id])) {
            if (
$state) {
                
$this->tasks[$id]['flags'] != $flag;
            } else {
                
$this->tasks[$id]['flags'] &= $flag;
            }
        }
    }

    
/**
     * Gets the requested flag's value.
     *
     * @param int       $id         The ID of the task task to examine.
     * @param int       $flag       The flag whose value to return.
     *
     * @return boolean  The state of the requested flag.
     */
    
function getFlag($id$flag)
    {
        if (isset(
$this->tasks[$id])) {
            return (
$this->tasks[$id]['flags'] & $flag);
        }

        return 
null;
    }

    
/**
     * Purges those tasks that have the "deleted" flag set.
     */
    
function purgeDeleted()
    {
        
$deleted_ids array_keys($this->listTasks(TASK_DELETED));
        foreach (
$deleted_ids as $task_id) {
            unset(
$this->tasks[$task_id]);
        }
    }

}
?>