Completed
Push — 4.0 ( 4d6b64...872671 )
by Marco
03:00
created

Dispatcher::dispatch()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 83
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 8.3593

Importance

Changes 3
Bugs 1 Features 0
Metric Value
dl 0
loc 83
ccs 20
cts 41
cp 0.4878
rs 8.3634
c 3
b 1
f 0
cc 5
eloc 43
nc 5
nop 0
crap 8.3593

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php namespace Comodojo\Dispatcher;
2
3
use \Comodojo\Dispatcher\Components\AbstractModel;
4
use \Comodojo\Dispatcher\Components\DefaultConfiguration;
5
use \Comodojo\Dispatcher\Cache\ServerCache;
6
use \Comodojo\Dispatcher\Request\Model as Request;
7
use \Comodojo\Dispatcher\Router\Model as Router;
8
use \Comodojo\Dispatcher\Response\Model as Response;
9
use \Comodojo\Dispatcher\Extra\Model as Extra;
10
use \Comodojo\Dispatcher\Output\Processor;
11
use \Comodojo\Dispatcher\Events\DispatcherEvent;
12
use \Comodojo\Dispatcher\Events\ServiceEvent;
13
use \Comodojo\Dispatcher\Traits\CacheTrait;
14
use \Comodojo\Dispatcher\Traits\RequestTrait;
15
use \Comodojo\Dispatcher\Traits\ResponseTrait;
16
use \Comodojo\Dispatcher\Traits\RouterTrait;
17
use \Comodojo\Dispatcher\Traits\ExtraTrait;
18
use \Comodojo\Dispatcher\Traits\EventsTrait;
19
use \Comodojo\Foundation\Base\Configuration;
20
use \Comodojo\Foundation\Timing\TimingTrait;
21
use \Comodojo\Foundation\Events\Manager as EventsManager;
22
use \Comodojo\Foundation\Logging\Manager as LogManager;
23
use \Comodojo\SimpleCache\Manager as SimpleCacheManager;
24
use \Psr\Log\LoggerInterface;
25
use \Comodojo\Exception\DispatcherException;
26
use \Exception;
27
28
/**
29
 * @package     Comodojo Dispatcher
30
 * @author      Marco Giovinazzi <[email protected]>
31
 * @author      Marco Castiello <[email protected]>
32
 * @license     GPL-3.0+
33
 *
34
 * LICENSE:
35
 *
36
 * This program is free software: you can redistribute it and/or modify
37
 * it under the terms of the GNU Affero General Public License as
38
 * published by the Free Software Foundation, either version 3 of the
39
 * License, or (at your option) any later version.
40
 *
41
 * This program is distributed in the hope that it will be useful,
42
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44
 * GNU Affero General Public License for more details.
45
 *
46
 * You should have received a copy of the GNU Affero General Public License
47
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
48
 */
