Skip to content

Commit

Permalink
Allow to set version truncation (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
renanbr authored Apr 15, 2022
1 parent 1519354 commit edc75d7
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 3 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ acsiomatic_device_detector:

# If true, DeviceDetector will trigger parser() when necessary
auto_parse: true

# Version truncation behavior, it may assume: major, minor, patch, build, or none
# By default minor versions will be returned (e.g. X.Y)
version_truncation: 'minor'
```
## Usage in controllers
Expand Down
3 changes: 2 additions & 1 deletion phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ parameters:
twig: array{
variable_name: string|null
},
auto_parse: bool
auto_parse: bool,
version_truncation: 'major'|'minor'|'patch'|'build'|'none'
}
'''
tmpDir: var/phpstan
Expand Down
1 change: 0 additions & 1 deletion rector.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?php

use Rector\Core\Configuration\Option;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
Expand Down
13 changes: 13 additions & 0 deletions src/DependencyInjection/AcsiomaticDeviceDetectorExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Acsiomatic\DeviceDetectorBundle\Twig\TwigExtension;
use DeviceDetector\DeviceDetector;
use DeviceDetector\Parser\AbstractBotParser;
use DeviceDetector\Parser\AbstractParser;
use DeviceDetector\Parser\Client\AbstractClientParser;
use DeviceDetector\Parser\Device\AbstractDeviceParser;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
Expand Down Expand Up @@ -40,6 +41,17 @@ final class AcsiomaticDeviceDetectorExtension extends Extension
*/
private const DEVICE_PARSER_TAG = 'acsiomatic.device_detector.device_parser';

/**
* @var array<string, int>
*/
private const VERSION_TRUNCATION_MAP = [
'major' => AbstractParser::VERSION_TRUNCATION_MAJOR,
'minor' => AbstractParser::VERSION_TRUNCATION_MINOR,
'patch' => AbstractParser::VERSION_TRUNCATION_PATCH,
'build' => AbstractParser::VERSION_TRUNCATION_BUILD,
'none' => AbstractParser::VERSION_TRUNCATION_NONE,
];

/**
* @param array<string, mixed> $configs
*/
Expand Down Expand Up @@ -105,6 +117,7 @@ private function setupDeviceDetectorFactory(ContainerBuilder $container, array $
->setArguments([
$config['bot']['skip_detection'],
$config['bot']['discard_information'],
self::VERSION_TRUNCATION_MAP[$config['version_truncation']],
new Reference(ClientHintsFactoryInterface::class),
$config['cache']['pool'] !== null ? new Reference($config['cache']['pool']) : null,
$config['auto_parse'] ? new Reference(DeviceDetectorProxyFactory::class) : null,
Expand Down
8 changes: 7 additions & 1 deletion src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ public function getConfigTreeBuilder(): TreeBuilder

->booleanNode('auto_parse')->defaultTrue()->end()

->end();
->enumNode('version_truncation')
->values(['major', 'minor', 'patch', 'build', 'none'])
->defaultValue('minor')
->end()

->end()
;

return $builder;
}
Expand Down
9 changes: 9 additions & 0 deletions src/Factory/DeviceDetectorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ final class DeviceDetectorFactory implements DeviceDetectorFactoryInterface
*/
private $discardBotInformation = false;

/**
* @var int
*/
private $versionTruncation;

/**
* @var ClientHintsFactoryInterface
*/
Expand Down Expand Up @@ -67,6 +72,7 @@ final class DeviceDetectorFactory implements DeviceDetectorFactoryInterface
public function __construct(
bool $skipBotDetection,
bool $discardBotInformation,
int $versionTruncation,
ClientHintsFactoryInterface $clientHintsFactory,
?CacheItemPoolInterface $cache,
?DeviceDetectorProxyFactory $proxyFactory,
Expand All @@ -76,6 +82,7 @@ public function __construct(
) {
$this->skipBotDetection = $skipBotDetection;
$this->discardBotInformation = $discardBotInformation;
$this->versionTruncation = $versionTruncation;
$this->clientHintsFactory = $clientHintsFactory;
$this->cache = $cache;
$this->proxyFactory = $proxyFactory;
Expand All @@ -93,6 +100,8 @@ public function createDeviceDetector(): DeviceDetector
$detector->skipBotDetection($this->skipBotDetection);
$detector->discardBotInformation($this->discardBotInformation);

AbstractDeviceParser::setVersionTruncation($this->versionTruncation);

if ($this->cache !== null) {
$detector->setCache(new PSR6Bridge($this->cache));
}
Expand Down
121 changes: 121 additions & 0 deletions tests/VersionTruncationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

namespace Acsiomatic\DeviceDetectorBundle\Tests;

use Acsiomatic\DeviceDetectorBundle\AcsiomaticDeviceDetectorBundle;
use Acsiomatic\DeviceDetectorBundle\Contracts\DeviceDetectorFactoryInterface;
use Acsiomatic\DeviceDetectorBundle\Tests\Util\Compiler\CompilerPassFactory;
use Acsiomatic\DeviceDetectorBundle\Tests\Util\HttpKernel\Kernel;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;

final class VersionTruncationTest extends TestCase
{
/**
* @var string
*/
private const USER_AGENT = 'Mozilla/5.0 (Linux; Android 4.2.2; ARCHOS 101 PLATINUM Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Safari/537.36';

public function testDefaultsTargetsToMinor(): void
{
$kernel = new Kernel('test', true);
$kernel->appendBundle(new FrameworkBundle());
$kernel->appendBundle(new AcsiomaticDeviceDetectorBundle());
$kernel->appendExtensionConfiguration('framework', ['test' => true, 'secret' => '53CR37']);

$kernel->appendCompilerPass(
CompilerPassFactory::createPublicAlias(
'device_detector_factory.public',
DeviceDetectorFactoryInterface::class
)
);

$kernel->boot();

/** @var DeviceDetectorFactoryInterface $deviceDetectorFactory */
$deviceDetectorFactory = $kernel->getContainer()->get('device_detector_factory.public');
$deviceDetector = $deviceDetectorFactory->createDeviceDetector();

$deviceDetector->setUserAgent(self::USER_AGENT);
$deviceDetector->parse();

static::assertSame('4.2', $deviceDetector->getOs('version'));
static::assertSame('34.0', $deviceDetector->getClient('version'));
}

/**
* @dataProvider getVersionTruncationFixtures
*/
public function testSetVersionTruncation(
string $userAgent,
string $truncation,
string $expectedOsVersion,
string $expectedClientVersion
): void {
$kernel = new Kernel('test', true);
$kernel->appendBundle(new FrameworkBundle());
$kernel->appendBundle(new AcsiomaticDeviceDetectorBundle());
$kernel->appendExtensionConfiguration('framework', ['test' => true, 'secret' => '53CR37']);
$kernel->appendExtensionConfiguration('acsiomatic_device_detector', ['version_truncation' => $truncation]);

$kernel->appendCompilerPass(
CompilerPassFactory::createPublicAlias(
'device_detector_factory.public',
DeviceDetectorFactoryInterface::class
)
);

$kernel->boot();

/** @var DeviceDetectorFactoryInterface $deviceDetectorFactory */
$deviceDetectorFactory = $kernel->getContainer()->get('device_detector_factory.public');
$deviceDetector = $deviceDetectorFactory->createDeviceDetector();

$deviceDetector->setUserAgent($userAgent);
$deviceDetector->parse();

static::assertSame($expectedOsVersion, $deviceDetector->getOs('version'));
static::assertSame($expectedClientVersion, $deviceDetector->getClient('version'));
}

/**
* @return iterable<array{user_agent: string, truncation: string, os_version: string, client_version: string}>
*/
public function getVersionTruncationFixtures(): iterable
{
yield 'none' => [
'user_agent' => self::USER_AGENT,
'truncation' => 'none',
'os_version' => '4.2.2',
'client_version' => '34.0.1847.114',
];

yield 'build' => [
'user_agent' => self::USER_AGENT,
'truncation' => 'build',
'os_version' => '4.2.2',
'client_version' => '34.0.1847.114',
];

yield 'patch' => [
'user_agent' => self::USER_AGENT,
'truncation' => 'patch',
'os_version' => '4.2.2',
'client_version' => '34.0.1847',
];

yield 'minor' => [
'user_agent' => self::USER_AGENT,
'truncation' => 'minor',
'os_version' => '4.2',
'client_version' => '34.0',
];

yield 'major' => [
'user_agent' => self::USER_AGENT,
'truncation' => 'major',
'os_version' => '4',
'client_version' => '34',
];
}
}

0 comments on commit edc75d7

Please sign in to comment.