summaryrefslogtreecommitdiffstats
path: root/src/Router/Middleware/NotFound.php
blob: 2484a438afdbaf033ec7430adc37dac4bdf36026 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php

namespace Jasny\Router\Middleware;

use Jasny\Router\Routes;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

/**
 * Set response to 'not found' or 'method not allowed' if route is non exist 
 */
class NotFound
{    
    /**
     * Routes
     * @var Routes
     */
    protected $routes = null;

    /**
     * Action for 'not found' case
     * @var callback|int
     **/
    protected $notFound = null;

    /**
     * Action for 'method not allowed' case
     * @var callback|int
     **/
    protected $methodNotAllowed = null;

    
    /**
     * Class constructor
     * 
     * @param Routes $routes
     * @param callback|int $notFound 
     * @param callback|int $methodNotAllowed 
     */
    public function __construct(Routes $routes, $notFound = 404, $methodNotAllowed = null)
    {
        if (is_string($notFound) && ctype_digit($notFound)) {
            $notFound = (int)$notFound;
        }
        if (!(is_int($notFound) && $notFound >= 100 && $notFound <= 999) && !is_callable($notFound)) {
            throw new \InvalidArgumentException("'notFound' should be valid HTTP status code or a callback");
        }

        if (is_string($methodNotAllowed) && ctype_digit($methodNotAllowed)) {
            $methodNotAllowed = (int)$methodNotAllowed;
        }
        if (
            isset($methodNotAllowed) &&
            !(is_int($methodNotAllowed) && $methodNotAllowed >= 100 && $methodNotAllowed <= 999) &&
            !is_callable($methodNotAllowed)
        ) {
            throw new \InvalidArgumentException("'methodNotAllowed' should be valid HTTP status code or a callback");   
        }

        $this->routes = $routes;
        $this->notFound = $notFound;
        $this->methodNotAllowed = $methodNotAllowed;
    }

    /**
     * Get routes
     *
     * @return Routes
     */
    public function getRoutes()
    {
        return $this->routes;
    }
    

    /**
     * Run middleware action
     *
     * @param ServerRequestInterface $request
     * @param ResponseInterface      $response
     * @param callback               $next
     * @return ResponseInterface
     */
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
    {
        if (!is_callable($next)) {
            throw new \InvalidArgumentException("'next' should be a callback");            
        }

        if (!$this->getRoutes()->hasRoute($request)) {
            $status = $this->methodNotAllowed && $this->getRoutes()->hasRoute($request, false) ? 
                $this->methodNotAllowed : $this->notFound;

            return is_numeric($status) ? $this->simpleResponse($response, $status) : $status($request, $response);
        }
        
        return $next($request, $response);
    }

    /**
     * Simple response
     *
     * @param ResponseInterface $response
     * @param int               $code
     * @return ResponseInterface
     */
    protected function simpleResponse(ResponseInterface $response, $code)
    {
        $notFound = $response->withStatus($code);
        $notFound->getBody()->write('Not found');

        return $notFound;
    }
}