Passed
Pull Request — master (#9)
by Pavel
12:36
created

Router::warmUp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
ccs 0
cts 6
cp 0
rs 9.4285
cc 1
eloc 5
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Bankiru\Api\Rpc\Routing;
4
5
use Symfony\Component\Config\ConfigCacheFactory;
6
use Symfony\Component\Config\ConfigCacheFactoryInterface;
7
use Symfony\Component\Config\ConfigCacheInterface;
8
use Symfony\Component\Config\Resource\FileResource;
9
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
10
11
final class Router implements MethodMatcher, WarmableInterface
12
{
13
    /** @var MethodCollectionLoader */
14
    private $loader;
15
    /** @var MethodCollection */
16
    private $collection;
17
    /** @var MethodMatcher */
18
    private $matcher;
19
    /**
20
     * @var string
21
     */
22
    private $name;
23
    /** @var ConfigCacheFactoryInterface */
24
    private $configCacheFactory;
25
    private $options = [];
26
27
    /**
28
     * Router constructor.
29
     *
30
     * @param MethodCollectionLoader $loader
31
     * @param string                 $name
32
     * @param array                  $options
33
     */
34 11
    public function __construct(MethodCollectionLoader $loader, $name, array $options = [])
35
    {
36 11
        $this->loader = $loader;
37 11
        $this->name   = $name;
38 11
        $this->setOptions($options);
39 11
    }
40
41
    /**
42
     * @return MethodCollection
43 11
     */
44 2
    public function getMethodCollection()
45 11
    {
46 2
        if (null === $this->collection) {
47 13
            $this->collection = $this->loader->loadCollection();
48 13
        }
49 11
50 13
        return $this->collection;
51
    }
52
53
    /** {@inheritdoc} */
54 9
    public function match($method)
55 1
    {
56 9
        return $this->getMatcher()->match($method);
57 1
    }
58 1
59 1
    /**
60 1
     * Warms up the cache.
61 1
     *
62
     * @param string $cacheDir The cache directory
63 1
     */
64
    public function warmUp($cacheDir)
65
    {
66
        $currentDir = $this->getOption('cache_dir');
67
68
        // force cache generation
69
        $this->setOption('cache_dir', $cacheDir);
70
71
        $this->getMatcher();
72
        $this->setOption('cache_dir', $currentDir);
73
    }
74
75
    /**
76
     * Sets an option.
77
     *
78
     * @param string $key   The key
79
     * @param mixed  $value The value
80
     *
81
     * @throws \InvalidArgumentException
82
     */
83 View Code Duplication
    public function setOption($key, $value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
84
    {
85
        if (!array_key_exists($key, $this->options)) {
86
            throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
87
        }
88
89
        $this->options[$key] = $value;
90
    }
91
92 1
    /**
93
     * Gets an option value.
94 1
     *
95 1
     * @param string $key The key
96 1
     *
97 1
     * @return mixed The value
98
     *
99 1
     * @throws \InvalidArgumentException
100
     */
101 1 View Code Duplication
    public function getOption($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
102
    {
103 1
        if (!array_key_exists($key, $this->options)) {
104 1
            throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
105
        }
106 1
107 1
        return $this->options[$key];
108
    }
109 1
110 1
    /**
111
     * Sets options.
112 1
     *
113 1
     * Available options:
114 1
     *
115 1
     *   * cache_dir:              The cache directory (or null to disable caching)
116 1
     *   * debug:                  Whether to enable debugging or not (false by default)
117 1
     *
118 1
     * @param array $options An array of options
119 1
     *
120
     * @throws \InvalidArgumentException When unsupported option is provided
121
     */
122 11
    public function setOptions(array $options)
123
    {
124 11
        $this->options = [
125 11
            'cache_dir'           => null,
126 11
            'debug'               => false,
127 11
            'matcher_cache_class' => ucfirst($this->name) . 'MethodMatcher',
128
        ];
129
130
        // check option names and live merge, if errors are encountered Exception will be thrown
131 11
        $invalid = [];
132 12
        foreach ($options as $key => $value) {
133 11
            if (array_key_exists($key, $this->options)) {
134 12
                $this->options[$key] = $value;
135 11
            } else {
136
                $invalid[] = $key;
137
            }
138 11
        }
139
140 11
        if ($invalid) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $invalid of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
141
            throw new \InvalidArgumentException(
142 1
                sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid))
143
            );
144
        }
145 11
    }
146 1
147
    /**
148 1
     * @return MethodMatcher
149
     */
150 9
    private function getMatcher()
151
    {
152 9
        if (null !== $this->matcher) {
153
            return $this->matcher;
154
        }
155
156 9
        if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) {
157
            $this->matcher = new CollectionMatcher($this->getMethodCollection());
158
159
            return $this->matcher;
160
        }
161
162 9
        $cache = $this->getConfigCacheFactory()->cache(
163 9
            $this->options['cache_dir'] . '/rpc/' . $this->options['matcher_cache_class'] . '.php',
164 1
            function (ConfigCacheInterface $cache) {
165 1
                $dumper = new MatcherDumper();
166
167
                $options = [
168 1
                    'class' => $this->options['matcher_cache_class'],
169 1
                ];
170
171 1
                $resources   = $this->getMethodCollection()->getResources();
172 1
                $refl        = new \ReflectionClass(MatcherDumper::class);
173 1
                $resources[] = new FileResource($refl->getFileName());
174 1
175 1
                $cache->write($dumper->dump($this->getMethodCollection(), $options), $resources);
176 2
            }
177 9
        );
178
179 9
        require_once $cache->getPath();
180
181 9
        $this->matcher = new $this->options['matcher_cache_class']($cache);
182
183 9
        return $this->matcher;
184
    }
185
186
    /**
187
     * Provides the ConfigCache factory implementation, falling back to a
188
     * default implementation if necessary.
189
     *
190
     * @return ConfigCacheFactoryInterface $configCacheFactory
191
     */
192 9
    private function getConfigCacheFactory()
193
    {
194 9
        if (null === $this->configCacheFactory) {
195 9
            $this->configCacheFactory = new ConfigCacheFactory(true);
196 9
        }
197
198 9
        return $this->configCacheFactory;
199
    }
200
}
201