These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace ByJG\RestServer; |
||
4 | |||
5 | use ByJG\Cache\Psr16\NoCacheEngine; |
||
6 | use ByJG\RestServer\Exception\ClassNotFoundException; |
||
7 | use ByJG\RestServer\Exception\Error404Exception; |
||
8 | use ByJG\RestServer\Exception\Error405Exception; |
||
9 | use ByJG\RestServer\Exception\Error520Exception; |
||
10 | use ByJG\RestServer\Exception\InvalidClassException; |
||
11 | use ByJG\RestServer\Exception\OperationIdInvalidException; |
||
12 | use ByJG\RestServer\Exception\SchemaInvalidException; |
||
13 | use ByJG\RestServer\Exception\SchemaNotFoundException; |
||
14 | use ByJG\RestServer\HandleOutput\HandleOutputInterface; |
||
15 | use ByJG\RestServer\HandleOutput\HtmlHandler; |
||
16 | use ByJG\RestServer\HandleOutput\JsonHandler; |
||
17 | use ByJG\RestServer\HandleOutput\XmlHandler; |
||
18 | use FastRoute\Dispatcher; |
||
19 | use FastRoute\RouteCollector; |
||
20 | use Psr\SimpleCache\CacheInterface; |
||
21 | |||
22 | class ServerRequestHandler |
||
23 | { |
||
24 | const OK = "OK"; |
||
25 | const METHOD_NOT_ALLOWED = "NOT_ALLOWED"; |
||
26 | const NOT_FOUND = "NOT FOUND"; |
||
27 | |||
28 | protected $routes = null; |
||
29 | |||
30 | protected $defaultHandler = null; |
||
31 | |||
32 | protected $mimeTypeHandler = [ |
||
33 | "text/xml" => XmlHandler::class, |
||
34 | "application/xml" => XmlHandler::class, |
||
35 | "text/html" => HtmlHandler::class, |
||
36 | "application/json" => JsonHandler::class |
||
37 | ]; |
||
38 | |||
39 | protected $pathHandler = [ |
||
40 | |||
41 | ]; |
||
42 | |||
43 | public function getRoutes() |
||
44 | { |
||
45 | return $this->routes; |
||
46 | } |
||
47 | |||
48 | /** |
||
49 | * @param \ByJG\RestServer\RoutePattern[] $routes |
||
50 | */ |
||
51 | public function setRoutes($routes) |
||
52 | { |
||
53 | foreach ((array)$routes as $route) { |
||
54 | $this->addRoute($route); |
||
55 | } |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * @param \ByJG\RestServer\RoutePattern $route |
||
60 | */ |
||
61 | public function addRoute(RoutePattern $route) |
||
62 | { |
||
63 | if (is_null($this->routes)) { |
||
64 | $this->routes = []; |
||
65 | } |
||
66 | $this->routes[] = $route; |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * @return HandleOutputInterface |
||
71 | */ |
||
72 | public function getDefaultHandler() |
||
73 | { |
||
74 | if (empty($this->defaultHandler)) { |
||
75 | $this->defaultHandler = new JsonHandler(); |
||
76 | } |
||
77 | return $this->defaultHandler; |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * @param HandleOutputInterface $defaultHandler |
||
82 | */ |
||
83 | public function setDefaultHandler(HandleOutputInterface $defaultHandler) |
||
84 | { |
||
85 | $this->defaultHandler = $defaultHandler; |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * @throws \ByJG\RestServer\Exception\ClassNotFoundException |
||
90 | * @throws \ByJG\RestServer\Exception\Error404Exception |
||
91 | * @throws \ByJG\RestServer\Exception\Error405Exception |
||
92 | * @throws \ByJG\RestServer\Exception\Error520Exception |
||
93 | * @throws \ByJG\RestServer\Exception\InvalidClassException |
||
94 | */ |
||
95 | protected function process() |
||
0 ignored issues
–
show
|
|||
96 | { |
||
97 | // Initialize ErrorHandler with default error handler |
||
98 | ErrorHandler::getInstance()->register(); |
||
99 | |||
100 | // Get the URL parameters |
||
101 | $httpMethod = $_SERVER['REQUEST_METHOD']; |
||
102 | $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); |
||
103 | parse_str(parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY), $queryStr); |
||
104 | |||
105 | // Generic Dispatcher for RestServer |
||
106 | $dispatcher = \FastRoute\simpleDispatcher(function (RouteCollector $r) { |
||
107 | |||
108 | foreach ($this->getRoutes() as $route) { |
||
109 | $r->addRoute( |
||
110 | $route->properties('method'), |
||
111 | $route->properties('pattern'), |
||
112 | [ |
||
113 | "handler" => $route->properties('handler'), |
||
114 | "class" => $route->properties('class'), |
||
115 | "function" => $route->properties('function') |
||
116 | ] |
||
117 | ); |
||
118 | } |
||
119 | }); |
||
120 | |||
121 | $routeInfo = $dispatcher->dispatch($httpMethod, $uri); |
||
122 | |||
123 | // Default Handler for errors |
||
124 | $this->getDefaultHandler()->writeHeader(); |
||
125 | ErrorHandler::getInstance()->setHandler($this->getDefaultHandler()->getErrorHandler()); |
||
126 | |||
127 | // Processing |
||
128 | switch ($routeInfo[0]) { |
||
129 | case Dispatcher::NOT_FOUND: |
||
130 | throw new Error404Exception("404 Route '$uri' Not found"); |
||
131 | |||
132 | case Dispatcher::METHOD_NOT_ALLOWED: |
||
133 | throw new Error405Exception('405 Method Not Allowed'); |
||
134 | |||
135 | case Dispatcher::FOUND: |
||
136 | // ... 200 Process: |
||
137 | $vars = array_merge($routeInfo[2], $queryStr); |
||
138 | |||
139 | // Instantiate the Service Handler |
||
140 | $handlerRequest = $routeInfo[1]; |
||
141 | |||
142 | // Execute the request |
||
143 | $handler = !empty($handlerRequest['handler']) ? $handlerRequest['handler'] : $this->getDefaultHandler(); |
||
144 | $this->executeRequest( |
||
145 | new $handler(), |
||
146 | $handlerRequest['class'], |
||
147 | $handlerRequest['function'], |
||
148 | $vars |
||
149 | ); |
||
150 | |||
151 | break; |
||
152 | |||
153 | default: |
||
154 | throw new Error520Exception('Unknown'); |
||
155 | } |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * @param HandleOutputInterface $handler |
||
160 | * @param string $class |
||
161 | * @param string $function |
||
162 | * @param array $vars |
||
163 | * @throws \ByJG\RestServer\Exception\ClassNotFoundException |
||
164 | * @throws \ByJG\RestServer\Exception\InvalidClassException |
||
165 | */ |
||
166 | protected function executeRequest($handler, $class, $function, $vars) |
||
0 ignored issues
–
show
executeRequest uses the super-global variable $_REQUEST which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
executeRequest uses the super-global variable $_GET which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
executeRequest uses the super-global variable $_POST which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
executeRequest uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
executeRequest uses the super-global variable $_SESSION which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
executeRequest uses the super-global variable $_COOKIE which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
167 | { |
||
168 | // Setting Default Headers and Error Handler |
||
169 | $handler->writeHeader(); |
||
170 | ErrorHandler::getInstance()->setHandler($handler->getErrorHandler()); |
||
171 | |||
172 | // Set all default values |
||
173 | foreach (array_keys($vars) as $key) { |
||
174 | $_REQUEST[$key] = $_GET[$key] = $vars[$key]; |
||
175 | } |
||
176 | |||
177 | // Create the Request and Response methods |
||
178 | $request = new HttpRequest($_GET, $_POST, $_SERVER, isset($_SESSION) ? $_SESSION : [], $_COOKIE); |
||
179 | $response = new HttpResponse(); |
||
180 | |||
181 | // Process Closure |
||
182 | if ($function instanceof \Closure) { |
||
183 | $function($response, $request); |
||
184 | echo $handler->processResponse($response); |
||
185 | return; |
||
186 | } |
||
187 | |||
188 | // Process Class::Method() |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
50% 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...
|
|||
189 | if (!class_exists($class)) { |
||
190 | throw new ClassNotFoundException("Class '$class' defined in the route is not found"); |
||
191 | } |
||
192 | $instance = new $class(); |
||
193 | if (!method_exists($instance, $function)) { |
||
194 | throw new InvalidClassException("There is no method '$class::$function''"); |
||
195 | } |
||
196 | $instance->$function($response, $request); |
||
197 | $handler->processResponse($response); |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * Handle the ROUTE (see web/app-dist.php) |
||
202 | * |
||
203 | * @param \ByJG\RestServer\RoutePattern[]|null $routePattern |
||
204 | * @param bool $outputBuffer |
||
205 | * @param bool $session |
||
206 | * @throws \ByJG\RestServer\Exception\ClassNotFoundException |
||
207 | * @throws \ByJG\RestServer\Exception\Error404Exception |
||
208 | * @throws \ByJG\RestServer\Exception\Error405Exception |
||
209 | * @throws \ByJG\RestServer\Exception\Error520Exception |
||
210 | * @throws \ByJG\RestServer\Exception\InvalidClassException |
||
211 | */ |
||
212 | public function handle($routePattern = null, $outputBuffer = true, $session = true) |
||
0 ignored issues
–
show
handle uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
213 | { |
||
214 | if ($outputBuffer) { |
||
215 | ob_start(); |
||
216 | } |
||
217 | if ($session) { |
||
218 | session_start(); |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * @var ServerRequestHandler |
||
223 | */ |
||
224 | $this->setRoutes($routePattern); |
||
0 ignored issues
–
show
It seems like
$routePattern defined by parameter $routePattern on line 212 can also be of type null ; however, ByJG\RestServer\ServerRequestHandler::setRoutes() does only seem to accept array<integer,object<ByJ...stServer\RoutePattern>> , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
225 | |||
226 | // -------------------------------------------------------------------------- |
||
227 | // Check if script exists or if is itself |
||
228 | // -------------------------------------------------------------------------- |
||
229 | |||
230 | $debugBacktrace = debug_backtrace(); |
||
231 | if (!empty($_SERVER['SCRIPT_FILENAME']) |
||
232 | && file_exists($_SERVER['SCRIPT_FILENAME']) |
||
233 | && basename($_SERVER['SCRIPT_FILENAME']) !== basename($debugBacktrace[0]['file']) |
||
234 | ) { |
||
235 | $file = $_SERVER['SCRIPT_FILENAME']; |
||
236 | if (strpos($file, '.php') !== false) { |
||
237 | require_once($file); |
||
238 | } else { |
||
239 | header("Content-Type: " . $this->mimeContentType($file)); |
||
240 | |||
241 | echo file_get_contents($file); |
||
242 | } |
||
243 | return; |
||
244 | } |
||
245 | |||
246 | $this->process(); |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * Get the Mime Type based on the filename |
||
251 | * |
||
252 | * @param string $filename |
||
253 | * @return string |
||
254 | */ |
||
255 | protected function mimeContentType($filename) |
||
256 | { |
||
257 | |||
258 | $mimeTypes = array( |
||
259 | 'txt' => 'text/plain', |
||
260 | 'htm' => 'text/html', |
||
261 | 'html' => 'text/html', |
||
262 | 'php' => 'text/html', |
||
263 | 'css' => 'text/css', |
||
264 | 'js' => 'application/javascript', |
||
265 | 'json' => 'application/json', |
||
266 | 'xml' => 'application/xml', |
||
267 | 'swf' => 'application/x-shockwave-flash', |
||
268 | 'flv' => 'video/x-flv', |
||
269 | // images |
||
270 | 'png' => 'image/png', |
||
271 | 'jpe' => 'image/jpeg', |
||
272 | 'jpeg' => 'image/jpeg', |
||
273 | 'jpg' => 'image/jpeg', |
||
274 | 'gif' => 'image/gif', |
||
275 | 'bmp' => 'image/bmp', |
||
276 | 'ico' => 'image/vnd.microsoft.icon', |
||
277 | 'tiff' => 'image/tiff', |
||
278 | 'tif' => 'image/tiff', |
||
279 | 'svg' => 'image/svg+xml', |
||
280 | 'svgz' => 'image/svg+xml', |
||
281 | // archives |
||
282 | 'zip' => 'application/zip', |
||
283 | 'rar' => 'application/x-rar-compressed', |
||
284 | 'exe' => 'application/x-msdownload', |
||
285 | 'msi' => 'application/x-msdownload', |
||
286 | 'cab' => 'application/vnd.ms-cab-compressed', |
||
287 | // audio/video |
||
288 | 'mp3' => 'audio/mpeg', |
||
289 | 'qt' => 'video/quicktime', |
||
290 | 'mov' => 'video/quicktime', |
||
291 | // adobe |
||
292 | 'pdf' => 'application/pdf', |
||
293 | 'psd' => 'image/vnd.adobe.photoshop', |
||
294 | 'ai' => 'application/postscript', |
||
295 | 'eps' => 'application/postscript', |
||
296 | 'ps' => 'application/postscript', |
||
297 | // ms office |
||
298 | 'doc' => 'application/msword', |
||
299 | 'rtf' => 'application/rtf', |
||
300 | 'xls' => 'application/vnd.ms-excel', |
||
301 | 'ppt' => 'application/vnd.ms-powerpoint', |
||
302 | // open office |
||
303 | 'odt' => 'application/vnd.oasis.opendocument.text', |
||
304 | 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', |
||
305 | ); |
||
306 | |||
307 | $ext = strtolower(array_pop(explode('.', $filename))); |
||
308 | if (array_key_exists($ext, $mimeTypes)) { |
||
309 | return $mimeTypes[$ext]; |
||
310 | } elseif (function_exists('finfo_open')) { |
||
311 | $finfo = finfo_open(FILEINFO_MIME); |
||
312 | $mimetype = finfo_file($finfo, $filename); |
||
313 | finfo_close($finfo); |
||
314 | return $mimetype; |
||
315 | } else { |
||
316 | return 'application/octet-stream'; |
||
317 | } |
||
318 | } |
||
319 | |||
320 | /** |
||
321 | * @param $swaggerJson |
||
322 | * @param \Psr\SimpleCache\CacheInterface|null $cache |
||
323 | * @throws \ByJG\RestServer\Exception\SchemaInvalidException |
||
324 | * @throws \ByJG\RestServer\Exception\SchemaNotFoundException |
||
325 | * @throws \ByJG\RestServer\Exception\OperationIdInvalidException |
||
326 | */ |
||
327 | public function setRoutesSwagger($swaggerJson, CacheInterface $cache = null) |
||
328 | { |
||
329 | if (!file_exists($swaggerJson)) { |
||
330 | throw new SchemaNotFoundException("Schema '$swaggerJson' not found"); |
||
331 | } |
||
332 | |||
333 | $schema = json_decode(file_get_contents($swaggerJson), true); |
||
334 | if (!isset($schema['paths'])) { |
||
335 | throw new SchemaInvalidException("Schema '$swaggerJson' is invalid"); |
||
336 | } |
||
337 | |||
338 | if (is_null($cache)) { |
||
339 | $cache = new NoCacheEngine(); |
||
340 | } |
||
341 | |||
342 | $routePattern = $cache->get('SERVERHANDLERROUTES', false); |
||
343 | if ($routePattern === false) { |
||
344 | $routePattern = $this->generateRoutes($schema); |
||
345 | $cache->set('SERVERHANDLERROUTES', $routePattern); |
||
346 | } |
||
347 | $this->setRoutes($routePattern); |
||
348 | } |
||
349 | |||
350 | /** |
||
351 | * @param $schema |
||
352 | * @return array |
||
353 | * @throws \ByJG\RestServer\Exception\OperationIdInvalidException |
||
354 | */ |
||
355 | protected function generateRoutes($schema) |
||
356 | { |
||
357 | $pathList = $this->sortPaths(array_keys($schema['paths'])); |
||
358 | |||
359 | $routes = []; |
||
360 | foreach ($pathList as $path) { |
||
361 | foreach ($schema['paths'][$path] as $method => $properties) { |
||
362 | $handler = $this->getMethodHandler($method, $path, $properties); |
||
363 | if (!isset($properties['operationId'])) { |
||
364 | throw new OperationIdInvalidException('OperationId was not found'); |
||
365 | } |
||
366 | |||
367 | $parts = explode('::', $properties['operationId']); |
||
368 | if (count($parts) !== 2) { |
||
369 | throw new OperationIdInvalidException( |
||
370 | 'OperationId needs to be in the format Namespace\\class::method' |
||
371 | ); |
||
372 | } |
||
373 | |||
374 | $routes[] = new RoutePattern( |
||
375 | strtoupper($method), |
||
376 | $path, |
||
377 | $handler, |
||
378 | $parts[1], |
||
379 | $parts[0] |
||
380 | ); |
||
381 | } |
||
382 | } |
||
383 | |||
384 | return $routes; |
||
385 | } |
||
386 | |||
387 | protected function sortPaths($pathList) |
||
388 | { |
||
389 | usort($pathList, function ($left, $right) { |
||
390 | View Code Duplication | if (strpos($left, '{') === false && strpos($right, '{') !== false) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
391 | return -16384; |
||
392 | } |
||
393 | View Code Duplication | if (strpos($left, '{') !== false && strpos($right, '{') === false) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
394 | return 16384; |
||
395 | } |
||
396 | if (strpos($left, $right) !== false) { |
||
397 | return -16384; |
||
398 | } |
||
399 | if (strpos($right, $left) !== false) { |
||
400 | return 16384; |
||
401 | } |
||
402 | return strcmp($left, $right); |
||
403 | }); |
||
404 | |||
405 | return $pathList; |
||
406 | } |
||
407 | |||
408 | /** |
||
409 | * @param $method |
||
410 | * @param $path |
||
411 | * @param $properties |
||
412 | * @return string |
||
413 | * @throws \ByJG\RestServer\Exception\OperationIdInvalidException |
||
414 | */ |
||
415 | protected function getMethodHandler($method, $path, $properties) |
||
416 | { |
||
417 | $method = strtoupper($method); |
||
418 | if (isset($this->pathHandler["$method::$path"])) { |
||
419 | return $this->pathHandler["$method::$path"]; |
||
420 | } |
||
421 | if (!isset($properties['produces'])) { |
||
422 | return get_class($this->getDefaultHandler()); |
||
423 | } |
||
424 | |||
425 | $produces = $properties['produces']; |
||
426 | if (is_array($produces)) { |
||
427 | $produces = $produces[0]; |
||
428 | } |
||
429 | |||
430 | if (!isset($this->mimeTypeHandler[$produces])) { |
||
431 | throw new OperationIdInvalidException("There is no handler for $produces"); |
||
432 | } |
||
433 | |||
434 | return $this->mimeTypeHandler[$produces]; |
||
435 | } |
||
436 | |||
437 | public function setMimeTypeHandler($mimetype, $handler) |
||
438 | { |
||
439 | $this->mimeTypeHandler[$mimetype] = $handler; |
||
440 | } |
||
441 | |||
442 | public function setPathHandler($method, $path, $handler) |
||
443 | { |
||
444 | $method = strtoupper($method); |
||
445 | $this->pathHandler["$method::$path"] = $handler; |
||
446 | } |
||
447 | } |
||
448 |
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: