Test Failed
Push — master ( a25a4c...498f08 )
by Divine Niiquaye
13:17
created

AppBuilder   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 40
c 1
b 0
f 0
dl 0
loc 172
rs 10
wmc 19

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A pipe() 0 3 1
A group() 0 8 1
A generateUri() 0 3 1
A options() 0 3 1
A match() 0 5 1
A doAnalyse() 0 5 1
A patch() 0 3 1
A put() 0 3 1
A delete() 0 3 1
A post() 0 3 1
A pipes() 0 3 1
A __call() 0 13 4
A build() 0 23 3
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of DivineNii opensource projects.
7
 *
8
 * PHP version 7.4 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 DivineNii (https://divinenii.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Rade;
19
20
use Flight\Routing\Interfaces\RouteMatcherInterface;
21
use Flight\Routing\Route;
22
use Flight\Routing\RouteCollection;
23
use Flight\Routing\Router;
24
use Symfony\Component\Config\ConfigCache;
25
26
/**
27
 * Create a cacheable application.
28
 *
29
 @author Divine Niiquaye Ibok <[email protected]>
30
 */
31
class AppBuilder extends DI\ContainerBuilder implements RouterInterface
32
{
33
    use Traits\HelperTrait;
34
35
    private int $routeIndex = -1;
36
37
    private string $routesId = 'router.collection_a';
38
39
    public function __construct(bool $debug = true)
40
    {
41
        parent::__construct(Application::class);
42
43
        $this->parameters['debug'] = $debug;
44
        $this->set('http.router', new DI\Definition(Router::class))->autowire([Router::class, RouteMatcherInterface::class]);
45
    }
46
47
    /**
48
     * @param array<int,mixed> $arguments
49
     *
50
     * @return $this
51
     */
52
    public function __call(string $name, array $arguments)
53
    {
54
        if (!(isset($this->parameters['routes'][$this->routeIndex]) || \method_exists(Route::class, $name))) {
55
            throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', __CLASS__, $name));
56
        }
57
58
        if (1 === \count($arguments)) {
59
            $arguments = $arguments[0];
60
        }
61
62
        $this->parameters['routes'][$this->routeIndex][$name] = $arguments;
63
64
        return $this;
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     *
70
     * @param Reference|Statement|callable ...$middlewares
0 ignored issues
show
Bug introduced by
The type Rade\Reference was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type Rade\Statement was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
71
     */
72
    public function pipe(object ...$middlewares): void
73
    {
74
        $this->definition('http.router')->bind('pipe', \func_get_args());
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     *
80
     * @param Reference|Statement|callable ...$middlewares
81
     */
82
    public function pipes(string $named, object ...$middlewares): void
83
    {
84
        $this->definition('http.router')->bind('pipes', \func_get_args());
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function generateUri(string $routeName, array $parameters = []): DI\Definitions\Statement
91
    {
92
        return new Di\Definitions\Statement([new DI\Definitions\Reference('http.router'), 'generateUri'], \func_get_args());
0 ignored issues
show
Bug Best Practice introduced by
The expression return new Rade\Di\Defin...Uri'), func_get_args()) returns the type Rade\Di\Definitions\Statement which is incompatible with the return type mandated by Rade\RouterInterface::generateUri() of Rade\GeneratedUri.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function match(string $pattern, array $methods = Route::DEFAULT_METHODS, $to = null)
99
    {
100
        $this->parameters['routes'][++$this->routeIndex] = ['path' => $pattern, 'method' => $methods, 'run' => $to];
101
102
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Rade\AppBuilder which is incompatible with the return type mandated by Rade\RouterInterface::match() of Flight\Routing\Route.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108
    public function post(string $pattern, $to = null)
109
    {
110
        return $this->match($pattern, [Router::METHOD_POST], $to);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->match($pat...ter::METHOD_POST), $to) returns the type Rade\AppBuilder which is incompatible with the return type mandated by Rade\RouterInterface::post() of Flight\Routing\Route.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public function put(string $pattern, $to = null)
117
    {
118
        return $this->match($pattern, [Router::METHOD_PUT], $to);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->match($pat...uter::METHOD_PUT), $to) returns the type Rade\AppBuilder which is incompatible with the return type mandated by Rade\RouterInterface::put() of Flight\Routing\Route.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function delete(string $pattern, $to = null)
125
    {
126
        return $this->match($pattern, [Router::METHOD_DELETE], $to);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->match($pat...r::METHOD_DELETE), $to) returns the type Rade\AppBuilder which is incompatible with the return type mandated by Rade\RouterInterface::delete() of Flight\Routing\Route.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function options(string $pattern, $to = null)
133
    {
134
        return $this->match($pattern, [Router::METHOD_OPTIONS], $to);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->match($pat...::METHOD_OPTIONS), $to) returns the type Rade\AppBuilder which is incompatible with the return type mandated by Rade\RouterInterface::options() of Flight\Routing\Route.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140
    public function patch(string $pattern, $to = null)
141
    {
142
        return $this->match($pattern, [Router::METHOD_PATCH], $to);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->match($pat...er::METHOD_PATCH), $to) returns the type Rade\AppBuilder which is incompatible with the return type mandated by Rade\RouterInterface::patch() of Flight\Routing\Route.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     */
148
    public function group(string $prefix)
149
    {
150
        $this->set($this->routesId, new DI\Definition(RouteCollection::class, [$prefix]));
151
        $this->parameters['routes'][++$this->routeIndex] = ['bind' => '@' . $this->routesId];
152
153
        ++$this->routesId;
154
155
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Rade\AppBuilder which is incompatible with the return type mandated by Rade\RouterInterface::group() of Flight\Routing\RouteCollection.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
156
    }
157
158
    /**
159
     * Compiled container and build the application.
160
     *
161
     * supported $options config (defaults):
162
     * - compiled_file => sys_get_temp_dir(), The directory where compiled application class will live in.
163
     * - strictAutowiring => true, Resolvable services which are not typed, will be resolved if false.
164
     * - shortArraySyntax => true, Controls whether [] or array() syntax should be used for an array.
165
     * - containerClass => CompiledApplication, The class name of the compiled application.
166
     *
167
     * @param callable            $application write services in here
168
     * @param array<string,mixed> $options
169
     */
170
    public static function build(callable $application, array $options = []): Application
171
    {
172
        $cache = new ConfigCache($options['compiled_file'] ?? (\sys_get_temp_dir() . '/rade_container.php'), $debug = $options['debug'] ?? false);
173
174
        if (!$cache->isFresh()) {
175
            $appBuilder = new static($debug);
176
177
            if (isset($options['strictAutowiring'])) {
178
                $appBuilder->getResolver()->setStrictAutowiring($options['strictAutowiring']);
179
            }
180
181
            $application($appBuilder);
182
183
            // Default node visitors.
184
            $appBuilder->addNodeVisitor(new DI\NodeVisitor\AutowiringResolver());
185
186
            // Write the compiled application class to path.
187
            $cache->write($appBuilder->compile($options += ['containerClass' => 'CompiledApplication']), $appBuilder->getResources());
0 ignored issues
show
Bug introduced by
It seems like $appBuilder->compile(AssignPlusNode) can also be of type PhpParser\Node[]; however, parameter $content of Symfony\Component\Config...kerConfigCache::write() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

187
            $cache->write(/** @scrutinizer ignore-type */ $appBuilder->compile($options += ['containerClass' => 'CompiledApplication']), $appBuilder->getResources());
Loading history...
188
        }
189
190
        include $cache->getPath();
191
192
        return new $options['containerClass']();
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198
    protected function doAnalyse(array $definitions, bool $onlyDefinitions = false): array
199
    {
200
        unset($this->parameters['routes'], $definitions['builder.loader_resolver']);
201
202
        return parent::doAnalyse($definitions, $onlyDefinitions);
203
    }
204
}
205