<?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 fusionLib
 * @copyright Copyright (c) 2011 - 2015 fusionLib. All rights reserved.
 * @link http://fusionlib.com
 */

 /**
  * flTemplateManager Class
  *
  * Class to manage template elements withing the database.
  *
  * @package fusionLib
  */
class flTemplateManager {

	/**
	 * Database to use.
	 *
	 * @var flDb
	 */
	private $db;

	/**
	 * Construct the manager object.
	 *
	 * @param flDb $db The database object.
	 */
	function __construct($db) {
		$this->db = $db;
	}

	/**
	 * Get the list of available themes.
	 *
	 * @param bool $manager true if querying for manager themes; else false.
	 * @return array Array of available theme names and descriptions.
	 */
	function getThemeList($manager = false) {
		$folders = glob(FLTHEMEPATH . '*', GLOB_ONLYDIR);
		$templates = array();
		foreach($folders as $path) {
			$path = basename($path);
			try {
				$tinfo = new flConfigIni(FLTHEMEPATH . "$path/$path.ini", $manager ? 'manager' : 'theme');
				if($name = $tinfo->get('name'))
					$templates[$path] = $name;
			} catch(flConfigException $e) {
			}
		}
		return $templates;
	}

	/**
	 * Get the theme information.
	 *
	 * @param string $themeName The name of the theme to query.
	 * @param bool $manager true for manager themes; else false.
	 * @return flConfig The config information.
	 */
	function getThemeInfo($themeName, $manager = false) {
		try {
			$tinfo = new flConfigIni(FLTHEMEPATH . "$themeName/$themeName.ini", $manager ? 'manager' : 'theme');
			if($tinfo->get('name'))
				return $tinfo;
		} catch(flConfigException $e) {
		}
		return null;
	}

	/**
	 * Get the list of custom fields used by a theme.
	 *
	 * @param string $themeName The name of the theme to query.
	 * @return array The config information.
	 */
	function getThemeFields($themeName) {
		$fields = array();
		$templates = array();
		try {
			$tinfo = new flConfigIni(FLTHEMEPATH . "$themeName/$themeName.ini", 'fields');
			foreach($tinfo as $template => $v) {
				if(is_array($v)) {
					foreach($v as $l) {
						$l = preg_split('/\s*,\s*/', $l, 3);
						if(count($l) == 3) {
							$templates[$template][] = $fields[$l[0]] = array(
								'name' => $l[0],
								'type' => $l[1],
								'caption' => $l[2]
							);
						}
						else if(count($l) == 1 && isset($fields[$l[0]]))
							$templates[$template][] = $fields[$l[0]];
					}
				}
			}
		} catch(flConfigException $e) {
		}

		return $templates;
	}

	/**
	 * Add a theme to the the database.
	 *
	 * @param string $name The name of the theme.
	 * @return int 0 if the theme was not added; else the theme ID.
	 */
	function addChildTheme($name) {
		if($this->db->insert('fl_themes', array('themename' => $name)))
			return $this->db->insertID();
		return 0;
	}

	/**
	 * Update a theme.
	 *
	 * @param int $id The id of the theme to update.
	 * @param string $name The new name of the theme.
	 * @return bool true if the theme was updated; else false.
	 */
	function updateChildTheme($id, $name) {
		return $this->db->update('fl_themes', array('themename' => $name), 'themeid=?', $id);
	}

	/**
	 * Delete a theme and all chunks associated with it.
	 *
	 * @param int $id The id of the theme to delete.
	 */
	function deleteChildTheme($id) {
		$this->db->delete('fl_themes', 'themeid=?', $id);
		$this->db->delete('fl_chunks', 'themeid=?', $id);
	}

	/**
	 * Get the list of child themes stored in the database by Id.
	 *
	 * @return array The available child themes.
	 */
	function getChildThemesByID() {
		$r = array();
		$result = $this->db->query('SELECT themeid,themename FROM fl_themes ORDER BY themename');
		while($row = $result->fetch())
			$r[$row['themeid']] = $row['themename'];
		return $r;
	}

	/**
	 * Get a list of all the themes available.
	 *
	 * @param string $theme The theme to get the child themes from.
	 * @return array The available themes.
	 */
	function getChildThemeList($theme = '') {
		$r = array();

		// Get child themes from theme
		if(!empty($theme)) {
			$info = $this->getThemeInfo($theme);
			if($info && isset($info->childtheme) && is_array($info->childtheme)) {
				foreach($info->childtheme as $themename)
					$r[$themename] = "$themename [$theme]";
			}
		}

		$result = $this->db->query('SELECT themename FROM fl_themes ORDER BY themename');
		while($row = $result->fetch())
			$r[$row['themename']] = $row['themename'];
		return $r;
	}

