Completed
Push — master ( c989b6...64dbd8 )
by Emlyn
15:37 queued 13:31
created

Application::performRequest()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 39
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 2.0008
Metric Value
dl 0
loc 39
ccs 16
cts 17
cp 0.9412
rs 8.8571
cc 2
eloc 18
nc 2
nop 1
crap 2.0008
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
	/**
40
	 * @var array
41
	 */
42
	protected $config;
43
44 7
	public static function init(array $config) : Application
45
	{
46
		// Ensure the needed config entries exists
47 7
		$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 7
		$this->initDependencyContainer($config, $dependencyContainer);
56
57
		// register any events from the config
58 7
		$this->registerEvents($config['events']);
59
60
		// Load components
61 7
		$this->loadComponents($config['components']);
62
63 7
		$this->registerRoutes();
64
65
		// trigger app created event
66 7
		$this->dependencyContainer
67 7
			->get('fuel.application.event')
68 7
			->emit(new AppStarted($this));
69 7
	}
70
71 7
	protected function registerRoutes()
72
	{
73
		/** @var Router $router */
74 7
		$router = $this->dependencyContainer->get('fuel.application.router');
75
76
		/** @var Container $config */
77 7
		$config = $this->dependencyContainer->get('fuel.config');
78 7
		$config->load('routing', 'routing');
79
80 7
		foreach ($config->get('routing', []) as $uri => $routeConfig)
81
		{
82 2
			$router->all($uri)->filters($routeConfig);
83
		}
84 7
	}
85
86 7
	public function setDependencyContainer(ContainerInterface $dependencyContainer)
87
	{
88 7
		$this->dependencyContainer = $dependencyContainer;
89 7
	}
90
91 7
	public function getDependencyContainer() : ContainerInterface
92
	{
93 7
		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
		$this->dependencyContainer
103
			->get('fuel.application.event')
104
			->emit(new ResponseStarted($this));
105
106
		http_response_code($response->getStatusCode());
107
		echo $response->getBody();
108
109
		// send shutdown event
110
		$this->dependencyContainer
111
			->get('fuel.application.event')
112
			->emit(new ResponseFinished($this));
113
114
		$this->dependencyContainer
115
			->get('fuel.application.event')
116
			->emit(new AppShutdown($this));
117
	}
118
119 1
	public function performRequest(RequestInterface $request) : ResponseInterface
120
	{
121 1
		$this->dependencyContainer->add('fuel.application.request', $request);
122
123
		// trigger request started event
124 1
		$this->dependencyContainer
125 1
			->get('fuel.application.event')
126 1
			->emit(new RequestStarted($this));
127
128
		// route to and call controller
129
		// TODO: Handle 404 and 500?
130
		/** @var Router $router */
131 1
		$router = $this->dependencyContainer->get('fuel.application.router');
132 1
		$match = $router->translate($request->getUri()->getPath(), $request->getMethod());
133
134
		// TODO: Use dependency magic to create the controller instance
135 1
		$controller = new $match->controller();
136
		// TODO: Pass params through
137 1
		$controller_result = $controller->{$match->action}();
138
139
		// trigger request ended event
140 1
		$this->dependencyContainer
141 1
			->get('fuel.application.event')
142 1
			->emit(new RequestFinished($this));
143
144
		// generate and send response
145
		// If the controller response is a response object then just pass that back out
146 1
		if ($controller_result instanceof ResponseInterface) {
147
			return $controller_result;
148
		}
149
150
		// Else update the application response with the controller result#
151
		/** @var ResponseInterface $response */
152 1
		$response = $this->dependencyContainer->get('fuel.application.response');
153 1
		$response->withStatus(200);
154
		$response = $response->withBody(new CallbackStream(function() use ($controller_result) {return $controller_result; }));
155
156 1
		return $response;
157
	}
158
159
	/**
160
	 * @param array $events
161
	 */
162 7
	protected function registerEvents(array $events)
163
	{
164
		/** @var Emitter $eventContainer */
165 7
		$eventContainer = $this->dependencyContainer->get('fuel.application.event');
166
167 7
		foreach ($events as $event)
168
		{
169 3
			$eventContainer->addListener(
170 3
				$event['name'],
171 3
				$event['listener'],
172 3
				$event['priority'] ?? $eventContainer::P_NORMAL
173
			);
174
		}
175 7
	}
176
177
	/**
178
	 * @param string[] $components
179
	 */
180 7
	protected function loadComponents(array $components)
181
	{
182
		/** @var ComponentManagerInterface $componentManager */
183 7
		$componentManager = $this->getDependencyContainer()
184 7
			->get('fuel.application.component_manager');
185
186 7
		foreach ($components as $component)
187
		{
188 2
			$componentManager->load($component);
189
		}
190 7
	}
191
192
	/**
193
	 * @param array              $config
194
	 * @param ContainerInterface $dependencyContainer
195
	 */
196 7
	protected function initDependencyContainer(array $config, ContainerInterface $dependencyContainer = null)
197
	{
198 7
		$this->setDependencyContainer($dependencyContainer ?? new DependencyContainer());
199
		// So our application can be fetched
200 7
		$this->dependencyContainer->add('fuel.application', $this);
201
		// And our application config if needed
202 7
		$this->dependencyContainer->add('fuel.application.config', $config);
203
		// Also create a config container for our services
204 7
		$this->dependencyContainer->add('fuel.config', new ConfigContainer());
205
		// Finally add all our application level services
206 7
		$this->dependencyContainer->addServiceProvider(new ApplicationServicesProvider());
207 7
	}
208
209
}
210