Show:

File: platform/classes/Q/Mustache.php

<?php

/**
 * @module Q
 */
/**
 * This class lets you output render mustache templates
 * @class Q_Mustache
 */
class Q_Mustache {
	/**
	 * Render view using Mustache rendering engine
	 * @method render
	 * @static
	 * @param {string} $template
	 * @param {mixed} [$data=array()]
	 * @return {string} Rendered template
	 */
	static function render($template, $data = array()) {
		return self::mustache()->render($template, $data);
	}
	
	/**
	 * Render source using Mustache rendering engine
	 * @method render
	 * @static
	 * @param {string} $source
	 * @param {mixed} [$data=array()]
	 * @return {string} Rendered template
	 */
	static function renderSource($source, $data = array()) {
		return self::mustache()->loadSource($source)->render($data);
	}
	
	static function mustache()
	{
		if (isset(self::$mustache)) {
			return self::$mustache;
		}
		return self::$mustache = new Mustache_Engine(array(
			'cache' => APP_FILES_DIR.DS.'Q'.DS.'cache'.DS.'mustache',
			'loader' => new Q_Mustache_Loader(),
			'partials_loader' => new Q_Mustache_Loader('partials'),
			'escape' => function($value) {
				return htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
			}
		));
	}

	private static $mustache = null;
}

class Q_Mustache_Loader implements Mustache_Loader {
	/**
	 * Q_Mustache filesystem Loader constructor.
	 *
	 * Passing an $options array allows overriding certain Loader options during instantiation:
	 *
	 *	 $options = array(
	 *		 // The filename extension used for Mustache templates. Defaults to '.mustache'
	 *		 'extension' => '.ms',
	 *	 );
	 *
	 * @class Q_Mustache_Loader
	 * @private
	 * @constructor
	 * @param {string} [$xpath=''] Extra path to add to standard view path (for partials)
	 * @param {array} [$options=array()] Array of Loader options
	 */
	public function __construct($xpath = '', $options = array()) {
		if (!empty($xpath)) $xpath = DS.$xpath;
		// the last resourt is to search Qbix views
		if (file_exists(Q_VIEWS_DIR.$xpath)) {
			array_unshift(self::$loaders, new Mustache_Loader_FilesystemLoader(Q_VIEWS_DIR.$xpath, $options));
		}

		// search plugin views
		$plugins = Q_Config::get('Q', 'plugins', array());
		foreach ($plugins as $k => $v) {
			$plugin = is_numeric($k) ? $v : $k;
			$PLUGIN = strtoupper($plugin);
			if (file_exists(constant($PLUGIN.'_PLUGIN_VIEWS_DIR').$xpath)) {
				array_unshift(self::$loaders, new Mustache_Loader_FilesystemLoader(constant($PLUGIN.'_PLUGIN_VIEWS_DIR').$xpath, $options));
			}
		}

		// application views
		if (file_exists(APP_VIEWS_DIR.$xpath)) {
			array_unshift(self::$loaders, new Mustache_Loader_FilesystemLoader(APP_VIEWS_DIR.$xpath, $options));
		}
	}
	/**
	 * Load a Template by name.
	 * @method load
	 * @param {string} $name
	 * @return {string} Mustache Template source
	 */
	public function load($name) {
		if (!isset(self::$templates[$name])) {
			self::$templates[$name] = $this->loadFile($name);
		}
		return self::$templates[$name];
	}
	/**
	 * Helper function for loading a Mustache file by name.
	 * @method loadFile
	 * @protected
	 * @throws {Q_Exception_MissingFile} if a template file is not found.
	 * @param {string} $name
	 * @return {string} Mustache Template source
	 */
	protected function loadFile($name) {
		$tpl = null;
		foreach (self::$loaders as $loader) {
			try {
				$tpl = $loader->load($name);
				break;
			} catch (InvalidArgumentException $e) {}
		}
		if (!isset($tpl)) throw new Q_Exception_MissingFile(array('filename' => $name));
		return $tpl;
	}

	private static $loaders = array();
	private static $templates = array();
}