From 3d86d072c9e5703bc7bc4760e23843f45345af5d Mon Sep 17 00:00:00 2001 From: USAMI Kenta Date: Sat, 27 Jun 2015 03:18:44 +0900 Subject: [PATCH 1/2] Impl ArrayAccess, IteratorAggregate --- src/AcceptLanguage.php | 101 +++++++++++++++++++++++----- tests/AcceptLanguageTest.php | 40 +++++------ tests/AcceptLanguage_ObjectTest.php | 80 ++++++++++++++++++++++ 3 files changed, 184 insertions(+), 37 deletions(-) create mode 100644 tests/AcceptLanguage_ObjectTest.php diff --git a/src/AcceptLanguage.php b/src/AcceptLanguage.php index fa18903..2895546 100644 --- a/src/AcceptLanguage.php +++ b/src/AcceptLanguage.php @@ -9,9 +9,31 @@ * @copyright Copyright (c) 2014 USAMI Kenta * @author USAMI Kenta * @license MIT License + * + * @property-read string $language + * @property-read string $script + * @property-read string $region + * @property-read string $variant1 + * @property-read string $variant2 + * @property-read string $variant3 + * @property-read string $private1 + * @property-read string $private2 + * @property-read string $private3 */ -class AcceptLanguage +class AcceptLanguage implements \ArrayAccess, \IteratorAggregate { + private $locale = [ + 'language' => '', + 'script' => '', + 'region' => '', + 'variant1' => '', + 'variant2' => '', + 'variant3' => '', + 'private1' => '', + 'private2' => '', + 'private3' => '', + ]; + /** * @param string $http_accept_language * @return array @@ -115,7 +137,7 @@ public static function parse($locale_str) $locale['language'] = '*'; } - return array($q, self::fillLocaleArrayKey($locale)); + return array($q, new AcceptLanguage($locale)); } /** @@ -134,23 +156,68 @@ private static function sort_tags(array $a, array $b) /** * @param array $locale - * @return array * @link http://php.net/manual/locale.composelocale.php */ - private static function fillLocaleArrayKey(array $locale) + public function __construct(array $locale) + { + foreach ($locale as $l => $v) { + $this->locale[$l] = $v; + } + } + + /** + * @return array + */ + public function getAsArray() + { + return $this->locale; + } + + /** + * @return \ArrayIterator + */ + public function getIterator() + { + return new \ArrayIterator($this->locale); + } + + /** + * @throws \OutOfRangeException + */ + public function __get($name) + { + if (!array_key_exists($name, $this->locale)) { + throw new \OutOfRangeException($name); + } + + return $this->locale[$name]; + } + + public function __isset($name) + { + return isset($this->locale[$name]); + } + + /** + * @throws \OutOfBoundsException + */ + public function offsetGet($name) { - static $empty_locale = [ - 'language' => '', - 'script' => '', - 'region' => '', - 'variant1' => '', - 'variant2' => '', - 'variant3' => '', - 'private1' => '', - 'private2' => '', - 'private3' => '', - ]; - - return $locale + $empty_locale; + if (!array_key_exists($name, $this->locale)) { + throw new \OutOfBoundsException($name); + } + + return $this->locale[$name]; } + + public function offsetExists($offset) + { + return isset($this->locale[$offset]); + } + + // AcceptLanguage class is immutable. + public function __set($_name, $_value) { throw new \LogicException; } + public function __unset($_name) { throw new \LogicException; } + public function offsetSet($_offset, $_value) { throw new \LogicException; } + public function offsetUnset($_offset) { throw new \LogicException; } } diff --git a/tests/AcceptLanguageTest.php b/tests/AcceptLanguageTest.php index de659b0..f3b260d 100644 --- a/tests/AcceptLanguageTest.php +++ b/tests/AcceptLanguageTest.php @@ -41,40 +41,40 @@ public function dataProviderFor_getLanguage() ['ja', 'expected' => [ 100 => [ - ['language' => 'ja'] + $e, + new AcceptLanguage(['language' => 'ja'] + $e), ], ], ], ['ja-Hrkt-JPN;q=0.111111', 'expected' => [ 11 => [ - ['language' => 'ja', 'script' => 'Hrkt', 'region' => 'JP'] + $e, + new AcceptLanguage(['language' => 'ja', 'script' => 'Hrkt', 'region' => 'JP'] + $e), ], ], ], ['ja;q=0.9, en-GB', 'expected' => [ 100 => [ - ['language' => 'en', 'region' => 'GB'] + $e + new AcceptLanguage(['language' => 'en', 'region' => 'GB'] + $e), ], 90 => [ - ['language' => 'ja'] + $e + new AcceptLanguage(['language' => 'ja'] + $e), ], ], ], ['ja-Kata;q=0.1,en_PCN;q=0.8,zh_HKG;q=0.9,tlh-Latn-US', 'expected' => [ 100 => [ - ['language' => 'tlh', 'script' => 'Latn', 'region' => 'US'] + $e + new AcceptLanguage(['language' => 'tlh', 'script' => 'Latn', 'region' => 'US'] + $e), ], 90 => [ - ['language' => 'zh', 'region' => 'HK'] + $e + new AcceptLanguage(['language' => 'zh', 'region' => 'HK'] + $e), ], 80 => [ - ['language' => 'en', 'region' => 'PN'] + $e + new AcceptLanguage(['language' => 'en', 'region' => 'PN'] + $e), ], 10 => [ - ['language' => 'ja', 'script' => 'Kata'] + $e + new AcceptLanguage(['language' => 'ja', 'script' => 'Kata'] + $e), ], ], ], @@ -96,17 +96,17 @@ public function dataProviderFor_parse() $e = self::$empty_locale; return [ - ['ja', 'expected' => [1.0, ['language' => 'ja'] + $e]], - ['ja-JP', 'expected' => [1.0, ['language' => 'ja', 'region' => 'JP'] + $e]], - ['ja-Hira', 'expected' => [1.0, ['language' => 'ja', 'script' => 'Hira'] + $e]], - ['ja;q=1.0', 'expected' => [1.0, ['language' => 'ja'] + $e]], - ['ja; q=1.0', 'expected' => [1.0, ['language' => 'ja'] + $e]], - ['ja-JP;q=1', 'expected' => [1.0, ['language' => 'ja', 'region' => 'JP'] + $e]], - ['ja;q=1.00', 'expected' => [1.0, ['language' => 'ja'] + $e]], - ['*', 'expected' => [1.0, ['language' => '*'] + $e]], - ['*-Hant;q=0.1', 'expected' => [0.1, ['language' => '*', 'script' => 'Hant'] + $e]], - ['zh-*-TW', 'expected' => [1.0, ['language' => 'zh', 'region' => 'TW'] + $e]], - ['xx', 'expected' => [1.0, ['language' => 'xx'] + $e]], + ['ja', [1.0, new AcceptLanguage(['language' => 'ja'] + $e)]], + ['ja-JP', [1.0, new AcceptLanguage(['language' => 'ja', 'region' => 'JP'] + $e)]], + ['ja-Hira', [1.0, new AcceptLanguage(['language' => 'ja', 'script' => 'Hira'] + $e)]], + ['ja;q=1.0', [1.0, new AcceptLanguage(['language' => 'ja'] + $e)]], + ['ja; q=1.0', [1.0, new AcceptLanguage(['language' => 'ja'] + $e)]], + ['ja-JP;q=1', [1.0, new AcceptLanguage(['language' => 'ja', 'region' => 'JP'] + $e)]], + ['ja;q=1.00', [1.0, new AcceptLanguage(['language' => 'ja'] + $e)]], + ['*', [1.0, new AcceptLanguage(['language' => '*'] + $e)]], + ['*-Hant;q=0.1', [0.1, new AcceptLanguage(['language' => '*', 'script' => 'Hant'] + $e)]], + ['zh-*-TW', [1.0, new AcceptLanguage(['language' => 'zh', 'region' => 'TW'] + $e)]], + ['xx', [1.0, new AcceptLanguage(['language' => 'xx'] + $e)]], ]; } @@ -116,7 +116,7 @@ public function dataProviderFor_parse() public function test_detect($accept_language, $default, $expected) { $known_languages = ['ja', 'en', 'es', 'ko']; - $strategy = function (array $locale) use ($known_languages) { + $strategy = function (AcceptLanguage $locale) use ($known_languages) { $is_wildcard = isset($locale['language']) && $locale['language'] === '*'; if (empty($locale['language']) && !$is_wildcard) { return null; diff --git a/tests/AcceptLanguage_ObjectTest.php b/tests/AcceptLanguage_ObjectTest.php new file mode 100644 index 0000000..9fb46fa --- /dev/null +++ b/tests/AcceptLanguage_ObjectTest.php @@ -0,0 +1,80 @@ + + * @license MIT License + */ +class AcceptLanguage_ObjectTest extends TestCase +{ + public static $empty_locale = [ + 'language' => '', + 'script' => '', + 'region' => '', + 'variant1' => '', + 'variant2' => '', + 'variant3' => '', + 'private1' => '', + 'private2' => '', + 'private3' => '', + ]; + + public function test() + { + $actual = new AcceptLanguage([]); + + $this->assertSame(self::$empty_locale, $actual->getAsArray()); + foreach (self::$empty_locale as $l => $v) { + $this->assertSame($v, $actual[$l]); + $this->assertSame($v, $actual->$l); + $this->assertTrue(isset($actual[$l])); + $this->assertTrue(empty($actual[$l])); + $this->assertTrue(isset($actual->$l)); + $this->assertTrue(empty($actual->$l)); + } + + foreach ($actual as $a => $b) { + $this->assertSame(self::$empty_locale[$a], $b); + } + } + + /** + * @expectedException \LogicException + */ + public function test_set() + { + $actual = new AcceptLanguage([]); + $actual->error = '/(^o^)\'; + } + + /** + * @expectedException \LogicException + */ + public function test_unset() + { + $actual = new AcceptLanguage([]); + unset($actual->error); + } + + /** + * @expectedException \LogicException + */ + public function test_offsetSet() + { + $actual = new AcceptLanguage([]); + $actual['error'] = '/(^o^)\'; + } + + /** + * @expectedException \LogicException + */ + public function test_offsetUnset() + { + $actual = new AcceptLanguage([]); + unset($actual['error']); + } +} From ba8f57a72aa1718b931bf3bd4960abc9e47f868c Mon Sep 17 00:00:00 2001 From: USAMI Kenta Date: Sat, 27 Jun 2015 10:33:31 +0900 Subject: [PATCH 2/2] Add AcceptLanguageLocale class --- src/AcceptLanguage.php | 94 +--------------- src/AcceptLanguageLocale.php | 103 ++++++++++++++++++ ...tTest.php => AcceptLanguageLocaleTest.php} | 10 +- tests/AcceptLanguageTest.php | 40 +++---- 4 files changed, 132 insertions(+), 115 deletions(-) create mode 100644 src/AcceptLanguageLocale.php rename tests/{AcceptLanguage_ObjectTest.php => AcceptLanguageLocaleTest.php} (87%) diff --git a/src/AcceptLanguage.php b/src/AcceptLanguage.php index 2895546..6f7bf3d 100644 --- a/src/AcceptLanguage.php +++ b/src/AcceptLanguage.php @@ -9,30 +9,11 @@ * @copyright Copyright (c) 2014 USAMI Kenta * @author USAMI Kenta * @license MIT License - * - * @property-read string $language - * @property-read string $script - * @property-read string $region - * @property-read string $variant1 - * @property-read string $variant2 - * @property-read string $variant3 - * @property-read string $private1 - * @property-read string $private2 - * @property-read string $private3 */ -class AcceptLanguage implements \ArrayAccess, \IteratorAggregate +class AcceptLanguage { - private $locale = [ - 'language' => '', - 'script' => '', - 'region' => '', - 'variant1' => '', - 'variant2' => '', - 'variant3' => '', - 'private1' => '', - 'private2' => '', - 'private3' => '', - ]; + /** @throws \BadMethodCallException */ + private function __construct() { throw new \BadMethodCallException(); } /** * @param string $http_accept_language @@ -137,7 +118,7 @@ public static function parse($locale_str) $locale['language'] = '*'; } - return array($q, new AcceptLanguage($locale)); + return array($q, new AcceptLanguageLocale($locale)); } /** @@ -153,71 +134,4 @@ private static function sort_tags(array $a, array $b) return ($a[0] < $b[0]) ? -1 : 1; } - - /** - * @param array $locale - * @link http://php.net/manual/locale.composelocale.php - */ - public function __construct(array $locale) - { - foreach ($locale as $l => $v) { - $this->locale[$l] = $v; - } - } - - /** - * @return array - */ - public function getAsArray() - { - return $this->locale; - } - - /** - * @return \ArrayIterator - */ - public function getIterator() - { - return new \ArrayIterator($this->locale); - } - - /** - * @throws \OutOfRangeException - */ - public function __get($name) - { - if (!array_key_exists($name, $this->locale)) { - throw new \OutOfRangeException($name); - } - - return $this->locale[$name]; - } - - public function __isset($name) - { - return isset($this->locale[$name]); - } - - /** - * @throws \OutOfBoundsException - */ - public function offsetGet($name) - { - if (!array_key_exists($name, $this->locale)) { - throw new \OutOfBoundsException($name); - } - - return $this->locale[$name]; - } - - public function offsetExists($offset) - { - return isset($this->locale[$offset]); - } - - // AcceptLanguage class is immutable. - public function __set($_name, $_value) { throw new \LogicException; } - public function __unset($_name) { throw new \LogicException; } - public function offsetSet($_offset, $_value) { throw new \LogicException; } - public function offsetUnset($_offset) { throw new \LogicException; } } diff --git a/src/AcceptLanguageLocale.php b/src/AcceptLanguageLocale.php new file mode 100644 index 0000000..85d58f4 --- /dev/null +++ b/src/AcceptLanguageLocale.php @@ -0,0 +1,103 @@ + + * @license MIT License + * + * @property-read string $language + * @property-read string $script + * @property-read string $region + * @property-read string $variant1 + * @property-read string $variant2 + * @property-read string $variant3 + * @property-read string $private1 + * @property-read string $private2 + * @property-read string $private3 + */ +class AcceptLanguageLocale implements \ArrayAccess, \IteratorAggregate +{ + private $locale = [ + 'language' => '', + 'script' => '', + 'region' => '', + 'variant1' => '', + 'variant2' => '', + 'variant3' => '', + 'private1' => '', + 'private2' => '', + 'private3' => '', + ]; + + /** + * @param array $locale + * @link http://php.net/manual/locale.composelocale.php + */ + public function __construct(array $locale) + { + foreach ($locale as $l => $v) { + $this->locale[$l] = $v; + } + } + + /** + * @return array + */ + public function getAsArray() + { + return $this->locale; + } + + /** + * @return \ArrayIterator + */ + public function getIterator() + { + return new \ArrayIterator($this->locale); + } + + /** + * @throws \OutOfRangeException + */ + public function __get($name) + { + if (!array_key_exists($name, $this->locale)) { + throw new \OutOfRangeException($name); + } + + return $this->locale[$name]; + } + + public function __isset($name) + { + return isset($this->locale[$name]); + } + + /** + * @throws \OutOfBoundsException + */ + public function offsetGet($name) + { + if (!array_key_exists($name, $this->locale)) { + throw new \OutOfBoundsException($name); + } + + return $this->locale[$name]; + } + + public function offsetExists($offset) + { + return isset($this->locale[$offset]); + } + + // AcceptLanguage class is immutable. + public function __set($_name, $_value) { throw new \LogicException; } + public function __unset($_name) { throw new \LogicException; } + public function offsetSet($_offset, $_value) { throw new \LogicException; } + public function offsetUnset($_offset) { throw new \LogicException; } +} diff --git a/tests/AcceptLanguage_ObjectTest.php b/tests/AcceptLanguageLocaleTest.php similarity index 87% rename from tests/AcceptLanguage_ObjectTest.php rename to tests/AcceptLanguageLocaleTest.php index 9fb46fa..769675d 100644 --- a/tests/AcceptLanguage_ObjectTest.php +++ b/tests/AcceptLanguageLocaleTest.php @@ -25,7 +25,7 @@ class AcceptLanguage_ObjectTest extends TestCase public function test() { - $actual = new AcceptLanguage([]); + $actual = new AcceptLanguageLocale([]); $this->assertSame(self::$empty_locale, $actual->getAsArray()); foreach (self::$empty_locale as $l => $v) { @@ -47,7 +47,7 @@ public function test() */ public function test_set() { - $actual = new AcceptLanguage([]); + $actual = new AcceptLanguageLocale([]); $actual->error = '/(^o^)\'; } @@ -56,7 +56,7 @@ public function test_set() */ public function test_unset() { - $actual = new AcceptLanguage([]); + $actual = new AcceptLanguageLocale([]); unset($actual->error); } @@ -65,7 +65,7 @@ public function test_unset() */ public function test_offsetSet() { - $actual = new AcceptLanguage([]); + $actual = new AcceptLanguageLocale([]); $actual['error'] = '/(^o^)\'; } @@ -74,7 +74,7 @@ public function test_offsetSet() */ public function test_offsetUnset() { - $actual = new AcceptLanguage([]); + $actual = new AcceptLanguageLocale([]); unset($actual['error']); } } diff --git a/tests/AcceptLanguageTest.php b/tests/AcceptLanguageTest.php index f3b260d..ec72a9b 100644 --- a/tests/AcceptLanguageTest.php +++ b/tests/AcceptLanguageTest.php @@ -41,40 +41,40 @@ public function dataProviderFor_getLanguage() ['ja', 'expected' => [ 100 => [ - new AcceptLanguage(['language' => 'ja'] + $e), + new AcceptLanguageLocale(['language' => 'ja'] + $e), ], ], ], ['ja-Hrkt-JPN;q=0.111111', 'expected' => [ 11 => [ - new AcceptLanguage(['language' => 'ja', 'script' => 'Hrkt', 'region' => 'JP'] + $e), + new AcceptLanguageLocale(['language' => 'ja', 'script' => 'Hrkt', 'region' => 'JP'] + $e), ], ], ], ['ja;q=0.9, en-GB', 'expected' => [ 100 => [ - new AcceptLanguage(['language' => 'en', 'region' => 'GB'] + $e), + new AcceptLanguageLocale(['language' => 'en', 'region' => 'GB'] + $e), ], 90 => [ - new AcceptLanguage(['language' => 'ja'] + $e), + new AcceptLanguageLocale(['language' => 'ja'] + $e), ], ], ], ['ja-Kata;q=0.1,en_PCN;q=0.8,zh_HKG;q=0.9,tlh-Latn-US', 'expected' => [ 100 => [ - new AcceptLanguage(['language' => 'tlh', 'script' => 'Latn', 'region' => 'US'] + $e), + new AcceptLanguageLocale(['language' => 'tlh', 'script' => 'Latn', 'region' => 'US'] + $e), ], 90 => [ - new AcceptLanguage(['language' => 'zh', 'region' => 'HK'] + $e), + new AcceptLanguageLocale(['language' => 'zh', 'region' => 'HK'] + $e), ], 80 => [ - new AcceptLanguage(['language' => 'en', 'region' => 'PN'] + $e), + new AcceptLanguageLocale(['language' => 'en', 'region' => 'PN'] + $e), ], 10 => [ - new AcceptLanguage(['language' => 'ja', 'script' => 'Kata'] + $e), + new AcceptLanguageLocale(['language' => 'ja', 'script' => 'Kata'] + $e), ], ], ], @@ -96,17 +96,17 @@ public function dataProviderFor_parse() $e = self::$empty_locale; return [ - ['ja', [1.0, new AcceptLanguage(['language' => 'ja'] + $e)]], - ['ja-JP', [1.0, new AcceptLanguage(['language' => 'ja', 'region' => 'JP'] + $e)]], - ['ja-Hira', [1.0, new AcceptLanguage(['language' => 'ja', 'script' => 'Hira'] + $e)]], - ['ja;q=1.0', [1.0, new AcceptLanguage(['language' => 'ja'] + $e)]], - ['ja; q=1.0', [1.0, new AcceptLanguage(['language' => 'ja'] + $e)]], - ['ja-JP;q=1', [1.0, new AcceptLanguage(['language' => 'ja', 'region' => 'JP'] + $e)]], - ['ja;q=1.00', [1.0, new AcceptLanguage(['language' => 'ja'] + $e)]], - ['*', [1.0, new AcceptLanguage(['language' => '*'] + $e)]], - ['*-Hant;q=0.1', [0.1, new AcceptLanguage(['language' => '*', 'script' => 'Hant'] + $e)]], - ['zh-*-TW', [1.0, new AcceptLanguage(['language' => 'zh', 'region' => 'TW'] + $e)]], - ['xx', [1.0, new AcceptLanguage(['language' => 'xx'] + $e)]], + ['ja', [1.0, new AcceptLanguageLocale(['language' => 'ja'] + $e)]], + ['ja-JP', [1.0, new AcceptLanguageLocale(['language' => 'ja', 'region' => 'JP'] + $e)]], + ['ja-Hira', [1.0, new AcceptLanguageLocale(['language' => 'ja', 'script' => 'Hira'] + $e)]], + ['ja;q=1.0', [1.0, new AcceptLanguageLocale(['language' => 'ja'] + $e)]], + ['ja; q=1.0', [1.0, new AcceptLanguageLocale(['language' => 'ja'] + $e)]], + ['ja-JP;q=1', [1.0, new AcceptLanguageLocale(['language' => 'ja', 'region' => 'JP'] + $e)]], + ['ja;q=1.00', [1.0, new AcceptLanguageLocale(['language' => 'ja'] + $e)]], + ['*', [1.0, new AcceptLanguageLocale(['language' => '*'] + $e)]], + ['*-Hant;q=0.1', [0.1, new AcceptLanguageLocale(['language' => '*', 'script' => 'Hant'] + $e)]], + ['zh-*-TW', [1.0, new AcceptLanguageLocale(['language' => 'zh', 'region' => 'TW'] + $e)]], + ['xx', [1.0, new AcceptLanguageLocale(['language' => 'xx'] + $e)]], ]; } @@ -116,7 +116,7 @@ public function dataProviderFor_parse() public function test_detect($accept_language, $default, $expected) { $known_languages = ['ja', 'en', 'es', 'ko']; - $strategy = function (AcceptLanguage $locale) use ($known_languages) { + $strategy = function (AcceptLanguageLocale $locale) use ($known_languages) { $is_wildcard = isset($locale['language']) && $locale['language'] === '*'; if (empty($locale['language']) && !$is_wildcard) { return null;