]> git.mxchange.org Git - shipsimu.git/blob - application/selector/class_ApplicationSelector.php
code comments including license information added, type hints added, minor rewrites...
[shipsimu.git] / application / selector / class_ApplicationSelector.php
1 <?php
2 /**
3  * The application selector class.
4  *
5  * Please remember that this include file is being loaded *before* the class
6  * loader is loading classes from "exceptions", "interfaces" and "main"!
7  *
8  * @todo                Extend a later BaseFrameworkApplication class
9  * @author              Roland Haeder <webmaster@ship-simu.org>
10  * @version             0.0.0
11  * @copyright   Copyright(c) 2007, 2008 Roland Haeder, this is free software
12  * @license             GNU GPL 3.0 or any newer version
13  * @link                http://www.ship-simu.org
14  *
15  * This program is free software: you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation, either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27  */
28 class ApplicationSelector extends BaseFrameworkSystem {
29         /**
30          * An ArrayObject for all found applications
31          */
32         private $foundApps = null;
33
34         /**
35          * An array object for all loaded application templates (selector_app-name.tpl)
36          */
37         private $loadedTemplates = null;
38
39         /**
40          * The application selector's own template engine handler
41          */
42         private $selectorTplEngine = null;
43
44         /**
45          * A list of items we shall ignore while reading from directories
46          */
47         private $dirIgnoreList = array(
48                 ".",
49                 "..",
50                 ".htaccess"
51         );
52
53         /**
54          * The language instance for the template loader
55          */
56         private $langInstance = null;
57
58         /**
59          * The file I/O instance for the template loader
60          */
61         private $fileIOInstance = null;
62
63         /**
64          * The private constructor. No direct instances can be created from this.
65          *
66          * @return      void
67          */
68         private function __construct() {
69                 // Call parent constructor
70                 parent::constructor(__CLASS__);
71
72                 // Set description
73                 $this->setPartDescr("Applikationswechsler");
74
75                 // Create unique ID number
76                 $this->createUniqueID();
77
78                 // Remove system array and thousand seperator
79                 $this->removeSystemArray();
80                 $this->removeNumberFormaters();
81
82                 // Initialize the array lists
83                 $this->initializeAppsList();
84                 $this->initializeTemplatesList();
85         }
86
87         /**
88          * Create a prepared instance of ApplicationSelector
89          *
90          * @param               $langInstance           The language sub-system: LanguageSystem
91          * @param               $fileIOInstance The file I/O instance
92          * @return              $selInstance            An instance of ApplicationSelector
93          */
94         public static function createApplicationSelector (ManageableLanguage $langInstance, FileIOHandler $fileIOInstance) {
95                 // Get a new instance
96                 $selInstance = new ApplicationSelector();
97
98                 // Get all applications
99                 $selInstance->readApplicationDirectory();
100
101                 // Set language and file I/O instances
102                 $selInstance->setLanguageInstance($langInstance);
103                 $selInstance->setFileIOInstance($fileIOInstance);
104
105                 // Return the prepared instance
106                 return $selInstance;
107         }
108
109         /**
110          * Initialize the application list
111          *
112          * @return      void
113          */
114         private function initializeAppsList () {
115                 $this->foundApps = new FrameworkArrayObject();
116         }
117
118         /**
119          * Initialize the loaded templates list
120          *
121          * @return      void
122          */
123         private function initializeTemplatesList () {
124                 $this->loadedTemplates = new FrameworkArrayObject();
125         }
126
127         /**
128          * Private getter for language instance
129          *
130          * @return      $langInstance   An instance to the language sub-system
131          */
132         private function getLanguageInstance () {
133                 return $this->langInstance;
134         }
135
136         /**
137          * Private getter for file IO instance
138          *
139          * @return      $fileIOInstance An instance to the file I/O sub-system
140          */
141         private function getFileIOInstance () {
142                 return $this->fileIOInstance;
143         }
144
145         /**
146          * Prepare the template engine (TemplateEngine by default) for a give
147          * application helper instance (ApplicationHelper by default).
148          *
149          * @param               $appInstance    An application helper instance
150          * @return              $tplEngine      The template engine instance
151          * @throws              NullPointerException    If the template engine could not
152          *                                                                              be initialized
153          * @throws              NoObjectException               If $tplEngine is not an object
154          * @throws              MissingMethodException  If $tplEngine misses a required
155          *                                                                              method 'loadWebTemplate()'
156          */
157         private function prepareTemplateEngine (BaseFrameworkSystem $appInstance) {
158                 // Generate FQFN for all application templates
159                 $fqfn = sprintf("%s%s/%s/%s",
160                         PATH,
161                         $this->getConfigInstance()->readConfig("application_path"),
162                         strtolower($appInstance->getAppShortName()),
163                         $this->getConfigInstance()->readConfig("tpl_base_path")
164                 );
165
166                 // Initialize the template engine
167                 $tplEngine = null;
168                 $eval = sprintf("\$tplEngine = %s::create%s(
169         \"%s\",
170         \$this->getLanguageInstance(),
171         \$this->getFileIOInstance()
172 );",
173                         $this->getConfigInstance()->readConfig("tpl_engine"),
174                         $this->getConfigInstance()->readConfig("tpl_engine"),
175                         $fqfn
176                 );
177
178                 // Debug message
179                 if ((!is_null($this->getDebugInstance())) && (defined('DEBUG_EVAL'))) {
180                         $this->getDebugInstance()->output(sprintf("[%s:] Konstruierte PHP-Anweisung: <pre><em>%s</em></pre><br />\n",
181                                 $this->__toString(),
182                                 htmlentities($eval)
183                         ));
184                 }
185
186                 // Run the command
187                 @eval($eval);
188
189                 // Is it a valid instance?
190                 if (is_null($tplEngine)) {
191                         // No class returned
192                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
193                 } elseif (!is_object($tplEngine)) {
194                         // Not an object! ;-(
195                         throw new NoObjectException($tplEngine, self::EXCEPTION_IS_NO_OBJECT);
196                 } elseif (!method_exists($tplEngine, 'loadWebTemplate')) {
197                         // Nope, so throw exception
198                         throw new MissingMethodException(array($tplEngine, 'loadWebTemplate'), self::EXCEPTION_MISSING_METHOD);
199                 }
200
201                 // Return the prepared instance
202                 return $tplEngine;
203         }
204
205         /**
206          * Load the init.php script of an application and append the application
207          * instance to $foundApps
208          *
209          * @param               $initScript     The FQFN of init.php
210          * @param               $appName                The application's Uni* name
211          * @return      void
212          * @throws      AppVarIsNotSetException If 'app' is not set
213          * @throws      NullPointerException    If 'app' is null
214          * @throws      NoObjectException               If 'app' is not an object
215          * @throws      MissingMethodException  If a required method is missing
216          */
217         private function loadInitScript ($initScript, $appName) {
218                 // Is it a file and readable?
219                 if ((is_file($initScript)) && (is_readable($initScript))) {
220                         // Then include it
221                         include ($initScript);
222
223                         // We now should have $app re-defined!
224                         if (!isset($app)) {
225                                 // This application shall not be loaded
226                                 return;
227                         } elseif (is_null($app)) {
228                                 // The class instance is null
229                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
230                         } elseif (!is_object($app)) {
231                                 // Not an object
232                                 throw new NoObjectException($app, self::EXCEPTION_IS_NO_OBJECT);
233                         } elseif (!method_exists($app, $this->getConfigInstance()->readConfig("entry_method"))) {
234                                 // Method not found!
235                                 throw new MissingMethodException(array($app, $this->getConfigInstance()->readConfig("entry_method")), self::EXCEPTION_MISSING_METHOD);
236                         }
237
238                         // Add the current instance to the list
239                         $this->foundApps->append($app);
240
241                 } // END - if ((is_file(...
242         }
243
244         /**
245          * Setter for the selector's template engine instance
246          *
247          * @param               $tplEngine      An instance of TemplateEngine
248          */
249         private function setSelectorTemplateEngine (CompileableTemplate $tplEngine) {
250                 $this->selectorTplEngine = $tplEngine;
251         }
252
253         /**
254          * Getter for the selector's template engine instance
255          *
256          * @return      $selectTplEngine        The selector's template engine
257          */
258         private function getSelectorTemplateEngine () {
259                 return $this->selectorTplEngine;
260         }
261
262         /**
263          * Getter for the $loadedTemplates array object
264          *
265          * @return      $loadedTemplates        An array object holding all loaded
266          *                                                      application templates
267          */
268         private function getLoadedTemplates () {
269                 return $this->loadedTemplates;
270         }
271
272         /**
273          * Method for compatiblity with prepareTemplateEngine()
274          *
275          * @return      $shortName      This selector's short name
276          */
277         private function getAppShortName() {
278                 $shortName = $this->getConfigInstance()->readConfig("selector_path");
279                 return $shortName;
280         }
281
282         /**
283          * Add a directory/file to the ignore list
284          *
285          * @param               $ignoreItem     The file/directory we shall ignore
286          * @return      void
287          */
288         public function addDirIgnoreList ($ignoreItem) {
289                 // Cast and add it
290                 $ignoreItem = (string) $ignoreItem;
291                 $this->dirIgnoreList[] = $ignoreItem;
292         }
293
294         /**
295          * Setter for language instance
296          *
297          * @param               $langInstance   An instance to the language sub-system
298          * @return      void
299          * @see         LanguageSystem
300          */
301         public final function setLanguageInstance (ManageableLanguage $langInstance) {
302                 $this->langInstance = $langInstance;
303         }
304
305         /**
306          * Setter for file I/O instance
307          *
308          * @param               $fileIOInstance An instance to the file I/O sub-system
309          * @return      void
310          */
311         public final function setFileIOInstance (FileIOHandler $fileIOInstance) {
312                 $this->fileIOInstance = $fileIOInstance;
313         }
314
315         /**
316          * Read the base path for all applications (application/) and create a
317          * list of all found applications
318          *
319          * @return      void
320          */
321         public function readApplicationDirectory () {
322                 // Generate the base path for all applications
323                 $appBasePath = sprintf("%s%s/",
324                         PATH,
325                         $this->getConfigInstance()->readConfig("application_path")
326                 );
327
328                 // Add the selector path to the ignore list
329                 $this->addDirIgnoreList($this->getConfigInstance()->readConfig("selector_path"));
330
331                 // Get a directory pointer for the application path
332                 $dirInstance = FrameworkDirectoryPointer::createFrameworkDirectoryPointer($appBasePath);
333
334                 // Backup and remove the 'app' from global name space
335                 /*$appBackup = $app;
336                 unset($app);*/
337
338                 // Read all directories&files except some parts
339                 while ($appName = $dirInstance->readDirectoryExcept($this->dirIgnoreList)) {
340                         // Generate FQFN for the application name (or better directory name)
341                         $fqfn = sprintf("%s%s", $appBasePath, $appName);
342
343                         // Is this a readable directory? (files will be ignored silently)
344                         if ((is_dir($fqfn)) && (is_readable($fqfn))) {
345                                 // Then get the init.php script for analyzing
346                                 $initScript = sprintf("%s/init%s", $fqfn, $this->getConfigInstance()->readConfig("php_extension"));
347
348                                 // Load the application's init.php script and append the
349                                 // application to the ArrayObject
350                                 $this->loadInitScript($initScript, $appName);
351
352                         } // END - if ((is_dir(...
353
354                 } // END - while
355
356                 // Close directory pointer
357                 $dirInstance->closeDirectory();
358
359                 // Restore old 'app' from backup
360                 //$app = $appBackup;
361         }
362
363         /**
364          * Load all templates for found applications in previous scan
365          *
366          * @return      void
367          */
368         public function loadApplicationTemplates () {
369                 // Iterate through all applications
370                 for ($idx = $this->foundApps->getIterator(); $idx->valid(); $idx->next()) {
371                         // Get current application
372                         $appInstance = $idx->current();
373
374                         // Prepare the template engine for the current template
375                         $tplEngine = $this->prepareTemplateEngine($appInstance);
376
377                         // Try to load the web template
378                         $tplEngine->loadWebTemplate(sprintf("%s_%s",
379                                 $this->getConfigInstance()->readConfig("tpl_selector_prefix"),
380                                 strtolower($appInstance->getAppShortName())
381                         ));
382
383                         // Remember this template and the application for later usage
384                         $this->loadedTemplates->append(array(
385                                 'tpl_engine'   => $tplEngine,
386                                 'app_instance' => $appInstance
387                         ));
388                 }
389
390                 // Re-initialize the application list to avoid double loading
391                 $this->initializeAppsList();
392         }
393
394         /**
395          * Removes $dirIgnoreList from the object to save some memory
396          *
397          * @return      void
398          */
399         public function removeDirIgnoreList () {
400                 unset($this->dirIgnoreList);
401         }
402
403         /**
404          * Loads the selector's own main template. This step is not linking the
405          * application's templates into the main one.
406          *
407          * @return      void
408          */
409         public function loadSelectorTemplate () {
410                 // Prepare the template engine
411                 $tplEngine = $this->prepareTemplateEngine($this);
412
413                 // Load the selector's template
414                 $tplEngine->loadCodeTemplate($this->getConfigInstance()->readConfig("selector_main_tpl"));
415
416                 // Now store it in the class
417                 $this->setSelectorTemplateEngine($tplEngine);
418         }
419
420         /**
421          * Inserts all loaded application templates into the selector's template
422          *
423          * @return      void
424          * @throws      NullPointerException            If $curr is null
425          * @throws      NoArrayException                        If $curr is not an array
426          * @throws      InvalidArrayCountException      If $curr contains an
427          *                                                                      unexpected count of elements
428          * @throws      MissingArrayElementsException   If $curr is missing expected
429          *                                                                      array elements
430          */
431         public function insertApplicationTemplates () {
432                 // First prepare the instance
433                 $tplEngine = $this->prepareTemplateEngine($this);
434
435                 // Load template which shall later hold all application templates
436                 $tplEngine->loadCodeTemplate($this->getConfigInstance()->readConfig("selector_apps_tpl"));
437
438                 // Add all loaded application templates together
439                 $dummy = "";
440                 for ($idx = $this->getLoadedTemplates()->getIterator(); $idx->valid(); $idx->next()) {
441                         // Get current item from array object
442                         $curr = $idx->current();
443
444                         // Do some sanity checks on the loaded item
445                         if (is_null($curr)) {
446                                 // $curr is null
447                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
448                         } elseif (!is_array($curr)) {
449                                 // Not an array
450                                 throw new NoArrayException($curr, self::EXCEPTION_IS_NO_ARRAY);
451                         } elseif (count($curr) != 2) {
452                                 // Not expected count of entries
453                                 throw new InvalidArrayCountException(array($this, "curr", count($curr), 2), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
454                         } elseif (!isset($curr['tpl_engine']) || (!isset($curr['app_instance']))) {
455                                 // Expected entries missing
456                                 throw new MissingArrayElementsException(array($this, "curr", array('tpl_engine', 'app_instance')), self::EXCEPTION_ARRAY_ELEMENTS_MISSING);
457                         }
458                         die("<pre>".print_r($curr, true)."</pre>");
459
460                 } // END - for
461         }
462
463         /**
464          * Stub!
465          */
466         public function saveObjectToDatabase () {
467                 $this->getDebugInstance()->output(sprintf("[%s:] Stub <strong>%s</strong> erreicht.",
468                         $this->__toString(),
469                         __FUNCTION__
470                 ));
471         }
472 }
473
474 // [EOF]
475 ?>