<?php

/**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package clearFusionCMS
 * @copyright Copyright (c) 2012 - 2016 clearFusionCMS. All rights reserved.
 * @link http://clearfusioncms.com
 */

/**
 * cfContentTree Class
 *
 * Class to draw the tree for the content and allow selection of items.
 *
 * @package clearFusionCMS
 */
class cfContentTree {

	/**
	 * The module for the link.
	 *
	 * @var string
	 */
	protected $module;

	/**
	 * The action for the link.
	 *
	 * @var string
	 */
	protected $action;

	/**
	 * The router.
	 *
	 * @var flRouter
	 */
	protected $router;

	/**
	 * The active node.
	 *
	 * @var int
	 */
	protected $active;

	/**
	 * Flags if moving
	 *
	 * @var bool
	 */
	protected $move;

	/**
	 * The content object.
	 *
	 * @var cfContent
	 */
	protected $content;

	/**
	 * The tree.
	 *
	 * @var flWidgetTreeView
	 */
	protected $tree;

	/**
	 * Flags if the slug name should be used for the document title.
	 *
	 * @var bool
	 */
	protected $useSlugs;

	/**
	 * Construct the tree for the content.
	 *
	 * @param string $treeName The name of the tree.
	 * @param cfContent $content The content object.
	 * @param string $module The module name or null and $action null to insert the document id as the link #[[~1]].
	 * @param string $action The action name or null to insert the document id.
	 * @param int $active The ID of the active node.
	 * @param bool $move true if using tree to move a node; else false for navigation.
	 */
	function __construct($treeName, $content, $module, $action, $active, $move = false) {
		$this->module = $module;
		$this->action = $action;
		$this->router = clearFusionCMS::getRouter();
		$this->active = $active;
		$this->move = $move;
		$this->content = $content;
		$this->useSlugs = clearFusionCMS::getSiteConfig('cfSystemCtntEdit')->get('useSlugs', false);

		// Build the content tree
		$this->tree = new flWidgetTreeView($treeName);
		$t = $this->buildContentTree(0);
		$this->tree->addNode($t !== null ? $t : new flWidgetTreeLinkNode(__('Root', 'cfBackend'), $this->assemble(), flWidgetTreeNode::CONTAINER));
	}

	/**
	 * Assemble a manager URI.
	 *
	 * @param array $data Array of data to include.
	 * @return string The composed URI.
	 */
	protected function assemble($data = array()) {
		return $this->router->assemble('cfManager', array('module' => $this->module, 'action' => $this->action, '*' => $data));
	}

	/**
	 * Recursive function to build a tree of the content.
	 *
	 * @param int $id ID of the node to build the tree for.
	 * @return flWidgetTreeNode The tree.
	 */
	protected function buildContentTree($id) {
		if($this->move)
			$link = $this->active == $id ? null : $this->assemble(array('move', $this->active, $id));
		elseif($this->module === null && $this->action === null)
			$link = '#' . fusionLib::htmlChars("&#91;&#91;~$id&#93;&#93;");
		else
			$link = $this->assemble(array($id));

		$nodes = $this->content->getChildren($id, array('id', 'title', 'menutitle', 'restype', 'slug'));
		if(empty($nodes)) {
			if(!($d = $this->content->getNodeData($id, array('title', 'menutitle', 'restype', 'published', 'slug'))))
				return null;

			switch($d['restype']) {
				case 'link': $icon = flWidgetTreeNode::LINK; break;
				case 'static': $icon = flWidgetTreeNode::RESOURCE; break;
				case 'folder': $icon = flWidgetTreeNode::CONTAINER; break;
				case 'doc':
				default:
					$icon = flWidgetTreeNode::DOC;
			}

			if(!$d['published'])
				$icon .= ' unpublished';

			$title = ($this->useSlugs ? $d['slug'] : (empty($d['menutitle']) ? $d['title'] : $d['menutitle'])) . " [$id]";
			$node = $link === null ? new flWidgetTreeNode($title, $icon, $id) : new flWidgetTreeLinkNode($title, $link, $icon, $id);
		} else {
			$tree = new flWidgetTreeView();
			foreach($nodes as $node)
				$tree->addNode($this->buildContentTree($node['id']));

			if($id == 0) {
				$d['title'] = $d['slug'] = __('Root', 'cfBackend');
				$icon = flWidgetTreeNode::CONTAINEROPEN;
			} else {
				$d = $this->content->getNodeData($id, array('title', 'menutitle', 'slug', 'restype', 'published'));
				switch($d['restype']) {
					case 'link': $icon = flWidgetTreeNode::LINK; break;
					case 'static': $icon = flWidgetTreeNode::RESOURCE; break;
					case 'folder': $icon = flWidgetTreeNode::CONTAINER; break;
					case 'doc':
					default:
						$icon = flWidgetTreeNode::DOC;
				}

				if(!$d['published'])
					$icon .= ' unpublished';
			}
			$title = ($this->useSlugs ? $d['slug'] : (empty($d['menutitle']) ? $d['title'] : $d['menutitle'])) . " [$id]";
			$node = new flWidgetTreeChildNode($title, $tree, $id ? false : null, $link, $icon, $id);
		}

		if($id == $this->active)
			$node->setActive();

		return $node;
	}

	/**
	 * Render the tree.
	 *
	 * @param flBufferCode $buffer The code buffer object if any.
	 * @param bool $innerOnly true to render inner tree portion only; else false.
	 * @return string The HTML to render the tree.
	 */
	function render($buffer, $innerOnly = false) {
		return $this->tree->render($buffer, $innerOnly);
	}

	/**
	 * Set the address of the optional AJAX node move handler.
	 *
	 * @param string $handler The URI of the AJAX handler.
	 */
	function setAJAXMoveHandler($handler) {
		$this->tree->setAJAXMoveHandler($handler);
	}
}
