Completed
Push — master ( d5541c...74532d )
by Timo
02:43
created

RequestLimitRuleset   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 13
dl 0
loc 155
ccs 41
cts 41
cp 1
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A _setCacheStrategy() 0 22 3
A _setStorageAdapter() 0 22 3
A cache() 0 3 1
A _implementsInterface() 0 2 1
A create() 0 3 1
A getRequestLimitGroup() 0 14 3
1
<?php
2
3
namespace hamburgscleanest\GuzzleAdvancedThrottle;
4
5
use GuzzleHttp\Promise\PromiseInterface;
6
use hamburgscleanest\GuzzleAdvancedThrottle\Cache\Adapters\ArrayAdapter;
7
use hamburgscleanest\GuzzleAdvancedThrottle\Cache\Adapters\LaravelAdapter;
8
use hamburgscleanest\GuzzleAdvancedThrottle\Cache\Interfaces\CacheStrategy;
9
use hamburgscleanest\GuzzleAdvancedThrottle\Cache\Interfaces\StorageInterface;
10
use hamburgscleanest\GuzzleAdvancedThrottle\Cache\Strategies\Cache;
11
use hamburgscleanest\GuzzleAdvancedThrottle\Cache\Strategies\ForceCache;
12
use hamburgscleanest\GuzzleAdvancedThrottle\Cache\Strategies\NoCache;
13
use hamburgscleanest\GuzzleAdvancedThrottle\Exceptions\HostNotDefinedException;
14
use hamburgscleanest\GuzzleAdvancedThrottle\Exceptions\UnknownCacheStrategyException;
15
use hamburgscleanest\GuzzleAdvancedThrottle\Exceptions\UnknownStorageAdapterException;
16
use Illuminate\Config\Repository;
17
use Psr\Http\Message\RequestInterface;
18
19
/**
20
 * Class RequestLimitRuleset
21
 * @package hamburgscleanest\GuzzleAdvancedThrottle
22
 */
