Completed
Push — master ( af7267...09bff1 )
by Matthias
02:44
created

Framework::resetFramework()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
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\Request\RequestAbstract;
44
use \Zepi\Turbo\Response\Response;
45
use Zepi\Turbo\Manager\Zepi\Turbo\Manager;
46
47
/**
48
 * The Framework object delivers the root functionality for
49
 * zepi Turbo.
50
 * 
51
 * @author Matthias Zobrist <[email protected]>
52
 * @copyright Copyright (c) 2015 zepi
53
 */
54
class Framework
55
{
56
    /**
57
     * @static
58
     * @access protected
59
     * @var Framework
60
     */
61
    static protected $instance;
62
    
63
    /**
64
     * @access protected
65
     * @var string
66
     */
67
    protected $rootDirectory;
68
    
69
    /**
70
     * @access protected
71
     * @var array
72
     */
73
    protected $moduleDirectories = array();
74
    
75
    /**
76
     * @access protected
77
     * @var array
78
     */
79
    protected $moduleNamespaces = array();
80
    
81
    /**
82
     * @access protected
83
     * @var array
84
     */
85
    protected $modules = array();
86
    
87
    /**
88
     * @access protected
89
     * @var \Zepi\Turbo\Manager\DataSourceManager
90
     */
91
    protected $dataSourceManager;
92
93
    /**
94
     * @access protected
95
     * @var \Zepi\Turbo\Manager\ModuleManager
96
     */
97
    protected $moduleManager;
98
    
99
    /**
100
     * @access protected
101
     * @var \Zepi\Turbo\Manager\RuntimeManager
102
     */
103
    protected $runtimeManager;
104
    
105
    /**
106
     * @access protected
107
     * @var \Zepi\Turbo\Manager\RouteManager
108
     */
109
    protected $routeManager;
110
    
111
    /**
112
     * @access protected
113
     * @var \Zepi\Turbo\Manager\RequestManager
114
     */
115
    protected $requestManager;
116
    
117
    /**
118
     * @access protected
119
     * @var \Zepi\Turbo\Request\RequestAbstract
120
     */
121
    protected $request;
122
    
123
    /**
124
     * @access protected
125
     * @var \Zepi\Turbo\Response\Response
126
     */
127
    protected $response;
128
    
129
    /**
130
     * Constructs the object
131
     * 
132
     * @access private
133
     * @param string $rootDirectory
134
     */
135
    private function __construct($rootDirectory)
136
    {
137
        $this->rootDirectory = $rootDirectory;
138
    }
139
    
140
    /**
141
     * Returns a instance of the Framework
142
     * 
143
     * @static
144
     * @access public
145
     * @param string $rootDirectory
146
     * @return Framework
147
     */
148
    public static function getFrameworkInstance($rootDirectory)
149
    {
150
        if (self::$instance === null) {
151
            self::$instance = new Framework($rootDirectory);
152
            self::$instance->initializeFramework();
153
        }
154
        
155
        return self::$instance;
156
    }
157
    
158
    /**
159
     * Resets the framework
160
     * 
161
     * @static
162
     * @access public
163
     */
164
    public static function resetFramework()
165
    {
166
        self::$instance = null;
167
    }
168
    
169
    /**
170
     * Returns the path to the framework directory.
171
     * 
172
     * @access public
173
     * @return string
174
     */
175
    public function getRootDirectory()
176
    {
177
        return $this->rootDirectory;
178
    }
179
    
180
    /**
181
     * Initializes the framework and creates all needed managers.
182
     * 
183
     * @access protected
184
     */
185
    protected function initializeFramework()
186
    {
187
        $this->registerAutoloader();
188
        
189
        $this->requestManager = new RequestManager($this);
190
        $this->request = $this->requestManager->buildRequest();
191
        
192
        $this->response = new Response($this->request);
193
        
194
        $this->dataSourceManager = new DataSourceManager($this, $this->getInstance('Zepi\\Turbo\\Backend\\VirtualDataSourceBackend'));
195
        $this->dataSourceManager->initializeDataSourceManager();
196
        
197
        $this->moduleManager = new ModuleManager($this, $this->getInstance('Zepi\\Turbo\\Backend\\VirtualModuleBackend'));
198
        $this->moduleManager->initializeModuleSystem();
199
        
200
        $this->runtimeManager = new RuntimeManager($this, $this->getInstance('Zepi\\Turbo\\Backend\\VirtualHandlerBackend'));
201
        $this->runtimeManager->initializeManager();
202
        
203
        $this->routeManager = new RouteManager($this, $this->getInstance('Zepi\\Turbo\\Backend\\VirtualRouteBackend'));
204
        $this->routeManager->initializeRoutingTable();
205
    }
206
    
207
    /**
208
     * Returns the data source manager for the framework
209
     *
210
     * @access public
211
     * @return \Zepi\Turbo\Manager\DataSourceManager
212
     */
213
    public function getDataSourceManager()
214
    {
215
        return $this->dataSourceManager;
216
    }
217
218
    /**
219
     * Returns the module manager for the framework
220
     * 
221
     * @access public
222
     * @return \Zepi\Turbo\Manager\ModuleManager
223
     */
224
    public function getModuleManager()
225
    {
226
        return $this->moduleManager;
227
    }
228
    
229
    /**
230
     * Returns the runtime manager for the framework
231
     * 
232
     * @access public
233
     * @return \Zepi\Turbo\Manager\RuntimeManager
234
     */
235
    public function getRuntimeManager()
236
    {
237
        return $this->runtimeManager;
238
    }
239
    
240
    /**
241
     * Returns the route manager for the framework 
242
     * 
243
     * @access public
244
     * @return \Zepi\Turbo\Manager\RouteManager
245
     */
246
    public function getRouteManager()
247
    {
248
        return $this->routeManager;
249
    }
250
    
251
    /**
252
     * Returns the RequestManager object
253
     * 
254
     * @access public
255
     * @return \Zepi\Turbo\Manager\RequestManager
256
     */
257
    public function getRequestManager()
258
    {
259
        return $this->requestManager;
260
    }
261
    
262
    /**
263
     * Returns the request object for the request
264
     * 
265
     * @access public
266
     * @return \Zepi\Turbo\Request\RequestAbstract
267
     */
268
    public function getRequest()
269
    {
270
        return $this->request;
271
    }
272
    
273
    /**
274
     * Returns the response for the request
275
     * 
276
     * @access public
277
     * @return \Zepi\Turbo\Response\Response
278
     */
279
    public function getResponse()
280
    {
281
        return $this->response;
282
    }
283
    
284
    /**
285
     * Registers the global autloader.
286
     * 
287
     * @access protected
288
     */
289
    protected function registerAutoloader()
290
    {
291
        spl_autoload_register(array($this, 'loadClass'));
292
    }
293
    
294
    /**
295
     * Prepares the class name and adds a backslash in front
296
     * of the class name if there isn't a bachslash.
297
     * 
298
     * @static
299
     * @access public
300
     * @param string $className
301
     * @return string
302
     */
303
    public static function prepareClassName($className)
304
    {
305
        if (substr($className, 0, 1) !== '\\') {
306
            $className = '\\' . $className;
307
        }
308
        
309
        return $className;
310
    }
311
    
312
    /**
313
     * Prepares the namespace and adds on both sides of the
314
     * namespace the backslashes.
315
     * 
316
     * @static
317
     * @access public
318
     * @param string $namespace
319
     * @return string
320
     */
321
    public static function prepareNamespace($namespace)
322
    {
323
        if (substr($namespace, 0, 1) !== '\\') {
324
            $namespace = '\\' . $namespace;
325
        }
326
        
327
        if (substr($namespace, -1) !== '\\') {
328
            $namespace .= '\\';
329
        }
330
        
331
        return $namespace;
332
    }
333
    
334
    /**
335
     * Framework autoloader: This function is called from the SPL Autoloader
336
     * to load the correct class. If the class isn't in the framework the
337
     * function will trying to load and initialize the module.
338
     * 
339
     * @access public
340
     * @param string $className
341
     * 
342
     * @throws \Exception Cannot find the class "$className"!
343
     */
344
    public function loadClass($className)
345
    {
346
        $path = false;
347
        $module = false;
348
        $className = self::prepareClassName($className);
349
        
350
        if (strpos($className, '\\Zepi\\Turbo\\') === 0) {
351
            $sourceDirectory = realpath(__DIR__ . '/../../');
352
            
353
            // The class is from the framework, so we load the class file from the framework directory
354
            $path = $sourceDirectory . str_replace('\\', '/', $className) . '.php';
355
        } else {
356
            // The class isn't from the framework, so we need the module for the given class name
357
            $module = $this->moduleManager->getModuleByClassName($className);
358
            
359
            if ($module !== false) {
360
                $fileName = substr($className, strlen($module->getNamespace()));
361
                $path = $module->getDirectory() . '/src/' . str_replace('\\', '/', $fileName) . '.php';
362
            }
363
        }
364
365
        if ($path !== false && file_exists($path)) {
366
            require_once($path);
367
        } else if ($module !== false) {
368
            throw new Exception('Cannot find the class "' . $className . '"!');
369
        }
370
    }
371
    
372
    /**
373
     * Returns an instance of an object. If the module for the object
374
     * isn't initialized, the function will load the module and 
375
     * initialize the module.
376
     * 
377
     * @access public
378
     * @param string $className
379
     * @return mixed
380
     * 
381
     * @throws \Zepi\Turbo\Exception Cannot find the module for the given class name.
382
     * @throws \Zepi\Turbo\Exception Instance isn't an object!
383
     */
384
    public function getInstance($className)
385
    {
386
        $className = self::prepareClassName($className);
387
        
388
        if (strpos($className, '\\Zepi\\Turbo') === 0) {
389
            $instance = $this->getCoreInstance($className);
390
        } else {
391
            $module = $this->moduleManager->getModuleByClassName($className);
392
            
393
            if ($module === false) {
394
                throw new Exception('Cannot find the module for the given class name "' . $className . '".');
395
            }
396
            
397
            $instance = $module->getInstance($className);
398
        }
399
        
400
        if (!is_object($instance)) {
401
            throw new Exception('Instance for class name "' . $className . '" isn\'t an object!');
402
        }
403
        
404
        return $instance;
405
    }
406
    
407
    /**
408
     * Returns the instance of a framework object
409
     * 
410
     * @access protected
411
     * @param string $className
412
     * @return mixed
413
     * 
414
     * @throws \Zepi\Turbo\Exception Class "{className}" is not defined.
415
     */
416
    protected function getCoreInstance($className)
417
    {
418
        $className = self::prepareClassName($className);
419
420
        switch ($className) {
421
            case '\\Zepi\\Turbo\\Backend\\VirtualModuleBackend':
422
                $path = $this->rootDirectory . '/data/modules.data';
423
                return new \Zepi\Turbo\Backend\FileObjectBackend($path);
424
                break;
425
            case '\\Zepi\\Turbo\\Backend\\VirtualHandlerBackend':
426
                $path = $this->rootDirectory . '/data/handlers.data';
427
                return new \Zepi\Turbo\Backend\FileObjectBackend($path);
428
                break;
429
            case '\\Zepi\\Turbo\\Backend\\VirtualRouteBackend':
430
                $path = $this->rootDirectory . '/data/routes.data';
431
                return new \Zepi\Turbo\Backend\FileObjectBackend($path);
432
                break;
433
            case '\\Zepi\\Turbo\\Backend\\VirtualDataSourceBackend':
434
                $path = $this->rootDirectory . '/data/data-sources.data';
435
                return new \Zepi\Turbo\Backend\FileObjectBackend($path);
436
                break;
437
            default:
438
                if (class_exists($className, true)) {
439
                    return new $className();
440
                } else {
441
                    throw new Exception('Class "' . $className . '" is not defined.');
442
                }
443
                break;
1 ignored issue
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
444
        }
445
    }
446
    
447
    /**
448
     * Executes the framework. This executes the pre and post execution events.
449
     * Between these two events we call the correct request event. The 
450
     * routing table from the RouteManager returns the needed event name.
451
     * 
452
     * @access public
453
     */
454
    public function execute()
455
    {
456
        // Execute the before execution event
457
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\BeforeExecution');
458
        
459
        // Get the event name for the request and execute the event
460
        $eventName = $this->routeManager->getEventNameForRoute($this->request);
461
        $eventName = $this->runtimeManager->executeFilter('\\Zepi\\Turbo\\Filter\\VerifyEventName', $eventName);
462
463
        if ($eventName !== false && $eventName != '') {
464
            $this->runtimeManager->executeEvent($eventName);
465
        } else {
466
            $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\RouteNotFound');
467
        }
468
        
469
        // Execute the after execution event
470
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\AfterExecution');
471
472
        // Finalize the output
473
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\FinalizeOutput');
474
        
475
        // Execute the before output event
476
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\BeforeOutput');
477
        
478
        // Print the output
479
        echo $this->response->getOutput();
480
        
481
        // Execute the after output event
482
        $this->runtimeManager->executeEvent('\\Zepi\\Turbo\\Event\\AfterOutput');
483
    }
484
}
485