Ini::getBrowser()   B
last analyzed

Complexity

Conditions 8
Paths 5

Size

Total Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
dl 0
loc 49
ccs 0
cts 24
cp 0
rs 7.8682
c 0
b 0
f 0
cc 8
nc 5
nop 1
crap 72
1
<?php
2
declare(strict_types = 1);
3
4
namespace BrowscapPHP\Parser;
5
6
use BrowscapPHP\Formatter\FormatterInterface;
7
use BrowscapPHP\Parser\Helper\GetDataInterface;
8
use BrowscapPHP\Parser\Helper\GetPatternInterface;
9
10
/**
11
 * Ini parser class (compatible with PHP 5.3+)
12
 */
13
final class Ini implements ParserInterface
14
{
15
    /**
16
     * @var Helper\GetPatternInterface
17
     */
18
    private $patternHelper;
19
20
    /**
21
     * @var Helper\GetDataInterface
22
     */
23
    private $dataHelper;
24
25
    /**
26
     * Formatter to use
27
     *
28
     * @var \BrowscapPHP\Formatter\FormatterInterface
29
     */
30
    private $formatter;
31
32
    /**
33
     * class constructor
34
     *
35
     * @param \BrowscapPHP\Parser\Helper\GetPatternInterface $patternHelper
36
     * @param \BrowscapPHP\Parser\Helper\GetDataInterface    $dataHelper
37
     * @param \BrowscapPHP\Formatter\FormatterInterface      $formatter
38
     */
39
    public function __construct(
40
        GetPatternInterface $patternHelper,
41
        GetDataInterface $dataHelper,
42
        FormatterInterface $formatter
43
    ) {
44
        $this->patternHelper = $patternHelper;
45
        $this->dataHelper = $dataHelper;
46
        $this->formatter = $formatter;
47
    }
48
49
    /**
50
     * Gets the browser data formatr for the given user agent
51
     * (or null if no data avaailble, no even the default browser)
52
     *
53
     * @param  string                  $userAgent
54
     *
55
     * @throws \UnexpectedValueException
56
     *
57
     * @return FormatterInterface|null
58
     */
59
    public function getBrowser(string $userAgent) : ?FormatterInterface
60
    {
61
        $userAgent = strtolower($userAgent);
62
        $formatter = null;
63
64
        foreach ($this->patternHelper->getPatterns($userAgent) as $patterns) {
65
            $patternToMatch = '/^(?:' . str_replace("\t", ')|(?:', $patterns) . ')$/i';
66
67
            if (! preg_match($patternToMatch, $userAgent)) {
68
                continue;
69
            }
70
71
            // strtok() requires less memory than explode()
72
            $pattern = strtok($patterns, "\t");
73
74
            while (false !== $pattern) {
75
                $pattern = str_replace('[\d]', '(\d)', $pattern);
76
                $quotedPattern = '/^' . $pattern . '$/i';
77
                $matches = [];
78
79
                if (preg_match($quotedPattern, $userAgent, $matches)) {
80
                    // Insert the digits back into the pattern, so that we can search the settings for it
81
                    if (1 < count($matches)) {
82
                        array_shift($matches);
83
                        foreach ($matches as $oneMatch) {
84
                            $numPos = strpos($pattern, '(\d)');
85
                            $pattern = substr_replace($pattern, $oneMatch, $numPos, 4);
86
                        }
87
                    }
88
89
                    // Try to get settings - as digits have been replaced to speed up the pattern search (up to 90 faster),
90
                    // we won't always find the data in the first step - so check if settings have been found and if not,
91
                    // search for the next pattern.
92
                    $settings = $this->dataHelper->getSettings($pattern);
93
94
                    if (0 < count($settings)) {
95
                        $formatter = $this->formatter;
96
                        $formatter->setData($settings);
97
98
                        break 2;
99
                    }
100
                }
101
102
                $pattern = strtok("\t");
103
            }
104
        }
105
106
        return $formatter;
107
    }
108
}
109