Framework::initializeFramework()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 23
ccs 15
cts 15
cp 1
rs 9.0856
cc 1
eloc 14
nc 1
nop 0
crap 1
1
<?php
2
/*
3
 * The MIT License (MIT)
4
 *
5
 * Copyright (c) 2015 zepi
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 *
25
 */
26
27
/**
28
 * The Framework object delivers the root functionality for
29
 * zepi Turbo.
30
 * 
31
 * @package Zepi\Turbo
32
 * @author Matthias Zobrist <[email protected]>
33
 * @copyright Copyright (c) 2015 zepi
34
 */
35
36
namespace Zepi\Turbo;
37
38
use \Zepi\Turbo\Manager\DataSourceManager;
39
use \Zepi\Turbo\Manager\ModuleManager;
40
use \Zepi\Turbo\Manager\RuntimeManager;
41
use \Zepi\Turbo\Manager\RouteManager;
42
use \Zepi\Turbo\Manager\RequestManager;
43
use \Zepi\Turbo\Manager\DependencyInjectionManager;
44
use \Zepi\Turbo\Request\RequestAbstract;
45
use \Zepi\Turbo\Response\Response;
46
use Zepi\Turbo\Manager\Zepi\Turbo\Manager;
47
48
/**
49
 * The Framework object delivers the root functionality for
50
 * zepi Turbo.
51
 * 
52
 * @author Matthias Zobrist <[email protected]>
53
 * @copyright Copyright (c) 2015 zepi
54
 */
