<?php
/**
 * The Category_null:: class provides a dummy implementation of the
 * Category:: API; no categories will last beyond a single page
 * request.
 *
 * $Horde: horde/lib/Category/null.php,v 1.8 2003/06/17 01:56:04 chuck Exp $
 *
 * Copyright 1999, 2000, 2001, 2002 Stephane Huther <shuther@bigfoot.com>
 * Copyright 2001, 2002 Chuck Hagenbuch <chuck@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  Chuck Hagenbuch <chuck@horde.org>
 * @version $Revision: 1.8 $
 * @since   Horde 3.0
 * @package horde.category
 */
class Category_null extends Category {

    /**
     * Cache of attributes for any categories created during this page
     * request.
     * @var array $_attributeCache
     */
    var $_attributeCache = array();

    /**
     * Cache of data for any categories created during this page
     * request.
     * @var array $_dataCache
     */
    var $_dataCache = array();

    /**
     * Load (a subset of) the category tree into the $_categories
     * array. Part of the Category API that must be overridden by
     * subclasses.
     *
     * @param optional string  $root    Which portion of the category
     *                                  tree to load. Defaults to all of it.
     * @param optional boolean $reload  Re-load already loaded values?
     *
     * @return mixed  True on success or a PEAR_Error on failure.
     *
     * @access private
     */
    function _load($root = null, $reload = false)
    {
    }

    /**
     * Load a specific category identified by its unique ID ($id), and
     * its parents, into the $_categories array.
     *
     * @param integer $cid  The unique ID of the category to load.
     *
     * @return mixed  True on success or a PEAR_Error on failure.
     *
     * @access private
     */
    function _loadById($cid)
    {
    }

    /**
     * Add a category. Part of the Category API that must be
     * overridden by subclasses.
     *
     * @param mixed $fullname  The category to add (string or CategoryObject).
     */
    function addCategory($category)
    {
        if (is_a($category, 'CategoryObject')) {
            $fullname = $category->getName();
            $order = $category->order;
        } else {
            $fullname = $category;
            $order = null;
        }

        $id = md5(mt_rand());
        if (strstr($fullname, ':')) {
            $parts = explode(':', $fullname);
            $name = array_pop($parts);
            $parent = implode(':', $parts);
            $pid = $this->getCategoryId($parent);
            if (is_a($pid, 'PEAR_Error')) {
                $this->addCategory($parent);
            }
        } else {
            $pid = '-1';
        }

        if (parent::exists($fullname)) {
            return PEAR::raiseError('Already exists');
        }

        $added = parent::_addCategory($fullname, $id, $pid, $order);
        if (is_a($added, 'PEAR_Error')) {
            return $added;
        }
        return $this->updateCategoryData($category);
    }

    function getCategoryData($cid)
    {
        return isset($this->_dataCache[$cid]) ?
            $this->_dataCache[$cid] :
            array();
    }

    /**
     * Retrieve data for a category from the horde_category_attributes
     * table.
     *
     * @param integer $cid  The category id to fetch.
     */
    function getCategoryAttributes($cid)
    {
        if (is_array($cid)) {
            $data = array();
            foreach ($cid as $id) {
                if (isset($this->_attributeCache[$id])) {
                    $data[$id] = $this->_attributeCache[$id];
                }
            }

            return $data;
        } else {
            return isset($this->_attributeCache[$cid]) ?
                $this->_attributeCache[$cid] :
                array();
        }
    }

    /**
     * Return a set of category ids based on a set of attribute
     * criteria.
     *
     * @param array $criteria  The array of criteria.
     */
    function getCategoriesByAttributes($criteria)
    {
        if (!count($criteria)) {
            return array();
        }

        return array_keys($this->_attributeCache);
    }

    /**
     * Update the data in a category. Does not change the category's
     * parent or name, just serialized data.
     *
     * @param string $category  The category object.
     */
    function updateCategoryData($category)
    {
        if (!is_a($category, 'CategoryObject')) {
            return true;
        }

        $cid = $this->getCategoryId($category->getName());
        if (is_a($cid, 'PEAR_Error')) {
            return $cid;
        }

        // We handle category differently if we can map it to
        // attributes.
        if (method_exists($category, '_toAttributes')) {
            $this->_attributeCache[$cid] = $category->_toAttributes();
        } else {
            $this->_dataCache[$cid] = $category->getData();
        }

        return true;
    }

    /**
     * Change order of subcategories within a category.
     *
     * @param string $parents The parent category id string path.
     * @param mixed  $order   A specific new order position or an
     *                        array containing the new positions
     *                        for the given $parents category.
     * @param int    $cid     If provided indicates insertion of
     *                        a new child to the category, and
     *                        will be used to avoid incrementing
     *                        it when shifting up all other
     *                        children's order. If not provided
     *                        indicates deletion, hence shift all
     *                        other positions down one.
     */
    function reorderCategory($parents, $order = null, $cid = null)
    {
        if (is_array($order) && !empty($order)) { // Multi update
            $this->_reorderCategory($pid, $order); // Reorder cache
        }
    }

}
