<?php
/**
 * Storage class for RDO.
 *
 * $Horde: framework/RDO/RDO/Storage.php,v 1.4.2.1 2005/10/18 11:01:23 jan Exp $
 *
 * @package RDO
 */
abstract class RDO_Storage {

    /**
     * Human-readable name for this Storage driver.
     *
     * @var string $name
     */
    public $name;

    /**
     * Parameters for this Storage driver.
     *
     * @var array $params
     */
    protected $params;

    public static function singleton($backend, $params)
    {
        static $instances = array();

        $backend = strtolower($backend);
        $signature = serialize(array($backend, $params));
        if (!isset($instances[$signature])) {
            $class = 'RDO_Storage_' . $backend;
            if (!class_exists($class)) {
                throw new RDO_Exception('Storage class "' . $backend . '" not found');
            }

            $instances[$signature] = new $class($params);
        }

        return $instances[$signature];
    }

    protected function __construct($params)
    {
        $this->params = $params;
    }

    /**
     * Free any resources that are open.
     */
    public function __destruct()
    {
    }

    /**
     * Allow $storage->param access to storage parameters.
     *
     * @param string $param The parameter to fetch.
     */
    public function __get($param)
    {
        return isset($this->params[$param]) ? $this->params[$param] : null;
    }

    /**
     * Turn any of the acceptable criteria shorthands into a full
     * RDO_Criteria object.
     *
     * @param mixed $criteria The criteria to convert to an object.
     * @param RDO_Mapper $mapper The mapper object governing this clause.
     *
     * @return RDO_Criteria The full RDO_Criteria object.
     */
    public function toCriteria($criteria, RDO_Mapper $mapper)
    {
        if ($criteria instanceof RDO_Criteria) {
            $criteria->setMapper($mapper);
            return $criteria;
        }

        $c = new RDO_Criterion($mapper);

        if (is_scalar($criteria)) {
            $c->addTest($mapper->describe()->key, '=', $criteria);
        } elseif ($criteria) {
            $c->combineWith('AND');
            foreach ($criteria as $key => $value) {
                $c->addTest($key, '=', $value);
            }
        }

        return $c;
    }

    /**
     */
    public abstract function begin();

    /**
     */
    public abstract function commit();

    /**
     */
    public abstract function rollback();

}
