Passed
Push — master ( 96eda9...4e4eee )
by Petr
07:51
created

Factory::whichKey()   B

Complexity

Conditions 8
Paths 7

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 14
c 1
b 0
f 0
dl 0
loc 22
ccs 15
cts 15
cp 1
rs 8.4444
cc 8
nc 7
nop 1
crap 8
1
<?php
2
3
namespace kalanis\kw_storage\Access;
4
5
6
use kalanis\kw_storage\Interfaces;
7
use kalanis\kw_storage\Interfaces\IStorage;
8
use kalanis\kw_storage\Storage;
9
use kalanis\kw_storage\Storage\Key;
10
use kalanis\kw_storage\Storage\Target;
11
use kalanis\kw_storage\StorageException;
12
use kalanis\kw_storage\Traits\TLang;
13
use ReflectionClass;
14
use ReflectionException;
15
16
17
/**
18
 * Class Factory
19
 * @package kalanis\kw_storage\Access
20
 * @todo Je to skladacka - klice + uloziste a to cele se nacpe libce; nevede tu statickou variantu
21
 */
22
class Factory
23
{
24
    use TLang;
25
26
    /** @var array<string|int, class-string> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string|int, class-string> at position 6 could not be parsed: Unknown type name 'class-string' at position 6 in array<string|int, class-string>.
Loading history...
27
    protected $targetMap = [
28
        10 => Target\Memory::class,
29
        20 => Target\Volume::class,
30
        21 => Target\VolumeStream::class,
31
        22 => Target\VolumeTargetFlat::class,
32
        'mem' => Target\Memory::class,
33
        'memory' => Target\Memory::class,
34
        'vol' => Target\Volume::class,
35
        'volume' => Target\Volume::class,
36
        'volume::local' => Target\Volume::class,
37
        'local' => Target\Volume::class,
38
        'stream' => Target\VolumeStream::class,
39
        'volume::stream' => Target\VolumeStream::class,
40
        'volume::flat' => Target\VolumeTargetFlat::class,
41
    ];
42
43 32
    public function __construct(?Interfaces\IStTranslations $lang = null)
44
    {
45 32
        $this->setStLang($lang);
46 32
    }
47
48
    /**
49
     * @param array<string|int, string|int|float|object|bool|array<string|int|float|object>>|string|object|int|bool|null $params
50
     * @throws StorageException
51
     * @return IStorage
52
     */
53 30
    public function getStorage($params): IStorage
54
    {
55 30
        $key = $target = null;
56 30
        if (is_object($params)) {
57
            // IStorage -> thru
58
            // IKey -> select storage, return combination
59
            // ITarget -> select key, return combination
60
61 8
            if ($params instanceof IStorage) {
62 1
                return $params;
63
64 7
            } elseif ($params instanceof Interfaces\IKey) {
65 5
                $key = $params;
66 5
                $target = $this->targetByKey($key);
67
68 2
            } elseif ($params instanceof Interfaces\ITarget) {
69 1
                $target = $params;
70 6
                $key = new Key\DefaultKey();
71
            }
72
73 22
        } elseif (is_string($params)) {
74
            // string -> key as path prefix, target is always volume
75 1
            $key = $this->whichKey(['storage_key' => $params]);
76 1
            $target = new Target\Volume($this->getStLang());
77
78 21
        } elseif (is_array($params)) {
79
            // array -> params decide which storage library will be initialized
80 18
            $key = $this->whichKey($params);
81 17
            $target = $this->targetByKey($key, $params);
82
83
        }
84
        // int, bool, etc. -> exception
85
86 27
        if ($key && $target) {
87 23
            if ($target instanceof Interfaces\ITargetVolume) {
88 17
                return new Storage\StorageDirs($key, $target);
89
            }
90 7
            return new Storage\Storage($key, $target);
91
        }
92 4
        throw new StorageException($this->getStLang()->stConfigurationUnavailable());
93
    }
94
95
    /**
96
     * @param Interfaces\IKey $key
97
     * @param array<string|int, string|int|float|object|bool|array<string|int|float|object>> $params
98
     * @throws StorageException
99
     * @return Interfaces\ITarget
100
     */
101 22
    protected function targetByKey(Interfaces\IKey $key, array $params = []): Interfaces\ITarget
102
    {
103
        try {
104 22
            return $this->whichTarget($params);
105 18
        } catch (StorageException $ex) {
106
            // nothing found - use this
107
        }
108 18
        if ($key instanceof Key\ArrayKey) {
109 11
            return new Target\VolumeStream($this->getStLang());
110
        }
111 7
        if ($key instanceof Key\DirKey) {
112 2
            return new Target\Volume($this->getStLang());
113
        }
114 5
        if ($key instanceof Key\StaticPrefixKey) {
115 1
            return new Target\Volume($this->getStLang());
116
        }
117 4
        if ($key instanceof Key\DefaultKey) {
118 3
            return new Target\Memory($this->getStLang());
119
        }
120 1
        throw new StorageException($this->getStLang()->stConfigurationUnavailable());
121
    }
122
123
    /**
124
     * @param array<string|int, string|int|float|object|bool|array<string|int|float|object>> $params
125
     * @throws StorageException
126
     * @return Interfaces\IKey
127
     */
128 19
    protected function whichKey(array $params): Interfaces\IKey
129
    {
130 19
        if (isset($params['storage_key'])) {
131 19
            if (is_object($params['storage_key'])) {
132 2
                if ($params['storage_key'] instanceof Interfaces\IKey) {
133 1
                    return $params['storage_key'];
134
                }
135 1
                throw new StorageException($this->getStLang()->stConfigurationUnavailable());
136
            }
137 17
            if (is_array($params['storage_key'])) {
138 14
                $separator = DIRECTORY_SEPARATOR;
139 14
                if (isset($params['storage_delimiter'])) {
140 1
                    $separator = strval($params['storage_delimiter']);
141
                }
142 14
                $strArr = array_map('strval', $params['storage_key']);
143 14
                return new Key\ArrayKey($strArr, $separator);
144
            }
145 3
            if (is_string($params['storage_key']) && ($pt = realpath($params['storage_key']))) {
146 2
                return new Key\DirKey($pt . DIRECTORY_SEPARATOR);
147
            }
148
        }
149 1
        return new Key\DefaultKey();
150
    }
151
152
    /**
153
     * @param array<string|int, string|int|float|object|bool|array<string|int|float|object>> $params
154
     * @throws StorageException
155
     * @return Interfaces\ITarget
156
     */
157 22
    protected function whichTarget(array $params): Interfaces\ITarget
158
    {
159 22
        if (isset($params['storage_target'])) {
160 12
            if (is_object($params['storage_target'])) {
161 2
                if ($params['storage_target'] instanceof Interfaces\ITarget) {
162 1
                    return $params['storage_target'];
163
                }
164 1
                throw new StorageException($this->getStLang()->stConfigurationUnavailable());
165
            }
166 10
            if (is_string($params['storage_target']) || is_int($params['storage_target'])) {
167 10
                if (isset($this->targetMap[$params['storage_target']])) {
168
                    try {
169 7
                        $reflection = new ReflectionClass($this->targetMap[$params['storage_target']]);
170 6
                        $class = $reflection->newInstance($this->getStLang());
171 3
                    } catch (ReflectionException $ex) {
172 3
                        throw new StorageException($ex->getMessage(), $ex->getCode(), $ex);
173
                    }
174 4
                    if ($class instanceof Interfaces\ITarget) {
175 3
                        return $class;
176
                    } else {
177 1
                        throw new StorageException($this->getStLang()->stConfigurationUnavailable());
178
                    }
179
                }
180
            }
181
        }
182 13
        throw new StorageException($this->getStLang()->stConfigurationUnavailable());
183
    }
184
}
185