Completed
Push — 4.0 ( b44693...cafdfc )
by Marco
02:39
created

Model::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 17
ccs 0
cts 7
cp 0
rs 9.4285
c 1
b 0
f 0
cc 1
eloc 11
nc 1
nop 5
crap 2
1
<?php namespace Comodojo\Dispatcher\Router;
2
3
use \Comodojo\Dispatcher\Traits\CacheTrait;
4
use \Comodojo\Dispatcher\Traits\EventsTrait;
5
use \Comodojo\Dispatcher\Traits\RequestTrait;
6
use \Comodojo\Dispatcher\Traits\ResponseTrait;
7
use \Comodojo\Dispatcher\Traits\ExtraTrait;
8
use \Comodojo\Dispatcher\Components\AbstractModel;
9
use \Comodojo\Dispatcher\Request\Model as Request;
10
use \Comodojo\Dispatcher\Response\Model as Response;
11
use \Comodojo\Dispatcher\Extra\Model as Extra;
12
use \Comodojo\Foundation\Base\Configuration;
13
use \Comodojo\Foundation\Events\Manager as EventsManager;
14
use \Comodojo\SimpleCache\Manager as SimpleCacheManager;
15
use \Psr\Log\LoggerInterface;
16
use \Comodojo\Exception\DispatcherException;
17
use \Exception;
18
19
/**
20
 * @package     Comodojo Dispatcher
21
 * @author      Marco Giovinazzi <[email protected]>
22
 * @author      Marco Castiello <[email protected]>
23
 * @license     GPL-3.0+
24
 *
25
 * LICENSE:
26
 *
27
 * This program is free software: you can redistribute it and/or modify
28
 * it under the terms of the GNU Affero General Public License as
29
 * published by the Free Software Foundation, either version 3 of the
30
 * License, or (at your option) any later version.
31
 *
32
 * This program is distributed in the hope that it will be useful,
33
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35
 * GNU Affero General Public License for more details.
36
 *
37
 * You should have received a copy of the GNU Affero General Public License
38
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
39
 */
40
41
class Model extends AbstractModel {
42
43
    use CacheTrait;
44
    use EventsTrait;
45
    use RequestTrait;
46
    use ResponseTrait;
47
    use ExtraTrait;
48
49
    protected $bypass_routing = false;
50
    protected $bypass_service = false;
51
    protected $table;
52
53
    public function __construct(
54
        Configuration $configuration,
55
        LoggerInterface $logger,
56
        SimpleCacheManager $cache,
57
        EventsManager $events,
58
        Extra $extra
59
    ) {
60
61
        parent::__construct($configuration, $logger);
62
63
        $this->setCache($cache);
64
        $this->setExtra($extra);
65
        $this->setEvents($events);
66
67
        $this->setTable(new Table($cache, $this));
68
69
    }
70
71 1
    public function getTable() {
72
73 1
        return $this->table;
74
75
    }
76
77
    public function setTable(Table $table) {
78
79
        $this->table = $table;
80
81
    }
82
83 1
    public function bypassRouting(Route $route) {
84
85 1
        $this->bypass_routing = true;
86
87 1
        $this->route = $route;
0 ignored issues
show
Bug introduced by
The property route does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
88
89 1
        return $this;
90
91
    }
92
93
    public function bypassService() {
94
95
        $this->bypass_service = true;
96
97
        return $this;
98
99
    }
100
101
    public function getRoute() {
102
103
        return $this->route;
104
105
    }
106
107 1
    public function route(Request $request) {
108
109 1
        $method = (string) $request->getMethod();
110
111 1
        $methods = $this->configuration->get('allowed-http-methods');
112
113 1
        if ( !empty($methods) && in_array($method, $methods) === false ) {
114
115
            throw new DispatcherException("Method not allowed", 0, null, 405, array(
116
                "Allow" => implode(",",$methods)
117
            ));
118
119
        }
120
121 1
        $this->setRequest($request);
122
123 1
        if ( $this->bypass_routing === false ) {
124
125
            if ( !$this->parse() ) throw new DispatcherException("Unable to find a valid route for the specified uri", 0, null, 404);
126
127
        }
128
129 1
        return $this->route;
130
131
    }
132
133 1
    public function getServiceInstance() {
134
135 1
        $class = $this->route->getClassName();
136
137 1
        if ( class_exists($class) ) {
138
139
            // All the route parameters are also added to the query parameters
140 1
            foreach ($this->route->getRequestParameters() as $parameter => $value) {
141
                $this->getRequest()->getQuery()->set($parameter, $value);
142 1
            }
143
144 1
            return new $class(
145 1
                $this->getConfiguration(),
146 1
                $this->getLogger(),
147 1
                $this->getCache(),
148 1
                $this->getEvents(),
149 1
                $this->getRequest(),
150 1
                $this,
151 1
                $this->getResponse(),
152 1
                $this->getExtra()
153 1
            );
154
155
        }
156
157
        return null;
158
159
    }
160
161 1
    public function compose(Response $response) {
162
163 1
        $this->setResponse($response);
164
165 1
        if ( is_null($this->route) ) {
166
167
            throw new DispatcherException("Route has not been loaded!");
168
169
        }
170
171 1
        if ( $this->bypass_service ) {
172
173
            return;
174
175
        }
176
177 1
        $service = $this->getServiceInstance();
178
179 1
        if ( !is_null($service) ) {
180
181 1
            $result = "";
182
183 1
            $method = (string) $this->getRequest()->getMethod();
184
185 1
            $methods = $service->getImplementedMethods();
186
187 1
            if ( in_array($method, $methods) ) {
188
189 1
                $callable = $service->getMethod($method);
190
191
                try {
192
193 1
                    $result = call_user_func([$service, $callable]);
194
195 1
                } catch (DispatcherException $de) {
196
197
                    throw $de;
198
199
                } catch (Exception $e) {
200
201
                    throw new DispatcherException(sprintf("Service '%s' execution failed for method '%s': %s", $this->route->getClassName(), $method, $e->getMessage()), 0, $e, 500);
202
203
                }
204
205 1
            } else {
206
207
                throw new DispatcherException(sprintf("Service '%s' doesn't implement method '%s'", $this->route->getServiceName(), $method), 0, null, 501, array(
208
                    "Allow" => implode(",", $methods)
209
                ));
210
211
            }
212
213 1
            $this->getResponse()->getContent()->set($result);
214
215 1
        } else {
216
217
            throw new DispatcherException(sprintf("Unable to execute service '%s'", $this->route->getClassName()), 0, null, 500);
218
219
        }
220
221 1
    }
222
223
    private function parse() {
224
225
        $path = $this->getRequest()->route();
226
227
        foreach ($this->table->getRoutes() as $regex => $value) {
228
229
            // The current uri is checked against all the global regular expressions associated with the routes
230
            if ( preg_match("/" . $regex . "/", $path, $matches) ) {
231
232
                /* If a route is matched, all the bits of the route string are evalued in order to create
233
                 * new query parameters which will be available for the service class
234
                 */
235
                $this->route = $value->path($matches);
236
237
                return true;
238
239
            }
240
241
        }
242
243
        return false;
244
245
    }
246
247
}
248