Skip to content

Commit ddc1755

Browse files
committed
Initial commit
1 parent fee33a9 commit ddc1755

11 files changed

Lines changed: 364 additions & 0 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
composer.lock
2+
composer.phar
3+
/vendor/
4+
build/logs/*

.travis.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
sudo: false
2+
language: php
3+
php:
4+
- 7.0
5+
- 5.6
6+
- 5.5
7+
- 5.4
8+
- hhvm
9+
before_install:
10+
- composer selfupdate
11+
install:
12+
- composer install
13+
after_script:
14+
- CODECLIMATE_REPO_TOKEN=33dec833c8c38b66895abeedd80633f19ad8e08bacf3a2421d1fef5b36ef207f ./vendor/bin/test-reporter

README.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
[![Build Status](https://travis-ci.org/VIPnytt/UserAgentParser.svg?branch=master)](https://travis-ci.org/VIPnytt/UserAgentParser)
2+
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/VIPnytt/UserAgentParser/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/VIPnytt/UserAgentParser/?branch=master)
3+
[![Code Climate](https://codeclimate.com/github/VIPnytt/UserAgentParser/badges/gpa.svg)](https://codeclimate.com/github/VIPnytt/UserAgentParser)
4+
[![Test Coverage](https://codeclimate.com/github/VIPnytt/UserAgentParser/badges/coverage.svg)](https://codeclimate.com/github/VIPnytt/UserAgentParser/coverage)
5+
[![License](https://poser.pugx.org/VIPnytt/UserAgentParser/license)](https://github.com/VIPnytt/UserAgentParser/blob/master/LICENSE)
6+
[![Packagist](https://img.shields.io/packagist/v/vipnytt/useragentparser.svg)](https://packagist.org/packages/vipnytt/useragentparser)
7+
[![Chat](https://badges.gitter.im/VIPnytt/UserAgentParser.svg)](https://gitter.im/VIPnytt/UserAgentParser)
8+
9+
# User-Agent string parser class
10+
PHP class to parse User-Agent strings.
11+
12+
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/1386c14c-546c-4c42-ac55-91ea3a3a1ae1/big.png)](https://insight.sensiolabs.com/projects/1386c14c-546c-4c42-ac55-91ea3a3a1ae1)
13+
14+
## Installation
15+
The library is available for install via [Composer](https://getcomposer.org). Just add this to your `composer.json` file:
16+
```json
17+
{
18+
"require": {
19+
"vipnytt/useragentparser": "0.1.*"
20+
}
21+
}
22+
```
23+
Then run `composer update`.
24+
25+
## Features
26+
- Strip the version tag.
27+
- Find different groups the User-Agent belongs to.
28+
- Determine the correct group of records by finding the group with the most specific user-agent that still matches.
29+
30+
## When do I need it?
31+
- Parsing of `robots.txt`, the rules for robots online.
32+
- Parsing of the _X-Robots-Tag_ HTTP-header.
33+
- Parsing of _Robots meta tags_ in HTML documents
34+
35+
36+
## Getting Started
37+
38+
### Strip the version tag.
39+
```php
40+
use vipnytt\UserAgentParser;
41+
42+
$parser = new UserAgentParser('googlebot/2.1');
43+
var_dump($parser->stripVersion());
44+
/* googlebot */
45+
```
46+
47+
### Find different groups the User-Agent belongs to.
48+
```php
49+
use vipnytt\UserAgentParser;
50+
51+
$parser = new UserAgentParser('googlebot-news/2.1');
52+
var_dump($parser->export());
53+
/*
54+
* googlebot-news/2.1
55+
* googlebot-news
56+
* googlebot
57+
*/
58+
```
59+
60+
### Determine the correct group
61+
Determine the correct group of records by finding the group with the most specific user-agent that still matches.
62+
```php
63+
use vipnytt\UserAgentParser;
64+
65+
$parser = new UserAgentParser('googlebot-news');
66+
var_dump($parser->match(['googlebot/2.1', 'googlebot-images','googlebot']));
67+
/* googlebot */
68+
```

build/logs/.gitkeep

Whitespace-only changes.

composer.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"name": "vipnytt/useragentparser",
3+
"description": "User-Agent string parser class",
4+
"keywords": [
5+
"UserAgent",
6+
"User-Agent",
7+
"UserAgent-string",
8+
"robots.txt",
9+
"X-Robots-tag",
10+
"Robots-meta-tag",
11+
"Robot",
12+
"Spider",
13+
"Web-Crawler"
14+
],
15+
"homepage": "https://github.com/VIPnytt/UserAgentParser",
16+
"type": "library",
17+
"license": "MIT",
18+
"minimum-stability": "dev",
19+
"prefer-stable": true,
20+
"require": {
21+
"php": ">=5.4.0"
22+
},
23+
"require-dev": {
24+
"phpunit/phpunit": ">=4.0",
25+
"codeclimate/php-test-reporter": ">=0.2.0"
26+
},
27+
"authors": [
28+
{
29+
"name": "VIP nytt",
30+
"email": "vipnytt@gmail.com",
31+
"role": "creator"
32+
},
33+
{
34+
"name": "Jan-Petter Gundersen",
35+
"email": "europe.jpg@gmail.com",
36+
"role": "developer"
37+
}
38+
],
39+
"autoload": {
40+
"psr-4": {
41+
"vipnytt\\": "src/"
42+
}
43+
},
44+
"autoload-dev": {
45+
"psr-4": {
46+
"vipnytt\\UserAgentParser\\Tests\\": "tests/"
47+
}
48+
}
49+
}

phpunit.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="./tests/bootstrap.php">
3+
<testsuites>
4+
<testsuite>
5+
<directory>tests</directory>
6+
</testsuite>
7+
</testsuites>
8+
<filter>
9+
<whitelist>
10+
<directory suffix=".php">src</directory>
11+
</whitelist>
12+
</filter>
13+
<logging>
14+
<log type="coverage-clover" target="build/logs/clover.xml"/>
15+
</logging>
16+
</phpunit>

src/UserAgentParser.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
namespace vipnytt;
3+
4+
/**
5+
* Class UserAgentParser
6+
*
7+
* @package vipnytt
8+
*/
9+
class UserAgentParser
10+
{
11+
private $userAgent;
12+
private $groups = [];
13+
14+
/**
15+
* Constructor
16+
*
17+
* @param string $userAgent
18+
*/
19+
public function __construct($userAgent)
20+
{
21+
$this->userAgent = mb_strtolower(trim($userAgent));
22+
$this->explode();
23+
}
24+
25+
/**
26+
* Parses all possible User-Agent groups to an array
27+
*
28+
* @return array
29+
*/
30+
private function explode()
31+
{
32+
$this->groups = [$this->userAgent];
33+
$this->groups[] = $this->stripVersion();
34+
while (strpos(end($this->groups), '-') !== false) {
35+
$current = end($this->groups);
36+
$this->groups[] = substr($current, 0, strrpos($current, '-'));
37+
}
38+
$this->groups = array_unique($this->groups);
39+
}
40+
41+
/**
42+
* Strip version number
43+
*
44+
* @return string
45+
*/
46+
public function stripVersion()
47+
{
48+
if (strpos($this->userAgent, '/') !== false) {
49+
return explode('/', $this->userAgent, 2)[0];
50+
}
51+
return $this->userAgent;
52+
}
53+
54+
/**
55+
* Find matching User-Agent
56+
* Selects the best matching from an array, or $fallback if none matches
57+
*
58+
* @param array $array
59+
* @param string|null $fallback
60+
* @return string|false
61+
*/
62+
public function match($array, $fallback = null)
63+
{
64+
foreach ($this->groups as $userAgent) {
65+
if (in_array($userAgent, array_map('strtolower', $array))) {
66+
return $userAgent;
67+
}
68+
}
69+
return isset($fallback) ? $fallback : false;
70+
}
71+
72+
/**
73+
* Export all User-Agents as an array
74+
*
75+
* @return array
76+
*/
77+
public function export()
78+
{
79+
return $this->groups;
80+
}
81+
}

tests/ExportTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
namespace vipnytt\UserAgentParser\Tests;
3+
4+
use vipnytt\UserAgentParser;
5+
6+
/**
7+
* Class ExportTest
8+
*
9+
* @package vipnytt\UserAgentParser\Tests
10+
*/
11+
class ExportTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* @dataProvider generateDataForTest
15+
* @param string $userAgent
16+
* @param array $result
17+
*/
18+
public function testExport($userAgent, $result)
19+
{
20+
$parser = new UserAgentParser($userAgent);
21+
$this->assertInstanceOf('vipnytt\UserAgentParser', $parser);
22+
$this->assertTrue($parser->export() == $result);
23+
}
24+
25+
/**
26+
* Generate test data
27+
* @return array
28+
*/
29+
public
30+
function generateDataForTest()
31+
{
32+
return [
33+
[
34+
'googlebot-news/2.1',
35+
[
36+
'googlebot-news/2.1',
37+
'googlebot-news',
38+
'googlebot',
39+
]
40+
]
41+
];
42+
}
43+
}

tests/MatchTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
namespace vipnytt\UserAgentParser\Tests;
3+
4+
use vipnytt\UserAgentParser;
5+
6+
/**
7+
* Class MatchTest
8+
*
9+
* @package vipnytt\UserAgentParser\Tests
10+
*/
11+
class MatchTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* @dataProvider generateDataForTest
15+
* @param string $userAgent
16+
* @param array $array
17+
*/
18+
public function testMatch($userAgent, $array)
19+
{
20+
$parser = new UserAgentParser($userAgent);
21+
$this->assertInstanceOf('vipnytt\UserAgentParser', $parser);
22+
$this->assertNotFalse($parser->match($array));
23+
}
24+
25+
/**
26+
* Generate test data
27+
* @return array
28+
*/
29+
public
30+
function generateDataForTest()
31+
{
32+
return [
33+
[
34+
'googlebot-news/2.1',
35+
[
36+
'googlebot-news',
37+
'googlebot-images',
38+
'googlebot-news/2.0',
39+
'googlebot',
40+
]
41+
]
42+
];
43+
}
44+
}

tests/VersionTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
namespace vipnytt\UserAgentParser\Tests;
3+
4+
use vipnytt\UserAgentParser;
5+
6+
/**
7+
* Class VersionTest
8+
*
9+
* @package vipnytt\UserAgentParser\Tests
10+
*/
11+
class VersionTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* @dataProvider generateDataForTest
15+
* @param string $userAgent
16+
* @param string $result
17+
*/
18+
public function testVersion($userAgent, $result)
19+
{
20+
$parser = new UserAgentParser($userAgent);
21+
$this->assertInstanceOf('vipnytt\UserAgentParser', $parser);
22+
$this->assertTrue($parser->stripVersion() == $result);
23+
}
24+
25+
/**
26+
* Generate test data
27+
* @return array
28+
*/
29+
public
30+
function generateDataForTest()
31+
{
32+
return [
33+
[
34+
'googlebot/2.1',
35+
'googlebot',
36+
],
37+
[
38+
'bingbot/2.0',
39+
'bingbot',
40+
]
41+
];
42+
}
43+
}

0 commit comments

Comments
 (0)