Page MenuHomeDevCentral

No OneTemporary

diff --git a/src/Collections/WeightedList.php b/src/Collections/WeightedList.php
index 4060c22..ca8d5ef 100644
--- a/src/Collections/WeightedList.php
+++ b/src/Collections/WeightedList.php
@@ -1,75 +1,103 @@
<?php
namespace Keruald\OmniTools\Collections;
use ArrayIterator;
use Countable;
use Iterator;
use IteratorAggregate;
class WeightedList implements IteratorAggregate, Countable {
/**
* @var WeightedValue[]
*/
private $list;
public function __construct () {
$this->list = [];
}
+ /**
+ * @param string $expression A string like "a,b;q=0.1,c;q=0.4"
+ *
+ * @return WeightedList
+ *
+ * @see RFC 7231, section 5.3.1
+ */
+ public static function parse (string $expression) : WeightedList {
+ $list = new WeightedList();
+
+ if ($expression !== "") {
+ $items = explode(',', $expression);
+ foreach ($items as $item) {
+ $list->addFromString($item);
+ }
+ }
+
+ return $list;
+ }
+
///
/// Helper methods
///
public function add ($item, float $weight = 1.0) : void {
$this->list[] = new WeightedValue($item, $weight);
}
+ public function addWeightedValue (WeightedValue $value) : void {
+ $this->list[] = $value;
+ }
+
+ public function addFromString (string $expression) : void {
+ $this->addWeightedValue(WeightedValue::parse($expression));
+ }
+
public function clear () : void {
$this->list = [];
}
public function getHeaviest () {
$value = null;
foreach ($this->list as $candidate) {
if ($value === null || $candidate->compareTo($value) > 0) {
$value = $candidate;
}
}
return $value;
}
public function toSortedArray () : array {
$weights = [];
$values = [];
foreach ($this->list as $item) {
$weights[] = $item->getWeight();
$values[] = $item->getValue();
}
array_multisort($weights, SORT_DESC, $values, SORT_ASC);
return $values;
}
///
/// IteratorAggregate implementation
///
public function getIterator () : Iterator {
return new ArrayIterator($this->list);
}
///
/// Countable implementation
///
public function count () : int {
return count($this->list);
}
}
diff --git a/src/Collections/WeightedValue.php b/src/Collections/WeightedValue.php
index 921a523..a86555a 100644
--- a/src/Collections/WeightedValue.php
+++ b/src/Collections/WeightedValue.php
@@ -1,75 +1,85 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\Collections;
use TypeError;
class WeightedValue implements Comparable {
///
/// Constants
///
const DEFAULT_WEIGHT = 1.0;
///
/// Private members
///
/**
* @var float
*/
private $weight = self::DEFAULT_WEIGHT;
/**
* @var mixed
*/
private $value;
///
- /// Constructor
+ /// Constructors
///
public function __construct ($value, float $weight = self::DEFAULT_WEIGHT) {
$this->value = $value;
$this->weight = $weight;
}
+ public static function parse (string $expression) : WeightedValue {
+ $pair = explode(';q=', $expression);
+
+ if (count($pair) == 1) {
+ return new WeightedValue($pair[0]);
+ }
+
+ return new WeightedValue($pair[0], (float)$pair[1]);
+ }
+
///
/// Getters and setters
///
public function getWeight () : float {
return $this->weight;
}
public function setWeight (float $weight) : self {
$this->weight = $weight;
return $this;
}
public function getValue () {
return $this->value;
}
public function setValue ($value) : self {
$this->value = $value;
return $this;
}
///
/// Helper methods
///
public function compareTo (object $other) : int {
if (!$other instanceof WeightedValue) {
throw new TypeError;
}
return $this->getWeight() <=> $other->getWeight();
}
}
diff --git a/src/HTTP/Requests/AcceptedLanguages.php b/src/HTTP/Requests/AcceptedLanguages.php
new file mode 100644
index 0000000..4cf3222
--- /dev/null
+++ b/src/HTTP/Requests/AcceptedLanguages.php
@@ -0,0 +1,40 @@
+<?php
+declare(strict_types=1);
+
+namespace Keruald\OmniTools\HTTP\Requests;
+
+use Keruald\OmniTools\Collections\WeightedList;
+
+class AcceptedLanguages {
+
+ /**
+ * @var string
+ */
+ private $acceptedLanguages;
+
+ ///
+ /// Constructor
+ ///
+
+ public function __construct (string $acceptedLanguages = '') {
+ $this->acceptedLanguages = $acceptedLanguages;
+ }
+
+ public static function fromServer () : self {
+ return new self(self::extractFromHeaders());
+ }
+
+ ///
+ /// Helper methods to determine the languages
+ ///
+
+ public static function extractFromHeaders () : string {
+ return $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? "";
+ }
+
+ public function getLanguageCodes () : array {
+ return WeightedList::parse($this->acceptedLanguages)
+ ->toSortedArray();
+ }
+
+}
diff --git a/src/HTTP/Requests/Request.php b/src/HTTP/Requests/Request.php
index 2d8c2b3..aea7a9d 100644
--- a/src/HTTP/Requests/Request.php
+++ b/src/HTTP/Requests/Request.php
@@ -1,10 +1,11 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\HTTP\Requests;
class Request {
+ use WithAcceptedLanguages;
use WithRemoteAddress;
}
diff --git a/src/HTTP/Requests/WithAcceptedLanguages.php b/src/HTTP/Requests/WithAcceptedLanguages.php
new file mode 100644
index 0000000..a23a3d4
--- /dev/null
+++ b/src/HTTP/Requests/WithAcceptedLanguages.php
@@ -0,0 +1,22 @@
+<?php
+declare(strict_types=1);
+
+
+namespace Keruald\OmniTools\HTTP\Requests;
+
+
+trait WithAcceptedLanguages {
+
+ /**
+ * Gets the languages accepted by the browser, by order of priority.
+ *
+ * This will read the HTTP_ACCEPT_LANGUAGE variable sent by the browser in the
+ * HTTP request.
+ *
+ * @return string[] each item a language accepted by browser
+ */
+ public static function getAcceptedLanguages () : array {
+ return AcceptedLanguages::fromServer()->getLanguageCodes();
+ }
+
+}
diff --git a/tests/Collections/WeightedListTest.php b/tests/Collections/WeightedListTest.php
index e3daeb9..f600887 100644
--- a/tests/Collections/WeightedListTest.php
+++ b/tests/Collections/WeightedListTest.php
@@ -1,79 +1,87 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\Tests\Collections;
use Keruald\OmniTools\Collections\WeightedValue;
use Keruald\OmniTools\Collections\WeightedList;
use PHPUnit\Framework\TestCase;
class WeightedListTest extends TestCase {
/**
* @var WeightedList
*/
private $list;
///
/// Fixtures
///
protected function setUp () : void {
$this->list = new WeightedList;
$this->list->add("LOW", 0.1);
$this->list->add("HIGH", 4);
$this->list->add("AVERAGE");
}
///
/// Tests
///
public function testAdd () : void {
$count = count($this->list);
$this->list->add("ANOTHER");
$this->assertEquals($count + 1, count($this->list));
}
+ public function testAddWeightedValue () : void {
+ $count = count($this->list);
+
+ $this->list->addWeightedValue(new WeightedValue("ANOTHER"));
+
+ $this->assertEquals($count + 1, count($this->list));
+ }
+
public function testClear () : void {
$this->list->clear();
$this->assertEquals(0, count($this->list));
}
public function testGetHeaviest () : void {
$this->assertEquals(4, $this->list->getHeaviest()->getWeight());
}
public function testToSortedArray () : void {
$array = $this->list->toSortedArray();
$this->assertEquals(3, count($array));
$this->assertEquals(["HIGH", "AVERAGE", "LOW"], $array);
}
public function testToSortedArrayWithDuplicateValues () : void {
$this->list->add("AVERAGE");
$array = $this->list->toSortedArray();
$this->assertEquals(4, count($array));
$this->assertEquals(["HIGH", "AVERAGE", "AVERAGE", "LOW"], $array);
}
public function testGetIterator () : void {
$count = 0;
foreach ($this->list as $item) {
$this->assertInstanceOf(WeightedValue::class, $item);
$count++;
}
$this->assertEquals(3, $count);
}
public function testCount() : void {
$this->assertEquals(3, $this->list->count());
}
}
diff --git a/tests/Collections/WeightedValueTest.php b/tests/Collections/WeightedValueTest.php
index f26be5a..e56747d 100644
--- a/tests/Collections/WeightedValueTest.php
+++ b/tests/Collections/WeightedValueTest.php
@@ -1,79 +1,101 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\Tests\Collections;
use Keruald\OmniTools\Collections\WeightedValue;
use PHPUnit\Framework\TestCase;
class WeightedValueTest extends TestCase {
/**
* @var WeightedValue
*/
private $lowValue;
/**
* @var WeightedValue
*/
private $highValue;
///
/// Fixtures
///
protected function setUp () : void {
$this->lowValue = new WeightedValue("LOW", 0.1);
$this->highValue = new WeightedValue("HIGH");
}
///
/// Tests
///
public function testGetWeight () : void {
$this->assertSame(0.1, $this->lowValue->getWeight());
$this->assertSame(
WeightedValue::DEFAULT_WEIGHT,
$this->highValue->getWeight()
);
}
public function testSetWeight () : void {
$this->lowValue->setWeight(0.2);
$this->assertSame(0.2, $this->lowValue->getWeight());
}
public function testGetValue () : void {
$this->assertEquals("LOW", $this->lowValue->getValue());
$this->assertEquals("HIGH", $this->highValue->getValue());
}
public function testSetValue () : void {
$this->lowValue->setValue("FOO");
$this->assertEquals("FOO", $this->lowValue->getValue());
}
public function testCompareTo () : void {
$this->assertEquals(
0,
$this->lowValue->compareTo($this->lowValue)
);
$this->assertEquals(
-1,
$this->lowValue->compareTo($this->highValue)
);
$this->assertEquals(
1,
$this->highValue->compareTo($this->lowValue)
);
}
public function testCompareToWithApplesAndPears () : void {
$this->expectException("TypeError");
$this->highValue->compareTo(new \stdClass);
}
+ /**
+ * @dataProvider provideExpressionstoParse
+ */
+ public function testParse ($expression, $expectedValue, $expectedWeight) : void {
+ $value = WeightedValue::Parse($expression);
+
+ $this->assertEquals($expectedValue, $value->getValue());
+ $this->assertEquals($expectedWeight, $value->getWeight());
+ }
+
+ ///
+ /// Data providers
+ ///
+
+ public function provideExpressionstoParse () : iterable {
+ yield ["", "", 1.0];
+ yield ["de", "de", 1.0];
+ yield ["de;q=1.0", "de", 1.0];
+ yield ["de;q=0.7", "de", 0.7];
+ yield [";;q=0.7", ";", 0.7];
+ }
+
}
diff --git a/tests/HTTP/Requests/AcceptedLanguagesTest.php b/tests/HTTP/Requests/AcceptedLanguagesTest.php
new file mode 100644
index 0000000..d210050
--- /dev/null
+++ b/tests/HTTP/Requests/AcceptedLanguagesTest.php
@@ -0,0 +1,47 @@
+<?php
+declare(strict_types=1);
+
+namespace Keruald\OmniTools\Tests\HTTP\Requests;
+
+use Keruald\OmniTools\HTTP\Requests\AcceptedLanguages;
+use PHPUnit\Framework\TestCase;
+
+class AcceptedLanguagesTest extends TestCase {
+
+ /**
+ * @var AcceptedLanguages
+ */
+ private $languages;
+
+ protected function setUp () : void {
+ $this->languages = new AcceptedLanguages("en-US,en;q=0.9,fr;q=0.8");
+ }
+
+ public function testExtractFromHeaders () : void {
+ $this->assertEquals("", AcceptedLanguages::extractFromHeaders());
+
+ $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "de";
+ $this->assertEquals("de", AcceptedLanguages::extractFromHeaders());
+ }
+
+ public function testFromServer () : void {
+ $_SERVER['HTTP_ACCEPT_LANGUAGE'] = "de";
+ $languages = AcceptedLanguages::fromServer();
+
+ $this->assertEquals(["de"], $languages->getLanguageCodes());
+ }
+
+ public function testGetLanguageCodes () : void {
+ $this->assertEquals(
+ ["en-US", "en", "fr"],
+ $this->languages->getLanguageCodes()
+ );
+ }
+
+ public function testGetLanguageCodesWithBlankInformation () : void {
+ $languages = new AcceptedLanguages;
+
+ $this->assertEquals([], $languages->getLanguageCodes());
+ }
+
+}
diff --git a/tests/HTTP/Requests/RequestTest.php b/tests/HTTP/Requests/RequestTest.php
index 6b721a1..f55338e 100644
--- a/tests/HTTP/Requests/RequestTest.php
+++ b/tests/HTTP/Requests/RequestTest.php
@@ -1,33 +1,48 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\Tests\HTTP\Requests;
use Keruald\OmniTools\HTTP\Requests\Request;
use PHPUnit\Framework\TestCase;
class RequestTest extends TestCase {
/**
* @covers \Keruald\OmniTools\HTTP\Requests\Request::getRemoteAddress
* @backupGlobals enabled
*/
public function testGetRemoteAddress () : void {
$this->assertEmpty(Request::getRemoteAddress());
$_SERVER = [
'REMOTE_ADDR' => '10.0.0.2',
];
$this->assertEquals('10.0.0.2', Request::getRemoteAddress());
$_SERVER += [
'HTTP_X_FORWARDED_FOR' => '10.0.0.3',
'HTTP_CLIENT_IP' => '10.0.0.4',
];
$this->assertEquals(
'10.0.0.3', Request::getRemoteAddress(),
"HTTP_X_FORWARDED_FOR must be prioritized."
);
}
+ /**
+ * @covers \Keruald\OmniTools\HTTP\Requests\Request::getAcceptedLanguages
+ * @backupGlobals enabled
+ */
+ public function testGetAcceptedLanguages () : void {
+ $_SERVER = [
+ 'HTTP_ACCEPT_LANGUAGE' => 'fr,en-US;q=0.7,en;q=0.3',
+ ];
+
+ $this->assertEquals(
+ ["fr", "en-US", "en"],
+ Request::getAcceptedLanguages()
+ );
+ }
+
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Sep 18, 07:25 (9 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2990174
Default Alt Text
(14 KB)

Event Timeline