Completed
Push — 4.0 ( 2ca4e1...0c3d7c )
by Marco
15:24
created

Dispatcher::__construct()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 32
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 12
Bugs 1 Features 2
Metric Value
c 12
b 1
f 2
dl 0
loc 32
rs 8.5806
cc 4
eloc 17
nc 8
nop 4
1
<?php namespace Comodojo\Dispatcher;
2
3
use \Monolog\Logger;
4
use \Comodojo\Dispatcher\Components\Configuration;
5
use \Comodojo\Dispatcher\Components\DefaultConfiguration;
6
use \Comodojo\Dispatcher\Request\Model as Request;
7
use \Comodojo\Dispatcher\Router\Collector as RouteCollector;
8
use \Comodojo\Dispatcher\Response\Model as Response;
9
use \Comodojo\Dispatcher\Extra\Model as Extra;
10
use \Comodojo\Dispatcher\Components\Timestamp as TimestampTrait;
11
use \Comodojo\Dispatcher\Output\Processor;
12
use \Comodojo\Dispatcher\Events\DispatcherEvent;
13
use \Comodojo\Dispatcher\Events\ServiceEvent;
14
use \Comodojo\Dispatcher\Router\RoutingTableInterface;
15
use \Comodojo\Dispatcher\Log\DispatcherLogger;
16
use \Comodojo\Dispatcher\Cache\DispatcherCache;
17
use \Comodojo\Dispatcher\Events\EventsManager;
18
use \Comodojo\Cache\CacheManager;
19
use \League\Event\Emitter;
20
use \Comodojo\Exception\DispatcherException;
21
use \Exception;
22
23
/**
24
 * @package     Comodojo Dispatcher
25
 * @author      Marco Giovinazzi <[email protected]>
26
 * @author      Marco Castiello <[email protected]>
27
 * @license     GPL-3.0+
28
 *
29
 * LICENSE:
30
 *
31
 * This program is free software: you can redistribute it and/or modify
32
 * it under the terms of the GNU Affero General Public License as
33
 * published by the Free Software Foundation, either version 3 of the
34
 * License, or (at your option) any later version.
35
 *
36
 * This program is distributed in the hope that it will be useful,
37
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39
 * GNU Affero General Public License for more details.
40
 *
41
 * You should have received a copy of the GNU Affero General Public License
42
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
43
 */
