<?php
/*
* @package LabCMS
* @copyright (c) 2006 Alexander Levin aka Loki (loki_angel@mail.ru)
* @support http://labcms.ru
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/

class admin_tree_module
{
	public function __construct()
	{
		$this->mapper=Factory::create('admin_tree.mapper');
	}
	
	public function getNodeById($id)
	{
		if (!is_numeric($id)) return null;

		$nodes = $this->getNodesByArrayId(array($id));

		if (isset($nodes[$id])) {
			return $nodes[$id];
		}
		return null;
	}
	
	public function getNodesByArrayId($id)
	{
		if ($data=$this->_getNodesByArrayId($id)) {
			foreach ($data as $node) {

			}
		}
		return $data;
	}
	
	public function getNodesByParentId($id)
	{
		$ids=$this->mapper->getIdsByParentId($id);
		if ($ids) return $this->getNodesByArrayId($ids);
		return array();
	}
	
	protected function _getNodesByArrayId($id)
	{
		if (!$id) return array();
		/*if (config::get('sys.cache.solid')) {
			return $this->GetBlogsByArrayIdSolid($id, $aOrder);
		}*/
		if (!is_array($id)) $id = array($id);
		$idNeedToGet = array_unique($id);
		$result = array();

		Factory::load('admin_tree.node_entity');

		$cacheKeys = build_cache_keys($idNeedToGet, 'node_');
		if (false !== ($data = TCache::get($cacheKeys))) {
			foreach ($cacheKeys as $id => $key) {
				if (array_key_exists($id, $data)) {
					if ($data[$id]) {
						$result[$data[$id]->id] = $data[$id];
					}
					unset($cacheKeys[$id]);
				}
			}
		}

		//если остались ключи без значений, то запрашиваем данные из хранилища
		if (count($cacheKeys) && $data = $this->mapper->getNodesByArrayId(array_keys($cacheKeys))) {
			foreach ($data as $node) {
				$result[$node->id] = $node;
				TCache::Set($node, "node_{$node->id}", array(), 60 * 60 * 24 * 7);
				unset($cacheKeys[$node->id]);
			}
		}

		//если и теперь остались ключи без результата, то сохраняем их в кэш пустыми
		if (count($cacheKeys)) {
			foreach ($cacheKeys as $id=>$key) {
				TCache::Set(null, $key, array(), 60 * 60 * 24 * 7);
			}
		}
		$result = array_sort_by_keys($result, $idNeedToGet);
		return $result;
	}
	
	public function add($node)
	{
		if ($id=$this->mapper->addNode($node)) {
			$node->id=$id;
			//TODO сброс кэша
			return $node;
		}
		return null;
	}
	
	public function delete()
	{
		echo 111;exit;
		$ids=$this->_getRecurseId($this->id);
		$ids[]=$this->id;
		Db::i()->query("DELETE FROM ?_includes WHERE tree_id IN (?a)", $ids);
		Db::i()->query("DELETE FROM ?_tree WHERE tree_id IN (?a)", $ids);
		$this->_resetItemCache();
	}
	
	function _getRecurseId($id, &$data=array())
	{
		$result=Db::i()->selectCol("SELECT tree_id FROM ?_tree WHERE parent_id=?", $id);
		foreach ($result as $tree_id) {
			$data[]=$tree_id;
			$this->_getRecurseId($tree_id, $data);
		}
		return $data;
	}

	
	public function getTree($parent_id=0, $level=0, $tree_arr=array())
	{
		$result=$this->getNodesByParentId($parent_id);
		if (count($result)) {
			foreach ($result as $node) {
				$node->level=$level;
				$tree_arr[]=$node;
				$tree_arr+=$this->getTree($node->id, $level+1, $tree_arr);
			}
			return $tree_arr;
		} else {
			return array();
		}
	}
	
	public function getSelectTree($current=null, $parent_id=0, $level=0)
	{
		$parent_select=array();
		$result=Db::i()->select("SELECT t.tree_id,  name  FROM ?_tree t  WHERE t.parent_id=? ORDER BY pos", $parent_id);
		if (count($result)) {
			foreach ($result as $tree) {
				if (is_numeric($current) && $tree['tree_id']==$current) continue;
				$parent_select[$tree['tree_id']]=str_repeat('&nbsp;', $level*3).$tree['name'];
				$parent_select+=$this->getSelectTree($current, $tree['tree_id'], $level+1);
			}
			
		}
		return $parent_select;
	}
	
	public function getModules($node)
	{
		//выбираем список модулей
		$result=Db::i()->select(
			"SELECT m.module_id, name, i.tree_id, component, `static`
			FROM ?_modules m
			LEFT JOIN ?_includes i ON m.module_id=i.module_id AND i.tree_id=?
			WHERE m.disable = 0 ORDER BY name", $node->id
		);

		foreach ($result as $module) {
			$modules_list[]=array(
				"id"=>$module['module_id'],
				"name"=>$module['name'],
				'checked'=>$module['tree_id']?1:0,
				'component'=>$module['component'],
				'static'=>$module['static']
			);
		}
		return $modules_list;
	}
	
	//получаем список страниц, имеющих одинаковый адрес
	public function getDuples()
	{
		$result=Db::i()->select(
			"SELECT t.path, t.tree_id, t.name
			FROM ?_tree t
			JOIN ?_tree t1
			ON t.path=t1.path AND t.tree_id!=t1.tree_id
			AND t.path!='' AND t1.symlink=0 AND t.symlink=0
			ORDER BY t.path, t1.tree_id"
		);
		$duples=array();
		if (count($result)) {
			foreach ($result as $tmp)
			$duples[$tmp['path']][]=array($tmp['tree_id'], $tmp['name']);
		}
		return $duples;
	}
	
	public function getAllNodes()
	{
		$ids=$this->mapper->getAllNodesId();
		return $this->getNodesByArrayId($ids);
	}
	
	public function sortMainTree($tree, $parent_id=0)
	{
		if (!isset($this->items)) $this->items=$this->getAllNodes();
		$pos=0;
		foreach ($tree as $key=>$item) {
			$key=str_replace('id', '', $key);
			if (is_object($item)) {
				$this->sortMainTree($item, $key);
			}
			$node=$this->items[$key];
			if ($node->parent_id!=$parent_id || $node->pos!=$pos) {
				$node->pos=$pos;
				$node->parent_id=$parent_id;
				$this->mapper->updateNode($node);
				unset($this->items[$key]);
			}
			$pos++;
		}
		//TODO сброс кэша
	}
	
	public function updateNode($node)
	{
		$this->mapper->updateNode($node);
	}
	
	public function validatePost()
	{
		if ($_SERVER['REQUEST_METHOD']!='POST') return;
		if (trim($_POST['name'])=='') return LabCMS::i()->error(_m('Название не может быть пустым'));
		return true;
	}
	
	protected function _updateModules($modules=array())
	{
		Db::i()->query("DELETE FROM ?_includes WHERE tree_id=?", $this->id);
		if (count($modules)) {
			foreach ($modules as $val) {
				Db::i()->query("INSERT INTO ?_includes (tree_id, module_id) VALUES(?, ?)", $this->id, $val);
			}
		}
	}
	
	public function getPostData()
	{
		$_POST['path']=trim($_POST['path']);
		if ($_POST['path'] && empty($_POST['external'])) {
			$_POST['path']=Url::filter($_POST['path']);
		}
		
		//если узел является ссылкой, то остальные данные удаляем
		if ($_POST['symlink']) {
            $_POST['params']=$_POST['path']=$_POST['external']='';
		}
		if (!isset($_POST['module'])) $_POST['module']='';
		
		return $_POST;
	}
}