xref: /plugin/statistics/vendor/matomo/device-detector/Parser/Client/AbstractClientParser.php (revision d5ef99ddb7dfb0cfae33e9257bd1d788f682c50f)
1*d5ef99ddSAndreas Gohr<?php
2*d5ef99ddSAndreas Gohr
3*d5ef99ddSAndreas Gohr/**
4*d5ef99ddSAndreas Gohr * Device Detector - The Universal Device Detection library for parsing User Agents
5*d5ef99ddSAndreas Gohr *
6*d5ef99ddSAndreas Gohr * @link https://matomo.org
7*d5ef99ddSAndreas Gohr *
8*d5ef99ddSAndreas Gohr * @license http://www.gnu.org/licenses/lgpl.html LGPL v3 or later
9*d5ef99ddSAndreas Gohr */
10*d5ef99ddSAndreas Gohr
11*d5ef99ddSAndreas Gohrdeclare(strict_types=1);
12*d5ef99ddSAndreas Gohr
13*d5ef99ddSAndreas Gohrnamespace DeviceDetector\Parser\Client;
14*d5ef99ddSAndreas Gohr
15*d5ef99ddSAndreas Gohruse DeviceDetector\Parser\AbstractParser;
16*d5ef99ddSAndreas Gohr
17*d5ef99ddSAndreas Gohrabstract class AbstractClientParser extends AbstractParser
18*d5ef99ddSAndreas Gohr{
19*d5ef99ddSAndreas Gohr    /**
20*d5ef99ddSAndreas Gohr     * @var string
21*d5ef99ddSAndreas Gohr     */
22*d5ef99ddSAndreas Gohr    protected $fixtureFile = '';
23*d5ef99ddSAndreas Gohr
24*d5ef99ddSAndreas Gohr    /**
25*d5ef99ddSAndreas Gohr     * @var string
26*d5ef99ddSAndreas Gohr     */
27*d5ef99ddSAndreas Gohr    protected $parserName = '';
28*d5ef99ddSAndreas Gohr
29*d5ef99ddSAndreas Gohr    /**
30*d5ef99ddSAndreas Gohr     * Parses the current UA and checks whether it contains any client information
31*d5ef99ddSAndreas Gohr     *
32*d5ef99ddSAndreas Gohr     * @see $fixtureFile for file with list of detected clients
33*d5ef99ddSAndreas Gohr     *
34*d5ef99ddSAndreas Gohr     * Step 1: Build a big regex containing all regexes and match UA against it
35*d5ef99ddSAndreas Gohr     * -> If no matches found: return
36*d5ef99ddSAndreas Gohr     * -> Otherwise:
37*d5ef99ddSAndreas Gohr     * Step 2: Walk through the list of regexes in feed_readers.yml and try to match every one
38*d5ef99ddSAndreas Gohr     * -> Return the matched feed reader
39*d5ef99ddSAndreas Gohr     *
40*d5ef99ddSAndreas Gohr     * NOTE: Doing the big match before matching every single regex speeds up the detection
41*d5ef99ddSAndreas Gohr     *
42*d5ef99ddSAndreas Gohr     * @return array|null
43*d5ef99ddSAndreas Gohr     */
44*d5ef99ddSAndreas Gohr    public function parse(): ?array
45*d5ef99ddSAndreas Gohr    {
46*d5ef99ddSAndreas Gohr        $result = null;
47*d5ef99ddSAndreas Gohr
48*d5ef99ddSAndreas Gohr        if ($this->preMatchOverall()) {
49*d5ef99ddSAndreas Gohr            foreach ($this->getRegexes() as $regex) {
50*d5ef99ddSAndreas Gohr                $matches = $this->matchUserAgent($regex['regex']);
51*d5ef99ddSAndreas Gohr
52*d5ef99ddSAndreas Gohr                if ($matches) {
53*d5ef99ddSAndreas Gohr                    $result = [
54*d5ef99ddSAndreas Gohr                        'type'    => $this->parserName,
55*d5ef99ddSAndreas Gohr                        'name'    => $this->buildByMatch($regex['name'], $matches),
56*d5ef99ddSAndreas Gohr                        'version' => $this->buildVersion((string) $regex['version'], $matches),
57*d5ef99ddSAndreas Gohr                    ];
58*d5ef99ddSAndreas Gohr
59*d5ef99ddSAndreas Gohr                    break;
60*d5ef99ddSAndreas Gohr                }
61*d5ef99ddSAndreas Gohr            }
62*d5ef99ddSAndreas Gohr        }
63*d5ef99ddSAndreas Gohr
64*d5ef99ddSAndreas Gohr        return $result;
65*d5ef99ddSAndreas Gohr    }
66*d5ef99ddSAndreas Gohr
67*d5ef99ddSAndreas Gohr    /**
68*d5ef99ddSAndreas Gohr     * Returns all names defined in the regexes
69*d5ef99ddSAndreas Gohr     *
70*d5ef99ddSAndreas Gohr     * Attention: This method might not return all names of detected clients
71*d5ef99ddSAndreas Gohr     *
72*d5ef99ddSAndreas Gohr     * @return array
73*d5ef99ddSAndreas Gohr     */
74*d5ef99ddSAndreas Gohr    public static function getAvailableClients(): array
75*d5ef99ddSAndreas Gohr    {
76*d5ef99ddSAndreas Gohr        $instance = new static(); // @phpstan-ignore-line
77*d5ef99ddSAndreas Gohr        $regexes  = $instance->getRegexes();
78*d5ef99ddSAndreas Gohr        $names    = [];
79*d5ef99ddSAndreas Gohr
80*d5ef99ddSAndreas Gohr        foreach ($regexes as $regex) {
81*d5ef99ddSAndreas Gohr            if (false !== \strpos($regex['name'], '$1')) {
82*d5ef99ddSAndreas Gohr                continue;
83*d5ef99ddSAndreas Gohr            }
84*d5ef99ddSAndreas Gohr
85*d5ef99ddSAndreas Gohr            $names[] = $regex['name'];
86*d5ef99ddSAndreas Gohr        }
87*d5ef99ddSAndreas Gohr
88*d5ef99ddSAndreas Gohr        if (static::class === MobileApp::class) {
89*d5ef99ddSAndreas Gohr            $names = \array_merge($names, [
90*d5ef99ddSAndreas Gohr                // Microsoft Office $1
91*d5ef99ddSAndreas Gohr                'Microsoft Office Access', 'Microsoft Office Excel', 'Microsoft Office OneDrive for Business',
92*d5ef99ddSAndreas Gohr                'Microsoft Office OneNote', 'Microsoft Office PowerPoint', 'Microsoft Office Project',
93*d5ef99ddSAndreas Gohr                'Microsoft Office Publisher', 'Microsoft Office Visio', 'Microsoft Office Word',
94*d5ef99ddSAndreas Gohr                // Podkicker$1
95*d5ef99ddSAndreas Gohr                'Podkicker', 'Podkicker Pro', 'Podkicker Classic',
96*d5ef99ddSAndreas Gohr                // radio.$1
97*d5ef99ddSAndreas Gohr                'radio.at', 'radio.de', 'radio.dk', 'radio.es', 'radio.fr',
98*d5ef99ddSAndreas Gohr                'radio.it',  'radio.pl', 'radio.pt', 'radio.se',  'radio.net',
99*d5ef99ddSAndreas Gohr            ]);
100*d5ef99ddSAndreas Gohr        }
101*d5ef99ddSAndreas Gohr
102*d5ef99ddSAndreas Gohr        \natcasesort($names);
103*d5ef99ddSAndreas Gohr
104*d5ef99ddSAndreas Gohr        return \array_unique($names);
105*d5ef99ddSAndreas Gohr    }
106*d5ef99ddSAndreas Gohr}
107