Completed
Branch 2.0.1 (3659a8)
by Serhii
03:59
created

Detector::setPathToData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/**
3
 * @author Sergey Nehaenko <[email protected]>
4
 * @license GPL
5
 * @copyright Sergey Nehaenko &copy 2016
6
 * @version 2.0
7
 * @project browser-detector
8
 */
9
10
namespace EndorphinStudio\Detector;
11
12
13
class Detector
14
{
15
    /**
16
     * @return string Path to directory with xml data files
17
     */
18
    public function getPathToData()
19
    {
20
        return $this->PathToData;
21
    }
22
23
    /**
24
     * @return array Xml data object
25
     */
26
    public function getXmlData()
27
    {
28
        return $this->xmlData;
29
    }
30
31
    /**
32
     * @param string $PathToData
33
     */
34
    public function setPathToData($PathToData)
35
    {
36
        $this->PathToData = $PathToData;
37
    }
38
39
    /**
40
     * @param array $xmlData Xml data object
41
     */
42
    public function setXmlData($xmlData)
43
    {
44
        $this->xmlData = $xmlData;
45
    }
46
    /** @var  string Path to directory with xml data */
47
    private $PathToData;
48
49
    /** @var array Xml Data */
50
    private $xmlData;
51
52
    /**
53
     * Detector constructor.
54
     * @param string $pathToData Path to directory with xml data files
55
     */
56
    private function __construct($pathToData='auto')
57
    {
58
        if($pathToData == 'auto')
59
        {
60
            $this->setPathToData(str_replace('src','data',__DIR__).'/');
61
        }
62
63
        $xml = array('robot','browser','device','os');
64
        $xmlData = array();
65
        foreach($xml as $name)
66
        {
67
            $xmlData[$name] = simplexml_load_file($this->getPathToData().$name.'.xml');
68
        }
69
        $this->setXmlData($xmlData);
70
    }
71
72
    public static function analyse($uaString='UA', $pathToData='auto')
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...
73
    {
74
        $ua = $uaString;
75
        if($uaString == 'UA')
76
        {
77
            $ua = $_SERVER['HTTP_USER_AGENT'];
78
        }
79
80
        $detector = new Detector($pathToData);
81
        $xml = $detector->getXmlData();
82
        $data = array();
83
        foreach($xml as $key => $item)
84
        {
85
            $data[$key] = self::analysePart($xml,$key,$ua);
86
        }
87
88
        $detectorResult = new DetectorResult();
89
        $detectorResult->uaString = $ua;
90
        $isRobot = false;
91
92
        foreach($data as $key => $result)
93
        {
94
            if(!$isRobot)
95
            {
96
                switch ($key)
97
                {
98
                    case 'robot':
99
                        if($result !== null)
100
                        {
101
                            $robot = new Robot($result);
102
                            $detectorResult->Robot = $robot;
103
                            if ($robot->getName() != 'N\A') {
104
                                $isRobot = true;
105
                            }
106
                        }
107
                        break;
108 View Code Duplication
                    case 'os':
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...
109
                        if($result !== null)
110
                        {
111
                            $os = new OS($result);
112
                            $os->setVersion(self::getVersion($result, $ua));
113
                            $detectorResult->OS = $os;
114
                        }
115
                        break;
116
                    case 'device':
117
                        if($result !== null)
118
                        {
119
                            $device = new Device($result);
120
                            $detectorResult->Device = $device;
121
                        }
122
                        break;
123 View Code Duplication
                    case 'browser':
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...
124
                        if($result !== null)
125
                        {
126
                            $browser = new Browser($result);
127
                            $browser->setVersion(self::getVersion($result, $ua));
128
                            $detectorResult->Browser = $browser;
129
                        }
130
                        break;
131
                }
132
            }
133
        }
134
135
        return $detectorResult;
136
    }
137
138
    /**
139
     * @param array $xmlData Xml data array
140
     * @param string $key Key in data array
141
     * @param string $uaString User agent
142
     * @return \SimpleXMLElement xml element
143
     */
144
    private static function analysePart($xmlData,$key,$uaString)
145
    {
146
        $data = $xmlData[$key]->data;
147
        foreach($data as $xmlItem)
148
        {
149
            $pattern = '/'.$xmlItem->pattern.'/';
150
            if(preg_match($pattern,$uaString))
151
            {
152
                return $xmlItem;
153
            }
154
        }
155
        return null;
156
    }
157
158
    /**
159
     * @param \SimpleXMLElement $xmlItem xmlItem
160
     * @param string $uaString User agent
161
     * @return string Version
162
     */
163
    private static function getVersion(\SimpleXMLElement $xmlItem,$uaString)
164
    {
165
        if($xmlItem !== null)
166
        {
167
            if(isset($xmlItem->versionPattern))
168
            {
169
                $vPattern = $xmlItem->versionPattern;
0 ignored issues
show
Bug introduced by
The property versionPattern does not seem to exist in SimpleXMLElement.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
170
                $version = '/' . $vPattern . '(\/| )[\w-._]{1,15}/';
171
                $uaString = str_replace(' NT', '', $uaString);
172
                if (preg_match($version, $uaString)) {
173
                    preg_match($version, $uaString, $v);
174
                    $version = $v[0];
175
                    $version = preg_replace('/' . $vPattern . '/', '', $version);
176
                    $version = str_replace(';', '', $version);
177
                    $version = str_replace(' ', '', $version);
178
                    $version = str_replace('/', '', $version);
179
                    $version = str_replace('_', '.', $version);
180
181
                    if ($xmlItem->id == 'Windows') {
182
                        $version = self::getWindowsVersion($version);
183
                    }
184
185
                    return $version;
186
                }
187
            }
188
        }
189
        return 'N\A';
190
    }
191
192
    /**
193
     * @param $version Windows number version
194
     * @return string Windows version
195
     */
196
    private static function getWindowsVersion($version)
197
    {
198
        $versions = array(
199
            '5.1' => 'XP',
200
            '5.2' => 'Server 2003',
201
            '6.0' => 'Vista',
202
            '6.1' => '7',
203
            '6.2' => '8',
204
            '6.3' => '8.1',
205
            '6.4' => '10'
206
        );
207
208
        return $versions[$version];
209
    }
210
}
211