Completed
Push — master ( 4952c2...c989b6 )
by Steve
15:45
created

Application   B

Complexity

Total Complexity 14

Size/Duplication

Total Lines 175
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 18

Test Coverage

Coverage 88.89%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 14
c 1
b 0
f 0
lcom 1
cbo 18
dl 0
loc 175
ccs 56
cts 63
cp 0.8889
rs 7.3333

10 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 8 1
A __construct() 0 17 1
A registerRoutes() 0 14 2
A setDependencyContainer() 0 4 1
A getDependencyContainer() 0 4 1
A run() 0 19 1
B performRequest() 0 39 2
A registerEvents() 0 14 2
A loadComponents() 0 11 2
A initDependencyContainer() 0 12 1
1
<?php
2
/**
3
 * @package    Fuel\Foundation
4
 * @version    2.0
5
 * @author     Fuel Development Team
6
 * @license    MIT License
7
 * @copyright  2010 - 2016 Fuel Development Team
8
 * @link       http://fuelphp.com
9
 */
10
11
declare(strict_types=1);
12
13
namespace Fuel\Foundation;
14
15
use Fuel\Config\Container as ConfigContainer;
16
use Fuel\Config\Container;
17
use Fuel\Dependency\Container as DependencyContainer;
18
use Fuel\Foundation\Event\AppShutdown;
19
use Fuel\Foundation\Event\AppStarted;
20
use Fuel\Foundation\Event\RequestFinished;
21
use Fuel\Foundation\Event\RequestStarted;
22
use Fuel\Foundation\Event\ResponseFinished;
23
use Fuel\Foundation\Event\ResponseStarted;
24
use Fuel\Foundation\Request\RequestInterface;
25
use Fuel\Foundation\Response\ResponseInterface;
26
use Fuel\Routing\Router;
27
use League\Container\ContainerInterface;
28
use League\Event\Emitter;
29
use Zend\Diactoros\CallbackStream;
30
use Zend\Diactoros\Stream;
31
32
class Application
33
{
34
	/**
35
	 * @var ContainerInterface
36
	 */
37
	protected $dependencyContainer;
38
39 7
	/**
40
	 * @var array
41
	 */
42 7
	protected $config;
43 7
44
	public static function init(array $config) : Application
45 7
	{
46
		// Ensure the needed config entries exists
47
		$config['events'] = $config['events'] ?? [];
48 7
		$config['components'] = $config['components'] ?? [];
49
50 7
		return new static($config);
51
	}
52
53 7
	public function __construct(array $config, ContainerInterface $dependencyContainer = null)
54
	{
55
		$this->initDependencyContainer($config, $dependencyContainer);
56 7
57
		// register any events from the config
58 7
		$this->registerEvents($config['events']);
59
60
		// Load components
61 7
		$this->loadComponents($config['components']);
62 7
63 7
		$this->registerRoutes();
64 7
65
		// trigger app created event
66 7
		$this->dependencyContainer
67
			->get('fuel.application.event')
68
			->emit(new AppStarted($this));
69 7
	}
70
71
	protected function registerRoutes()
72 7
	{
73 7
		/** @var Router $router */
74
		$router = $this->dependencyContainer->get('fuel.application.router');
75 7
76
		/** @var Container $config */
77 2
		$config = $this->dependencyContainer->get('fuel.config');
78
		$config->load('routing', 'routing');
79 7
80
		foreach ($config->get('routing', []) as $uri => $routeConfig)
81 7
		{
82
			$router->all($uri)->filters($routeConfig);
83 7
		}
84 7
	}
85
86 7
	public function setDependencyContainer(ContainerInterface $dependencyContainer)
87
	{
88 7
		$this->dependencyContainer = $dependencyContainer;
89
	}
90
91
	public function getDependencyContainer() : ContainerInterface
92
	{
93
		return $this->dependencyContainer;
94
	}
95
96
	public function run()
97
	{
98
		$request = $this->dependencyContainer->get('fuel.application.request');
99
		$response = $this->performRequest($request);
100
101
		// trigger response started event
102 1
		$this->dependencyContainer
103
			->get('fuel.application.event')
104 1
			->emit(new ResponseStarted($this));
105
106
		http_response_code($response->getStatusCode());
107
		echo $response->getBody();
108
109
		// send shutdown event
110
		$this->dependencyContainer
111 1
			->get('fuel.application.event')
112 1
			->emit(new ResponseFinished($this))
113
			->emit(new AppShutdown($this));
114
	}
115 1
116
	public function performRequest(RequestInterface $request) : ResponseInterface
117 1
	{
118
		$this->dependencyContainer->add('fuel.application.request', $request);
119
120
		// trigger request started event
121
		$this->dependencyContainer
122
			->get('fuel.application.event')
123
			->emit(new RequestStarted($this));
124
125 1
		// route to and call controller
126
		// TODO: Handle 404 and 500?
127
		/** @var Router $router */
128
		$router = $this->dependencyContainer->get('fuel.application.router');
129
		$match = $router->translate($request->getUri()->getPath(), $request->getMethod());
130
131 1
		// TODO: Use dependency magic to create the controller instance
132 1
		$controller = new $match->controller();
133
		// TODO: Pass params through
134
		$controller_result = $controller->{$match->action}();
135 1
136
		// trigger request ended event
137
		$this->dependencyContainer
138
			->get('fuel.application.event')
139
			->emit(new RequestFinished($this));
140
141 7
		// generate and send response
142
		// If the controller response is a response object then just pass that back out
143
		if ($controller_result instanceof ResponseInterface) {
144 7
			return $controller_result;
145
		}
146 7
147
		// Else update the application response with the controller result#
148 2
		/** @var ResponseInterface $response */
149 2
		$response = $this->dependencyContainer->get('fuel.application.response');
150 2
		$response->withStatus(200);
151 2
		$response = $response->withBody(new CallbackStream(function() use ($controller_result) {return $controller_result; }));
152
153
		return $response;
154 7
	}
155
156
	/**
157
	 * @param array $events
158
	 */
159 7
	protected function registerEvents(array $events)
160
	{
161
		/** @var Emitter $eventContainer */
162 7
		$eventContainer = $this->dependencyContainer->get('fuel.application.event');
163 7
164
		foreach ($events as $event)
165 7
		{
166
			$eventContainer->addListener(
167 2
				$event['name'],
168
				$event['listener'],
169 7
				$event['priority'] ?? $eventContainer::P_NORMAL
170
			);
171
		}
172
	}
173
174
	/**
175 7
	 * @param string[] $components
176
	 */
177 7
	protected function loadComponents(array $components)
178
	{
179 7
		/** @var ComponentManagerInterface $componentManager */
180
		$componentManager = $this->getDependencyContainer()
181 7
			->get('fuel.application.component_manager');
182
183 7
		foreach ($components as $component)
184
		{
185 7
			$componentManager->load($component);
186 7
		}
187
	}
188
189
	/**
190
	 * @param array              $config
191
	 * @param ContainerInterface $dependencyContainer
192
	 */
193
	protected function initDependencyContainer(array $config, ContainerInterface $dependencyContainer = null)
194
	{
195
		$this->setDependencyContainer($dependencyContainer ?? new DependencyContainer());
196
		// So our application can be fetched
197
		$this->dependencyContainer->add('fuel.application', $this);
198
		// And our application config if needed
199
		$this->dependencyContainer->add('fuel.application.config', $config);
200
		// Also create a config container for our services
201
		$this->dependencyContainer->add('fuel.config', new ConfigContainer());
202
		// Finally add all our application level services
203
		$this->dependencyContainer->addServiceProvider(new ApplicationServicesProvider());
204
	}
205
206
}
207