Completed
Pull Request — master (#218)
by Thomas
05:43
created

GetData   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 142
Duplicated Lines 3.52 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 7
dl 5
loc 142
ccs 0
cts 48
cp 0
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B getSettings() 0 42 6
C getIniPart() 5 49 8

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
declare(strict_types = 1);
3
4
namespace BrowscapPHP\Parser\Helper;
5
6
use BrowscapPHP\Cache\BrowscapCacheInterface;
7
use BrowscapPHP\Data\PropertyFormatter;
8
use BrowscapPHP\Data\PropertyHolder;
9
use BrowscapPHP\Helper\QuoterInterface;
10
use Psr\Log\LoggerInterface;
11
12
/**
13
 * extracts the data and the data for theses pattern from the ini content, optimized for PHP 5.5+
14
 */
15
final class GetData implements GetDataInterface
16
{
17
    /**
18
     * The cache instance
19
     *
20
     * @var \BrowscapPHP\Cache\BrowscapCacheInterface
21
     */
22
    private $cache;
23
24
    /**
25
     * a logger instance
26
     *
27
     * @var \Psr\Log\LoggerInterface
28
     */
29
    private $logger;
30
31
    /**
32
     * @var \BrowscapPHP\Helper\Quoter
33
     */
34
    private $quoter;
35
36
    /**
37
     * class contsructor
38
     *
39
     * @param \BrowscapPHP\Cache\BrowscapCacheInterface $cache
40
     * @param \Psr\Log\LoggerInterface                  $logger
41
     * @param \BrowscapPHP\Helper\QuoterInterface       $quoter
42
     */
43
    public function __construct(BrowscapCacheInterface $cache, LoggerInterface $logger, QuoterInterface $quoter)
44
    {
45
        $this->cache = $cache;
46
        $this->logger = $logger;
47
        $this->quoter = $quoter;
0 ignored issues
show
Documentation Bug introduced by
$quoter is of type object<BrowscapPHP\Helper\QuoterInterface>, but the property $quoter was declared to be of type object<BrowscapPHP\Helper\Quoter>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
48
    }
49
50
    /**
51
     * Gets the settings for a given pattern (method calls itself to
52
     * get the data from the parent patterns)
53
     *
54
     * @param  string $pattern
55
     * @param  array  $settings
56
     * @return array
57
     */
58
    public function getSettings(string $pattern, array $settings = []) : array
59
    {
60
        // The pattern has been pre-quoted on generation to speed up the pattern search,
61
        // but for this check we need the unquoted version
62
        $unquotedPattern = $this->quoter->pregUnQuote($pattern);
63
64
        // Try to get settings for the pattern
65
        $addedSettings = $this->getIniPart($unquotedPattern);
66
67
        // set some additional data
68
        if (count($settings) === 0) {
69
            // The optimization with replaced digits get can now result in setting searches, for which we
70
            // won't find a result - so only add the pattern information, is settings have been found.
71
            //
72
            // If not an empty array will be returned and the calling function can easily check if a pattern
73
            // has been found.
74
            if (count($addedSettings) > 0) {
75
                $settings['browser_name_regex'] = '/^' . $pattern . '$/';
76
                $settings['browser_name_pattern'] = $unquotedPattern;
77
            }
78
        }
79
80
        // check if parent pattern set, only keep the first one
81
        $parentPattern = null;
82
83
        if (isset($addedSettings['Parent'])) {
84
            $parentPattern = $addedSettings['Parent'];
85
86
            if (isset($settings['Parent'])) {
87
                unset($addedSettings['Parent']);
88
            }
89
        }
90
91
        // merge settings
92
        $settings += $addedSettings;
93
94
        if (is_string($parentPattern)) {
95
            return $this->getSettings($this->quoter->pregQuote($parentPattern), $settings);
96
        }
97
98
        return $settings;
99
    }
100
101
    /**
102
     * Gets the relevant part (array of settings) of the ini file for a given pattern.
103
     *
104
     * @param  string $pattern
105
     * @return array
106
     */
107
    private function getIniPart(string $pattern) : array
108
    {
109
        $pattern = strtolower($pattern);
110
        $patternhash = Pattern::getHashForParts($pattern);
111
        $subkey = SubKey::getIniPartCacheSubKey($patternhash);
112
113 View Code Duplication
        if (! $this->cache->hasItem('browscap.iniparts.' . $subkey, true)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
114
            $this->logger->debug('cache key "browscap.iniparts.' . $subkey . '" not found');
115
116
            return [];
117
        }
118
119
        $success = null;
120
        $file = $this->cache->getItem('browscap.iniparts.' . $subkey, true, $success);
121
122
        if (! $success) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $success of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
123
            $this->logger->debug('cache key "browscap.iniparts.' . $subkey . '" not found');
124
125
            return [];
126
        }
127
128
        if (! is_array($file) || ! count($file)) {
129
            $this->logger->debug('cache key "browscap.iniparts.' . $subkey . '" was empty');
130
131
            return [];
132
        }
133
134
        $propertyFormatter = new PropertyFormatter(new PropertyHolder());
135
        $return = [];
136
137
        foreach ($file as $buffer) {
138
            list($tmpBuffer, $patterns) = explode("\t", $buffer, 2);
139
140
            if ($tmpBuffer === $patternhash) {
141
                $return = json_decode($patterns, true);
142
143
                foreach (array_keys($return) as $property) {
144
                    $return[$property] = $propertyFormatter->formatPropertyValue(
145
                        $return[$property],
146
                        $property
147
                    );
148
                }
149
150
                break;
151
            }
152
        }
153
154
        return $return;
155
    }
156
}
157