Completed
Push — master ( 6004de...5c6062 )
by Steve
04:10
created

Application   C

Complexity

Total Complexity 18

Size/Duplication

Total Lines 212
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 20

Test Coverage

Coverage 98.9%

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 20
dl 0
loc 212
ccs 90
cts 91
cp 0.989
rs 6.4705
c 0
b 0
f 0

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