<?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 MenuNodes
 */

include_once('classes/core/DBAccessorObject.class.php');
include_once('classes/core/DBManipulator.class.php');
include_once('classes/core/menuNodes/MenuNode.class.php');
include_once('classes/core/pages/Page.class.php');
include_once('classes/core/pages/PagesManager.class.php');

/**
 * Manage the instances of Container objects.
 *
 * @access     public
 * @author	   Cedric Francoys <cedric.francoys@easy-cms.org>
 * @version	   MenuNodesManager.class, Sat Nov 13 11:39:53 CET 2004
 * @package	   Core
 * @subpackage MenuNodes
 */
class MenuNodesManager extends DBAccessorObject {
	/**
	 * @var object
	 */
	var $pagesManager;

	/**
	 * @var object
	 */
	var $menusManager;

	/**
	 * Array of Container objects
	 *
	 * @var array
	 */
	var $menuNodesTable;


	/**
	 * Class constructor
	 *
	 * @param object  $dbManipulator
	 * @param object  $pagesManager
	 */
	function MenuNodesManager(&$dbManipulator, &$pagesManager, &$menusManager){
		parent::DBAccessorObject($dbManipulator);
		$this->pagesManager = &$pagesManager;
		$this->menusManager = &$menusManager;
		$this->menuNodesTable = array();
	}

	/**
	 * Loads MenuNode
	 *
	 * @param  mixed   $menuNodeId
	 * @param  integer $langId
	 * @return boolean
	 */
	function loadMenuNode($node_id, $langId=LOAD_ALL_LANGUAGES){
    $this->debug('MenuNodesManager::loadMenuNode, status : function invoked ('.$node_id.')', 10, DBG_OPEN);
    $result = true;
		$db = &$this->getDBManipulator();

		$cond = '`id` in ('.implode(',', (array)$node_id).')';

		if($result_array = $db->getRecord(MENU_NODES_TABLE, -1, $cond)) {
			while($fields = $db->fetchArray($result_array)) {
				$menu_id      = $fields['menu_id'];
				$page_id      = $fields['page_id'];
				$parent_id    = $fields['parent_node_id'];
				$index        = $fields['index'];
				$deleted      = $fields['deleted'];
				
				if(!is_object($page = &$this->pagesManager->getPage($page_id, false, false, true, $langId))) {
					// page does not exist or has been deleted : remove the associated MenuNode
					$this->removeMenuNode($node_id);
					$result = false;
				}
        else {

  				if(!is_object($menu = &$this->menusManager->getMenu($menu_id))) {
  					// no associated menu : error
  					$this->debug('MenuNodesManager::loadMenuNode, error : unable to load associated menu # '.$menuId, 2);
  					$result = false;
  				}
  				else {

    				$acl = &$page->getPageAcl();

    				$sortingType  = $menu->getMenuSortingType();
    				$sortField    = $menu->getMenuSortField();
    				$sortOrder    = $menu->getMenuSortOrder();

    				$this->menuNodesTable[$node_id] = &new MenuNode($node_id, $page_id, $sortingType, $sortField, $sortOrder, $acl->getAclId());
    				$this->menuNodesTable[$node_id]->setMenuNodeMenuId($menu_id);
    				$this->menuNodesTable[$node_id]->setMenuNodePage($page);
    				$this->menuNodesTable[$node_id]->setMenuNodeAcl($acl);
    				$this->menuNodesTable[$node_id]->setMenuNodeParentNodeId($parent_id);
    				$this->menuNodesTable[$node_id]->setMenuNodeIndex($index);
    				$this->menuNodesTable[$node_id]->setMenuNodeDeleted($deleted);

            // get child nodes
            $node_count = 0;
        		if($result_array = $db->getRecord(MENU_NODES_TABLE, -1, "`parent_node_id` = '$node_id'", 'id', 'index')) {
              while($row = $db->fetchArray($result_array)) {
                $node = &$this->getMenuNode($row['id']);
                $this->menuNodesTable[$node_id]->addNode($node);
                ++$node_count;
              }
            }

            // check nodes/pages coherence
    				if($node_count < $this->pagesManager->countSubPages($page->getPageId())) {
              $index = $node_count;
    					$pagesList = &$this->pagesManager->getSubPagesList($page->getPageId());
    					foreach($pagesList as $subPageId) {
    						if(!$this->pageIdInSubNodes($node_id, $subPageId)) {
    							if(is_object($subPage = &$this->pagesManager->getPage($subPageId, false, false, true, $langId))) {
                    ++$index;
    								$acl = &$subPage->getPageAcl();
    								$newMenuNode = &new MenuNode(0, $subPageId, $sortingType, $sortField, $sortOrder, $acl->getAclId());
    								$newMenuNode->setMenuNodePage($subPage);
    								$newMenuNode->setMenuNodeAcl($acl);
    								$newMenuNode->setMenuNodeMenuId($menu_id);
    								$newMenuNode->setMenuNodeIndex($index);
                    $newMenuNode->setMenuNodeDeleted(0);
                    $newMenuNode->setMenuNodeParentNodeId($node_id);
    								$this->setMenuNode($newMenuNode);
    								$newId = $this->storeMenuNode(0);
    								$this->menuNodesTable[$node_id]->addNode($newMenuNode);
    								unset($subPage);
    							}
    						}
    					}
    				}
          }
        }
			}
		}
    $this->debug('MenuNodesManager::loadMenuNode, status : function completed', 10, DBG_CLOSE);
		return $result;
 	}

