<?php
/*
 * This file is part of the easy-CMS project.
 * easy-CMS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * easy-CMS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with easy-CMS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
 
/**
 * @package    Core
 * @subpackage Types
 */

include_once('classes/core/DBAccessorObject.class.php');
include_once('classes/core/types/Type.class.php');
include_once('classes/core/DBManipulator.class.php');
include_once('classes/types/Bool.class.php');
include_once('classes/types/Color.class.php');
include_once('classes/types/Date.class.php');
include_once('classes/types/Document.class.php');
include_once('classes/types/Image.class.php');
include_once('classes/types/Integer.class.php');
include_once('classes/types/Float.class.php');
include_once('classes/types/Reference.class.php');
include_once('classes/types/String.class.php');
include_once('classes/types/ShortText.class.php');
include_once('classes/types/Link.class.php');
include_once('classes/types/Text.class.php');
include_once('classes/types/Time.class.php');


/**
 * Manages types and instantiates objects parts of content.
 *
 * @author	   Cedric Francoys <cedric.francoys@easy-cms.org>
 * @version	   ShortText.class, Sun Nov 28 13:26:21 CET 2004
 * @package    Core
 * @subpackage Types
 */
class TypesManager extends DBAccessorObject {
	/**
	 * Type Objects Array
	 *
	 * @access private
	 * @var array
	 */
	var $typesTable;

	/**
	 * Constructor
	 *
	 * @access public
	 * @param object  $dbManipulator
	 */
	function TypesManager(&$dbManipulator) {
		parent::DBAccessorObject($dbManipulator);
	}

	/**
	 * @return array
	 */
	function &getTypesTable() {
		return $this->typesTable;
	}

	/**
	 * Loads Type
	 *
	 * loadType first checks if an instance already exists. if not it will 
	 * try to instanciate the type if its corresponding table exists in the 
	 * database.
	 *
	 * @access private
	 * @param  string  $name type's name
	 * @return boolean
	 */
	function loadType($name) {
    $result = true;
		if (!$this->dbManipulator->typeExists($name)) {
			$result = false;
		}
    else {
		  $this->typesTable[$name] = &new Type($name, $this->dbManipulator);
      $this->typesTable[$name]->loadFieldsTable();
    }
		return $result;
	}

	/**
	 * Stores type
	 *
	 * @param  string $name
	 * @return integer Type ID or <0 if error
	 */
  function storeType($name) {
    $this->debug('TypesManager::storeType, status : function invoked ('.$name.')', 10, DBG_OPEN);
    $result = true;
    $privateFieldsArray = Type::getPrivateFieldsArray();

		if(!$this->isValidTypeName($name) || is_null($type = &$this->getType($name))) {
      trigger_error('TypesManager::storeType, error : unable to get type ('.$name.')', E_USER_ERROR);
      $result = false;
		}
    else {
			$newFieldsArray = array();
			$oldFieldsArray = array();

  		if($this->dbManipulator->tableExists($type->getTableName())){
  			$fieldsTable = &$type->getFieldsTable();
  			$fieldsArray = &$this->dbManipulator->getFieldsArray($type->getTableName());

  			foreach($fieldsTable as $key => $value) {
  				if(!isset($fieldsArray[$key])){
            $newFieldsArray[$key] = $this->dbManipulator->getDBMSType($value);
          }
  			}
  			foreach($fieldsArray as $key => $value) {
  				if(!isset($fieldsTable[$key])) {
            $oldFieldsArray[$key] = $this->dbManipulator->getDBMSType($value);
          }
  			}
  			$result = $this->dbManipulator->updateTable($type->getTableName(), $newFieldsArray, $oldFieldsArray);
  		}
  		else {
  			foreach($type->getFieldsTable() as $key => $value) {
          if(!array_key_exists($key, $privateFieldsArray)) {
  				  $newFieldsArray[$key] = $this->dbManipulator->getDBMSType($value);
          }
          else {
  				  $newFieldsArray[$key] = $privateFieldsArray[$key];
          }
  			}
  			$result = $this->dbManipulator->createTable($type->getTableName(), $newFieldsArray);
  		}
    }

    $this->debug('TypesManager::storeType, status : function completed', 10, DBG_CLOSE);
		return $result;
	}

	/**
	 * Removes Type
	 *
	 * @param  string $name
	 * @return boolean
	 */
  function removeType($name) {
    $result = true;
    if(!$this->typeExists($name)) {
      $result = false;
    }
    else {
      $type = &$this->typesTable[$name];
  		if (!$this->dbManipulator->dropTable($type->getTableName())) {
  			$result = false;
  		}
  		unset($this->typesTable[$name]);
    }
		return $result;
  }

