Passed
Push — 6.0.3 ( cc0216 )
by Serhii
02:23
created

Detector::findDataDirectory()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 6
c 1
b 0
f 1
nc 4
nop 0
dl 0
loc 10
rs 10
1
<?php
2
/**
3
 * @author Serhii Nekhaienko <[email protected]>
4
 * @license GPL
5
 * @copyright Serhii Nekhaienko &copy 2018
6
 * @version 4.0.0
7
 * @project endorphin-studio/browser-detector
8
 */
9
10
namespace EndorphinStudio\Detector;
11
12
use Composer\Composer;
13
use EndorphinStudio\Detector\Data\Result;
14
use EndorphinStudio\Detector\Exception\StorageException;
15
use EndorphinStudio\Detector\Storage\StorageInterface;
16
use EndorphinStudio\Detector\Storage\YamlStorage;
17
use RuntimeException;
18
use Symfony\Component\HttpFoundation\Request;
19
20
/**
21
 * Class Detector
22
 * Detect OS, Device, Browser, Robot
23
 * @package EndorphinStudio\Detector
24
 */
25
class Detector
26
{
27
    private const DATA_PACKAGE = 'endorphin-studio/browser-detector-data-yaml';
28
29
    /**
30
     * @var array Array of options
31
     */
32
    protected $options = [
33
        'dataProvider' => YamlStorage::class,
34
        'dataDirectory' => 'auto',
35
        'cacheDirectory' => 'auto',
36
        'format' => 'yaml'
37
    ];
38
39
    private $version = '6.0.3';
40
41
    /**
42
     * @var StorageInterface
43
     */
44
    private $dataProvider;
45
46
    /**
47
     * @var Result Result object
48
     */
49
    private $resultObject;
50
51
    /**
52
     * @var string $ua User Agent
53
     */
54
    private $ua;
55
56
    /**
57
     * @var array
58
     */
59
    private $detectors;
60
61
    /**
62
     * Detector constructor.
63
     * Options:
64
     * 'dataProvider' => '\\EndorphinStudio\\Detector\\Storage\\YamlStorage',
65
     * 'dataDirectory' => 'auto',
66
     * 'cacheDirectory' => 'auto',
67
     * 'format' => 'yaml'
68
     * @param array $options Array of options
69
     * @throws StorageException
70
     * @SuppressWarnings(PHPMD.StaticAccess)
71
     */
72
    public function __construct(array $options = [])
73
    {
74
        $this->options = array_merge_recursive($options, $this->options);
75
76
        $this->init();
77
        $this->detectors = [];
78
        Tools::setWindowsConfig($this->dataProvider->getConfig()['windows']);
79
        foreach (['os', 'device', 'browser'] as $detectionType) {
80
            $this->initDetector($detectionType);
81
        }
82
    }
83
84
    /**
85
     * Initialisation method
86
     * @throws StorageException
87
     * @throws RuntimeException
88
     */
89
    protected function init(): void
90
    {
91
        $this->setDataProvider($this->createDataProvider());
92
        $this->dataProvider->setDataDirectory($this->findDataDirectory());
93
        $this->callMethod($this->dataProvider, 'setCacheDirectory', $this->findCacheDirectory());
94
        $this->callMethod($this->dataProvider, 'setCacheEnabled', true);
95
    }
96
97
    private function createDataProvider()
98
    {
99
        if (class_exists($this->options['dataProvider'])) {
100
            return new $this->options['dataProvider']();
101
        }
102
        throw new RuntimeException('Data Provider class isn\'t exist');
103
    }
104
105
    /**
106
     * @return string
107
     * @throws StorageException
108
     */
109
    private function findDataDirectory(): string
110
    {
111
        $dataDirectory = $this->options['dataDirectory'];
112
        if ($this->options['dataDirectory'] === 'auto') {
113
            $dataDirectory = sprintf('%s/data', $this->getPackagePath(self::DATA_PACKAGE));
114
        }
115
        if (is_dir($dataDirectory)) {
116
            return $dataDirectory;
117
        }
118
        throw new StorageException(sprintf(StorageException::DIRECTORY_NOT_FOUND, $dataDirectory));
119
    }
120
121
    private function getPackagePath(string $package): string
122
    {
123
        return (new Composer())->getInstallationManager()->getInstallPath($package);
124
    }
125
126
    protected function callMethod($object, string $methodName, ...$arguments): void
127
    {
128
        if (method_exists($object, $methodName)) {
129
            $object->$methodName($arguments);
130
        }
131
    }
132
133
    /**
134
     * @return string
135
     * @throws StorageException
136
     */
137
    private function findCacheDirectory(): string
138
    {
139
        $cacheDirectory = $this->options['cacheDirectory'];
140
        if ($this->options['cacheDirectory'] === 'auto') {
141
            $cacheDirectory = sprintf('%s/var/cache', dirname(__FILE__, 1));
142
        }
143
        if (is_dir($cacheDirectory)) {
144
            return $cacheDirectory;
145
        }
146
        throw new StorageException(sprintf(StorageException::DIRECTORY_NOT_FOUND, $cacheDirectory));
147
    }
148
149
    private function initDetector(string $type): void
150
    {
151
        $className = sprintf('\\EndorphinStudio\\Detector\\Detection\\%s', ucfirst(sprintf('%sDetector', $type)));
152
        if (class_exists($className)) {
153
            $this->detectors[$type] = new $className();
154
            $this->detectors[$type]->init($this);
155
        }
156
    }
157
158
    public function getVersion(): string
159
    {
160
        return $this->version;
161
    }
162
163
    /**
164
     * Get storage provider
165
     * @return StorageInterface
166
     */
167
    public function getDataProvider(): StorageInterface
168
    {
169
        return $this->dataProvider;
170
    }
171
172
    /**
173
     * Set data provider
174
     * @param StorageInterface $dataProvider
175
     */
176
    public function setDataProvider(StorageInterface $dataProvider): void
177
    {
178
        $this->dataProvider = $dataProvider;
179
    }
180
181
    /**
182
     * Get result object
183
     * @return Result Result object
184
     */
185
    public function getResultObject(): Result
186
    {
187
        return $this->resultObject;
188
    }
189
190
    /**
191
     * @return string
192
     */
193
    public function getUserAgent(): string
194
    {
195
        return $this->ua;
196
    }
197
198
    /**
199
     * Analyse User Agent String
200
     * @param string $ua
201
     * @return Result
202
     * @SuppressWarnings(PHPMD.StaticAccess)
203
     */
204
    public function analyse(string $ua = 'ua'): Result
205
    {
206
        $request = Request::createFromGlobals();
207
        $this->ua = $ua === 'ua' ? $request->server->get('HTTP_USER_AGENT') : $ua;
208
        $this->resultObject = new Result($this->ua, $this);
209
        foreach ($this->detectors as $detectionType => $detector) {
210
            $detector->detect();
211
        }
212
        return $this->resultObject;
213
    }
214
215
    /**
216
     * Get list of patterns from config
217
     * @param $list
218
     * @param $type
219
     * @return array
220
     */
221
    public function getPatternList($list, $type): array
222
    {
223
        return array_key_exists($type, $list) ? $list[$type] : [];
224
    }
225
}
226