44
45
class Dispatcher {
46
47
    use TimestampTrait;
48
49
    private $configuration;
50
51
    private $request;
52
53
    private $router;
54
55
    private $response;
56
57
    private $extra;
58
59
    private $logger;
60
61
    private $cache;
62
63
    private $events;
64
65
    public function __construct(
66
        $configuration = array(),
67
        Emitter $emitter = null,
68
        CacheManager $cache = null,
69
        Logger $logger = null
70
    ) {
71
72
        ob_start();
73
74
        $this->setTimestamp();
75
76
        $this->extra = new Extra($this->logger);
0 ignored issues
show
Unused Code introduced by
The call to Model::__construct() has too many arguments starting with $this->logger.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
77
78
        $this->configuration = new Configuration( DefaultConfiguration::get() );
79
80
        $this->configuration->merge($configuration);
81
82
        $this->events = is_null($emitter) ? new EventsManager() : $emitter;
83
84
        $this->logger = is_null($logger) ? DispatcherLogger::create($this->configuration) : $logger;
85
86
        $this->cache = is_null($cache) ? DispatcherCache::create($this->configuration, $this->logger) : $cache;
87
88
        $this->request = new Request($this->configuration, $this->logger);
89
90
        $this->router = new RouteCollector($this->configuration, $this->logger, $this->cache, $this->extra);
91
92
        $this->response = new Response($this->configuration, $this->logger);
93
94
        $this->logger->debug("Dispatcher ready, current date ".date('c', $this->getTimestamp()));
95
96
    }
97
98
    public function configuration() {
99
100
        return $this->configuration;
101
102
    }
103
104
    public function events() {
105
106
        return $this->events;
107
108
    }
109
110
    public function cache() {
111
112
        return $this->cache;
113
114
    }
115
116
    public function request() {
117
118
        return $this->request;
119
120
    }
121
122
    public function router() {
123
124
        return $this->router;
125
126
    }
127
128
    public function response() {
129
130
        return $this->response;
131
132
    }
133
134
    public function extra() {
135
136
        return $this->extra;
137
138
    }
139
140
    public function logger() {
141
142
        return $this->logger;
143
144
    }
145
146
    public function dispatch() {
147
148
        $this->logger->debug("Starting to dispatch.");
149
150
        $this->logger->debug("Emitting global dispatcher event.");
151
152
        $this->events->emit( new DispatcherEvent($this) );
153
154
        if ( $this->configuration()->get('enabled') === false ) {
155
156
            $this->logger->debug("Dispatcher disabled, shutting down gracefully.");
157
158
            $status = $this->configuration()->get('disabled-status');
159
160
            $content = $this->configuration()->get('disabled-message');
161
162
            $this->response()->status()->set($status);
163
164
            $this->response()->content()->set($content);
165
166
            return $this->shutdown();
167
168
        }
169
170
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.request') );
171
172
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.request.'.$this->request->method()->get()) );
173
174
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.request.#') );
175
176
        $this->logger->debug("Starting router.");
177
178
        try {
179
180
            $this->router->route($this->request);
181
182
        } catch (DispatcherException $de) {
183
184
            $this->logger->debug("Route error (".$de->getStatus()."), shutting down dispatcher.");
185
186
            $this->processDispatcherException($de);
187
188
            return $this->shutdown();
189
190
        }
191
192
        $route_type = $this->router->getType();
193
194
        $route_service = $this->router->getService();
195
196
        $this->logger->debug("Route acquired, type $route_type directed to $route_service.");
197
198
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.route') );
199
200
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.route.'.$route_type) );
201
202
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.route.'.$route_service) );
203
204
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.route.#') );
205
206
        // translate route to service
207
208
        $this->logger->debug("Running $route_service service.");
209
210
        try {
211
212
            $this->router->compose($this->response);
213
214
        } catch (DispatcherException $de) {
215
216
            $this->logger->debug("Service exception (".$de->getStatus()."), shutting down dispatcher.");
217
218
            $this->processDispatcherException($de);
219
220
        }
221
222
        return $this->shutdown();
223
224
    }
225
226
    private function emitServiceSpecializedEvents($name) {
227
228
        $this->logger->debug("Emitting $name service-event.");
229
230
        return new ServiceEvent(
231
            $name,
232
            $this->logger,
233
            $this->request,
234
            $this->router,
235
            $this->response,
236
            $this->extra
237
        );
238
239
    }
240
241
    private function processDispatcherException(DispatcherException $de) {
242
243
        $status = $de->getStatus();
244
245
        $message = $de->getMessage();
246
247
        $headers = $de->getHeaders();
0 ignored issues
show
Bug introduced by
The method getHeaders() does not seem to exist on object<Comodojo\Exception\DispatcherException>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
248
249
        $this->response()->status()->set($status);
250
251
        $this->response()->content()->set($message);
252
253
        $this->response()->headers()->merge($headers);
254
255
    }
256
257
    private function shutdown() {
258
259
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.response') );
260
261
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.response.'.$this->response->status()->get()) );
262
263
        $this->events->emit( $this->emitServiceSpecializedEvents('dispatcher.response.#') );
264
265
        $this->logger->debug("Composing return value.");
266
267
        $return = Processor::parse($this->configuration, $this->logger, $this->response);
268
269
        $this->logger->debug("Dispatcher run-cycle ends.");
270
271
        ob_end_clean();
272
273
        return $return;
274
275
    }
276
277
}
278