Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2
jobs:
test:
docker:
- image: circleci/php:7.0-apache-node-browsers
- image: circleci/php:7.1-apache-node-browsers
steps:
- checkout
- run: sudo composer self-update
Expand All @@ -12,4 +12,4 @@ workflows:
version: 2
test:
jobs:
- test
- test
3 changes: 3 additions & 0 deletions .codacy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
exclude_paths:
- "demo.php"
- "*.md"
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
}
],
"require": {
"php": ">=7.0",
"php": ">=7.1",
"endorphin-studio/browser-detector-detection": "^2.1",
"endorphin-studio/browser-detector-tools": "^1.2",
"endorphin-studio/browser-detector-data": "^1.2"
"endorphin-studio/browser-detector-data": "^1.2",
"endorphin-studio/browser-detector-data-yaml": "^1.0"
},
"require-dev":
{
Expand Down
223 changes: 125 additions & 98 deletions src/Detector.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

namespace EndorphinStudio\Detector;

use EndorphinStudio\Detector\Data\AbstractData;
use EndorphinStudio\Detector\Data\Result;
use EndorphinStudio\Detector\Exception\StorageException;
use EndorphinStudio\Detector\Storage\AbstractStorage;
use EndorphinStudio\Detector\Storage\StorageInterface;
use EndorphinStudio\Detector\Storage\YamlStorage;
use RuntimeException;
use Symfony\Component\HttpFoundation\Request;

/**
Expand All @@ -23,68 +23,33 @@
*/
class Detector
{
private $version = '6.0.1';

public function getVersion(): string
{
return $this->version;
}
private const DATA_PACKAGE = 'endorphin-studio/browser-detector-data-yaml';

/**
* @var array Array of options
*/
protected $options = [
'dataProvider' => '\\EndorphinStudio\\Detector\\Storage\\YamlStorage',
'dataProvider' => YamlStorage::class,
'dataDirectory' => 'auto',
'cacheDirectory' => 'auto',
'format' => 'yaml'
];

private $version = '6.0.3';

/**
* @var StorageInterface
*/
private $dataProvider;

/**
* Get storage provider
* @return StorageInterface
*/
public function getDataProvider(): StorageInterface
{
return $this->dataProvider;
}

/**
* Get result object
* @return Result Result object
*/
public function getResultObject(): Result
{
return $this->resultObject;
}

/**
* @var Result Result object
*/
private $resultObject;

/**
* Set data provider
* @param StorageInterface $dataProvider
*/
public function setDataProvider(StorageInterface $dataProvider)
{
$this->dataProvider = $dataProvider;
}

/**
* @return mixed
* @var string $ua User Agent
*/
public function getUserAgent()
{
return $this->ua;
}

private $ua;

/**
Expand All @@ -100,106 +65,168 @@ public function getUserAgent()
* 'cacheDirectory' => 'auto',
* 'format' => 'yaml'
* @param array $options Array of options
* @throws \ReflectionException
* @throws StorageException
* @SuppressWarnings(PHPMD.StaticAccess)
*/
public function __construct(array $options = [])
{
$this->options = array_merge_recursive($options, $this->options);

$this->init();
$this->detectors = [];
$check = ['os','device', 'browser', 'robot'];
Tools::setWindowsConfig($this->dataProvider->getConfig()['windows']);
foreach ($check as $detectionType) {
$className = sprintf('\\EndorphinStudio\\Detector\\Detection\\%s', ucfirst(sprintf('%sDetector', $detectionType)));
if(class_exists($className)) {
$this->detectors[$detectionType] = new $className();
$this->detectors[$detectionType]->init($this);
}
foreach (['os', 'device', 'browser'] as $detectionType) {
$this->initDetector($detectionType);
}
}

/**
* Analyse User Agent String
* @param string $ua
* @return Result
*/
public function analyse(string $ua = 'ua'): Result
{
$request = Request::createFromGlobals();
$this->ua = $ua === 'ua' ? $request->server->get('HTTP_USER_AGENT') : $ua;
$this->resultObject = new Result($this->ua, $this);
foreach ($this->detectors as $detectionType => $detector) {
$detector->detect();
}
return $this->resultObject;
}

/**
* Get list of patterns from config
* @param $list
* @param $type
* @return array
*/
public function getPatternList($list, $type)
{
return array_key_exists($type, $list) ? $list[$type] : [];
}

/**
* Initialisation method
* @throws \ReflectionException
* @throws StorageException
* @throws RuntimeException
*/
protected function init()
protected function init(): void
{
$dataProvider = new $this->options['dataProvider']();

/** @var StorageInterface $dataProvider */
$this->setDataProvider($dataProvider);
$this->setDataProvider($this->createDataProvider());
$this->dataProvider->setDataDirectory($this->findDataDirectory());
if(method_exists($this->dataProvider,'setCacheDirectory')) {
$this->dataProvider->setCacheDirectory($this->findCacheDirectory());
}
if(method_exists($this->dataProvider,'setCacheEnabled')) {
$this->dataProvider->setCacheEnabled(true);
$this->callMethod($this->dataProvider, 'setCacheDirectory', $this->findCacheDirectory());
$this->callMethod($this->dataProvider, 'setCacheEnabled', true);
}

private function createDataProvider()
{
if (class_exists($this->options['dataProvider'])) {
return new $this->options['dataProvider']();
}
throw new RuntimeException('Data Provider class isn\'t exist');
}

/**
* @return string
* @throws StorageException
* @throws \ReflectionException
*/
private function findDataDirectory(): string
{
$dataDirectory = $this->options['dataDirectory'];
if($this->options['dataDirectory'] === 'auto') {
$reflection = new \ReflectionClass(AbstractData::class);
$dataDirectory = sprintf('%s/var/%s', dirname($reflection->getFileName(),3), $this->options['format']);
if ($this->options['dataDirectory'] === 'auto') {
$dataDirectory = sprintf('%s/data', $this->getPackagePath(self::DATA_PACKAGE));
}
if(is_dir($dataDirectory)){
if (is_dir($dataDirectory)) {
return $dataDirectory;
}
throw new StorageException(sprintf(StorageException::DIRECTORY_NOT_FOUND, $dataDirectory));
}

private function getPackagePath(string $package): string
{
/**
* If running from vendor directory
*/
if (strpos(dirname(__FILE__, 3), 'endorphin-studio') !== false) {
$vendorDir = dirname(__FILE__, 4);
} else {
$vendorDir = dirname(__FILE__, 2) . '/vendor';
}
return sprintf('%s/%s', $vendorDir, $package);
}

protected function callMethod($object, string $methodName, ...$arguments): void
{
if (method_exists($object, $methodName)) {
$object->$methodName($arguments);
}
}

/**
* @return string
* @throws StorageException
* @throws \ReflectionException
*/
private function findCacheDirectory(): string
{
$cacheDirectory = $this->options['cacheDirectory'];
if($this->options['cacheDirectory'] === 'auto') {
$reflection = new \ReflectionClass(AbstractData::class);
$cacheDirectory = sprintf('%s/var/cache', dirname($reflection->getFileName(),3));
if ($this->options['cacheDirectory'] === 'auto') {
$cacheDirectory = sprintf('%s/var/cache', dirname(__FILE__, 2));
}
if(is_dir($cacheDirectory)){
if (is_dir($cacheDirectory)) {
return $cacheDirectory;
}
throw new StorageException(sprintf(StorageException::DIRECTORY_NOT_FOUND, $cacheDirectory));
}

private function initDetector(string $type): void
{
$className = sprintf('\\EndorphinStudio\\Detector\\Detection\\%s', ucfirst(sprintf('%sDetector', $type)));
if (class_exists($className)) {
$this->detectors[$type] = new $className();
$this->detectors[$type]->init($this);
}
}

public function getVersion(): string
{
return $this->version;
}

/**
* Get storage provider
* @return StorageInterface
*/
public function getDataProvider(): StorageInterface
{
return $this->dataProvider;
}

/**
* Set data provider
* @param StorageInterface $dataProvider
*/
public function setDataProvider(StorageInterface $dataProvider): void
{
$this->dataProvider = $dataProvider;
}

/**
* Get result object
* @return Result Result object
*/
public function getResultObject(): Result
{
return $this->resultObject;
}

/**
* @return string
*/
public function getUserAgent(): string
{
return $this->ua;
}

/**
* Analyse User Agent String
* @param string $ua
* @return Result
* @SuppressWarnings(PHPMD.StaticAccess)
*/
public function analyse(string $ua = 'ua'): Result
{
$request = Request::createFromGlobals();
$this->ua = $ua === 'ua' ? $request->server->get('HTTP_USER_AGENT') : $ua;
$this->resultObject = new Result($this->ua, $this);
foreach ($this->detectors as $detectionType => $detector) {
$detector->detect();
}
return $this->resultObject;
}

/**
* Get list of patterns from config
* @param $list
* @param $type
* @return array
*/
public function getPatternList($list, $type): array
{
return array_key_exists($type, $list) ? $list[$type] : [];
}
}
1 change: 1 addition & 0 deletions var/cache/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**