	/**
	 * Get the number of themes in the system.
	 *
	 * @return int The number of themes.
	 */
	function getChildThemeCount() {
		return $this->db->fetchOne('SELECT COUNT(*) FROM fl_themes');
	}

	/**
	 * Get the number of categories in the system.
	 *
	 * @return int The number of categories.
	 */
	function getCategoryCount() {
		return $this->db->fetchOne('SELECT COUNT(*) FROM fl_categories');
	}

	/**
	 * Add a category to the the database.
	 *
	 * @param string $name The name of the category.
	 * @return int 0 if the category was not added; else the theme ID.
	 */
	function addCategory($name) {
		if($this->db->insert('fl_categories', array('catname' => $name)))
			return $this->db->insertID();
		return 0;
	}

	/**
	 * Update a category.
	 *
	 * @param int $id The id of the category to update.
	 * @param string $name The new name of the category.
	 * @return bool true if the category was updated; else false.
	 */
	function updateCategory($id, $name) {
		return $this->db->update('fl_categories', array('catname' => $name), 'catid=?', $id);
	}

	/**
	 * Delete a category and set all items to not be in a category.
	 *
	 * @param int $id The ID of the category to delete.
	 * @return bool true if the category deleted.
	 */
	function deleteCategory($id) {
		$this->db->query('UPDATE fl_snippets SET catid=0 WHERE catid=?', $id);
		$this->db->query('UPDATE fl_chunks SET catid=0 WHERE catid=?', $id);
		return $this->db->delete('fl_categories', 'catid=?', $id);
	}

	/**
	 * Get a list of all categories.
	 *
	 * @return array Array of id => name pairs.
	 */
	function getCategories() {
		$r = array();
		$result = $this->db->query('SELECT catid,catname FROM fl_categories ORDER BY catname ASC');
		while($row = $result->fetch())
			$r[$row['catid']] = $row['catname'];
		return $r;
	}

	/**
	 * Count the number of elements in a category.
	 *
	 * @param int $id The category.
	 * @return int The number of elements in the category.
	 */
	function countInCategory($id) {
		return $this->db->fetchOne('SELECT COUNT(*) FROM fl_snippets WHERE catid=?', $id) + $this->db->fetchOne('SELECT COUNT(*) FROM fl_chunks WHERE catid=?', $id);
	}

	/**
	 * Create a chunk.
	 *
	 * @param string $name The name of the chunk.
	 * @param string $description The description of the chunk.
	 * @param string $content The content of the element.
	 * @param string $catId The category Id to add the chunk to.
	 * @param string $themeId The theme Id to add the chunk to.
	 * @param bool $isTemplate true if creating a template; else false.
	 * @return int ID of the new chunk; or false if failed.
	 */
	function createChunk($name, $description, $content, $catId, $themeId, $isTemplate) {
		if($this->db->insert('fl_chunks', array('chunkname' => $name, 'description' => $description, 'catid' => $catId, 'themeid' => $themeId ? $themeId : 0, 'content' => $content, 'istemplate' => $isTemplate ? '1' : '0')))
			return $this->db->insertID();
		return false;
	}

	/**
	 * Create a snippet.
	 *
	 * @param string $name The name of the snippet.
	 * @param string $description The description of the snippet.
	 * @param string $content The content of the snippet.
	 * @param string $catId The category to add the element to.
	 * @return int ID of the new snippet; or false if failed.
	 */
	function createSnippet($name, $description, $content, $catId) {
		if($this->db->insert('fl_snippets', array('snippetname' => $name, 'description' => $description, 'catid' => $catId, 'content' => preg_replace('/.*<\?php(.*)\?>.*$/s', '$1', $content))))
			return $this->db->insertID();
		return false;
	}

	/**
	 * Update a chunk.
	 *
	 * @param int $id ID of the chunk to update.
	 * @param string $name The name of the chunk.
	 * @param string $description The description of the chunk.
	 * @param string $content The content of the element.
	 * @param string $catId The category Id to add the chunk to.
	 * @param string $themeId The ID of the chunks theme.
	 * @return bool true if worked; else false.
	 */
	function updateChunk($id, $name, $description, $content, $catId, $themeId) {
		return $this->db->update('fl_chunks', array('chunkname' => $name, 'description' => $description, 'catid' => $catId, 'content' => $content, 'themeid' => $themeId), 'chunkid=?', $id);
	}

