3 * An ??? template engine class for XML templates
5 * @author Roland Haeder <webmaster@ship-simu.org>
7 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2012 Core Developer Team
8 * @license GNU GPL 3.0 or any newer version
9 * @link http://www.ship-simu.org
10 * @todo This template engine does not make use of setTemplateType()
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 class XmlAnnouncementAnswerTemplateEngine extends BaseTemplateEngine implements CompileableTemplate, Registerable {
27 * Main nodes in the XML tree
29 private $mainNodes = array(
34 * Sub nodes in the XML tree
36 private $subNodes = array(
37 // These nodes don't contain any data
40 // Data from *this* node
46 // Data from other node
49 // Answer status (code)
56 private $curr = array();
59 * Protected constructor
63 protected function __construct () {
64 // Call parent constructor
65 parent::__construct(__CLASS__);
69 * Creates an instance of the class TemplateEngine and prepares it for usage
71 * @return $templateInstance 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 static final function createXmlAnnouncementAnswerTemplateEngine () {
81 $templateInstance = new XmlAnnouncementAnswerTemplateEngine();
83 // Get application instance from registry
84 $applicationInstance = Registry::getRegistry()->getInstance('app');
86 // Determine base path
87 $templateBasePath = $templateInstance->getConfigInstance()->getConfigEntry('application_base_path') . $applicationInstance->getRequestInstance()->getRequestElement('app') . '/';
89 // Is the base path valid?
90 if (empty($templateBasePath)) {
92 throw new BasePathIsEmptyException($templateInstance, self::EXCEPTION_UNEXPECTED_EMPTY_STRING);
93 } elseif (!is_string($templateBasePath)) {
95 throw new InvalidBasePathStringException(array($templateInstance, $templateBasePath), self::EXCEPTION_INVALID_STRING);
96 } elseif (!is_dir($templateBasePath)) {
98 throw new BasePathIsNoDirectoryException(array($templateInstance, $templateBasePath), self::EXCEPTION_INVALID_PATH_NAME);
99 } elseif (!is_readable($templateBasePath)) {
101 throw new BasePathReadProtectedException(array($templateInstance, $templateBasePath), self::EXCEPTION_READ_PROTECED_PATH);
105 $templateInstance->setTemplateBasePath($templateBasePath);
107 // Set template extensions
108 $templateInstance->setRawTemplateExtension($templateInstance->getConfigInstance()->getConfigEntry('raw_template_extension'));
109 $templateInstance->setCodeTemplateExtension($templateInstance->getConfigInstance()->getConfigEntry('node_answer_template_extension'));
111 // Absolute output path for compiled templates
112 $templateInstance->setCompileOutputPath($templateInstance->getConfigInstance()->getConfigEntry('base_path') . $templateInstance->getConfigInstance()->getConfigEntry('compile_output_path'));
114 // Init a variable stacker
115 $stackerInstance = ObjectFactory::createObjectByConfiguredName('node_announcement_answer_stacker_class');
118 $templateInstance->setStackerInstance($stackerInstance);
120 // Return the prepared instance
121 return $templateInstance;
125 * Load a specified announcement-answer template into the engine
127 * @param $template The announcement-answer template we shall load which is
128 * located in 'announcement_answer' by default
131 public function loadAnnouncementAnswerTemplate ($template = 'announcement_answer') {
133 $this->setTemplateType($this->getConfigInstance()->getConfigEntry('node_announcement_answer_template_type'));
135 // Load the special template
136 $this->loadTemplate($template);
140 * Getter for current main node
142 * @return $currMainNode Current main node
144 public final function getCurrMainNode () {
145 return $this->curr['main_node'];
149 * Setter for current main node
151 * @param $element Element name to set as current main node
152 * @return $currMainNode Current main node
154 private final function setCurrMainNode ($element) {
155 $this->curr['main_node'] = (string) $element;
159 * Getter for main node array
161 * @return $mainNodes Array with valid main node names
163 public final function getMainNodes () {
164 return $this->mainNodes;
168 * Getter for sub node array
170 * @return $subNodes Array with valid sub node names
172 public final function getSubNodes () {
173 return $this->subNodes;
177 * Handles the start element of an XML resource
179 * @param $resource XML parser resource (currently ignored)
180 * @param $element The element we shall handle
181 * @param $attributes All attributes
183 * @throws InvalidXmlNodeException If an unknown/invalid XML node name was found
185 public function startElement ($resource, $element, array $attributes) {
186 // Initial method name which will never be called...
187 $methodName = 'initAnnouncementAnswer';
189 // Make the element name lower-case
190 $element = strtolower($element);
192 // Is the element a main node?
193 //* DEBUG: */ echo "START: >".$element."<<br />\n";
194 if (in_array($element, $this->getMainNodes())) {
195 // Okay, main node found!
196 $methodName = 'start' . $this->convertToClassName($element);
199 $this->setCurrMainNode($element);
200 } elseif (in_array($element, $this->getSubNodes())) {
202 $methodName = 'start' . $this->convertToClassName($element);
204 // Invalid node name found
205 throw new InvalidXmlNodeException(array($this, $element, $attributes), XmlParser::EXCEPTION_XML_NODE_UNKNOWN);
209 call_user_func_array(array($this, $methodName), $attributes);
213 * Ends the main or sub node by sending out the gathered data
215 * @param $resource An XML resource pointer (currently ignored)
216 * @param $nodeName Name of the node we want to finish
218 * @throws XmlNodeMismatchException If current main node mismatches the closing one
220 public function endElement ($resource, $nodeName) {
221 // Make all lower-case
222 $nodeName = strtolower($nodeName);
224 // Does this match with current main node?
225 //* DEBUG: */ echo "END: >".$nodeName."<<br />\n";
226 if (($nodeName != $this->getCurrMainNode()) && (in_array($nodeName, $this->getMainNodes()))) {
228 throw new XmlNodeMismatchException (array($this, $nodeName, $this->getCurrMainNode()), XmlParser::EXCEPTION_XML_NODE_MISMATCH);
231 // Construct method name
232 $methodName = 'finish' . $this->convertToClassName($nodeName);
234 // Call the corresponding method
235 //* DEBUG: */ echo "call: ".$methodName."<br />\n";
236 call_user_func_array(array($this, $methodName), array());
242 * @param $resource XML parser resource (currently ignored)
243 * @param $characters Characters to handle
245 * @todo Find something useful with this!
247 public function characterHandler ($resource, $characters) {
248 // Trim all spaces away
249 $characters = trim($characters);
251 // Is this string empty?
252 if (empty($characters)) {
253 // Then skip it silently
258 * Assign the found characters to variable and use the last entry from
261 parent::assignVariable($this->getStackerInstance()->getNamed('announcement_answer'), $characters);
265 * Getter for cache file (FQFN)
267 * @return $fqfn Full-qualified file name of the menu cache
269 public function getAnnouncementAnswerCacheFqfn () {
270 $this->partialStub('Please implement this method.');
274 * Starts the announcement-answer
278 private function startAnnouncementAnswer () {
279 // Push the node name on the stacker
280 $this->getStackerInstance()->pushNamed('announcement_answer', 'announcement-answer');
284 * Starts the node-data
288 private function startNodeData () {
289 // Push the node name on the stacker
290 $this->getStackerInstance()->pushNamed('announcement_answer', 'node-data');
294 * Starts the node-external-ip
298 private function startNodeExternalIp () {
299 // Push the node name on the stacker
300 $this->getStackerInstance()->pushNamed('announcement_answer', 'node-external-ip');
304 * Starts the node-internal-ip
308 private function startNodeInternalIp () {
309 // Push the node name on the stacker
310 $this->getStackerInstance()->pushNamed('announcement_answer', 'node-internal-ip');
314 * Starts the node-tcp-port
318 private function startNodeTcpPort () {
319 // Push the node name on the stacker
320 $this->getStackerInstance()->pushNamed('announcement_answer', 'node-tcp-port');
324 * Starts the node-udp-port
328 private function startNodeUdpPort () {
329 // Push the node name on the stacker
330 $this->getStackerInstance()->pushNamed('announcement_answer', 'node-udp-port');
334 * Starts the node-session-id
338 private function startNodeSessionId () {
339 // Push the node name on the stacker
340 $this->getStackerInstance()->pushNamed('announcement_answer', 'node-session-id');
344 * Starts the node-status
348 private function startNodeStatus () {
349 // Push the node name on the stacker
350 $this->getStackerInstance()->pushNamed('announcement_answer', 'node-status');
354 * Finishes the node-status
358 private function finishNodeStatus () {
359 // Pop the last entry
360 $this->getStackerInstance()->popNamed('announcement_answer');
364 * Finishes the node-session-id
368 private function finishNodeSessionId () {
369 // Pop the last entry
370 $this->getStackerInstance()->popNamed('announcement_answer');
374 * Finishes the node-udp-port
378 private function finishNodeUdpPort () {
379 // Pop the last entry
380 $this->getStackerInstance()->popNamed('announcement_answer');
384 * Finishes the node-tcp-port
388 private function finishNodeTcpPort () {
389 // Pop the last entry
390 $this->getStackerInstance()->popNamed('announcement_answer');
394 * Finishes the node-internal-ip
398 private function finishNodeInternalIp () {
399 // Pop the last entry
400 $this->getStackerInstance()->popNamed('announcement_answer');
404 * Finishes the node-external-ip
408 private function finishNodeExternalIp () {
409 // Pop the last entry
410 $this->getStackerInstance()->popNamed('announcement_answer');
414 * Finishes the node-data
418 private function finishNodeData () {
419 // Pop the last entry
420 $this->getStackerInstance()->popNamed('announcement_answer');
424 * Starts the other-data
428 private function startOtherData () {
429 // Push the node name on the stacker
430 $this->getStackerInstance()->pushNamed('announcement_answer', 'other-data');
434 * Starts the other-external-ip
438 private function startOtherExternalIp () {
439 // Push the node name on the stacker
440 $this->getStackerInstance()->pushNamed('announcement_answer', 'other-external-ip');
444 * Starts the other-internal-ip
448 private function startOtherInternalIp () {
449 // Push the node name on the stacker
450 $this->getStackerInstance()->pushNamed('announcement_answer', 'other-internal-ip');
454 * Starts the other-session-id
458 private function startOtherSessionId () {
459 // Push the node name on the stacker
460 $this->getStackerInstance()->pushNamed('announcement_answer', 'other-session-id');
464 * Finishes the other-session-id
468 private function finishOtherSessionId () {
469 // Pop the last entry
470 $this->getStackerInstance()->popNamed('announcement_answer');
474 * Finishes the other-internal-ip
478 private function finishOtherInternalIp () {
479 // Pop the last entry
480 $this->getStackerInstance()->popNamed('announcement_answer');
484 * Finishes the other-external-ip
488 private function finishOtherExternalIp () {
489 // Pop the last entry
490 $this->getStackerInstance()->popNamed('announcement_answer');
494 * Finishes the other-data
498 private function finishOtherData () {
499 // Pop the last entry
500 $this->getStackerInstance()->popNamed('announcement_answer');
504 * Starts the answer-status
508 private function startAnswerStatus () {
509 // Push the node name on the stacker
510 $this->getStackerInstance()->pushNamed('announcement_answer', 'answer-status');
514 * Finishes the answer-status
518 private function finishAnswerStatus () {
519 // Pop the last entry
520 $this->getStackerInstance()->popNamed('announcement_answer');
524 * Finishes the announcement-answer
528 private function finishAnnouncementAnswer () {
529 // Pop the last entry
530 $this->getStackerInstance()->popNamed('announcement_answer');