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; 14*d5ef99ddSAndreas Gohr 15*d5ef99ddSAndreas Gohr/** 16*d5ef99ddSAndreas Gohr * Class Bot 17*d5ef99ddSAndreas Gohr * 18*d5ef99ddSAndreas Gohr * Parses a user agent for bot information 19*d5ef99ddSAndreas Gohr * 20*d5ef99ddSAndreas Gohr * Detected bots are defined in regexes/bots.yml 21*d5ef99ddSAndreas Gohr */ 22*d5ef99ddSAndreas Gohrclass Bot extends AbstractBotParser 23*d5ef99ddSAndreas Gohr{ 24*d5ef99ddSAndreas Gohr /** 25*d5ef99ddSAndreas Gohr * @var string 26*d5ef99ddSAndreas Gohr */ 27*d5ef99ddSAndreas Gohr protected $fixtureFile = 'regexes/bots.yml'; 28*d5ef99ddSAndreas Gohr 29*d5ef99ddSAndreas Gohr /** 30*d5ef99ddSAndreas Gohr * @var string 31*d5ef99ddSAndreas Gohr */ 32*d5ef99ddSAndreas Gohr protected $parserName = 'bot'; 33*d5ef99ddSAndreas Gohr 34*d5ef99ddSAndreas Gohr /** 35*d5ef99ddSAndreas Gohr * @var bool 36*d5ef99ddSAndreas Gohr */ 37*d5ef99ddSAndreas Gohr protected $discardDetails = false; 38*d5ef99ddSAndreas Gohr 39*d5ef99ddSAndreas Gohr /** 40*d5ef99ddSAndreas Gohr * Enables information discarding 41*d5ef99ddSAndreas Gohr */ 42*d5ef99ddSAndreas Gohr public function discardDetails(): void 43*d5ef99ddSAndreas Gohr { 44*d5ef99ddSAndreas Gohr $this->discardDetails = true; 45*d5ef99ddSAndreas Gohr } 46*d5ef99ddSAndreas Gohr 47*d5ef99ddSAndreas Gohr /** 48*d5ef99ddSAndreas Gohr * Parses the current UA and checks whether it contains bot information 49*d5ef99ddSAndreas Gohr * 50*d5ef99ddSAndreas Gohr * @see bots.yml for list of detected bots 51*d5ef99ddSAndreas Gohr * 52*d5ef99ddSAndreas Gohr * Step 1: Build a big regex containing all regexes and match UA against it 53*d5ef99ddSAndreas Gohr * -> If no matches found: return 54*d5ef99ddSAndreas Gohr * -> Otherwise: 55*d5ef99ddSAndreas Gohr * Step 2: Walk through the list of regexes in bots.yml and try to match every one 56*d5ef99ddSAndreas Gohr * -> Return the matched data 57*d5ef99ddSAndreas Gohr * 58*d5ef99ddSAndreas Gohr * If $discardDetails is set to TRUE, the Step 2 will be skipped 59*d5ef99ddSAndreas Gohr * $bot will be set to TRUE instead 60*d5ef99ddSAndreas Gohr * 61*d5ef99ddSAndreas Gohr * NOTE: Doing the big match before matching every single regex speeds up the detection 62*d5ef99ddSAndreas Gohr * 63*d5ef99ddSAndreas Gohr * @return array|null 64*d5ef99ddSAndreas Gohr */ 65*d5ef99ddSAndreas Gohr public function parse(): ?array 66*d5ef99ddSAndreas Gohr { 67*d5ef99ddSAndreas Gohr $result = null; 68*d5ef99ddSAndreas Gohr 69*d5ef99ddSAndreas Gohr if ($this->preMatchOverall()) { 70*d5ef99ddSAndreas Gohr if ($this->discardDetails) { 71*d5ef99ddSAndreas Gohr return [true]; 72*d5ef99ddSAndreas Gohr } 73*d5ef99ddSAndreas Gohr 74*d5ef99ddSAndreas Gohr foreach ($this->getRegexes() as $regex) { 75*d5ef99ddSAndreas Gohr $matches = $this->matchUserAgent($regex['regex']); 76*d5ef99ddSAndreas Gohr 77*d5ef99ddSAndreas Gohr if ($matches) { 78*d5ef99ddSAndreas Gohr unset($regex['regex']); 79*d5ef99ddSAndreas Gohr $result = $regex; 80*d5ef99ddSAndreas Gohr 81*d5ef99ddSAndreas Gohr break; 82*d5ef99ddSAndreas Gohr } 83*d5ef99ddSAndreas Gohr } 84*d5ef99ddSAndreas Gohr } 85*d5ef99ddSAndreas Gohr 86*d5ef99ddSAndreas Gohr return $result; 87*d5ef99ddSAndreas Gohr } 88*d5ef99ddSAndreas Gohr} 89