23
class RequestLimitRuleset
24
{
25
26
    /** @var array */
27
    private const STORAGE_MAP = [
28
        'array'   => ArrayAdapter::class,
29
        'laravel' => LaravelAdapter::class
30
    ];
31
32
    /** @var array */
33
    private const CACHE_STRATEGIES = [
34
        'no-cache'    => NoCache::class,
35
        'cache'       => Cache::class,
36
        'force-cache' => ForceCache::class
37
    ];
38
39
    /** @var array */
40
    private $_rules;
41
42
    /** @var StorageInterface */
43
    private $_storage;
44
45
    /** @var CacheStrategy */
46
    private $_cacheStrategy;
47
48
    /** @var Repository */
49
    private $_config;
50
51
    /**
52
     * RequestLimitRuleset constructor.
53
     * @param array $rules
54
     * @param string $cacheStrategy
55
     * @param string|null $storageAdapter
56
     * @param Repository|null $config
57
     * @throws \hamburgscleanest\GuzzleAdvancedThrottle\Exceptions\UnknownCacheStrategyException
58
     * @throws \hamburgscleanest\GuzzleAdvancedThrottle\Exceptions\UnknownStorageAdapterException
59
     */
60 30
    public function __construct(array $rules, string $cacheStrategy = 'no-cache', string $storageAdapter = 'array', Repository $config = null)
61
    {
62 30
        $this->_rules = $rules;
63 30
        $this->_config = $config;
64 30
        $this->_setStorageAdapter($storageAdapter);
65 24
        $this->_setCacheStrategy($cacheStrategy);
66 22
    }
67
68
    /**
69
     * Sets internal storage adapter for this rule set.
70
     * @param string $adapterName
71
     * @throws \hamburgscleanest\GuzzleAdvancedThrottle\Exceptions\UnknownStorageAdapterException
72
     */
73 30
    private function _setStorageAdapter(string $adapterName) : void
74
    {
75
        // Storing this so we can potentially change it later
76 30
        $adapterClassName = $adapterName;
77
78
        // Set the actual class name from the map
79 30
        if (isset(self::STORAGE_MAP[$adapterName]))
80
        {
81 26
            $adapterClassName = self::STORAGE_MAP[$adapterName];
82
        }
83
84 30
        if (!$this->_implementsInterface($adapterClassName, StorageInterface::class))
85
        {
86
            $validStrategies = \array_filter(get_declared_classes(), function($className) {
87 2
                    return $this->_implementsInterface($className, StorageInterface::class);
88 2
                }
89
            );
90 2
            throw new UnknownStorageAdapterException($adapterClassName,
91 2
                $validStrategies + \array_values(self::STORAGE_MAP));
92
        }
93
94 28
        $this->_storage = new $adapterClassName($this->_config);
95 24
    }
96
97
    /**
98
     * Sets the caching strategy for this rule set.
99
     * @param string $cacheStrategy
100
     * @throws \hamburgscleanest\GuzzleAdvancedThrottle\Exceptions\UnknownCacheStrategyException
101
     */
102 24
    private function _setCacheStrategy(string $cacheStrategy) : void
103
    {
104
        // Storing this so we can potentially change it later
105 24
        $cacheStrategyClassName = $cacheStrategy;
106
107
        // Set the actual class name from the map
108 24
        if (isset(self::CACHE_STRATEGIES[$cacheStrategy]))
109
        {
110 21
            $cacheStrategyClassName = self::CACHE_STRATEGIES[$cacheStrategy];
111
        }
112
113 24
        if (!$this->_implementsInterface($cacheStrategyClassName, CacheStrategy::class))
114
        {
115
            $validStrategies = \array_filter(get_declared_classes(), function($className) {
116 2
                return $this->_implementsInterface($className, CacheStrategy::class);
117 2
            });
118
119 2
            throw new UnknownCacheStrategyException($cacheStrategyClassName,
120 2
                $validStrategies + \array_values(self::CACHE_STRATEGIES));
121
        }
122
123 22
        $this->_cacheStrategy = new $cacheStrategyClassName($this->_storage);
124 22
    }
125
126
    /**
127
     * Returns true|false if the $implementerClassName implements interface $interfaceName
128
     * @param string $implementerClassName class name of the implementation class to test
129
     * @param string $interfaceName name of the interface that should be implemented
130
     * @return bool TRUE if the $implementerClassName implements $interfaceName, FALSE otherwise
131
     */
132 30
    private function _implementsInterface(string $implementerClassName, string $interfaceName) : bool {
133 30
        return \in_array($interfaceName, \class_implements($implementerClassName), TRUE);
134
    }
135
136
    /**
137
     * @param array $rules
138
     * @param string $cacheStrategy
139
     * @param string $storageAdapter
140
     * @return static
141
     * @throws \hamburgscleanest\GuzzleAdvancedThrottle\Exceptions\UnknownStorageAdapterException
142
     * @throws \hamburgscleanest\GuzzleAdvancedThrottle\Exceptions\UnknownCacheStrategyException
143
     */
144 10
    public static function create(array $rules, string $cacheStrategy = 'no-cache', string $storageAdapter = 'array')
145
    {
146 10
        return new static($rules, $cacheStrategy, $storageAdapter);
147
    }
148
149
    /**
150
     * @param RequestInterface $request
151
     * @param callable $handler
152
     * @return PromiseInterface
153
     */
154 16
    public function cache(RequestInterface $request, callable $handler) : PromiseInterface
155
    {
156 16
        return $this->_cacheStrategy->request($request, $handler);
157
    }
158
159
    /**
160
     * @return RequestLimitGroup
161
     * @throws \Exception
162
     * @throws HostNotDefinedException
163
     */
164 18
    public function getRequestLimitGroup() : RequestLimitGroup
165
    {
166 18
        $requestLimitGroup = new RequestLimitGroup();
167 18
        foreach ($this->_rules as $host => $rules)
168
        {
169 18
            if (!\is_string($host))
170
            {
171 1
                throw new HostNotDefinedException();
172
            }
173
174 17
            $requestLimitGroup->addRules($host, $rules, $this->_storage);
175
        }
176
177 17
        return $requestLimitGroup;
178
    }
179
}