<?php
/**
 * singleton class manager
 * 
 * @author Haruki Setoyama <haruki@planewave.org>
 * @copyright Copyright &copy; 2003, Haruki SETOYAMA <haruki@planewave.org>
 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @version 3.0 $Id: singleton.php,v 1.7 2004/05/19 10:35:00 haruki Exp $
 * @access public 
 */
if (! class_exists('singleton')) {
    /**
     * require
     * singleton uses some PEAR static methods
     */
    require_once 'PEAR.php';
    /**
     * define
     */
    define('SINGLETON_ERROR', 1);
    
    /**
     * singleton
     * 
     * @access public
     * @static 
     */
    class singleton 
    {
        /**
         * singleton::getInstance()
         * 
         * @param string $name  class name that you want to make singleton.
         * @return object|PEARError
         * @access public 
         */
        function &getInstance($name)
        {
            $name = trim(strtolower($name));
            $instances =& PEAR::getStaticProperty('singleton', 'instances');
            if (! isset($instances[$name])) {
                if (! class_exists($name)) {
                    return PEAR::raiseError("class '$name' not exists. " , SINGLETON_ERROR);
                } 

                $obj =& new $name;
                if (! is_object($obj)) {
                    return PEAR::raiseError("failed to instantiate object with class '$name'. " , SINGLETON_ERROR);
                }

                $instances[$name] = $obj;
            } 
            return $instances[$name];
        } 

        /**
         * singleton::isInstanciated() 
         * create instance with parameters and factory method
         * 
         * @param string $name  class name that you want to make singleton.
         * @param array $params parameters for construstor or factory method
         * @param string $method factory method name
         * @return bool 
         * @access public 
         */     
        function &createInstance($name, $params, $method = null) 
        {
            $code = '$obj =& ';
            if (is_string($method)) {
                $code .= "$name::$method(";
            } else {
                $code .= "new $name(";
            }
            
            if (is_array($params)) {
                $attr = array();
                $num = count($params);
                for($i=0; $i<$num; $i++) {
                    $attr[] = '$params['.$i.']';
                }
                $code .= implode(',', $attr).'); ';
            } else {
                $code .= '$params);';
            }
            
            eval($code);
            if (! is_object($obj)) {
                return PEAR::raiseError("failed to craete instance with class '$name'. " , SINGLETON_ERROR);
            }

            $instances =& PEAR::getStaticProperty('singleton', 'instances');
            $instances[$name] = $obj;
            return $instances[$name];
        }

        /**
         * singleton::isInstanciated()
         * 
         * @param string $name  class name that you want to make singleton.
         * @return bool 
         * @access public 
         */
        function isInstanciated($name)
        {
            $name = trim(strtolower($name));
            $instances =& PEAR::getStaticProperty('singleton', 'instances');
            return isset($instances[$name]);
        } 

        /**
         * singleton::deleteInstance()
         * 
         * @param string $name  class name that you want to make singleton.
         * @return void 
         * @access public 
         */
        function deleteInstance($name)
        {
            $name = trim(strtolower($name));
            $instances =& PEAR::getStaticProperty('singleton', 'instances');
            unset($instances[$name]);
        } 
    } 
} 
?>