	/**
	 * Update a snippet.
	 *
	 * @param int $id The id of the snippet to update.
	 * @param string $name The name of the snippet.
	 * @param string $description The description of the snippet.
	 * @param string $content The content of the snippet.
	 * @param string $catId The category to add the element to.
	 * @return bool true if worked; else false.
	 */
	function updateSnippet($id, $name, $description, $content, $catId) {
		return $this->db->update('fl_snippets', array('snippetname' => $name, 'description' => $description, 'catid' => $catId, 'content' => preg_replace('/.*<\?php(.*)\?>.*$/s', '$1', $content)), 'snippetid=?', $id);
	}

	/**
	 * Delete a chunk.
	 *
	 * @param int $id The id of the chunk to delete.
	 */
	function deleteChunk($id = 0) {
		$this->db->delete('fl_chunks', 'chunkid=?', $id);
	}

	/**
	 * Delete a snippet.
	 *
	 * @param int $id The id of the snippet to delete.
	 * @return bool true if deleted; else false.
	 */
	function deleteSnippet($id) {
		return $this->db->delete('fl_snippets', 'snippetid=?', $id);
	}

	/**
	 * Get the data for a chunk.
	 *
	 * @param int $id The Id of the the chunk.
	 * @return array The chunk data.
	 */
	function getChunk($id) {
		return $this->db->fetchRow('SELECT chunkname,themeid,catid,description,content,istemplate FROM fl_chunks WHERE chunkid=?', $id);
	}
	/**
	 * Get the data for a snippet.
	 *
	 * @param int $id ID of the snippet to get.
	 * @return array Assosiative array of data or false if failed to read.
	 */
	function getSnippet($id) {
		return $this->db->fetchRow('SELECT snippetname,description,catid,content FROM fl_snippets WHERE snippetid=?', $id);
	}

	/**
	 * Get the list of chunks that are in a category for a specified theme.
	 *
	 * @param int $themeId The theme id.
	 * @param int $catId The category id.
	 * @param bool $templates true to get template chunks; else false
	 * @return array Array of chunks in the category for the theme.
	 */
	function getChunksInCat($themeId, $catId, $templates) {
		$r = array();
		$result = $this->db->query('SELECT chunkid,chunkname FROM fl_chunks WHERE themeid=? && catid=? && istemplate=? ORDER BY chunkname', $themeId, $catId, $templates ? 1 : 0);
		while($row = $result->fetch())
			$r[$row['chunkid']] = $row['chunkname'];
		return $r;
	}

	/**
	 * Get the list of templates.
	 *
	 * @param string $theme The name of the theme.
	 * @return array Array of template chunks.
	 */
	function getTemplateList($theme = '') {
		$r = array();

		// Get templates from theme
		if(!empty($theme)) {
			$info = $this->getThemeInfo($theme);
			if($info && isset($info->templates) && is_array($info->templates)) {
				foreach($info->templates as $chunk)
					$r[$chunk] = "$chunk [$theme]";
			}
		}

		$result = $this->db->query('SELECT chunkname FROM fl_chunks WHERE themeid=0 && istemplate=1 ORDER BY chunkname');
		while($row = $result->fetch())
			$r[$row['chunkname']] = $row['chunkname'];
		return $r;
	}

	/**
	 * Get the list of snippets that are in a category.
	 *
	 * @param int $catId The category id.
	 * @return array Array of snippets in the category.
	 */
	function getSnippetsInCat($catId) {
		$r = array();
		$result = $this->db->query('SELECT snippetid,snippetname FROM fl_snippets WHERE catid=? ORDER BY snippetname', $catId);
		while($row = $result->fetch())
			$r[$row['snippetid']] = $row['snippetname'];
		return $r;
	}

	/**
	 * Get the number of snippets in the system.
	 *
	 * @return int Number of snippets.
	 */
	function getSnippetCount() {
		return $this->db->fetchOne('SELECT COUNT(*) FROM fl_snippets');
	}

	/**
	 * Get the number of chunks in the system in a theme.
	 *
	 * @param int $themeId ID of the theme to count the chunks in.
	 * @param bool $templates true if counting template chunks; else false.
	 * @return int Number of chunks.
	 */
	function getChunkCount($themeId, $templates) {
		return $this->db->fetchOne('SELECT COUNT(*) FROM fl_chunks WHERE themeid=? && istemplate=?', $themeId, $templates ? 1: 0);
	}
}