  function renameType($type_name, $new_name) {
    $result = true;
    if(!$this->typeExists($type_name)) {
      $result = false;
    }
    else {
      $type = $this->getType($type_name);
      $oldTableName = $type->getTableName();
      $type->setTypeName($new_name);
  		unset($this->typesTable[$name]);
  		$this->typesTable[$new_name] = &$type;
  		if (!$this->dbManipulator->renameTable($oldTableName, $type->getTableName())) {
  			$result = false;
  		}
    }
		return $result;
  }

	/**
	 * Checks if instance of specified type exist
	 *
	 * @param  string $name type's name
	 * @return boolean
	 * @deprecated due to naming convention
	 * @todo approve deprecation
	 */
	function checkType($name) {
		return isset($this->typesTable[$name]);
	}

	function typeExists($name) {
		// try to load the type
		$this->getType($name);
		// returns true if the type exists
		return $this->checkType($name);
	}

    /**
	 * Gets Type
	 *
	 * Returns user defined Type object
	 *
	 * @access public
 	 * @param  string $name
 	 * @return object 
	 */
	function &getType($name) {
    $result = null;
		if(!$this->checkType($name)) {
			if(!$this->loadType($name)) {
				// error
			}
      else {
        $result = &$this->typesTable[$name];
      }
		}
    else {
      $result = &$this->typesTable[$name];
    }
		return $result;
	}
	
	function &getNewType($name) {
    $this->debug('TypesManager::getNewType, status : function invoked', 10, DBG_OPEN);
    $result = null;
    if(!$this->typeExists($name)) {
    	$this->typesTable[$name] = &new Type($name, $this->dbManipulator);
    	$result = &$this->typesTable[$name];
    }
    $this->debug('TypesManager::getNewType, status : function completed', 10, DBG_CLOSE);
		return $result;
	}

  function isValidFieldName($name) {
    return ereg("^[a-z0-9_]+$",$name);
  }

  function isValidTypeName($name) {
    return ereg("^[a-z_]+$",$name);
  }

  function isValidCMSType($cms_type) {
    return in_array($cms_type, $this->getCMSTypesArray());
  }

  function getCMSTypesArray() {
    return array(EASY_CMS_TYPE_INTEGER, EASY_CMS_TYPE_FLOAT, EASY_CMS_TYPE_BOOL, EASY_CMS_TYPE_STRING, EASY_CMS_TYPE_SHORTTEXT, EASY_CMS_TYPE_TEXT, EASY_CMS_TYPE_COLOR, EASY_CMS_TYPE_LINK, EASY_CMS_TYPE_DATE, EASY_CMS_TYPE_TIME, EASY_CMS_TYPE_DOCUMENT, EASY_CMS_TYPE_IMAGE, EASY_CMS_TYPE_REFERENCE);
  }

	/**
	 * Creates easy-CMS Simple Type
	 *
	 * @access public
	 * @param  integer $type
	 * @param  mixed $value
	 * @return object returns null if unknown type
	 */
	function &createTypeObject($type, &$value) {
		switch($type) {
		  case EASY_CMS_TYPE_BOOL:
  			$obj = &new Bool($value);
  			break;
  		case EASY_CMS_TYPE_INTEGER:
  			$obj = &new Integer($value);
  			break;
  		case EASY_CMS_TYPE_FLOAT:
  			$obj = &new Float($value);
  			break;
  		case EASY_CMS_TYPE_DATE:
  			$obj = &new Date($value);
  			break;
      case EASY_CMS_TYPE_TIME:
  			$obj = &new Time($value);
  			break;
      case EASY_CMS_TYPE_COLOR:
  			$obj = &new Color($value);
  			break;
      case EASY_CMS_TYPE_REFERENCE:
  			$obj = &new Reference($value);
  			break;
      case EASY_CMS_TYPE_STRING:
  			$obj = &new String($value);
  			break;
      case EASY_CMS_TYPE_SHORTTEXT:
  			$obj = &new ShortText($value);
  			break;
      case EASY_CMS_TYPE_TEXT:
  			$obj = &new Text($value);
  			break;
      case EASY_CMS_TYPE_LINK:
  			$obj = &new Link($value);
  			break;
      case EASY_CMS_TYPE_DOCUMENT:
  			$obj = &new Document($value);
  			break;
      case EASY_CMS_TYPE_IMAGE:
  			$obj = &new Image($value);
  			break;
      default:
			 $obj = null;
		}
		return $obj;
	}
}
?>