	/**
	 * Loads MenuNode's Nodes
	 *
	 * @param  integer $menuNodeId MenuNode Id
	 * @return boolean
	 */
	function pageIdInSubNodes($nodeId, $pageId) {
		$node = &$this->menuNodesTable[$nodeId];
		foreach($node->nodesTable as $subNode) {
			if($subNode->getMenuNodePageId() == $pageId) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Stores MenuNode
	 *
	 * @param  integer $menuNodeId
	 * @return integer menuNode ID or <0 if error
	 */
  function storeMenuNode($menuNodeId) {
    $this->debug('MenuNodesManager::storeMenuNode, status : function invoked ('.$menuNodeId.')', 10, DBG_OPEN);
    $result = -1;
    
		if (is_null($menuNode = &$this->getMenuNode($menuNodeId))) {
      trigger_error('MenuNodesManager::storeMenuNode, error : node ('.$menuNodeId.') not in manager', E_USER_ERROR);
			$menuNodeId = -1;
		}
    else {
  		$fieldsArray = array(
  			'menu_id'        => $menuNode->getMenuNodeMenuId(),
  			'page_id'        => $menuNode->getMenuNodePageId(),
  			'parent_node_id' => $menuNode->getMenuNodeParentNodeId(),
  			'index'          => $menuNode->getMenuNodeIndex(),
  			'deleted'        => $menuNode->getMenuNodeDeleted()
  		);

  		// new menuNode
  		if ($menuNodeId == 0) {
  			if (!$this->dbManipulator->addRecord(MENU_NODES_TABLE, $fieldsArray)) {
  				$this->debug('MenuNodesManager::storeMenuNode, error : unable to create new menuNode', 1);
  			}
  			else {
    			$new_id = $this->dbManipulator->getLastId();
    			$menuNode->setMenuNodeId($new_id);
    			$this->setMenuNode($menuNode);
    			// free the temporary menuNode entry (0)
    			unset($this->menuNodesTable[0]);
    			$this->menuNodesTable[0] = null;

   				$result = $new_id;
        }
  		}
  		else {
  			if (!$this->dbManipulator->setRecord(MENU_NODES_TABLE, $menuNodeId, $fieldsArray)) {
  				$this->debug('MenuNodesManager::storeMenuNode, error : unable to update menuNode ('.$menuNodeId.')', 1);
  			}
  			$subNodesTable = &$menuNode->getNodesTable();
  			for($i = 0; $i < count($subNodesTable); ++$i) {
  			 $subNodeId = $subNodesTable[$i]->getMenuNodeId();
  			 $this->storeMenuNode($subNodeId);
  			}
  		}
    }
    $this->debug('MenuNodesManager::storeMenuNode, status : function completed', 10, DBG_CLOSE);
		return $result;
	}

	/**
	 * Removes MenuNode
	 *
	 * @param  integer $menuNodeId
	 * @return boolean
	 */
  function removeMenuNode($menuNodeId) {
		$db = &$this->getDBManipulator();
		if($db->delRecord(MENU_NODES_TABLE, $menuNodeId) && $db->delRecord(MENU_NODES_NODES_TABLE, $menuNodeId, '', 'parent_node_id')){
			if($this->checkMenuNode($menuNodeId)) {
				unset($this->menuNodesTable[$menuNodeId]);
			}
			return true;
		}
		return false;
  }

  function checkMenuNode($menuNodeId) {
  	return isset($this->menuNodesTable[$menuNodeId]);
  }

	/**
	 * Tells if a menuNode is present in the database
	 *
	 * @param  integer $menuNodeId
	 * @return boolean
	 */
	function menuNodeExists($menuNodeId) {
		// try to load the menuNode
		$this->getMenuNode($menuNodeId);
		// returns true if the menuNode exists
		return $this->checkMenuNode($menuNodeId);
	}

 	/**
	 * Gets MenuNode From a Menu
	 *
 	 * @param  integer $menuNodeId
 	 * @return mixed object or null
	 */
	function &getRootMenuNode($menu_id, $root_page_id){
    $this->debug('MenuNodesManager::getRootMenuNode, status : function invoked ('.$menu_id.', '.$root_page_id.')', 10, DBG_OPEN);
    $node = null;
		$dbManipulator = &$this->getDBManipulator();

		$result = $dbManipulator->sendQuery("SELECT `id` from `".MENU_NODES_TABLE."` where `menu_id` = '$menu_id' and `page_id` = '$root_page_id';");

		if(!($row = $dbManipulator->fetchArray($result)) || !isset($row['id'])) {
			$this->debug('MenuNodesManager::getMenuNodeFromMenu, warning : unable to get menuNode for menu ('.$menu_id.') with root page ('.$root_page_id.')', 3);
		}
		else {
			$node_id = $row['id'];
			$node = &$this->getMenuNode($node_id);
		}
    $this->debug('MenuNodesManager::getRootMenuNode, status : function completed', 10, DBG_CLOSE);
  	return $node;
	}

 	/**
	 * Gets MenuNode
	 *
 	 * @param  integer $menuNodeId
 	 * @return mixed object or null
	 */
	function &getMenuNode($menu_node_id){
    $this->debug('MenuNodesManager::getMenuNode, status : function invoked ('.$menu_node_id.')', 10, DBG_OPEN);
    $node = null;
  	if (!$this->checkMenuNode($menu_node_id)){
			if (!$this->loadMenuNode($menu_node_id)){
				$this->debug('MenuNodesManager::getMenuNode, error : unable to get menuNode ('.$menu_node_id.')', 3);
			}
			else {
        $node = &$this->menuNodesTable[$menu_node_id];
			}
		}
		else {
      $node = &$this->menuNodesTable[$menu_node_id];
		}
    $this->debug('MenuNodesManager::getMenuNode, status : function completed', 10, DBG_CLOSE);
  	return $node;
	}

	/**
	 * Sets MenuNode into manager
	 *
	 * @param  object $menuNode
	 * @return boolean
	 */
	function setMenuNode(&$menuNode) {
		$menuNodeId = $menuNode->getMenuNodeId();
		$this->menuNodesTable[$menuNodeId] = &$menuNode;
		$this->debug('MenuNodesManager::setMenuNode, succes : menuNode #'.$menuNodeId.' set', 9);
		return true;
	}

	/**
	 * Gets New MenuNode
	 *
	 * Returns a new Container object
	 *
	 * @return object
	 */
	function &getNewMenuNode($aclId=1) {
		$id          = 0;
		$page_id     = 0;
		$sortingType = SORTING_BY_LIST;
		$sortField 	 = '';
		$sortOrder 	 = SORT_ASCENDING;

		$this->menuNodesTable[0] = &new MenuNode($id, $pageId, $sortingType, $sortField, $sortOrder, $aclId);
    $this->menuNodesTable[0]->setMenuNodeIndex(1);
    $this->menuNodesTable[0]->setMenuNodeDeleted(0);
		return $this->menuNodesTable[0];
	}
}
?>