Completed
Push — master ( 21b2df...093d50 )
by Oscar
03:00
created

Middleware::create()   C

Complexity

Conditions 7
Paths 4

Size

Total Lines 29
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 29
rs 6.7272
cc 7
eloc 16
nc 4
nop 2
1
<?php
2
3
namespace Psr7Middlewares;
4
5
use Psr\Http\Message\RequestInterface;
6
use Psr\Http\Message\ResponseInterface;
7
use RuntimeException;
8
use InvalidArgumentException;
9
10
class Middleware
11
{
12
    const KEY = 'Psr7Middlewares\\Middleware';
13
    const STORAGE_KEY = 'STORAGE_KEY';
14
15
    private static $streamFactory;
16
    private static $namespaces = ['Psr7Middlewares\\Middleware\\'];
17
18
    /**
19
     * Register a new namespace.
20
     *
21
     * @param string $namespace
22
     */
23
    public static function registerNamespace($namespace)
24
    {
25
        self::$namespaces[] = $namespace;
26
    }
27
28
    /**
29
     * Set the stream factory used by some middlewares.
30
     *
31
     * @param callable $streamFactory
32
     */
33
    public static function setStreamFactory(callable $streamFactory)
34
    {
35
        self::$streamFactory = $streamFactory;
36
    }
37
38
    /**
39
     * Set the stream factory used by some middlewares.
40
     *
41
     * @param callable|null
42
     */
43
    public static function getStreamFactory()
44
    {
45
        return self::$streamFactory;
46
    }
47
48
    /**
49
     * Create instances of the middlewares.
50
     *
51
     * @param string $name
52
     * @param array  $args
53
     */
54
    public static function __callStatic($name, $args)
55
    {
56
        foreach (self::$namespaces as $namespace) {
57
            $class = $namespace.ucfirst($name);
58
59
            if (class_exists($class)) {
60
                switch (count($args)) {
61
                    case 0:
62
                        return new $class();
63
64
                    case 1:
65
                        return new $class($args[0]);
66
67
                    default:
68
                        return (new \ReflectionClass($class))->newInstanceArgs($args);
69
                }
70
            }
71
        }
72
73
        throw new RuntimeException("The middleware {$name} does not exits");
74
    }
75
76
    /**
77
     * Create a middleware callable that acts as a "proxy" to a real middleware that must be returned by the given callback.
78
     *
79
     * @param callable|string $basePath The base path in which the middleware is created (optional)
80
     * @param callable        $factory  Takes no argument and MUST return a middleware callable or false
81
     * 
82
     * @return callable
83
     */
84
    public static function create($basePath, callable $factory = null)
85
    {
86
        if ($factory === null) {
87
            $factory = $basePath;
88
            $basePath = '';
89
        }
90
91
        if (!is_callable($factory)) {
92
            throw new InvalidArgumentException('Invalid callable provided');
93
        }
94
95
        return function (RequestInterface $request, ResponseInterface $response, callable $next) use ($basePath, $factory) {
96
            if (strlen($basePath) > 0 && strpos($request->getUri()->getPath(), $basePath) !== 0) {
97
                $middleware = false;
98
            } else {
99
                $middleware = $factory($request, $response);
100
            }
101
102
            if ($middleware === false) {
103
                return $next($request, $response);
104
            }
105
106
            if (!is_callable($middleware)) {
107
                throw new RuntimeException(sprintf('Factory returned "%s" instead of a callable or FALSE.', gettype($middleware)));
108
            }
109
110
            return $middleware($request, $response, $next);
111
        };
112
    }
113
}
114