49
50
class Dispatcher extends AbstractModel {
51
52
    use TimingTrait;
53
    use CacheTrait;
54
    use RequestTrait;
55
    use ResponseTrait;
56
    use RouterTrait;
57
    use ExtraTrait;
58
    use EventsTrait;
59
60
    protected $route;
61
62
    /**
63
     * The main dispatcher constructor.
64
     *
65
     */
66 1
    public function __construct(
67
        array $configuration = [],
68
        EventsManager $events = null,
69
        SimpleCacheManager $cache = null,
70
        LoggerInterface $logger = null
71
    ) {
72
73
        // starting output buffer
74 1
        ob_start();
75
76
        // fix current timestamp
77 1
        $this->setTiming();
78
79
        // init core components
80
        // create new configuration object and merge configuration
81 1
        $configuration_object = new Configuration( DefaultConfiguration::get() );
82 1
        $configuration_object->merge($configuration);
83
84 1
        $logger = is_null($logger) ? LogManager::createFromConfiguration($configuration_object)->getLogger() : $logger;
85
86 1
        parent::__construct($configuration_object, $logger);
87
88 1
        $this->logger->debug("--------------------------------------------------------");
89 1
        $this->logger->debug("Dispatcher run-cycle starts at ".$this->getTime()->format('c'));
90
91
        try {
92
93
            // init other components
94 1
            $this->setEvents(is_null($events) ? EventsManager::create($this->logger) : $events);
95 1
            $this->setCache(is_null($cache) ? SimpleCacheManager::createFromConfiguration($this->configuration, $this->logger) : $cache);
96
97
            // init models
98 1
            $this->setExtra(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...
99 1
            $this->setRequest(new Request($this->configuration, $this->logger));
100 1
            $this->setRouter(new Router($this->configuration, $this->logger, $this->cache, $this->events, $this->extra));
101 1
            $this->setResponse(new Response($this->configuration, $this->logger));
102
103 1
        } catch (Exception $e) {
104
105
            $this->logger->critical($e->getMessage(),$e->getTrace());
106
107
            throw $e;
108
109 1
        }
110
111
        // we're ready!
112 1
        $this->logger->debug("Dispatcher ready");
113
114 1
    }
115
116 1
    public function dispatch() {
117
118 1
        $logger = $this->getLogger();
119 1
        $configuration = $this->getConfiguration();
120 1
        $events = $this->getEvents();
121
122 1
        $logger->debug("Starting to dispatch.");
123
124 1
        $logger->debug("Emitting global dispatcher event.");
125 1
        $events->emit( new DispatcherEvent($this) );
126
127 1
        if ( $configuration->get('enabled') === false ) {
128
129
            $logger->debug("Dispatcher disabled, shutting down gracefully.");
130
131
            $status = $configuration->get('disabled-status');
132
            $content = $configuration->get('disabled-message');
133
134
            $this->getResponse()->getStatus()->set($status);
135
            $this->getResponse()->getContent()->set($content);
136
137
            return $this->shutdown();
138
139
        }
140
141 1
        $cache = new ServerCache($this->getCache());
142
143 1
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.request') );
144 1
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.request.'.$this->request->method->get()) );
0 ignored issues
show
Bug introduced by
The property method does not seem to exist in Comodojo\Dispatcher\Request\Model.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
145 1
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.request.#') );
146
147 1
        if ( $cache->read($this->request, $this->response) ) {
148
            // we have a cache!
149
            // shutdown immediately
150
            return $this->shutdown();
151
        }
152
153 1
        $logger->debug("Starting router");
154
155
        try {
156
157 1
            $this->route = $this->getRouter()->route($this->request);
158
159 1
        } catch (DispatcherException $de) {
160
161 1
            $logger->debug("Route error (".$de->getStatus()."), shutting down dispatcher");
162 1
            $this->processDispatcherException($de);
163 1
            return $this->shutdown();
164
165
        }
166
167
        $route_type = $this->route->getType();
168
169
        $route_service = $this->route->getServiceName();
170
171
        $logger->debug("Route acquired, type $route_type directed to $route_service");
172
173
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.route') );
174
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.route.'.$route_type) );
175
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.route.'.$route_service) );
176
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.route.#') );
177
178
        // translate route to service
179
        $logger->debug("Running $route_service service");
180
181
        try {
182
183
            $this->router->compose($this->response);
184
185
        } catch (DispatcherException $de) {
186
187 1
            $logger->debug("Service exception (".$de->getStatus()."), shutting down dispatcher");
188
            $this->processDispatcherException($de);
189
190
        }
191
192
        $this->processConfigurationParameters($this->route);
193
194
        $cache->dump($this->request, $this->response, $this->route);
195
196
        return $this->shutdown();
197
198
    }
199
200
    private function processConfigurationParameters($route) {
201
202
        $params = $route->getParameter('headers');
203
204
        if ( !empty($params) && is_array($params) ) {
205
            foreach($params as $name => $value) $this->getResponse()->getHeaders()->set($name, $value);
206
        }
207
208
    }
209
210 1
    private function createServiceSpecializedEvents($name) {
211
212 1
        $this->logger->debug("Emitting $name service-event");
213
214 1
        return new ServiceEvent(
215 1
            $name,
216 1
            $this->getConfiguration(),
217 1
            $this->getLogger(),
218 1
            $this->getCache(),
219 1
            $this->getEvents(),
220 1
            $this->getRequest(),
221 1
            $this->getRouter(),
222 1
            $this->getResponse(),
223 1
            $this->getExtra()
224 1
        );
225
226
    }
227
228 1
    private function processDispatcherException(DispatcherException $de) {
229
230 1
        $status = $de->getStatus();
231 1
        $message = $de->getMessage();
232 1
        $headers = $de->getHeaders();
233
234 1
        $response = $this->getResponse();
235
236 1
        $response->getStatus()->set($status);
237 1
        $response->getContent()->set($message);
238 1
        $response->getHeaders()->merge($headers);
239
240 1
    }
241
242 1
    private function shutdown() {
243
244 1
        $events = $this->getEvents();
245 1
        $request = $this->getRequest();
246 1
        $response = $this->getResponse();
247
248 1
        $response->consolidate($request, $this->route);
249
250 1
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.response') );
251 1
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.response.' . $response->getStatus()->get()) );
252 1
        $events->emit( $this->createServiceSpecializedEvents('dispatcher.response.#') );
253
254 1
        $this->logger->debug("Composing return value");
255
256 1
        $return = Processor::parse($this->getConfiguration(), $this->logger, $request, $response);
257
258 1
        $this->logger->debug("Dispatcher run-cycle ends");
259
260
        // This could cause WSOD with some PHP-FPM configurations
261
        // if ( function_exists('fastcgi_finish_request') ) fastcgi_finish_request();
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
262
        // else ob_end_clean();
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
263 1
        ob_end_clean();
264
265 1
        return $return;
266
267
    }
268
269
}
270