Completed
Push — 3.0.0 ( ceb3bc...0dd3e2 )
by Serhii
02:19
created

Detector::checkRules()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 20
rs 9.2
cc 4
eloc 13
nc 4
nop 1
1
<?php
2
/**
3
 * @author Sergey Nehaenko <[email protected]>
4
 * @license GPL
5
 * @copyright Sergey Nehaenko &copy 2016
6
 * @version 3.0.0
7
 * @project browser-detector
8
 */
9
10
namespace EndorphinStudio\Detector;
11
12
class Detector
13
{
14
    /** @var array Xml Data */
15
    public static $xmlData;
16
17
    private static function init($pathToData = 'auto')
18
    {
19
        if ($pathToData == 'auto')
20
        {
21
            $pathToData = str_replace('src', 'data', __DIR__) . '/';
22
        }
23
24
        if (self::$xmlData === null)
25
        {
26
            $xml = array('Robot', 'Browser', 'Device', 'OS');
27
            $xmlData = array();
28
            foreach ($xml as $name) {
29
                $xmlData[$name] = simplexml_load_file($pathToData . strtolower($name) . '.xml');
30
            }
31
            self::$xmlData = $xmlData;
32
        }
33
    }
34
35
    public static function analyse($uaString='UA')
0 ignored issues
show
Coding Style introduced by
analyse uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
36
    {
37
        $ua = $uaString;
38
        if($uaString == 'UA')
39
        {
40
            $ua = $_SERVER['HTTP_USER_AGENT'];
41
        }
42
43
        Detector::init();
44
        $xml = Detector::$xmlData;
45
46
        $detectorResult = new DetectorResult();
47
        $detectorResult->uaString = $ua;
48
        $ns = '\\EndorphinStudio\\Detector\\';
49
50
        foreach($xml as $key => $item)
51
        {
52
            $data = self::analysePart($xml,$key,$ua);
53
            $classname = $ns.$key;
54
            if($data !== null)
55
            {
56
                $object = new $classname($data);
57
                if($key == 'OS' || $key == 'Browser')
58
                {
59
                    $object->setVersion(self::getVersion($data, $ua));
60
                }
61
                if($key == 'Robot')
62
                {
63
                    if($object->getName() != D_NA)
64
                    {
65
                        $detectorResult->isBot = true;
66
                    }
67
                }
68
            }
69
            else
70
            {
71
                $object = $classname::initEmpty();
72
            }
73
            $detectorResult->$key = $object;
74
        }
75
76
        $detectorResult = self::checkRules($detectorResult);
77
78
        return $detectorResult;
79
    }
80
81
    /**
82
     * @param array $xmlData Xml data array
83
     * @param string $key Key in data array
84
     * @param string $uaString User agent
85
     * @return \SimpleXMLElement xml element
86
     */
87
    private static function analysePart($xmlData,$key,$uaString)
88
    {
89
        $data = $xmlData[$key]->data;
90
        foreach($data as $xmlItem)
91
        {
92
            $pattern = '/'.$xmlItem->pattern.'/';
93
            if(preg_match($pattern,$uaString))
94
            {
95
                return $xmlItem;
96
            }
97
        }
98
        return null;
99
    }
100
101
    /**
102
     * @param \SimpleXMLElement $xmlItem xmlItem
103
     * @param string $uaString User agent
104
     * @return string Version
105
     */
106
    private static function getVersion(\SimpleXMLElement $xmlItem,$uaString)
107
    {
108
        if($xmlItem !== null)
109
        {
110
            foreach($xmlItem->children() as $node)
111
            {
112
                if($node->getName() == 'versionPattern')
113
                {
114
                    $vPattern = $node->__toString();
115
                    $version = '/' . $vPattern . '(\/| )[\w-._]{1,15}/';
116
                    $uaString = str_replace(' NT', '', $uaString);
117
                    if (preg_match($version, $uaString)) {
118
                        preg_match($version, $uaString, $v);
119
                        $version = $v[0];
120
                        $version = preg_replace('/' . $vPattern . '/', '', $version);
121
                        $version = str_replace(';', '', $version);
122
                        $version = str_replace(' ', '', $version);
123
                        $version = str_replace('/', '', $version);
124
                        $version = str_replace('_', '.', $version);
125
126
                        if ($xmlItem->id == 'Windows') {
127
                            $version = self::getWindowsVersion($version);
128
                        }
129
130
                        return $version;
131
                    }
132
                }
133
            }
134
        }
135
        return D_NA;
136
    }
137
138
    /**
139
     * @param $version Windows number version
140
     * @return string Windows version
141
     */
142
    private static function getWindowsVersion($version)
143
    {
144
        $versions = array(
145
            '95' => '95',
146
            '3.1' => '3.1',
147
            '3.5' => '3.5',
148
            '3.51' => '3.51',
149
            '4.0' => '4.0',
150
            '2000' => '2000',
151
            '5.0' => '2000',
152
            '5.1' => 'XP',
153
            '5.2' => 'Server 2003',
154
            '6.0' => 'Vista',
155
            '6.1' => '7',
156
            '6.2' => '8',
157
            '6.3' => '8.1',
158
            '6.4' => '10',
159
            '10.0' => '10'
160
        );
161
162
        if(array_key_exists(strval($version),$versions))
163
            return $versions[strval($version)];
164
        else
165
            return D_NA;
166
    }
167
168
    /**
169
     * @param DetectorResult $result Detector result
170
     * @return DetectorResult Final result
171
     */
172
    private static function checkRules(DetectorResult $result)
173
    {
174
        $Rules = DetectorRule::loadRulesFromFile();
175
        foreach($Rules as $rule)
176
        {
177
            $objectType = $rule->getObjectType();
178
            $objectProperty = $rule->getObjectProperty();
179
            $targetType = $rule->getTargetType();
180
            $targetValue = $rule->isTargetValue();
181
            $func = 'get'.$objectProperty;
182
            if($result->$objectType !== null)
183
            {
184
                if ($result->$objectType->$func() == $rule->getObjectPropertyValue()) {
185
                    $result->$targetType = $targetValue;
186
                    break;
187
                }
188
            }
189
        }
190
        return $result;
191
    }
192
}
193
define('D_NA','N\A');
194