mirror of
https://github.com/werkraum-media/abtest.git
synced 2024-11-15 16:16:11 +01:00
270 lines
6.9 KiB
PHP
270 lines
6.9 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Device Detector - The Universal Device Detection library for parsing User Agents
|
||
|
*
|
||
|
* @link http://piwik.org
|
||
|
* @license http://www.gnu.org/licenses/lgpl.html LGPL v3 or later
|
||
|
*/
|
||
|
namespace WapplerSystems\ABTest2\DeviceDetector\Parser;
|
||
|
|
||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||
|
use WapplerSystems\ABTest2\DeviceDetector\Yaml\Parser;
|
||
|
|
||
|
/**
|
||
|
* Class ParserAbstract
|
||
|
*
|
||
|
* @package DeviceDetector\Parser
|
||
|
*/
|
||
|
abstract class ParserAbstract
|
||
|
{
|
||
|
/**
|
||
|
* Holds the path to the yml file containing regexes
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $fixtureFile;
|
||
|
/**
|
||
|
* Holds the internal name of the parser
|
||
|
* Used for caching
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $parserName;
|
||
|
|
||
|
/**
|
||
|
* Holds the user agent the should be parsed
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $userAgent;
|
||
|
|
||
|
/**
|
||
|
* Holds an array with method that should be available global
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $globalMethods;
|
||
|
|
||
|
/**
|
||
|
* Holds an array with regexes to parse, if already loaded
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $regexList;
|
||
|
|
||
|
/**
|
||
|
* Indicates how deep versioning will be detected
|
||
|
* if $maxMinorParts is 0 only the major version will be returned
|
||
|
* @var int
|
||
|
*/
|
||
|
protected static $maxMinorParts = 1;
|
||
|
|
||
|
/**
|
||
|
* Versioning constant used to set max versioning to major version only
|
||
|
* Version examples are: 3, 5, 6, 200, 123, ...
|
||
|
*/
|
||
|
|
||
|
const VERSION_TRUNCATION_MAJOR = 0;
|
||
|
|
||
|
/**
|
||
|
* Versioning constant used to set max versioning to minor version
|
||
|
* Version examples are: 3.4, 5.6, 6.234, 0.200, 1.23, ...
|
||
|
*/
|
||
|
const VERSION_TRUNCATION_MINOR = 1;
|
||
|
|
||
|
/**
|
||
|
* Versioning constant used to set max versioning to path level
|
||
|
* Version examples are: 3.4.0, 5.6.344, 6.234.2, 0.200.3, 1.2.3, ...
|
||
|
*/
|
||
|
const VERSION_TRUNCATION_PATCH = 2;
|
||
|
|
||
|
/**
|
||
|
* Versioning constant used to set versioning to build number
|
||
|
* Version examples are: 3.4.0.12, 5.6.334.0, 6.234.2.3, 0.200.3.1, 1.2.3.0, ...
|
||
|
*/
|
||
|
const VERSION_TRUNCATION_BUILD = 3;
|
||
|
|
||
|
/**
|
||
|
* Versioning constant used to set versioning to unlimited (no truncation)
|
||
|
*/
|
||
|
const VERSION_TRUNCATION_NONE = null;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @var Parser
|
||
|
*/
|
||
|
protected $yamlParser;
|
||
|
|
||
|
abstract public function parse();
|
||
|
|
||
|
public function __construct($ua='')
|
||
|
{
|
||
|
$this->setUserAgent($ua);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set how DeviceDetector should return versions
|
||
|
* @param int|null $type Any of the VERSION_TRUNCATION_* constants
|
||
|
*/
|
||
|
public static function setVersionTruncation($type)
|
||
|
{
|
||
|
if (in_array($type, array(self::VERSION_TRUNCATION_BUILD,
|
||
|
self::VERSION_TRUNCATION_NONE,
|
||
|
self::VERSION_TRUNCATION_MAJOR,
|
||
|
self::VERSION_TRUNCATION_MINOR,
|
||
|
self::VERSION_TRUNCATION_PATCH))) {
|
||
|
self::$maxMinorParts = $type;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the user agent to parse
|
||
|
*
|
||
|
* @param string $ua user agent
|
||
|
*/
|
||
|
public function setUserAgent($ua)
|
||
|
{
|
||
|
$this->userAgent = $ua;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the internal name of the parser
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getName()
|
||
|
{
|
||
|
return $this->parserName;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the result of the parsed yml file defined in $fixtureFile
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function getRegexes()
|
||
|
{
|
||
|
if (empty($this->regexList)) {
|
||
|
$this->regexList = $this->getYamlParser()->parse(
|
||
|
file_get_contents(GeneralUtility::getFileAbsFileName('EXT:abtest2/Configuration/YAML/'.$this->fixtureFile))
|
||
|
);
|
||
|
}
|
||
|
return $this->regexList;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function getRegexesDirectory()
|
||
|
{
|
||
|
return dirname(__DIR__);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Matches the useragent against the given regex
|
||
|
*
|
||
|
* @param $regex
|
||
|
* @return array|bool
|
||
|
*/
|
||
|
protected function matchUserAgent($regex)
|
||
|
{
|
||
|
// only match if useragent begins with given regex or there is no letter before it
|
||
|
$regex = '/(?:^|[^A-Z0-9\-_]|[^A-Z0-9\-]_|sprd-)(?:' . str_replace('/', '\/', $regex) . ')/i';
|
||
|
|
||
|
if (preg_match($regex, $this->userAgent, $matches)) {
|
||
|
return $matches;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $item
|
||
|
* @param array $matches
|
||
|
* @return string type
|
||
|
*/
|
||
|
protected function buildByMatch($item, $matches)
|
||
|
{
|
||
|
for ($nb=1;$nb<=3;$nb++) {
|
||
|
if (strpos($item, '$' . $nb) === false) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$replace = isset($matches[$nb]) ? $matches[$nb] : '';
|
||
|
$item = trim(str_replace('$' . $nb, $replace, $item));
|
||
|
}
|
||
|
return $item;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Builds the version with the given $versionString and $matches
|
||
|
*
|
||
|
* Example:
|
||
|
* $versionString = 'v$2'
|
||
|
* $matches = array('version_1_0_1', '1_0_1')
|
||
|
* return value would be v1.0.1
|
||
|
*
|
||
|
* @param $versionString
|
||
|
* @param $matches
|
||
|
* @return mixed|string
|
||
|
*/
|
||
|
protected function buildVersion($versionString, $matches)
|
||
|
{
|
||
|
$versionString = $this->buildByMatch($versionString, $matches);
|
||
|
$versionString = str_replace('_', '.', $versionString);
|
||
|
if (null !== self::$maxMinorParts && substr_count($versionString, '.') > self::$maxMinorParts) {
|
||
|
$versionParts = explode('.', $versionString);
|
||
|
$versionParts = array_slice($versionParts, 0, 1+self::$maxMinorParts);
|
||
|
$versionString = implode('.', $versionParts);
|
||
|
}
|
||
|
return trim($versionString, ' .');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Tests the useragent against a combination of all regexes
|
||
|
*
|
||
|
* All regexes returned by getRegexes() will be reversed and concated with '|'
|
||
|
* Afterwards the big regex will be tested against the user agent
|
||
|
*
|
||
|
* Method can be used to speed up detections by making a big check before doing checks for every single regex
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
protected function preMatchOverall()
|
||
|
{
|
||
|
$regexes = $this->getRegexes();
|
||
|
|
||
|
static $overAllMatch;
|
||
|
|
||
|
if (empty($overAllMatch)) {
|
||
|
// reverse all regexes, so we have the generic one first, which already matches most patterns
|
||
|
$overAllMatch = array_reduce(array_reverse($regexes), function ($val1, $val2) {
|
||
|
if (!empty($val1)) {
|
||
|
return $val1.'|'.$val2['regex'];
|
||
|
} else {
|
||
|
return $val2['regex'];
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return $this->matchUserAgent($overAllMatch);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Sets the YamlParser class
|
||
|
*
|
||
|
* @param Parser
|
||
|
*/
|
||
|
public function setYamlParser($yamlParser)
|
||
|
{
|
||
|
$this->yamlParser = $yamlParser;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns Parser object
|
||
|
*
|
||
|
* @return Parser
|
||
|
*/
|
||
|
public function getYamlParser()
|
||
|
{
|
||
|
return $this->yamlParser;
|
||
|
}
|
||
|
}
|