3 * A Menu template engine class
5 * @author Roland Haeder <webmaster@ship-simu.org>
7 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 Core Developer Team
8 * @license GNU GPL 3.0 or any newer version
9 * @link http://www.ship-simu.org
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 class MenuTemplateEngine extends BaseTemplateEngine implements CompileableTemplate {
26 * Main nodes in the XML tree ('menu' is ignored)
28 private $mainNodes = array(
35 * Sub nodes in the XML tree
37 private $subNodes = array(
49 private $menuInstance = null;
54 private $currMainNode = '';
57 * Protected constructor
61 protected function __construct () {
62 // Call parent constructor
63 parent::__construct(__CLASS__);
67 * Creates an instance of the class TemplateEngine and prepares it for usage
69 * @param $appInstance A manageable application
70 * @param $menuInstance A RenderableMenu instance
71 * @return $tplInstance An instance of TemplateEngine
72 * @throws BasePathIsEmptyException If the provided $templateBasePath is empty
73 * @throws InvalidBasePathStringException If $templateBasePath is no string
74 * @throws BasePathIsNoDirectoryException If $templateBasePath is no
75 * directory or not found
76 * @throws BasePathReadProtectedException If $templateBasePath is
79 public final static function createMenuTemplateEngine (ManageableApplication $appInstance, RenderableMenu $menuInstance) {
81 $tplInstance = new MenuTemplateEngine();
83 // Get language and file I/O instances from application
84 $langInstance = $appInstance->getLanguageInstance();
85 $ioInstance = $appInstance->getFileIoInstance();
87 // Determine base path
88 $templateBasePath = $tplInstance->getConfigInstance()->getConfigEntry('application_base_path') . $appInstance->getRequestInstance()->getRequestElement('app') . '/';
90 // Is the base path valid?
91 if (empty($templateBasePath)) {
93 throw new BasePathIsEmptyException($tplInstance, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
94 } elseif (!is_string($templateBasePath)) {
96 throw new InvalidBasePathStringException(array($tplInstance, $templateBasePath), self::EXCEPTION_INVALID_STRING);
97 } elseif (!is_dir($templateBasePath)) {
99 throw new BasePathIsNoDirectoryException(array($tplInstance, $templateBasePath), self::EXCEPTION_INVALID_PATH_NAME);
100 } elseif (!is_readable($templateBasePath)) {
102 throw new BasePathReadProtectedException(array($tplInstance, $templateBasePath), self::EXCEPTION_READ_PROTECED_PATH);
105 // Get configuration instance
106 $configInstance = FrameworkConfiguration::getInstance();
109 $tplInstance->setTemplateBasePath($templateBasePath);
111 // Set the language and IO instances
112 $tplInstance->setLanguageInstance($langInstance);
113 $tplInstance->setFileIoInstance($ioInstance);
115 // Set template extensions
116 $tplInstance->setRawTemplateExtension($configInstance->getConfigEntry('raw_template_extension'));
117 $tplInstance->setCodeTemplateExtension($configInstance->getConfigEntry('menu_template_extension'));
119 // Absolute output path for compiled templates
120 $tplInstance->setCompileOutputPath($configInstance->getConfigEntry('base_path') . $configInstance->getConfigEntry('compile_output_path'));
122 // Set the menu instance
123 $tplInstance->setMenuInstance($menuInstance);
125 // Return the prepared instance
130 * Load a specified menu template into the engine
132 * @param $template The menu template we shall load which is
133 * located in 'menu' by default
136 public function loadMenuTemplate ($template) {
138 $this->setTemplateType($this->getConfigInstance()->getConfigEntry('menu_template_type'));
140 // Load the special template
141 $this->loadTemplate($template);
145 * Getter for current main node
147 * @return $currMainNode Current main node
149 public final function getCurrMainNode () {
150 return $this->currMainNode;
154 * Getter for main node array
156 * @return $mainNodes Array with valid main node names
158 public final function getMainNodes () {
159 return $this->mainNodes;
163 * Getter for sub node array
165 * @return $subNodes Array with valid sub node names
167 public final function getSubNodes () {
168 return $this->subNodes;
172 * Handles the start element of an XML resource
174 * @param $resource XML parser resource (currently ignored)
175 * @param $element The element we shall handle
176 * @param $attributes All attributes
178 * @throws InvalidXmlNodeException If an unknown/invalid XML node name was found
180 public function startElement ($resource, $element, array $attributes) {
181 // Initial method name which will never be called...
182 $methodName = 'initMenu';
184 // Make the element name lower-case
185 $element = strtolower($element);
187 // Is the element a main node?
188 /* DEBUG: */ echo "START: >".$element."<<br />\n";
189 if (in_array($element, $this->getMainNodes())) {
190 // Okay, main node found!
191 $methodName = 'startMenu' . $this->convertToClassName($element);
194 $this->currMainNode = $element;
195 } elseif (in_array($element, $this->getSubNodes())) {
197 $methodName = 'setMenuProperty' . $this->convertToClassName($element);
198 } elseif ($element != 'menu') {
199 // Invalid node name found
200 throw new InvalidXmlNodeException(array($this, $element, $attributes), XmlParser::EXCEPTION_XML_NODE_UNKNOWN);
204 /* DEBUG: */ echo "call: ".$methodName."<br />\n";
205 call_user_func_array(array($this, $methodName), $attributes);
209 * Ends the main or sub node by sending out the gathered data
211 * @param $resource An XML resource pointer (currently ignored)
212 * @param $nodeName Name of the node we want to finish
214 * @throws XmlNodeMismatchException If current main node mismatches the closing one
216 public function endElement ($resource, $nodeName) {
217 // Make all lower-case
218 $nodeName = strtolower($nodeName);
220 // Does this match with current main node?
221 /* DEBUG: */ echo "END: >".$nodeName."<<br />\n";
222 if (($nodeName != $this->getCurrMainNode()) && (in_array($nodeName, $this->getMainNodes()))) {
224 throw new XmlNodeMismatchException (array($this, $nodeName, $this->getCurrMainNode()), XmlParser::EXCEPTION_XML_NODE_MISMATCH);
225 } elseif (in_array($nodeName, $this->getSubNodes())) {
226 // Silently ignore sub nodes
230 // Construct method name
231 $methodName = 'finish' . $this->convertToClassName($nodeName);
233 // Call the corresponding method
234 /* DEBUG: */ echo "call: ".$methodName."<br />\n";
235 call_user_func_array(array($this->getMenuInstance(), $methodName), array());
241 * @param $resource XML parser resource (currently ignored)
242 * @param $characters Characters to handle
244 * @todo Find something usefull with this!
246 public function characterHandler ($resource, $characters) {
247 // Trim all spaces away
248 $characters = trim($characters);
250 // Is this string empty?
251 if (empty($characters)) {
252 // Then skip it silently
257 $this->partialStub("Handling extra characters is not yet supported!");
261 * Intializes the menu
264 * @todo Add cache creation here
266 private function initMenu () {
268 $this->partialStub('Please implement this method.');
272 * Getter for menu cache file (FQFN)
274 * @return $fqfn Full-qualified file name of the menu cache
276 public function getMenuCacheFqfn () {
277 // Get the FQFN ready
278 $fqfn = sprintf("%s%s%s/%s.%s",
279 $this->getConfigInstance()->getConfigEntry('base_path'),
280 $this->getGenericBasePath(),
283 $this->getMenuInstance()->getMenuName() . ':' . $this->__toString() . ':' . $this->getMenuInstance()->__toString()
285 $this->getMenuInstance()->getMenuType()