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