]> git.mxchange.org Git - shipsimu.git/blob - application/selector/class_ApplicationSelector.php
New exception introduced, minor parts rewritten
[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              UnsupportedTemplateEngineException      If $tplEngine is an
154          *                                                                              unsupported template engine
155          */
156         private function prepareTemplateEngine (BaseFrameworkSystem $appInstance) {
157                 // Generate FQFN for all application templates
158                 $fqfn = sprintf("%s%s/%s/%s",
159                         PATH,
160                         $this->getConfigInstance()->readConfig("application_path"),
161                         strtolower($appInstance->getAppShortName()),
162                         $this->getConfigInstance()->readConfig("tpl_base_path")
163                 );
164
165                 // Initialize the template engine
166                 $tplEngine = null;
167                 $eval = sprintf("\$tplEngine = %s::create%s(
168         \"%s\",
169         \$this->getLanguageInstance(),
170         \$this->getFileIOInstance()
171 );",
172                         $this->getConfigInstance()->readConfig("tpl_engine"),
173                         $this->getConfigInstance()->readConfig("tpl_engine"),
174                         $fqfn
175                 );
176
177                 // Debug message
178                 if ((!is_null($this->getDebugInstance())) && (defined('DEBUG_EVAL'))) {
179                         $this->getDebugInstance()->output(sprintf("[%s:] Konstruierte PHP-Anweisung: <pre><em>%s</em></pre><br />\n",
180                                 $this->__toString(),
181                                 htmlentities($eval)
182                         ));
183                 }
184
185                 // Run the command
186                 @eval($eval);
187
188                 // Is it a valid instance?
189                 if (is_null($tplEngine)) {
190                         // No class returned
191                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
192                 } elseif (!$tplEngine instanceof CompileableTemplate) {
193                         // Not an object! ;-(
194                         throw new UnsupportedTemplateEngineException($tplEngine, self::EXCEPTION_TEMPLATE_ENGINE_UNSUPPORTED);
195                 }
196
197                 // Return the prepared instance
198                 return $tplEngine;
199         }
200
201         /**
202          * Load the init.php script of an application and append the application
203          * instance to $foundApps
204          *
205          * @param               $initScript     The FQFN of init.php
206          * @param               $appName                The application's Uni* name
207          * @return      void
208          * @throws      AppVarIsNotSetException If 'app' is not set
209          * @throws      NullPointerException    If 'app' is null
210          * @throws      NoObjectException               If 'app' is not an object
211          * @throws      MissingMethodException  If a required method is missing
212          */
213         private function loadInitScript ($initScript, $appName) {
214                 // Is it a file and readable?
215                 if ((is_file($initScript)) && (is_readable($initScript))) {
216                         // Then include it
217                         include ($initScript);
218
219                         // We now should have $app re-defined!
220                         if (!isset($app)) {
221                                 // This application shall not be loaded
222                                 return;
223                         } elseif (is_null($app)) {
224                                 // The class instance is null
225                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
226                         } elseif (!is_object($app)) {
227                                 // Not an object
228                                 throw new NoObjectException($app, self::EXCEPTION_IS_NO_OBJECT);
229                         } elseif (!method_exists($app, $this->getConfigInstance()->readConfig("entry_method"))) {
230                                 // Method not found!
231                                 throw new MissingMethodException(array($app, $this->getConfigInstance()->readConfig("entry_method")), self::EXCEPTION_MISSING_METHOD);
232                         }
233
234                         // Add the current instance to the list
235                         $this->foundApps->append($app);
236
237                 } // END - if ((is_file(...
238         }
239
240         /**
241          * Setter for the selector's template engine instance
242          *
243          * @param               $tplEngine      An instance of TemplateEngine
244          */
245         private function setSelectorTemplateEngine (CompileableTemplate $tplEngine) {
246                 $this->selectorTplEngine = $tplEngine;
247         }
248
249         /**
250          * Getter for the selector's template engine instance
251          *
252          * @return      $selectTplEngine        The selector's template engine
253          */
254         private function getSelectorTemplateEngine () {
255                 return $this->selectorTplEngine;
256         }
257
258         /**
259          * Getter for the $loadedTemplates array object
260          *
261          * @return      $loadedTemplates        An array object holding all loaded
262          *                                                      application templates
263          */
264         private function getLoadedTemplates () {
265                 return $this->loadedTemplates;
266         }
267
268         /**
269          * Method for compatiblity with prepareTemplateEngine()
270          *
271          * @return      $shortName      This selector's short name
272          */
273         private function getAppShortName() {
274                 $shortName = $this->getConfigInstance()->readConfig("selector_path");
275                 return $shortName;
276         }
277
278         /**
279          * Add a directory/file to the ignore list
280          *
281          * @param               $ignoreItem     The file/directory we shall ignore
282          * @return      void
283          */
284         public function addDirIgnoreList ($ignoreItem) {
285                 // Cast and add it
286                 $ignoreItem = (string) $ignoreItem;
287                 $this->dirIgnoreList[] = $ignoreItem;
288         }
289
290         /**
291          * Setter for language instance
292          *
293          * @param               $langInstance   An instance to the language sub-system
294          * @return      void
295          * @see         LanguageSystem
296          */
297         public final function setLanguageInstance (ManageableLanguage $langInstance) {
298                 $this->langInstance = $langInstance;
299         }
300
301         /**
302          * Setter for file I/O instance
303          *
304          * @param               $fileIOInstance An instance to the file I/O sub-system
305          * @return      void
306          */
307         public final function setFileIOInstance (FileIOHandler $fileIOInstance) {
308                 $this->fileIOInstance = $fileIOInstance;
309         }
310
311         /**
312          * Read the base path for all applications (application/) and create a
313          * list of all found applications
314          *
315          * @return      void
316          */
317         public function readApplicationDirectory () {
318                 // Generate the base path for all applications
319                 $appBasePath = sprintf("%s%s/",
320                         PATH,
321                         $this->getConfigInstance()->readConfig("application_path")
322                 );
323
324                 // Add the selector path to the ignore list
325                 $this->addDirIgnoreList($this->getConfigInstance()->readConfig("selector_path"));
326
327                 // Get a directory pointer for the application path
328                 $dirInstance = FrameworkDirectoryPointer::createFrameworkDirectoryPointer($appBasePath);
329
330                 // Backup and remove the 'app' from global name space
331                 /*$appBackup = $app;
332                 unset($app);*/
333
334                 // Read all directories&files except some parts
335                 while ($appName = $dirInstance->readDirectoryExcept($this->dirIgnoreList)) {
336                         // Generate FQFN for the application name (or better directory name)
337                         $fqfn = sprintf("%s%s", $appBasePath, $appName);
338
339                         // Is this a readable directory? (files will be ignored silently)
340                         if ((is_dir($fqfn)) && (is_readable($fqfn))) {
341                                 // Then get the init.php script for analyzing
342                                 $initScript = sprintf("%s/init%s", $fqfn, $this->getConfigInstance()->readConfig("php_extension"));
343
344                                 // Load the application's init.php script and append the
345                                 // application to the ArrayObject
346                                 $this->loadInitScript($initScript, $appName);
347
348                         } // END - if ((is_dir(...
349
350                 } // END - while
351
352                 // Close directory pointer
353                 $dirInstance->closeDirectory();
354
355                 // Restore old 'app' from backup
356                 //$app = $appBackup;
357         }
358
359         /**
360          * Load all templates for found applications in previous scan
361          *
362          * @return      void
363          */
364         public function loadApplicationTemplates () {
365                 // Iterate through all applications
366                 for ($idx = $this->foundApps->getIterator(); $idx->valid(); $idx->next()) {
367                         // Get current application
368                         $appInstance = $idx->current();
369
370                         // Prepare the template engine for the current template
371                         $tplEngine = $this->prepareTemplateEngine($appInstance);
372
373                         // Try to load the web template
374                         $tplEngine->loadWebTemplate(sprintf("%s_%s",
375                                 $this->getConfigInstance()->readConfig("tpl_selector_prefix"),
376                                 strtolower($appInstance->getAppShortName())
377                         ));
378
379                         // Remember this template and the application for later usage
380                         $this->loadedTemplates->append(array(
381                                 'tpl_engine'   => $tplEngine,
382                                 'app_instance' => $appInstance
383                         ));
384                 }
385
386                 // Re-initialize the application list to avoid double loading
387                 $this->initializeAppsList();
388         }
389
390         /**
391          * Removes $dirIgnoreList from the object to save some memory
392          *
393          * @return      void
394          */
395         public function removeDirIgnoreList () {
396                 unset($this->dirIgnoreList);
397         }
398
399         /**
400          * Loads the selector's own main template. This step is not linking the
401          * application's templates into the main one.
402          *
403          * @return      void
404          */
405         public function loadSelectorTemplate () {
406                 // Prepare the template engine
407                 $tplEngine = $this->prepareTemplateEngine($this);
408
409                 // Load the selector's template
410                 $tplEngine->loadCodeTemplate($this->getConfigInstance()->readConfig("selector_main_tpl"));
411
412                 // Now store it in the class
413                 $this->setSelectorTemplateEngine($tplEngine);
414         }
415
416         /**
417          * Inserts all loaded application templates into the selector's template
418          *
419          * @return      void
420          * @throws      NullPointerException            If $curr is null
421          * @throws      NoArrayException                        If $curr is not an array
422          * @throws      InvalidArrayCountException      If $curr contains an
423          *                                                                      unexpected count of elements
424          * @throws      MissingArrayElementsException   If $curr is missing expected
425          *                                                                      array elements
426          */
427         public function insertApplicationTemplates () {
428                 // First prepare the instance
429                 $tplEngine = $this->prepareTemplateEngine($this);
430
431                 // Load template which shall later hold all application templates
432                 $tplEngine->loadCodeTemplate($this->getConfigInstance()->readConfig("selector_apps_tpl"));
433
434                 // Add all loaded application templates together
435                 $dummy = "";
436                 for ($idx = $this->getLoadedTemplates()->getIterator(); $idx->valid(); $idx->next()) {
437                         // Get current item from array object
438                         $curr = $idx->current();
439
440                         // Do some sanity checks on the loaded item
441                         if (is_null($curr)) {
442                                 // $curr is null
443                                 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
444                         } elseif (!is_array($curr)) {
445                                 // Not an array
446                                 throw new NoArrayException($curr, self::EXCEPTION_IS_NO_ARRAY);
447                         } elseif (count($curr) != 2) {
448                                 // Not expected count of entries
449                                 throw new InvalidArrayCountException(array($this, "curr", count($curr), 2), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
450                         } elseif (!isset($curr['tpl_engine']) || (!isset($curr['app_instance']))) {
451                                 // Expected entries missing
452                                 throw new MissingArrayElementsException(array($this, "curr", array('tpl_engine', 'app_instance')), self::EXCEPTION_ARRAY_ELEMENTS_MISSING);
453                         }
454                         die("<pre>".print_r($curr, true)."</pre>");
455
456                 } // END - for
457         }
458
459         /**
460          * Stub!
461          */
462         public function saveObjectToDatabase () {
463                 $this->getDebugInstance()->output(sprintf("[%s:] Stub <strong>%s</strong> erreicht.",
464                         $this->__toString(),
465                         __FUNCTION__
466                 ));
467         }
468 }
469
470 // [EOF]
471 ?>