55
class Framework
56
{
57
    /**
58
     * @static
59
     * @access protected
60
     * @var Framework
61
     */
62
    static protected $instance;
63
    
64
    /**
65
     * @access protected
66
     * @var string
67
     */
68
    protected $rootDirectory;
69
    
70
    /**
71
     * @access protected
72
     * @var array
73
     */
74
    protected $moduleDirectories = array();
75
    
76
    /**
77
     * @access protected
78
     * @var array
79
     */
80
    protected $moduleNamespaces = array();
81
    
82
    /**
83
     * @access protected
84
     * @var array
85
     */
86
    protected $modules = array();
87
    
88
    /**
89
     * @access protected
90
     * @var \Zepi\Turbo\Manager\DataSourceManager
91
     */
92
    protected $dataSourceManager;
93
94
    /**
95
     * @access protected
96
     * @var \Zepi\Turbo\Manager\ModuleManager
97
     */
98
    protected $moduleManager;
99
    
100
    /**
101
     * @access protected
102
     * @var \Zepi\Turbo\Manager\RuntimeManager
103
     */
104
    protected $runtimeManager;
105
    
106
    /**
107
     * @access protected
108
     * @var \Zepi\Turbo\Manager\RouteManager
109
     */
110
    protected $routeManager;
111
    
112
    /**
113
     * @access protected
114
     * @var \Zepi\Turbo\Manager\RequestManager
115
     */
116
    protected $requestManager;
117
    
118
    /**
119
     * @access protected
120
     * @var \Zepi\Turbo\Manager\DependencyInjectionManager
121
     */
122
    protected $dependencyInjectionManager;
123
    
124
    /**
125
     * @access protected
126
     * @var \Zepi\Turbo\Request\RequestAbstract
127
     */
128
    protected $request;
129
    
130
    /**
131
     * @access protected
132
     * @var \Zepi\Turbo\Response\Response
133
     */
134
    protected $response;
135
    
136
    /**
137
     * Constructs the object
138
     * 
139
     * @access private
140
     * @param string $rootDirectory
141
     */
142 17
    private function __construct($rootDirectory)
143
    {
144 17
        $this->rootDirectory = $rootDirectory;
145 17
    }
146
    
147
    /**
148
     * Returns a instance of the Framework
149
     * 
150
     * @static
151
     * @access public
152
     * @param string $rootDirectory
153
     * @return Framework
154
     */
155 17
    public static function getFrameworkInstance($rootDirectory)
156
    {
157 17
        if (self::$instance === null) {
158 17
            self::$instance = new Framework($rootDirectory);
159 17
            self::$instance->initializeFramework();
160
        }
161
        
162 17
        return self::$instance;
163
    }
164
    
165
    /**
166
     * Resets the framework
167
     * 
168
     * @static
169
     * @access public
170
     */
171 19
    public static function resetFramework()
172
    {
173 19
        self::$instance = null;
174 19
    }
175
    
176
    /**
177
     * Returns the path to the framework directory.
178
     * 
179
     * @access public
180
     * @return string
181
     */
182 1
    public function getRootDirectory()
183
    {
184 1
        return $this->rootDirectory;
185
    }
186
    
187
    /**
188
     * Initializes the framework and creates all needed managers.
189
     * 
190
     * @access protected
191
     */
192 17
    protected function initializeFramework()
193
    {
194 17
        $this->registerAutoloader();
195
196 17
        $this->dependencyInjectionManager = new DependencyInjectionManager($this);
197
        
198 17
        $this->requestManager = new RequestManager($this);
199 17
        $this->request = $this->requestManager->buildRequest();
200
        
201 17
        $this->response = new Response($this->request);
202
        
203 17
        $this->dataSourceManager = new DataSourceManager($this, $this->getInstance('Zepi\\Turbo\\Backend\\VirtualDataSourceBackend'));
204 17
        $this->dataSourceManager->initializeDataSourceManager();
205
        
206 17
        $this->moduleManager = new ModuleManager($this, $this->getInstance('Zepi\\Turbo\\Backend\\VirtualModuleBackend'));
207 17
        $this->moduleManager->initializeModuleSystem();
208
        
209 17
        $this->runtimeManager = new RuntimeManager($this, $this->getInstance('Zepi\\Turbo\\Backend\\VirtualHandlerBackend'));
210 17
        $this->runtimeManager->initializeManager();
211
        
212 17
        $this->routeManager = new RouteManager($this, $this->getInstance('Zepi\\Turbo\\Backend\\VirtualRouteBackend'));
213 17
        $this->routeManager->initializeRoutingTable();
214 17
    }
215
    
216
    /**
217
     * Returns the data source manager for the framework
218
     *
219
     * @access public
220
     * @return \Zepi\Turbo\Manager\DataSourceManager
221
     */
222 1
    public function getDataSourceManager()
223
    {
224 1
        return $this->dataSourceManager;
225
    }
226
227
    /**
228
     * Returns the module manager for the framework
229
     * 
230
     * @access public
231
     * @return \Zepi\Turbo\Manager\ModuleManager
232
     */
233 6
    public function getModuleManager()
234
    {
235 6
        return $this->moduleManager;
236
    }
237
    
238
    /**
239
     * Returns the runtime manager for the framework
240
     * 
241
     * @access public
242
     * @return \Zepi\Turbo\Manager\RuntimeManager
243
     */
244 3
    public function getRuntimeManager()
245
    {
246 3
        return $this->runtimeManager;
247
    }
248
    
249
    /**
250
     * Returns the route manager for the framework 
251
     * 
252
     * @access public
253
     * @return \Zepi\Turbo\Manager\RouteManager
254
     */
255 2
    public function getRouteManager()
256
    {
257 2
        return $this->routeManager;
258
    }
259
    
260
    /**
261
     * Returns the RequestManager object
262
     * 
263
     * @access public
264
     * @return \Zepi\Turbo\Manager\RequestManager
265
     */
266 1
    public function getRequestManager()
267
    {
268 1
        return $this->requestManager;
269
    }
270
    
271
    /**
272
     * Returns the DependencyInjectionManager object
273
     *
274
     * @access public
275
     * @return \Zepi\Turbo\Manager\DependencyInjectionManager
276
     */
277
    public function getDependencyInjectionManager()
278
    {
279
        return $this->dependencyInjectionManager;
280
    }
281
    
282
    /**
283
     * Returns the request object for the request
284
     * 
285
     * @access public
286
     * @return \Zepi\Turbo\Request\RequestAbstract
287
     */
288 3
    public function getRequest()
289
    {
290 3
        return $this->request;
291
    }
292
    
293
    /**
294
     * Returns the response for the request
295
     * 
296
     * @access public
297
     * @return \Zepi\Turbo\Response\Response
298
     */
299 3
    public function getResponse()
300
    {
301 3
        return $this->response;
302
    }
303
    
304
    /**
305
     * Registers the global autloader.
306
     * 
307
     * @access protected
308
     */
309 17
    protected function registerAutoloader()
310
    {
311 17
        spl_autoload_register(array($this, 'loadClass'));
312 17
    }
313
    
314
    /**
315
     * Prepares the class name and adds a backslash in front
316
     * of the class name if there isn't a bachslash.
317
     * 
318
     * @static
319
     * @access public
320
     * @param string $className
321
     * @return string
322
     */
323 26
    public static function prepareClassName($className)
324
    {
325 26
        if (substr($className, 0, 1) !== '\\') {
326 19
            $className = '\\' . $className;
327
        }
328
        
329 26
        return $className;
330
    }
331
    
332
    /**
333
     * Prepares the namespace and adds on both sides of the
334
     * namespace the backslashes.
335
     * 
336
     * @static
337
     * @access public
338
     * @param string $namespace
339
     * @return string
340
     */
341 19
    public static function prepareNamespace($namespace)
342
    {
343 19
        if (substr($namespace, 0, 1) !== '\\') {
344 17
            $namespace = '\\' . $namespace;
345
        }
346
        
347 19
        if (substr($namespace, -1) !== '\\') {
348 17
            $namespace .= '\\';
349
        }
350
        
351 19
        return $namespace;
352
    }
353
    
354
    /**
355
     * Framework autoloader: This function is called from the SPL Autoloader
356
     * to load the correct class. If the class isn't in the framework the
357
     * function will trying to load and initialize the module.
358
     * 
359
     * @access public
360
     * @param string $className
361
     * 
362
     * @throws \Exception Cannot find the class "$className"!
363
     */
364 6
    public function loadClass($className)
365
    {
366 6
        $path = false;
367 6
        $module = false;
368 6
        $className = self::prepareClassName($className);
369
        
370 6
        if (strpos($className, '\\Zepi\\Turbo\\') === 0) {
371 2
            $sourceDirectory = realpath(__DIR__ . '/../../');
372
            
373
            // The class is from the framework, so we load the class file from the framework directory
374 2
            $path = $sourceDirectory . str_replace('\\', '/', $className) . '.php';
375
        } else {
376
            // The class isn't from the framework, so we need the module for the given class name
377 4
            $module = $this->moduleManager->getModuleByClassName($className);
378
            
379 4
            if ($module !== false) {
380 4
                $fileName = substr($className, strlen($module->getNamespace()));
381 4
                $path = $module->getDirectory() . '/src/' . str_replace('\\', '/', $fileName) . '.php';
382
            }
383
        }
384
385 6
        if ($path !== false && file_exists($path)) {
386 4
            require_once($path);
387 5
        } else if ($module !== false) {
388 1
            throw new Exception('Cannot find the class "' . $className . '"!');
389
        }
390 6
    }
391
    
392
    /**
393
     * Initiates the given class name
394
     * 
395
     * @param string $className
396
     * @param array $additionalParameters
397
     * @param boolean $shared
398
     * @return object
399
     */
400
    public function initiateObject($className, $additionalParameters = array(), $shared = false)
401
    {
402
        return $this->dependencyInjectionManager->initiateObject($className, $additionalParameters, $shared);
403
    }
404
    
405
    /**
406
     * Returns an instance of an object. If the module for the object
407
     * isn't initialized, the function will load the module and 
408
     * initialize the module.
409
     * 
410
     * @access public
411
     * @param string $className
412
     * @return mixed
413
     * 
414
     * @throws \Zepi\Turbo\Exception Cannot find the module for the given class name.
415
     * @throws \Zepi\Turbo\Exception Instance isn't an object!
416
     */
417 17
    public function getInstance($className)
418
    {
419 17
        $className = self::prepareClassName($className);
420
        
421 17
        if (strpos($className, '\\Zepi\\Turbo') === 0) {
422 17
            $instance = $this->getCoreInstance($className);
423
        } else {
424 6
            $module = $this->moduleManager->getModuleByClassName($className);
425
            
426 6
            if ($module === false) {
427 1
                throw new Exception('Cannot find the module for the given class name "' . $className . '".');
428
            }
429
            
430 5
            $instance = $module->getInstance($className);
431
        }
432
        
433 17
        if (!is_object($instance)) {
434 1
            throw new Exception('Instance for class name "' . $className . '" isn\'t an object!');
435
        }
436
        
437 17
        return $instance;
438
    }
439
    
440
    /**
441
     * Returns the instance of a framework object
442
     * 
443
     * @access protected
444
     * @param string $className
445
     * @return mixed
446
     * 
447
     * @throws \Zepi\Turbo\Exception Class "{className}" is not defined.
448
     */
449 17
    protected function getCoreInstance($className)
450
    {
451 17
        $className = self::prepareClassName($className);
452
453
        switch ($className) {
454 17
            case '\\Zepi\\Turbo\\Backend\\VirtualModuleBackend':
455 17
                $path = $this->rootDirectory . '/data/modules.data';
456 17
                return new \Zepi\Turbo\Backend\FileObjectBackend($path);
457
                break;
458 17
            case '\\Zepi\\Turbo\\Backend\\VirtualHandlerBackend':
459 17
                $path = $this->rootDirectory . '/data/handlers.data';
460 17
                return new \Zepi\Turbo\Backend\FileObjectBackend($path);
461
                break;
462 17
            case '\\Zepi\\Turbo\\Backend\\VirtualRouteBackend':
463 17
                $path = $this->rootDirectory . '/data/routes.data';
464 17
                return new \Zepi\Turbo\Backend\FileObjectBackend($path);
465
                break;
466 17
            case '\\Zepi\\Turbo\\Backend\\VirtualDataSourceBackend':
467 17
                $path = $this->rootDirectory . '/data/data-sources.data';
468 17
                return new \Zepi\Turbo\Backend\FileObjectBackend($path);
469
                break;
470
            default:
471 2
                if (class_exists($className, true)) {
472 1
                    return new $className();
473
                } else {
474 1
                    throw new Exception('Class "' . $className . '" is not defined.');
475
                }
476
                break;
477
        }
478
    }
479
    
480
    /**
481
     * Executes the framework. This executes the pre and post execution events.
482
     * Between these two events we call the correct request event. The 
483
     * routing table from the RouteManager returns the needed event name.
484
     * 
485
     * @access public
486
     */
487 2
    public function execute()
488
    {
489
        // Execute the before execution event
490 2
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\BeforeExecution');
491
        
492
        // Get the event name for the request and execute the event
493 2
        $eventName = $this->routeManager->getEventNameForRoute($this->request);
494 2
        $eventName = $this->runtimeManager->executeFilter('\\Zepi\\Turbo\\Filter\\VerifyEventName', $eventName);
495
496 2
        if ($eventName !== false && $eventName != '') {
497 1
            $this->runtimeManager->executeEvent($eventName);
498
        } else {
499 1
            $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\RouteNotFound');
500
        }
501
        
502
        // Execute the after execution event
503 2
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\AfterExecution');
504
505
        // Finalize the output
506 2
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\FinalizeOutput');
507
        
508
        // Execute the before output event
509 2
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\BeforeOutput');
510
        
511
        // Print the output
512 2
        echo $this->response->getOutput();
513
        
514
        // Execute the after output event
515 2
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\AfterOutput');
516 2
    }
517
}
518