From 0d03380e3bada92dc971a4d46c64d2cbae636f95 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 8 Jul 2012 18:05:32 +0200 Subject: [PATCH 01/63] Native string adapter don't need ext/mbstring --- src/StringAdapter/Iconv.php | 5 +++++ src/StringAdapter/MbString.php | 5 +++++ src/StringAdapter/Native.php | 9 --------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/StringAdapter/Iconv.php b/src/StringAdapter/Iconv.php index 896bd210a..314e67115 100644 --- a/src/StringAdapter/Iconv.php +++ b/src/StringAdapter/Iconv.php @@ -15,6 +15,11 @@ class Iconv extends AbstractStringAdapter 'UTF-8', // TODO ); + /** + * Constructor + * + * @throws Exception\ExtensionNotLoadedException + */ public function __construct() { if (!extension_loaded('iconv')) { diff --git a/src/StringAdapter/MbString.php b/src/StringAdapter/MbString.php index e3432530f..2e1566801 100644 --- a/src/StringAdapter/MbString.php +++ b/src/StringAdapter/MbString.php @@ -17,6 +17,11 @@ class MbString extends AbstractStringAdapter 'UTF-8', // TODO ); + /** + * Constructor + * + * @throws Exception\ExtensionNotLoadedException + */ public function __construct() { if (!extension_loaded('mbstring')) { diff --git a/src/StringAdapter/Native.php b/src/StringAdapter/Native.php index fa5f940db..32707abe3 100644 --- a/src/StringAdapter/Native.php +++ b/src/StringAdapter/Native.php @@ -20,15 +20,6 @@ class Native extends AbstractStringAdapter 'UCS-4', 'UCS-4BE', 'UCS-4LE', ); - public function __construct() - { - if (!extension_loaded('mbstring')) { - throw new Exception\ExtensionNotLoadedException( - 'PHP extension "mbstring" is required for this adapter' - ); - } - } - public function isCharsetSupported($charset) { $charset = strtoupper($charset); From 9bce95a459b0b5c58c7ad9bef53662cc9f83c9ba Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 8 Jul 2012 22:09:09 +0200 Subject: [PATCH 02/63] StringUtils: tests, no component deps --- src/StringAdapter/AbstractStringAdapter.php | 18 ++++ src/StringAdapter/Iconv.php | 6 -- src/StringAdapter/MbString.php | 6 -- src/StringAdapter/Native.php | 6 -- src/StringAdapter/StringAdapterInterface.php | 2 + src/StringUtils.php | 40 ++++---- test/StringUtilsTest.php | 96 ++++++++++++++++++++ 7 files changed, 138 insertions(+), 36 deletions(-) create mode 100644 test/StringUtilsTest.php diff --git a/src/StringAdapter/AbstractStringAdapter.php b/src/StringAdapter/AbstractStringAdapter.php index a0a01a935..01987b0f4 100644 --- a/src/StringAdapter/AbstractStringAdapter.php +++ b/src/StringAdapter/AbstractStringAdapter.php @@ -5,6 +5,24 @@ abstract class AbstractStringAdapter implements StringAdapterInterface { + /** + * List of supported character sets (upper case) + * + * @var string[] + */ + protected static $charsets = array(); + + public function isCharsetSupported($charset) + { + $charset = strtoupper($charset); + return in_array($charset, static::$charsets); + } + + public function getSupportedCharsets() + { + return static::$charsets; + } + /** * Word wrap * diff --git a/src/StringAdapter/Iconv.php b/src/StringAdapter/Iconv.php index 314e67115..3baf002c0 100644 --- a/src/StringAdapter/Iconv.php +++ b/src/StringAdapter/Iconv.php @@ -29,12 +29,6 @@ public function __construct() } } - public function isCharsetSupported($charset) - { - $charset = strtoupper($charset); - return in_array($charset, static::$charsets); - } - public function strlen($str, $charset = 'UTF-8') { return iconv_strlen($str, $charset); diff --git a/src/StringAdapter/MbString.php b/src/StringAdapter/MbString.php index 2e1566801..54036733b 100644 --- a/src/StringAdapter/MbString.php +++ b/src/StringAdapter/MbString.php @@ -31,12 +31,6 @@ public function __construct() } } - public function isCharsetSupported($charset) - { - $charset = strtoupper($charset); - return in_array($charset, static::$charsets); - } - public function strlen($str, $charset = 'UTF-8') { return mb_strlen($str, $charset); diff --git a/src/StringAdapter/Native.php b/src/StringAdapter/Native.php index 32707abe3..d4efbe1f3 100644 --- a/src/StringAdapter/Native.php +++ b/src/StringAdapter/Native.php @@ -20,12 +20,6 @@ class Native extends AbstractStringAdapter 'UCS-4', 'UCS-4BE', 'UCS-4LE', ); - public function isCharsetSupported($charset) - { - $charset = strtoupper($charset); - return in_array($charset, static::$charsets); - } - public function strlen($str, $charset = 'UTF-8') { if (StringUtils::isSingleByteCharset($charset)) { diff --git a/src/StringAdapter/StringAdapterInterface.php b/src/StringAdapter/StringAdapterInterface.php index 4b15ef5df..7b8c30efc 100644 --- a/src/StringAdapter/StringAdapterInterface.php +++ b/src/StringAdapter/StringAdapterInterface.php @@ -7,6 +7,8 @@ interface StringAdapterInterface public function isCharsetSupported($charset); + public function getSupportedCharsets(); + public function strlen($str, $charset = 'UTF-8'); public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8'); diff --git a/src/StringUtils.php b/src/StringUtils.php index a10f0ef9d..10d71a49b 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -4,6 +4,7 @@ use Zend\Loader\Broker, Zend\Loader\PluginBroker, + Zend\Stdlib\StringAdapter\StringAdapterInterface, Zend\Stdlib\StringAdapter\MbString as MbStringAdapter, Zend\Stdlib\StringAdapter\Iconv as IconvAdapter, Zend\Stdlib\StringAdapter\Native as NativeAdapter; @@ -11,7 +12,7 @@ class StringUtils { - protected static $broker; + protected static $adapterRegistry; protected static $singleByteCharsets = array( 'ASCII', '7BIT', '8BIT', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', @@ -23,44 +24,47 @@ class StringUtils ); /** - * Get broker + * Get registered string adapters * - * @return Zend\Loader\Broker + * @return Zend\Stdlib\StringAdapter\StringAdapterInterface[] */ - public static function getBroker() + public static function getRegisteredAdapters() { - if (static::$broker === null) { - $broker = new PluginBroker(); + if (static::$adapterRegistry === null) { + static::$adapterRegistry = array(); if (extension_loaded('mbstring')) { - $broker->register('mbstring', new MbStringAdapter()); + static::$adapterRegistry[] = new MbStringAdapter(); } if (extension_loaded('iconv')) { - $broker->register('iconv', new IconvAdapter()); + static::$adapterRegistry[] = new IconvAdapter(); } - $broker->register('native', new NativeAdapter()); - - static::setBroker($broker); + static::$adapterRegistry[] = new NativeAdapter(); } - return static::$broker; + + return static::$adapterRegistry; } - public static function setBroker(Broker $broker) + public static function registerAdapter(StringAdapterInterface $adapter) { - static::$broker = $broker; + if (!in_array($adapter, static::$adapterRegistry, true)) { + static::$adapterRegistry[] = $adapter; + } } - public static function resetBroker() + public static function unregisterAdapter(StringAdapterInterface $adapter) { - static::$broker = null; + $index = array_search($adapter, static::$adapterRegistry, true); + if ($index !== false) { + unset(static::$adapterRegistry[$index]); + } } public static function getAdapterByCharset($charset = 'UTF-8') { - $broker = static::getBroker(); - foreach ($broker->getPlugins() as $adapter) { + foreach (static::getRegisteredAdapters() as $adapter) { if ($adapter->isCharsetSupported($charset)) { return $adapter; } diff --git a/test/StringUtilsTest.php b/test/StringUtilsTest.php new file mode 100644 index 000000000..63c84d2f0 --- /dev/null +++ b/test/StringUtilsTest.php @@ -0,0 +1,96 @@ +bufferedAdapters = StringUtils::getRegisteredAdapters(); + } + + public function tearDown() + { + // reset registered adapters + foreach (StringUtils::getRegisteredAdapters() as $adapter) { + StringUtils::unregisterAdapter($adapter); + } + foreach ($this->bufferedAdapters as $adapter) { + StringUtils::registerAdapter($adapter); + } + + } + + public function singleByCharsets() + { + return array( + array('AscII'), + array('ISo-8859-1'), + ); + } + + public function nonSingleByteCharsets() + { + return array( + array('UTf-8'), + array('usC-2') + ); + } + + /** + * @dataProvider singleByCharsets + * @param string $charset + */ + public function testIsSingleByteCharsetReturnsTrue($charset) + { + $this->assertTrue(StringUtils::isSingleByteCharset($charset)); + } + + /** + * @dataProvider nonSingleByteCharsets + * @param string $charset + */ + public function testIsSingleByteCharsetReturnsFalse($charset) + { + $this->assertFalse(StringUtils::isSingleByteCharset($charset)); + } + + public function testGetAdapterByCharset() + { + $adapter = StringUtils::getAdapterByCharset('UTF-8'); + + if (extension_loaded('mbstring')) { + $this->assertInstanceOf('Zend\Stdlib\StringAdapter\MbString', $adapter); + } elseif (extension_loaded('iconv')) { + $this->assertInstanceOf('Zend\Stdlib\StringAdapter\Iconv', $adapter); + } else { + $this->assertInstanceOf('Zend\Stdlib\StringAdapter\Native', $adapter); + } + } +} From d66f8a899196dc82577bdd0bfcaddfd57cfe6b19 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 13 Jul 2012 08:39:35 +0200 Subject: [PATCH 03/63] intl string wrapper and some small other changes --- src/Exception/ExtensionNotLoadedException.php | 7 + src/Exception/RuntimeException.php | 7 + src/StringUtils.php | 27 +++- src/StringWrapper/AbstractStringWrapper.php | 6 +- src/StringWrapper/Iconv.php | 8 +- src/StringWrapper/Intl.php | 68 +++++++++ src/StringWrapper/MbString.php | 8 +- src/StringWrapper/Native.php | 141 +----------------- test/StringUtilsTest.php | 35 ++++- 9 files changed, 161 insertions(+), 146 deletions(-) create mode 100644 src/Exception/ExtensionNotLoadedException.php create mode 100644 src/Exception/RuntimeException.php create mode 100644 src/StringWrapper/Intl.php diff --git a/src/Exception/ExtensionNotLoadedException.php b/src/Exception/ExtensionNotLoadedException.php new file mode 100644 index 000000000..40ceaf4ee --- /dev/null +++ b/src/Exception/ExtensionNotLoadedException.php @@ -0,0 +1,7 @@ +isCharsetSupported($charset)) { - return $wrapper; + foreach ($charsets as $charset) { + if (!$wrapper->isCharsetSupported($charset)) { + continue 2; + } } + + return $wrapper; } - throw new Exception\RuntimeException("No wrapper found for charset '{$charset}'"); + throw new Exception\RuntimeException('No wrapper found supporting charset(s) ' . implode(', ', $charsets)); + } + + public static function getSingleByteCharsets() + { + return static::$singleByteCharsets; } public static function isSingleByteCharset($charset) { return in_array(strtoupper($charset), static::$singleByteCharsets); } + + public static function isValidUtf8($string) + { + return ($string === '' || preg_match('/^./su', $string) == 1); + } } diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index d3dda48a3..8394385a3 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -10,17 +10,17 @@ abstract class AbstractStringWrapper implements StringWrapperInterface * * @var string[] */ - protected static $charsets = array(); + protected $charsets = array(); public function isCharsetSupported($charset) { $charset = strtoupper($charset); - return in_array($charset, static::$charsets); + return in_array($charset, $this->charsets); } public function getSupportedCharsets() { - return static::$charsets; + return $this->$charsets; } /** diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 625285c18..4c99be628 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -11,7 +11,11 @@ class Iconv extends AbstractStringWrapper * @var string[] * @link http://php.net/manual/mbstring.supported-encodings.php */ - protected static $charsets = array( + protected $charsets = array( + 'ASCII', '7BIT', '8BIT', + 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', + 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10', + 'ISO-8859-11', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', 'UTF-8', // TODO ); @@ -24,7 +28,7 @@ public function __construct() { if (!extension_loaded('iconv')) { throw new Exception\ExtensionNotLoadedException( - 'PHP extension "iconv" is required for this adapter' + 'PHP extension "iconv" is required for this wrapper' ); } } diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php new file mode 100644 index 000000000..4a631f0b8 --- /dev/null +++ b/src/StringWrapper/Intl.php @@ -0,0 +1,68 @@ +charsets = StringUtils::getSingleByteCharsets(); + } public function strlen($str, $charset = 'UTF-8') { - if (StringUtils::isSingleByteCharset($charset)) { - return strlen($str); - } - - $charset = strtoupper($charset); - if ($charset == 'UTF-8') { - // replace multibyte characters with 1 byte and count bytes - return strlen(preg_replace('/(' - . '[\xc0-\xdf][\x80-\xbf]' // 2 bytes (110xxxxx 10xxxxxx) - . '|[\xe0-\xef][\x80-\xbf]{2}' // 3 bytes (1110xxxx [10xxxxxx, ...]) - . '|[\xf0-\xf7][\x80-\xbf]{3}' // 4 bytes (11110xxx [10xxxxxx, ...]) - . '|[\xf8-\xfb][\x80-\xbf]{4}' // 5 bytes (111110xx [10xxxxxx, ...]) - . '|[\xfd-\xfe][\x80-\xbf]{5}' // 6 bytes (1111110x [10xxxxxx, ...]) - . '|\xfe[\x80-\xbf]{6}' // 7 bytes (11111110 [10xxxxxx, ...]) - . ')/s', ' ', $str)); - } elseif ($charset == 'UTF-7') { - // TODO - } elseif ($charset == 'UTF-16' || $charset == 'UCS-2' || $charset == 'UCS-2BE' || $charset == 'UCS-2LE') { - return ceil(strlen($str) / 2); - } elseif ($charset == 'UTF-32' || $charset == 'UCS-4' || $charset == 'UCS-4BE' || $charset == 'UCS-4LE') { - return ceil(strlen($str) / 4); - } - - return false; + return strlen($str); } public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') { - if (StringUtils::isSingleByteCharset($charset)) { - return substr($str, $offset, $length); - } - - $charset = strtoupper($charset); - if ($charset == 'UTF-8') { - // TODO - } elseif ($charset == 'UTF-7') { - // TODO - } elseif ($charset == 'UTF-16' || $charset == 'UCS-2') { - return substr($str, $offset * 2, $length * 2); - } elseif ($charset == 'UTF-32' || $charset == 'UCS-4') { - return substr($str, $offset * 4, $length * 4); - } - - return false; + return substr($str, $offset, $length); } public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') { - if (StringUtils::isSingleByteCharset($charset)) { - return strpos($haystack, $needle, $offset); - } - - $charset = strtoupper($charset); - if ($charset == 'UTF-8') { - // TODO - } elseif ($charset == 'UTF-7') { - // TODO - } elseif ($charset == 'UTF-16' || $charset == 'UCS-2') { - // TODO - } elseif ($charset == 'UTF-32' || $charset == 'UCS-4') { - // TODO - } - - return false; + return strpos($haystack, $needle, $offset); } public function convert($str, $toCharset, $fromCharset = 'UTF-8') { - $fromName = str_replace('-', '', strtolower($fromCharset)); - $toName = str_replace('-', '', strtolower($toCharset)); - $method = 'convert' . $fromName . 'To' . $toName; - - if (method_exists($this, $method)) { - return $this->$method($str); - } - return false; } - - public function convertAsciiToUtf8($str) - { - return $str; - } - - public function convertAsciiToUtf16($str) - { - return preg_replace_callback("/./", function ($char) { - return "\0" . $char; - }, $str); - } - - public function convertAsciiToUcs2($str) - { - return $this->convertAsciiToUtf16($str); - } - - public function convertAsciiToUtf32($str) - { - return preg_replace_callback("/./", function ($char) { - return "\0\0\0" . $char; - }, $str); - } - - public function convertAsciiToUcs4($str) - { - return $this->convertAsciiToUtf32($str); - } - - public function convertUtf8ToAscii($str) - { - // TODO - return $str; - } - - public function convertUtf8ToUtf16($str) - { - // TODO - return $str; - } - - public function convertUtf8ToUcs2($str) - { - return $this->convertUtf8ToUtf16($str); - } - - public function convertUtf8ToUtf32($str) - { - // TODO - return $str; - } - - public function convertUtf8ToUcs4($str) - { - return $this->convertUtf8ToUtf32($str); - } } diff --git a/test/StringUtilsTest.php b/test/StringUtilsTest.php index b351aec9a..c38e6f221 100644 --- a/test/StringUtilsTest.php +++ b/test/StringUtilsTest.php @@ -83,8 +83,7 @@ public function testIsSingleByteCharsetReturnsFalse($charset) public function testGetWrapper() { - $wrapper = StringUtils::getWrapper('UTF-8'); - + $wrapper = StringUtils::getWrapper('ISO-8859-1'); if (extension_loaded('mbstring')) { $this->assertInstanceOf('Zend\Stdlib\StringWrapper\MbString', $wrapper); } elseif (extension_loaded('iconv')) { @@ -92,5 +91,37 @@ public function testGetWrapper() } else { $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Native', $wrapper); } + + try { + $wrapper = StringUtils::getWrapper('UTF-8'); + if (extension_loaded('intl')) { + $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Intl', $wrapper); + } elseif (extension_loaded('mbstring')) { + $this->assertInstanceOf('Zend\Stdlib\StringWrapper\MbString', $wrapper); + } elseif (extension_loaded('iconv')) { + $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Iconv', $wrapper); + } + } catch (Exception $e) { + if (extension_loaded('intl') + || extension_loaded('mbstring') + || extension_loaded('iconv') + ) { + $this->fail("Failed to get intl, mbstring or iconv wrapper for UTF-8"); + } + } + + try { + $wrapper = StringUtils::getWrapper('UTF-8', 'ISO-8859-1'); + if (extension_loaded('mbstring')) { + $this->assertInstanceOf('Zend\Stdlib\StringWrapper\MbString', $wrapper); + } elseif (extension_loaded('iconv')) { + $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Iconv', $wrapper); + } + } catch (Exception $e) { + if (extension_loaded('mbstring') || extension_loaded('iconv') + ) { + $this->fail("Failed to get mbstring or iconv wrapper for UTF-8 and ISO-8859-1"); + } + } } } From daddc6aa5488cacf072aa03fcb3dd8e53be2460e Mon Sep 17 00:00:00 2001 From: blanchonvincent Date: Tue, 7 Aug 2012 20:31:54 +0200 Subject: [PATCH 04/63] Add hydrator strategy Add hydrator strategy with serializer --- .../Strategy/SerializableStrategy.php | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/Hydrator/Strategy/SerializableStrategy.php diff --git a/src/Hydrator/Strategy/SerializableStrategy.php b/src/Hydrator/Strategy/SerializableStrategy.php new file mode 100644 index 000000000..31804fb03 --- /dev/null +++ b/src/Hydrator/Strategy/SerializableStrategy.php @@ -0,0 +1,128 @@ +setSerializer($serializer); + if($serializerOptions) { + $this->setSerializerOptions($serializerOptions); + } + } + + /** + * Serialize the given value so that it can be extracted by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be extracted. + */ + public function extract($value) + { + $serializer = $this->getSerializer(); + return $serializer->serialize($value); + } + + /** + * Unserialize the given value so that it can be hydrated by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be hydrated. + */ + public function hydrate($value) + { + $serializer = $this->getSerializer(); + return $serializer->unserialize($value); + } + + /** + * Set serializer + * + * @param string|SerializerAdapter $serializer + * @return Serializer + */ + public function setSerializer($serializer) + { + if (!is_string($serializer) && !$serializer instanceof SerializerAdapter) { + throw new InvalidArgumentException(sprintf( + '%s expects either a string serializer name or Zend\Serializer\Adapter\AdapterInterface instance; ' + . 'received "%s"', + __METHOD__, + (is_object($serializer) ? get_class($serializer) : gettype($serializer)) + )); + } + $this->serializer = $serializer; + return $this; + } + + /** + * Get serializer + * + * @return SerializerAdapter + */ + public function getSerializer() + { + if (is_string($this->serializer)) { + $options = $this->getSerializerOptions(); + $this->setSerializer(SerializerFactory::factory($this->serializer, $options)); + } elseif (null === $this->serializer) { + $this->setSerializer(SerializerFactory::getDefaultAdapter()); + } + + return $this->serializer; + } + + /** + * Set configuration options for instantiating a serializer adapter + * + * @param mixed $serializerOptions + * @return SerializableStrategy + */ + public function setSerializerOptions($serializerOptions) + { + $this->serializerOptions = $serializerOptions; + return $this; + } + + /** + * Get configuration options for instantiating a serializer adapter + * + * @return mixed + */ + public function getSerializerOptions() + { + return $this->serializerOptions; + } +} From f43755f1a44ccbe4f9105ac3f2a1cfe1e392c655 Mon Sep 17 00:00:00 2001 From: blanchonvincent Date: Tue, 7 Aug 2012 20:32:51 +0200 Subject: [PATCH 05/63] Add unit tests for wildcard Add unit tests for wirldcard --- test/HydratorTest.php | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/HydratorTest.php b/test/HydratorTest.php index 10fae389e..34365083a 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -16,6 +16,8 @@ use ZendTest\Stdlib\TestAsset\ClassMethodsUnderscore; use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCaseMissing; use ZendTest\Stdlib\TestAsset\Reflection as ReflectionAsset; +use Zend\Stdlib\Hydrator\Strategy\DefaultStrategy; +use Zend\Stdlib\Hydrator\Strategy\SerializableStrategy; /** * @category Zend @@ -146,4 +148,37 @@ public function testHydratorClassMethodsDefaultBehaviorIsConvertUnderscoreToCame $this->assertEquals($test->getFooBar(), 'foo'); $this->assertEquals($test->getFooBarBaz(), 'bar'); } + + public function testRetrieveWildStrategyAndOther() + { + $hydrator = new ClassMethods(); + $hydrator->addStrategy('default', new DefaultStrategy()); + $hydrator->addStrategy('*', new SerializableStrategy('phpserialize')); + $default = $hydrator->getStrategy('default'); + $this->assertEquals(get_class($default), 'Zend\Stdlib\Hydrator\Strategy\DefaultStrategy'); + $serializable = $hydrator->getStrategy('*'); + $this->assertEquals(get_class($serializable), 'Zend\Stdlib\Hydrator\Strategy\SerializableStrategy'); + } + + public function testUseWildStrategyByDefault() + { + $hydrator = new ClassMethods(); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], '1'); + $hydrator->addStrategy('*', new SerializableStrategy('phpserialize')); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], 's:1:"1";'); + } + + public function testUseWildStrategyAndOther() + { + $hydrator = new ClassMethods(); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], '1'); + $hydrator->addStrategy('foo_bar', new DefaultStrategy()); + $hydrator->addStrategy('*', new SerializableStrategy('phpserialize')); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], '1'); + $this->assertEquals($datas['foo_bar_baz'], 's:1:"2";'); + } } From 143f41a49099f28d167bc121a9b097aac3e8be4a Mon Sep 17 00:00:00 2001 From: blanchonvincent Date: Tue, 7 Aug 2012 20:33:58 +0200 Subject: [PATCH 06/63] Add unit tests for serializable strategy Add unit tests for serializable strategy --- test/Strategy/SerializableStrategyTest.php | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 test/Strategy/SerializableStrategyTest.php diff --git a/test/Strategy/SerializableStrategyTest.php b/test/Strategy/SerializableStrategyTest.php new file mode 100644 index 000000000..1bd88c774 --- /dev/null +++ b/test/Strategy/SerializableStrategyTest.php @@ -0,0 +1,53 @@ +setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $serializerStrategy = new SerializableStrategy(false); + } + + public function testUseBadSerilizerObject() + { + $serializer = Serializer::factory('phpserialize'); + $serializerStrategy = new SerializableStrategy($serializer); + $this->assertEquals($serializer, $serializerStrategy->getSerializer()); + } + + public function testUseBadSerilizerString() + { + $serializerStrategy = new SerializableStrategy('phpserialize'); + $this->assertEquals('Zend\Serializer\Adapter\PhpSerialize', get_class($serializerStrategy->getSerializer())); + } + + public function testCanSerialize() + { + $serializer = Serializer::factory('phpserialize'); + $serializerStrategy = new SerializableStrategy($serializer); + $serialized = $serializerStrategy->extract('foo'); + $this->assertEquals($serialized, 's:3:"foo";'); + } + + public function testCanUnserialize() + { + $serializer = Serializer::factory('phpserialize'); + $serializerStrategy = new SerializableStrategy($serializer); + $serialized = $serializerStrategy->hydrate('s:3:"foo";'); + $this->assertEquals($serialized, 'foo'); + } +} \ No newline at end of file From d5aec0df01200df2dad6c6cb9a9c506519eba9ee Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 14 Sep 2012 16:26:34 -0500 Subject: [PATCH 07/63] [zendframework/zf2#2125] CS fixes - Trailing whitespace --- src/Hydrator/AbstractHydrator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php index 44e77ba0d..8c8e94a9a 100644 --- a/src/Hydrator/AbstractHydrator.php +++ b/src/Hydrator/AbstractHydrator.php @@ -58,7 +58,7 @@ public function getStrategy($name) */ public function hasStrategy($name) { - return array_key_exists($name, $this->strategies) + return array_key_exists($name, $this->strategies) || array_key_exists('*', $this->strategies); } From 23e59eeb73569a2b20fa933f1bdd393793dc195c Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 14 Sep 2012 16:29:40 -0500 Subject: [PATCH 08/63] [zendframework/zf2#2125] Ensure we have a wildcard strategy before attempting to return it --- src/Hydrator/AbstractHydrator.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php index 8c8e94a9a..35e811713 100644 --- a/src/Hydrator/AbstractHydrator.php +++ b/src/Hydrator/AbstractHydrator.php @@ -11,6 +11,7 @@ namespace Zend\Stdlib\Hydrator; use ArrayObject; +use Zend\Stdlib\Exception; use Zend\Stdlib\Hydrator\StrategyEnabledInterface; use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; @@ -44,9 +45,18 @@ public function __construct() */ public function getStrategy($name) { - if(isset($this->strategies[$name])) { + if (isset($this->strategies[$name])) { return $this->strategies[$name]; } + + if (!isset($this->strategies['*'])) { + throw new Exception\InvalidArgumentException(sprintf( + '%s: no strategy by name of "%s", and no wildcard strategy present', + __METHOD__, + $name + )); + } + return $this->strategies['*']; } @@ -59,7 +69,7 @@ public function getStrategy($name) public function hasStrategy($name) { return array_key_exists($name, $this->strategies) - || array_key_exists('*', $this->strategies); + || array_key_exists('*', $this->strategies); } /** From 86deb2f3d1f1c68ad064bbe80904c58738bff67c Mon Sep 17 00:00:00 2001 From: bullfrogblues Date: Sat, 29 Sep 2012 22:00:26 +0100 Subject: [PATCH 09/63] Refactor; short-circuit if array given, no need to check if traversable too --- src/AbstractOptions.php | 17 ++++++++--------- test/OptionsTest.php | 9 +++++++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index b5d7be77f..628570a59 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -28,8 +28,6 @@ abstract class AbstractOptions implements ParameterObjectInterface /** * @param array|Traversable|null $options - * @return AbstractOptions - * @throws Exception\InvalidArgumentException */ public function __construct($options = null) { @@ -108,14 +106,15 @@ public function __set($key, $value) public function __get($key) { $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); - if (!method_exists($this, $getter)) { - throw new Exception\BadMethodCallException( - 'The option "' . $key . '" does not ' - . 'have a matching ' . $getter . ' getter method ' - . 'which must be defined' - ); + if (method_exists($this, $getter)) { + return $this->{$getter}(); } - return $this->{$getter}(); + + throw new Exception\BadMethodCallException( + 'The option "' . $key . '" does not ' + . 'have a matching ' . $getter . ' getter method ' + . 'which must be defined' + ); } /** diff --git a/test/OptionsTest.php b/test/OptionsTest.php index b41bf86bb..8b64e7715 100644 --- a/test/OptionsTest.php +++ b/test/OptionsTest.php @@ -13,7 +13,6 @@ use ArrayObject; use ZendTest\Stdlib\TestAsset\TestOptions; use ZendTest\Stdlib\TestAsset\TestOptionsNoStrict; -use ZendTest\Stdlib\TestAsset\TestTraversable; use Zend\Stdlib\Exception\InvalidArgumentException; class OptionsTest extends \PHPUnit_Framework_TestCase @@ -48,7 +47,6 @@ public function testNonStrictOptionsDoesNotThrowException() } } - public function testConstructionWithNull() { try { @@ -73,4 +71,11 @@ public function testUnsetThrowsInvalidArgumentException() $options = new TestOptions; unset($options->foobarField); } + + public function testGetThrowsBadMethodCallException() + { + $this->setExpectedException('BadMethodCallException'); + $options = new TestOptions(); + $options->fieldFoobar; + } } From 533337b7622a04b06c73041af6bfb89fa89f896b Mon Sep 17 00:00:00 2001 From: bullfrogblues Date: Sat, 29 Sep 2012 22:11:21 +0100 Subject: [PATCH 10/63] Make setFromArray() a fluent interface & refactor: short-circuit if array --- src/AbstractOptions.php | 19 ++++++++++--------- test/OptionsTest.php | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index 628570a59..8dadafa52 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -39,20 +39,21 @@ public function __construct($options = null) /** * @param array|Traversable $options * @throws Exception\InvalidArgumentException - * @return void + * @return AbstractOptions Provides fluent interface */ public function setFromArray($options) { - if (!is_array($options) && !$options instanceof Traversable) { - throw new Exception\InvalidArgumentException(sprintf( - 'Parameter provided to %s must be an array or Traversable', - __METHOD__ - )); + if (is_array($options) || $options instanceof Traversable) { + foreach ($options as $key => $value) { + $this->__set($key, $value); + } + return $this; } - foreach ($options as $key => $value) { - $this->__set($key, $value); - } + throw new Exception\InvalidArgumentException(sprintf( + 'Parameter provided to %s must be an array or Traversable', + __METHOD__ + )); } /** diff --git a/test/OptionsTest.php b/test/OptionsTest.php index 8b64e7715..93f5b7658 100644 --- a/test/OptionsTest.php +++ b/test/OptionsTest.php @@ -78,4 +78,20 @@ public function testGetThrowsBadMethodCallException() $options = new TestOptions(); $options->fieldFoobar; } + + public function testSetFromArrayAcceptsArray() + { + $array = array('test_field' => 3); + $options = new TestOptions(); + + $this->assertSame($options, $options->setFromArray($array)); + $this->assertEquals(3, $options->test_field); + } + + public function testSetFromArrayThrowsInvalidArgumentException() + { + $this->setExpectedException('InvalidArgumentException'); + $options = new TestOptions; + $options->setFromArray('asd'); + } } From a2e1fbc8cf445abf2352c96e1ce58f2f1a4c6484 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Wed, 3 Oct 2012 10:47:41 -0500 Subject: [PATCH 11/63] [zendframework/zf2#2621] revert changes to conditional flow - Reverts changes to conditional flows. Original code was more semantically correct, as it was validating arguments immediately, and then doing the work of the method in the method body, not in the conditional body. --- src/AbstractOptions.php | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/AbstractOptions.php b/src/AbstractOptions.php index 8dadafa52..f9365e811 100644 --- a/src/AbstractOptions.php +++ b/src/AbstractOptions.php @@ -43,17 +43,17 @@ public function __construct($options = null) */ public function setFromArray($options) { - if (is_array($options) || $options instanceof Traversable) { - foreach ($options as $key => $value) { - $this->__set($key, $value); - } - return $this; + if (!is_array($options) && !$options instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + 'Parameter provided to %s must be an array or Traversable', + __METHOD__ + )); } - throw new Exception\InvalidArgumentException(sprintf( - 'Parameter provided to %s must be an array or Traversable', - __METHOD__ - )); + foreach ($options as $key => $value) { + $this->__set($key, $value); + } + return $this; } /** @@ -107,15 +107,15 @@ public function __set($key, $value) public function __get($key) { $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); - if (method_exists($this, $getter)) { - return $this->{$getter}(); + if (!method_exists($this, $getter)) { + throw new Exception\BadMethodCallException( + 'The option "' . $key . '" does not ' + . 'have a matching ' . $getter . ' getter method ' + . 'which must be defined' + ); } - throw new Exception\BadMethodCallException( - 'The option "' . $key . '" does not ' - . 'have a matching ' . $getter . ' getter method ' - . 'which must be defined' - ); + return $this->{$getter}(); } /** From 214fff241865dc1672949a539fc1ce964c90aa56 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 26 Nov 2012 16:45:36 +0100 Subject: [PATCH 12/63] ZendTest namespace --- test/ArrayUtilsTest.php | 366 ++++++++++++++++++ test/CallbackHandlerTest.php | 175 +++++++++ test/ErrorHandlerTest.php | 90 +++++ test/GlobTest.php | 35 ++ test/HydratorStrategyTest.php | 147 +++++++ test/HydratorTest.php | 251 ++++++++++++ test/MessageTest.php | 72 ++++ test/OptionsTest.php | 97 +++++ test/ParametersTest.php | 66 ++++ test/PriorityQueueTest.php | 154 ++++++++ test/SignalHandlers/InstanceMethod.php | 24 ++ test/SignalHandlers/Invokable.php | 19 + test/SignalHandlers/ObjectCallback.php | 19 + test/SignalHandlers/Overloadable.php | 19 + test/SplPriorityQueueTest.php | 77 ++++ test/SplQueueTest.php | 54 +++ test/SplStackTest.php | 56 +++ test/Strategy/SerializableStrategyTest.php | 53 +++ test/TestAsset/ClassMethodsCamelCase.php | 92 +++++ .../ClassMethodsCamelCaseMissing.php | 44 +++ test/TestAsset/ClassMethodsUnderscore.php | 92 +++++ test/TestAsset/HydratorStrategy.php | 64 +++ test/TestAsset/HydratorStrategyEntityA.php | 75 ++++ test/TestAsset/HydratorStrategyEntityB.php | 46 +++ test/TestAsset/Reflection.php | 30 ++ test/TestAsset/TestOptions.php | 31 ++ test/TestAsset/TestOptionsNoStrict.php | 33 ++ test/_files/alpha | 0 test/_files/beta | 0 test/_files/delta | 0 test/_files/gamma | 0 31 files changed, 2281 insertions(+) create mode 100644 test/ArrayUtilsTest.php create mode 100644 test/CallbackHandlerTest.php create mode 100644 test/ErrorHandlerTest.php create mode 100644 test/GlobTest.php create mode 100644 test/HydratorStrategyTest.php create mode 100644 test/HydratorTest.php create mode 100644 test/MessageTest.php create mode 100644 test/OptionsTest.php create mode 100644 test/ParametersTest.php create mode 100644 test/PriorityQueueTest.php create mode 100644 test/SignalHandlers/InstanceMethod.php create mode 100644 test/SignalHandlers/Invokable.php create mode 100644 test/SignalHandlers/ObjectCallback.php create mode 100644 test/SignalHandlers/Overloadable.php create mode 100644 test/SplPriorityQueueTest.php create mode 100644 test/SplQueueTest.php create mode 100644 test/SplStackTest.php create mode 100644 test/Strategy/SerializableStrategyTest.php create mode 100644 test/TestAsset/ClassMethodsCamelCase.php create mode 100644 test/TestAsset/ClassMethodsCamelCaseMissing.php create mode 100644 test/TestAsset/ClassMethodsUnderscore.php create mode 100644 test/TestAsset/HydratorStrategy.php create mode 100644 test/TestAsset/HydratorStrategyEntityA.php create mode 100644 test/TestAsset/HydratorStrategyEntityB.php create mode 100644 test/TestAsset/Reflection.php create mode 100644 test/TestAsset/TestOptions.php create mode 100644 test/TestAsset/TestOptionsNoStrict.php create mode 100644 test/_files/alpha create mode 100644 test/_files/beta create mode 100644 test/_files/delta create mode 100644 test/_files/gamma diff --git a/test/ArrayUtilsTest.php b/test/ArrayUtilsTest.php new file mode 100644 index 000000000..15333bb1d --- /dev/null +++ b/test/ArrayUtilsTest.php @@ -0,0 +1,366 @@ + 'bar' + )), + array(array( + '15', + 'foo' => 'bar', + 'baz' => array('baz') + )), + array(array( + 0 => false, + 2 => null + )), + array(array( + -100 => 'foo', + 100 => 'bar' + )), + array(array( + 1 => 0 + )), + ); + } + + public static function validLists() + { + return array( + array(array(null)), + array(array(true)), + array(array(false)), + array(array(0)), + array(array(-0.9999)), + array(array('string')), + array(array(new stdClass)), + array(array( + 0 => 'foo', + 1 => 'bar', + 2 => false, + 3 => null, + 4 => array(), + 5 => new stdClass() + )) + ); + } + + public static function validArraysWithStringKeys() + { + return array( + array(array( + 'foo' => 'bar', + )), + array(array( + 'bar', + 'foo' => 'bar', + 'baz', + )), + ); + } + + public static function validArraysWithNumericKeys() + { + return array( + array(array( + 'foo', + 'bar' + )), + array(array( + '0' => 'foo', + '1' => 'bar', + )), + array(array( + 'bar', + '1' => 'bar', + 3 => 'baz' + )), + array(array( + -10000 => null, + '-10000' => null, + )), + array(array( + '-00000.00009' => 'foo' + )), + array(array( + 1 => 0 + )), + ); + } + + public static function validArraysWithIntegerKeys() + { + return array( + array(array( + 'foo', + 'bar,' + )), + array(array( + 100 => 'foo', + 200 => 'bar' + )), + array(array( + -100 => 'foo', + 0 => 'bar', + 100 => 'baz' + )), + array(array( + 'foo', + 'bar', + 1000 => 'baz' + )), + ); + } + + public static function invalidArrays() + { + return array( + array(new stdClass()), + array(15), + array('foo'), + array(new ArrayObject()), + ); + } + + public static function mergeArrays() + { + return array( + 'merge-integer-and-string keys' => array( + array( + 'foo', + 3 => 'bar', + 'baz' => 'baz' + ), + array( + 'baz', + ), + array( + 0 => 'foo', + 3 => 'bar', + 'baz' => 'baz', + 4 => 'baz' + ) + ), + 'merge-arrays-recursively' => array( + array( + 'foo' => array( + 'baz' + ) + ), + array( + 'foo' => array( + 'baz' + ) + ), + array( + 'foo' => array( + 0 => 'baz', + 1 => 'baz' + ) + ) + ), + 'replace-string-keys' => array( + array( + 'foo' => 'bar', + 'bar' => array() + ), + array( + 'foo' => 'baz', + 'bar' => 'bat' + ), + array( + 'foo' => 'baz', + 'bar' => 'bat' + ) + ), + ); + } + + public static function validIterators() + { + return array( + array(array( + 'foo' => 'bar', + ), array( + 'foo' => 'bar', + )), + array(new Config(array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), + array(new ArrayObject(array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), array( + 'foo' => array( + 'bar' => array( + 'baz' => array( + 'baz' => 'bat', + ), + ), + ), + )), + ); + } + + public static function invalidIterators() + { + return array( + array(null), + array(true), + array(false), + array(0), + array(1), + array(0.0), + array(1.0), + array('string'), + array(new stdClass), + ); + } + + /** + * @dataProvider validArraysWithStringKeys + */ + public function testValidArraysWithStringKeys($test) + { + $this->assertTrue(ArrayUtils::hasStringKeys($test)); + } + + /** + * @dataProvider validArraysWithIntegerKeys + */ + public function testValidArraysWithIntegerKeys($test) + { + $this->assertTrue(ArrayUtils::hasIntegerKeys($test)); + } + + /** + * @dataProvider validArraysWithNumericKeys + */ + public function testValidArraysWithNumericKeys($test) + { + $this->assertTrue(ArrayUtils::hasNumericKeys($test)); + } + + /** + * @dataProvider invalidArrays + */ + public function testInvalidArraysAlwaysReturnFalse($test) + { + $this->assertFalse(ArrayUtils::hasStringKeys($test, False)); + $this->assertFalse(ArrayUtils::hasIntegerKeys($test, False)); + $this->assertFalse(ArrayUtils::hasNumericKeys($test, False)); + $this->assertFalse(ArrayUtils::isList($test, False)); + $this->assertFalse(ArrayUtils::isHashTable($test, False)); + + $this->assertFalse(ArrayUtils::hasStringKeys($test, false)); + $this->assertFalse(ArrayUtils::hasIntegerKeys($test, false)); + $this->assertFalse(ArrayUtils::hasNumericKeys($test, false)); + $this->assertFalse(ArrayUtils::isList($test, false)); + $this->assertFalse(ArrayUtils::isHashTable($test, false)); + } + + /** + * @dataProvider validLists + */ + public function testLists($test) + { + $this->assertTrue(ArrayUtils::isList($test)); + $this->assertTrue(ArrayUtils::hasIntegerKeys($test)); + $this->assertTrue(ArrayUtils::hasNumericKeys($test)); + $this->assertFalse(ArrayUtils::hasStringKeys($test)); + $this->assertFalse(ArrayUtils::isHashTable($test)); + } + + /** + * @dataProvider validHashTables + */ + public function testHashTables($test) + { + $this->assertTrue(ArrayUtils::isHashTable($test)); + $this->assertFalse(ArrayUtils::isList($test)); + } + + public function testEmptyArrayReturnsTrue() + { + $test = array(); + $this->assertTrue(ArrayUtils::hasStringKeys($test, true)); + $this->assertTrue(ArrayUtils::hasIntegerKeys($test, true)); + $this->assertTrue(ArrayUtils::hasNumericKeys($test, true)); + $this->assertTrue(ArrayUtils::isList($test, true)); + $this->assertTrue(ArrayUtils::isHashTable($test, true)); + } + + public function testEmptyArrayReturnsFalse() + { + $test = array(); + $this->assertFalse(ArrayUtils::hasStringKeys($test, false)); + $this->assertFalse(ArrayUtils::hasIntegerKeys($test, false)); + $this->assertFalse(ArrayUtils::hasNumericKeys($test, false)); + $this->assertFalse(ArrayUtils::isList($test, false)); + $this->assertFalse(ArrayUtils::isHashTable($test, false)); + } + + /** + * @dataProvider mergeArrays + */ + public function testMerge($a, $b, $expected) + { + $this->assertEquals($expected, ArrayUtils::merge($a, $b)); + } + + /** + * @dataProvider validIterators + */ + public function testValidIteratorsReturnArrayRepresentation($test, $expected) + { + $result = ArrayUtils::iteratorToArray($test); + $this->assertEquals($expected, $result); + } + + /** + * @dataProvider invalidIterators + */ + public function testInvalidIteratorsRaiseInvalidArgumentException($test) + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $this->assertFalse(ArrayUtils::iteratorToArray($test)); + } +} diff --git a/test/CallbackHandlerTest.php b/test/CallbackHandlerTest.php new file mode 100644 index 000000000..124be3a90 --- /dev/null +++ b/test/CallbackHandlerTest.php @@ -0,0 +1,175 @@ +args)) { + unset($this->args); + } + } + + public function testCallbackShouldStoreMetadata() + { + $handler = new CallbackHandler('rand', array('event' => 'foo')); + $this->assertEquals('foo', $handler->getMetadatum('event')); + $this->assertEquals(array('event' => 'foo'), $handler->getMetadata()); + } + + public function testCallbackShouldBeStringIfNoHandlerPassedToConstructor() + { + $handler = new CallbackHandler('rand'); + $this->assertSame('rand', $handler->getCallback()); + } + + public function testCallbackShouldBeArrayIfHandlerPassedToConstructor() + { + $handler = new CallbackHandler(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test')); + $this->assertSame(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test'), $handler->getCallback()); + } + + public function testCallShouldInvokeCallbackWithSuppliedArguments() + { + $handler = new CallbackHandler(array( $this, 'handleCall' )); + $args = array('foo', 'bar', 'baz'); + $handler->call($args); + $this->assertSame($args, $this->args); + } + + public function testPassingInvalidCallbackShouldRaiseInvalidCallbackExceptionDuringInstantiation() + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler = new CallbackHandler('boguscallback'); + } + + public function testCallShouldReturnTheReturnValueOfTheCallback() + { + $handler = new CallbackHandler(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test')); + if (!is_callable(array('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback', 'test'))) { + echo "\nClass exists? " . var_export(class_exists('ZendTest\\Stdlib\\SignalHandlers\\ObjectCallback'), 1) . "\n"; + echo "Include path: " . get_include_path() . "\n"; + } + $this->assertEquals('bar', $handler->call(array())); + } + + public function testStringCallbackResolvingToClassDefiningInvokeNameShouldRaiseException() + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\Invokable'); + } + + public function testStringCallbackReferringToClassWithoutDefinedInvokeShouldRaiseException() + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $class = new SignalHandlers\InstanceMethod(); + $handler = new CallbackHandler($class); + } + + public function testCallbackConsistingOfStringContextWithNonStaticMethodShouldNotRaiseExceptionButWillRaiseEStrict() + { + $handler = new CallbackHandler(array('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod', 'handler')); + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $handler->call(); + restore_error_handler(); + $this->assertTrue($error); + } + + public function testStringCallbackConsistingOfNonStaticMethodShouldRaiseException() + { + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::handler'); + + if (version_compare(PHP_VERSION, '5.4.0rc1', '>=')) { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler->call(); + } else { + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $handler->call(); + restore_error_handler(); + $this->assertTrue($error); + } + } + + public function testStringStaticCallbackForPhp54() + { + if (version_compare(PHP_VERSION, '5.4.0rc1', '<=')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::staticHandler'); + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $result = $handler->call(); + restore_error_handler(); + $this->assertFalse($error); + $this->assertSame('staticHandler', $result); + } + + public function testStringStaticCallbackForPhp54WithMoreThan3Args() + { + if (version_compare(PHP_VERSION, '5.4.0rc1', '<=')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + $handler = new CallbackHandler('ZendTest\\Stdlib\\SignalHandlers\\InstanceMethod::staticHandler'); + $error = false; + set_error_handler(function ($errno, $errstr) use (&$error) { + $error = true; + }, E_STRICT); + $result = $handler->call(array(1, 2, 3, 4)); + restore_error_handler(); + $this->assertFalse($error); + $this->assertSame('staticHandler', $result); + } + + public function testCallbackToClassImplementingOverloadingButNotInvocableShouldRaiseException() + { + $this->setExpectedException('Zend\Stdlib\Exception\InvalidCallbackException'); + $handler = new CallbackHandler('foo', array( 'ZendTest\\Stdlib\\SignalHandlers\\Overloadable', 'foo' )); + } + + public function testClosureCallbackShouldBeInvokedByCall() + { + $handler = new CallbackHandler(function () { + return 'foo'; + }); + $this->assertEquals('foo', $handler->call()); + } + + public function testHandlerShouldBeInvocable() + { + $handler = new CallbackHandler(array($this, 'handleCall')); + $handler('foo', 'bar'); + $this->assertEquals(array('foo', 'bar'), $this->args); + } + + public function handleCall() + { + $this->args = func_get_args(); + } +} diff --git a/test/ErrorHandlerTest.php b/test/ErrorHandlerTest.php new file mode 100644 index 000000000..f1613d4e1 --- /dev/null +++ b/test/ErrorHandlerTest.php @@ -0,0 +1,90 @@ +assertFalse(ErrorHandler::started()); + + ErrorHandler::start(); + $this->assertTrue(ErrorHandler::started()); + + ErrorHandler::stop(); + $this->assertFalse(ErrorHandler::started()); + } + + public function testStartThrowsLogicException() + { + ErrorHandler::start(); + + $this->setExpectedException('Zend\Stdlib\Exception\LogicException'); + ErrorHandler::start(); + } + + public function testStopThrowsLogicException() + { + $this->setExpectedException('Zend\Stdlib\Exception\LogicException'); + ErrorHandler::stop(); + } + + public function testReturnCatchedError() + { + ErrorHandler::start(); + strpos(); // Invalid argument list + $err = ErrorHandler::stop(); + + $this->assertInstanceOf('ErrorException', $err); + } + + public function testThrowCatchedError() + { + ErrorHandler::start(); + strpos(); // Invalid argument list + + $this->setExpectedException('ErrorException'); + ErrorHandler::stop(true); + } + + public function testAddErrors() + { + ErrorHandler::start(); + ErrorHandler::addError(1, 'test-msg1', 'test-file1', 100); + ErrorHandler::addError(2, 'test-msg2', 'test-file2', 200); + $err = ErrorHandler::stop(); + + $this->assertInstanceOf('ErrorException', $err); + $this->assertEquals('test-file2', $err->getFile()); + $this->assertEquals('test-msg2', $err->getMessage()); + $this->assertEquals(200, $err->getLine()); + $this->assertEquals(0, $err->getCode()); + $this->assertEquals(2, $err->getSeverity()); + + $previous = $err->getPrevious(); + $this->assertInstanceOf('ErrorException', $previous); + $this->assertEquals('test-file1', $previous->getFile()); + $this->assertEquals('test-msg1', $previous->getMessage()); + $this->assertEquals(100, $previous->getLine()); + $this->assertEquals(0, $previous->getCode()); + $this->assertEquals(1, $previous->getSeverity()); + } +} diff --git a/test/GlobTest.php b/test/GlobTest.php new file mode 100644 index 000000000..6eca47add --- /dev/null +++ b/test/GlobTest.php @@ -0,0 +1,35 @@ +markTestSkipped('GLOB_BRACE not available'); + } + + $this->assertEquals( + glob(__DIR__ . '/_files/{alph,bet}a', GLOB_BRACE), + Glob::glob(__DIR__ . '/_files/{alph,bet}a', Glob::GLOB_BRACE, true) + ); + } + + public function testNonMatchingGlobReturnsArray() + { + $result = Glob::glob('/some/path/{,*.}{this,orthis}.php', Glob::GLOB_BRACE); + $this->assertInternalType('array', $result); + } +} diff --git a/test/HydratorStrategyTest.php b/test/HydratorStrategyTest.php new file mode 100644 index 000000000..6f83c2ec2 --- /dev/null +++ b/test/HydratorStrategyTest.php @@ -0,0 +1,147 @@ +hydrator = new ClassMethods(); + } + + public function testAddingStrategy() + { + $this->assertAttributeCount(0, 'strategies', $this->hydrator); + + $this->hydrator->addStrategy('myStrategy', new TestAsset\HydratorStrategy()); + + $this->assertAttributeCount(1, 'strategies', $this->hydrator); + } + + public function testCheckStrategyEmpty() + { + $this->assertFalse($this->hydrator->hasStrategy('myStrategy')); + } + + public function testCheckStrategyNotEmpty() + { + $this->hydrator->addStrategy('myStrategy', new TestAsset\HydratorStrategy()); + + $this->assertTrue($this->hydrator->hasStrategy('myStrategy')); + } + + public function testRemovingStrategy() + { + $this->assertAttributeCount(0, 'strategies', $this->hydrator); + + $this->hydrator->addStrategy('myStrategy', new TestAsset\HydratorStrategy()); + $this->assertAttributeCount(1, 'strategies', $this->hydrator); + + $this->hydrator->removeStrategy('myStrategy'); + $this->assertAttributeCount(0, 'strategies', $this->hydrator); + } + + public function testRetrieveStrategy() + { + $strategy = new TestAsset\HydratorStrategy(); + $this->hydrator->addStrategy('myStrategy', $strategy); + + $this->assertEquals($strategy, $this->hydrator->getStrategy('myStrategy')); + } + + public function testExtractingObjects() + { + $this->hydrator->addStrategy('entities', new TestAsset\HydratorStrategy()); + + $entityA = new TestAsset\HydratorStrategyEntityA(); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(111, 'AAA')); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(222, 'BBB')); + + $attributes = $this->hydrator->extract($entityA); + + $this->assertContains(111, $attributes['entities']); + $this->assertContains(222, $attributes['entities']); + } + + public function testHydratingObjects() + { + $this->hydrator->addStrategy('entities', new TestAsset\HydratorStrategy()); + + $entityA = new TestAsset\HydratorStrategyEntityA(); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(111, 'AAA')); + $entityA->addEntity(new TestAsset\HydratorStrategyEntityB(222, 'BBB')); + + $attributes = $this->hydrator->extract($entityA); + $attributes['entities'][] = 333; + + $this->hydrator->hydrate($attributes, $entityA); + $entities = $entityA->getEntities(); + + $this->assertCount(3, $entities); + } + + /** + * @dataProvider underscoreHandlingDataProvider + */ + public function testWhenUsingUnderscoreSeparatedKeysHydratorStrategyIsAlwaysConsideredUnderscoreSeparatedToo($underscoreSeparatedKeys, $formFieldKey) + { + $hydrator = new ClassMethods($underscoreSeparatedKeys); + + $strategy = $this->getMock('Zend\Stdlib\Hydrator\Strategy\StrategyInterface'); + + $entity = new TestAsset\ClassMethodsUnderscore(); + $value = $entity->getFooBar(); + + $hydrator->addStrategy($formFieldKey, $strategy); + + $strategy + ->expects($this->once()) + ->method('extract') + ->with($this->identicalTo($value)) + ->will($this->returnValue($value)) + ; + + $attributes = $hydrator->extract($entity); + + $strategy + ->expects($this->once()) + ->method('hydrate') + ->with($this->identicalTo($value)) + ->will($this->returnValue($value)) + ; + + $hydrator->hydrate($attributes, $entity); + } + + public function underscoreHandlingDataProvider() + { + return array( + array(true, 'foo_bar'), + array(false, 'fooBar'), + ); + } +} diff --git a/test/HydratorTest.php b/test/HydratorTest.php new file mode 100644 index 000000000..8a30585e3 --- /dev/null +++ b/test/HydratorTest.php @@ -0,0 +1,251 @@ +classMethodsCamelCase = new ClassMethodsCamelCase(); + $this->classMethodsCamelCaseMissing = new ClassMethodsCamelCaseMissing(); + $this->classMethodsUnderscore = new ClassMethodsUnderscore(); + $this->reflection = new ReflectionAsset; + } + + public function testInitiateValues() + { + $this->assertEquals($this->classMethodsCamelCase->getFooBar(), '1'); + $this->assertEquals($this->classMethodsCamelCase->getFooBarBaz(), '2'); + $this->assertEquals($this->classMethodsCamelCase->getIsFoo(), true); + $this->assertEquals($this->classMethodsCamelCase->isBar(), true); + $this->assertEquals($this->classMethodsCamelCase->getHasFoo(), true); + $this->assertEquals($this->classMethodsCamelCase->hasBar(), true); + $this->assertEquals($this->classMethodsUnderscore->getFooBar(), '1'); + $this->assertEquals($this->classMethodsUnderscore->getFooBarBaz(), '2'); + $this->assertEquals($this->classMethodsUnderscore->getIsFoo(), true); + $this->assertEquals($this->classMethodsUnderscore->isBar(), true); + $this->assertEquals($this->classMethodsUnderscore->getHasFoo(), true); + $this->assertEquals($this->classMethodsUnderscore->hasBar(), true); + } + + public function testHydratorReflection() + { + $hydrator = new Reflection; + $datas = $hydrator->extract($this->reflection); + $this->assertTrue(isset($datas['foo'])); + $this->assertEquals($datas['foo'], '1'); + $this->assertTrue(isset($datas['fooBar'])); + $this->assertEquals($datas['fooBar'], '2'); + $this->assertTrue(isset($datas['fooBarBaz'])); + $this->assertEquals($datas['fooBarBaz'], '3'); + + $test = $hydrator->hydrate(array('foo' => 'foo', 'fooBar' => 'bar', 'fooBarBaz' => 'baz'), $this->reflection); + $this->assertEquals($test->foo, 'foo'); + $this->assertEquals($test->getFooBar(), 'bar'); + $this->assertEquals($test->getFooBarBaz(), 'baz'); + } + + public function testHydratorClassMethodsCamelCase() + { + $hydrator = new ClassMethods(false); + $datas = $hydrator->extract($this->classMethodsCamelCase); + $this->assertTrue(isset($datas['fooBar'])); + $this->assertEquals($datas['fooBar'], '1'); + $this->assertTrue(isset($datas['fooBarBaz'])); + $this->assertFalse(isset($datas['foo_bar'])); + $this->assertTrue(isset($datas['isFoo'])); + $this->assertEquals($datas['isFoo'], true); + $this->assertTrue(isset($datas['isBar'])); + $this->assertEquals($datas['isBar'], true); + $this->assertTrue(isset($datas['hasFoo'])); + $this->assertEquals($datas['hasFoo'], true); + $this->assertTrue(isset($datas['hasBar'])); + $this->assertEquals($datas['hasBar'], true); + $test = $hydrator->hydrate( + array( + 'fooBar' => 'foo', + 'fooBarBaz' => 'bar', + 'isFoo' => false, + 'isBar' => false, + 'hasFoo' => false, + 'hasBar' => false, + ), + $this->classMethodsCamelCase + ); + $this->assertSame($this->classMethodsCamelCase, $test); + $this->assertEquals($test->getFooBar(), 'foo'); + $this->assertEquals($test->getFooBarBaz(), 'bar'); + $this->assertEquals($test->getIsFoo(), false); + $this->assertEquals($test->isBar(), false); + $this->assertEquals($test->getHasFoo(), false); + $this->assertEquals($test->hasBar(), false); + } + + public function testHydratorClassMethodsUnderscore() + { + $hydrator = new ClassMethods(true); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertTrue(isset($datas['foo_bar'])); + $this->assertEquals($datas['foo_bar'], '1'); + $this->assertTrue(isset($datas['foo_bar_baz'])); + $this->assertFalse(isset($datas['fooBar'])); + $this->assertTrue(isset($datas['is_foo'])); + $this->assertFalse(isset($datas['isFoo'])); + $this->assertEquals($datas['is_foo'], true); + $this->assertTrue(isset($datas['is_bar'])); + $this->assertFalse(isset($datas['isBar'])); + $this->assertEquals($datas['is_bar'], true); + $this->assertTrue(isset($datas['has_foo'])); + $this->assertFalse(isset($datas['hasFoo'])); + $this->assertEquals($datas['has_foo'], true); + $this->assertTrue(isset($datas['has_bar'])); + $this->assertFalse(isset($datas['hasBar'])); + $this->assertEquals($datas['has_bar'], true); + $test = $hydrator->hydrate( + array( + 'foo_bar' => 'foo', + 'foo_bar_baz' => 'bar', + 'is_foo' => false, + 'is_bar' => false, + 'has_foo' => false, + 'has_bar' => false, + ), + $this->classMethodsUnderscore + ); + $this->assertSame($this->classMethodsUnderscore, $test); + $this->assertEquals($test->getFooBar(), 'foo'); + $this->assertEquals($test->getFooBarBaz(), 'bar'); + $this->assertEquals($test->getIsFoo(), false); + $this->assertEquals($test->isBar(), false); + $this->assertEquals($test->getHasFoo(), false); + $this->assertEquals($test->hasBar(), false); + } + + public function testHydratorClassMethodsOptions() + { + $hydrator = new ClassMethods(); + $this->assertTrue($hydrator->getUnderscoreSeparatedKeys()); + $hydrator->setOptions(array('underscoreSeparatedKeys' => false)); + $this->assertFalse($hydrator->getUnderscoreSeparatedKeys()); + $hydrator->setUnderscoreSeparatedKeys(true); + $this->assertTrue($hydrator->getUnderscoreSeparatedKeys()); + } + + public function testHydratorClassMethodsIgnoresInvalidValues() + { + $hydrator = new ClassMethods(true); + $data = array( + 'foo_bar' => '1', + 'foo_bar_baz' => '2', + 'invalid' => 'value' + ); + $test = $hydrator->hydrate($data, $this->classMethodsUnderscore); + $this->assertSame($this->classMethodsUnderscore, $test); + } + + public function testHydratorClassMethodsDefaultBehaviorIsConvertUnderscoreToCamelCase() + { + $hydrator = new ClassMethods(); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertTrue(isset($datas['foo_bar'])); + $this->assertEquals($datas['foo_bar'], '1'); + $this->assertTrue(isset($datas['foo_bar_baz'])); + $this->assertFalse(isset($datas['fooBar'])); + $test = $hydrator->hydrate(array('foo_bar' => 'foo', 'foo_bar_baz' => 'bar'), $this->classMethodsUnderscore); + $this->assertSame($this->classMethodsUnderscore, $test); + $this->assertEquals($test->getFooBar(), 'foo'); + $this->assertEquals($test->getFooBarBaz(), 'bar'); + } + + public function testRetrieveWildStrategyAndOther() + { + $hydrator = new ClassMethods(); + $hydrator->addStrategy('default', new DefaultStrategy()); + $hydrator->addStrategy('*', new SerializableStrategy('phpserialize')); + $default = $hydrator->getStrategy('default'); + $this->assertEquals(get_class($default), 'Zend\Stdlib\Hydrator\Strategy\DefaultStrategy'); + $serializable = $hydrator->getStrategy('*'); + $this->assertEquals(get_class($serializable), 'Zend\Stdlib\Hydrator\Strategy\SerializableStrategy'); + } + + public function testUseWildStrategyByDefault() + { + $hydrator = new ClassMethods(); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], '1'); + $hydrator->addStrategy('*', new SerializableStrategy('phpserialize')); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], 's:1:"1";'); + } + + public function testUseWildStrategyAndOther() + { + $hydrator = new ClassMethods(); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], '1'); + $hydrator->addStrategy('foo_bar', new DefaultStrategy()); + $hydrator->addStrategy('*', new SerializableStrategy('phpserialize')); + $datas = $hydrator->extract($this->classMethodsUnderscore); + $this->assertEquals($datas['foo_bar'], '1'); + $this->assertEquals($datas['foo_bar_baz'], 's:1:"2";'); + } + + public function testHydratorClassMethodsCamelCaseWithSetterMissing() + { + $hydrator = new ClassMethods(false); + + $datas = $hydrator->extract($this->classMethodsCamelCaseMissing); + $this->assertTrue(isset($datas['fooBar'])); + $this->assertEquals($datas['fooBar'], '1'); + $this->assertTrue(isset($datas['fooBarBaz'])); + $this->assertFalse(isset($datas['foo_bar'])); + $test = $hydrator->hydrate(array('fooBar' => 'foo', 'fooBarBaz' => 1), $this->classMethodsCamelCaseMissing); + $this->assertSame($this->classMethodsCamelCaseMissing, $test); + $this->assertEquals($test->getFooBar(), 'foo'); + $this->assertEquals($test->getFooBarBaz(), '2'); + } +} diff --git a/test/MessageTest.php b/test/MessageTest.php new file mode 100644 index 000000000..9f81add04 --- /dev/null +++ b/test/MessageTest.php @@ -0,0 +1,72 @@ +setContent('I can set content'); + $this->assertInstanceOf('Zend\Stdlib\Message', $ret); + $this->assertEquals('I can set content', $message->getContent()); + } + + public function testMessageCanSetAndGetMetadataKeyAsString() + { + $message = new Message(); + $ret = $message->setMetadata('foo', 'bar'); + $this->assertInstanceOf('Zend\Stdlib\Message', $ret); + $this->assertEquals('bar', $message->getMetadata('foo')); + $this->assertEquals(array('foo' => 'bar'), $message->getMetadata()); + } + + public function testMessageCanSetAndGetMetadataKeyAsArray() + { + $message = new Message(); + $ret = $message->setMetadata(array('foo' => 'bar')); + $this->assertInstanceOf('Zend\Stdlib\Message', $ret); + $this->assertEquals('bar', $message->getMetadata('foo')); + } + + public function testMessageGetMetadataWillUseDefaultValueIfNoneExist() + { + $message = new Message(); + $this->assertEquals('bar', $message->getMetadata('foo', 'bar')); + } + + public function testMessageThrowsExceptionOnInvalidKeyForMetadataSet() + { + $message = new Message(); + + $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $message->setMetadata(new \stdClass()); + } + + public function testMessageThrowsExceptionOnInvalidKeyForMetadataGet() + { + $message = new Message(); + + $this->setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $message->getMetadata(new \stdClass()); + } + + public function testMessageToStringWorks() + { + $message = new Message(); + $message->setMetadata(array('Foo' => 'bar', 'One' => 'Two')); + $message->setContent('This is my content'); + $expected = "Foo: bar\r\nOne: Two\r\n\r\nThis is my content"; + $this->assertEquals($expected, $message->toString()); + } +} diff --git a/test/OptionsTest.php b/test/OptionsTest.php new file mode 100644 index 000000000..93f5b7658 --- /dev/null +++ b/test/OptionsTest.php @@ -0,0 +1,97 @@ + 1)); + + $this->assertEquals(1, $options->test_field); + } + + public function testConstructionWithTraversable() + { + $config = new ArrayObject(array('test_field' => 1)); + $options = new TestOptions($config); + + $this->assertEquals(1, $options->test_field); + } + + public function testInvalidFieldThrowsException() + { + $this->setExpectedException('BadMethodCallException'); + $options = new TestOptions(array('foo' => 'bar')); + } + + public function testNonStrictOptionsDoesNotThrowException() + { + try { + $options = new TestOptionsNoStrict(array('foo' => 'bar')); + } catch (\Exception $e) { + $this->fail('Nonstrict options should not throw an exception'); + } + } + + public function testConstructionWithNull() + { + try { + $options = new TestOptions(null); + } catch (InvalidArgumentException $e) { + $this->fail("Unexpected InvalidArgumentException raised"); + } + } + + public function testUnsetting() + { + $options = new TestOptions(array('test_field' => 1)); + + $this->assertEquals(true, isset($options->test_field)); + unset($options->testField); + $this->assertEquals(false, isset($options->test_field)); + } + + public function testUnsetThrowsInvalidArgumentException() + { + $this->setExpectedException('InvalidArgumentException'); + $options = new TestOptions; + unset($options->foobarField); + } + + public function testGetThrowsBadMethodCallException() + { + $this->setExpectedException('BadMethodCallException'); + $options = new TestOptions(); + $options->fieldFoobar; + } + + public function testSetFromArrayAcceptsArray() + { + $array = array('test_field' => 3); + $options = new TestOptions(); + + $this->assertSame($options, $options->setFromArray($array)); + $this->assertEquals(3, $options->test_field); + } + + public function testSetFromArrayThrowsInvalidArgumentException() + { + $this->setExpectedException('InvalidArgumentException'); + $options = new TestOptions; + $options->setFromArray('asd'); + } +} diff --git a/test/ParametersTest.php b/test/ParametersTest.php new file mode 100644 index 000000000..5ebba9b14 --- /dev/null +++ b/test/ParametersTest.php @@ -0,0 +1,66 @@ +assertInstanceOf('Zend\Stdlib\ParametersInterface', $parameters); + $this->assertInstanceOf('ArrayObject', $parameters); + $this->assertInstanceOf('ArrayAccess', $parameters); + $this->assertInstanceOf('Countable', $parameters); + $this->assertInstanceOf('Serializable', $parameters); + $this->assertInstanceOf('Traversable', $parameters); + } + + public function testParametersPersistNameAndValues() + { + $parameters = new Parameters(array('foo' => 'bar')); + $this->assertEquals('bar', $parameters['foo']); + $this->assertEquals('bar', $parameters->foo); + $parameters->offsetSet('baz', 5); + $this->assertEquals(5, $parameters->baz); + + $parameters->fromArray(array('bar' => 'foo')); + $this->assertEquals('foo', $parameters->bar); + + $parameters->fromString('bar=foo&five=5'); + $this->assertEquals('foo', $parameters->bar); + $this->assertEquals('5', $parameters->five); + $this->assertEquals(array('bar' => 'foo', 'five' => '5'), $parameters->toArray()); + $this->assertEquals('bar=foo&five=5', $parameters->toString()); + + $parameters->fromArray(array()); + $parameters->set('foof', 'barf'); + $this->assertEquals('barf', $parameters->get('foof')); + $this->assertEquals('barf', $parameters->foof); + + } + + public function testParametersOffsetgetReturnsNullIfNonexistentKeyIsProvided() + { + $parameters = new Parameters; + $this->assertNull($parameters->foo); + } + + public function testParametersGetReturnsDefaultValueIfNonExistent() + { + $parameters = new Parameters(); + + $this->assertEquals(5, $parameters->get('nonExistentProp', 5)); + } + +} diff --git a/test/PriorityQueueTest.php b/test/PriorityQueueTest.php new file mode 100644 index 000000000..6c5ce77b2 --- /dev/null +++ b/test/PriorityQueueTest.php @@ -0,0 +1,154 @@ +queue = new PriorityQueue(); + $this->queue->insert('foo', 3); + $this->queue->insert('bar', 4); + $this->queue->insert('baz', 2); + $this->queue->insert('bat', 1); + } + + public function testSerializationAndDeserializationShouldMaintainState() + { + $s = serialize($this->queue); + $unserialized = unserialize($s); + $count = count($this->queue); + $this->assertSame($count, count($unserialized), 'Expected count ' . $count . '; received ' . count($unserialized)); + + $expected = array(); + foreach ($this->queue as $item) { + $expected[] = $item; + } + $test = array(); + foreach ($unserialized as $item) { + $test[] = $item; + } + $this->assertSame($expected, $test, 'Expected: ' . var_export($expected, 1) . "\nReceived:" . var_export($test, 1)); + } + + public function testRetrievingQueueAsArrayReturnsDataOnlyByDefault() + { + $expected = array( + 'foo', + 'bar', + 'baz', + 'bat', + ); + $test = $this->queue->toArray(); + $this->assertSame($expected, $test, var_export($test, 1)); + } + + public function testCanCastToArrayOfPrioritiesOnly() + { + $expected = array( + 3, + 4, + 2, + 1, + ); + $test = $this->queue->toArray(PriorityQueue::EXTR_PRIORITY); + $this->assertSame($expected, $test, var_export($test, 1)); + } + + public function testCanCastToArrayOfDataPriorityPairs() + { + $expected = array( + array('data' => 'foo', 'priority' => 3), + array('data' => 'bar', 'priority' => 4), + array('data' => 'baz', 'priority' => 2), + array('data' => 'bat', 'priority' => 1), + ); + $test = $this->queue->toArray(PriorityQueue::EXTR_BOTH); + $this->assertSame($expected, $test, var_export($test, 1)); + } + + public function testCanIterateMultipleTimesAndReceiveSameResults() + { + $expected = array('bar', 'foo', 'baz', 'bat'); + + for ($i = 1; $i < 3; $i++) { + $test = array(); + foreach ($this->queue as $item) { + $test[] = $item; + } + $this->assertEquals($expected, $test, 'Failed at iteration ' . $i); + } + } + + public function testCanRemoveItemFromQueue() + { + $this->queue->remove('baz'); + $expected = array('bar', 'foo', 'bat'); + $test = array(); + foreach ($this->queue as $item) { + $test[] = $item; + } + $this->assertEquals($expected, $test); + } + + public function testCanTestForExistenceOfItemInQueue() + { + $this->assertTrue($this->queue->contains('foo')); + $this->assertFalse($this->queue->contains('foobar')); + } + + public function testCanTestForExistenceOfPriorityInQueue() + { + $this->assertTrue($this->queue->hasPriority(3)); + $this->assertFalse($this->queue->hasPriority(1000)); + } + + public function testCloningAlsoClonesQueue() + { + $foo = new \stdClass(); + $foo->name = 'bar'; + + $queue = new PriorityQueue(); + $queue->insert($foo, 1); + $queue->insert($foo, 2); + + $queueClone = clone $queue; + + while (!$queue->isEmpty()) { + $this->assertSame($foo, $queue->top()); + $queue->remove($queue->top()); + } + + $this->assertTrue($queue->isEmpty()); + $this->assertFalse($queueClone->isEmpty()); + $this->assertEquals(2, $queueClone->count()); + + while (!$queueClone->isEmpty()) { + $this->assertSame($foo, $queueClone->top()); + $queueClone->remove($queueClone->top()); + } + + $this->assertTrue($queueClone->isEmpty()); + } +} diff --git a/test/SignalHandlers/InstanceMethod.php b/test/SignalHandlers/InstanceMethod.php new file mode 100644 index 000000000..af7d905ff --- /dev/null +++ b/test/SignalHandlers/InstanceMethod.php @@ -0,0 +1,24 @@ +queue = new SplPriorityQueue(); + $this->queue->insert('foo', 3); + $this->queue->insert('bar', 4); + $this->queue->insert('baz', 2); + $this->queue->insert('bat', 1); + } + + public function testMaintainsInsertOrderForDataOfEqualPriority() + { + $queue = new SplPriorityQueue(); + $queue->insert('foo', 1000); + $queue->insert('bar', 1000); + $queue->insert('baz', 1000); + $queue->insert('bat', 1000); + + $expected = array('foo', 'bar', 'baz', 'bat'); + $test = array(); + foreach ($queue as $datum) { + $test[] = $datum; + } + $this->assertEquals($expected, $test); + } + + public function testSerializationAndDeserializationShouldMaintainState() + { + $s = serialize($this->queue); + $unserialized = unserialize($s); + $count = count($this->queue); + $this->assertSame($count, count($unserialized), 'Expected count ' . $count . '; received ' . count($unserialized)); + + $expected = array(); + foreach ($this->queue as $item) { + $expected[] = $item; + } + $test = array(); + foreach ($unserialized as $item) { + $test[] = $item; + } + $this->assertSame($expected, $test, 'Expected: ' . var_export($expected, 1) . "\nReceived:" . var_export($test, 1)); + } + + public function testCanRetrieveQueueAsArray() + { + $expected = array( + 'bar', + 'foo', + 'baz', + 'bat', + ); + $test = $this->queue->toArray(); + $this->assertSame($expected, $test, var_export($test, 1)); + } +} diff --git a/test/SplQueueTest.php b/test/SplQueueTest.php new file mode 100644 index 000000000..5eb3af1ac --- /dev/null +++ b/test/SplQueueTest.php @@ -0,0 +1,54 @@ +queue = new SplQueue(); + $this->queue->push('foo'); + $this->queue->push('bar'); + $this->queue->push('baz'); + } + + public function testSerializationAndDeserializationShouldMaintainState() + { + $s = serialize($this->queue); + $unserialized = unserialize($s); + $count = count($this->queue); + $this->assertSame($count, count($unserialized)); + + $expected = array(); + foreach ($this->queue as $item) { + $expected[] = $item; + } + $test = array(); + foreach ($unserialized as $item) { + $test[] = $item; + } + $this->assertSame($expected, $test); + } + + public function testCanRetrieveQueueAsArray() + { + $expected = array('foo', 'bar', 'baz'); + $this->assertSame($expected, $this->queue->toArray()); + } +} diff --git a/test/SplStackTest.php b/test/SplStackTest.php new file mode 100644 index 000000000..18c2ea0db --- /dev/null +++ b/test/SplStackTest.php @@ -0,0 +1,56 @@ +stack = new SplStack(); + $this->stack->push('foo'); + $this->stack->push('bar'); + $this->stack->push('baz'); + $this->stack->push('bat'); + } + + public function testSerializationAndDeserializationShouldMaintainState() + { + $s = serialize($this->stack); + $unserialized = unserialize($s); + $count = count($this->stack); + $this->assertSame($count, count($unserialized)); + + $expected = array(); + foreach ($this->stack as $item) { + $expected[] = $item; + } + $test = array(); + foreach ($unserialized as $item) { + $test[] = $item; + } + $this->assertSame($expected, $test); + } + + public function testCanRetrieveQueueAsArray() + { + $expected = array('bat', 'baz', 'bar', 'foo'); + $test = $this->stack->toArray(); + $this->assertSame($expected, $test, var_export($test, 1)); + } +} diff --git a/test/Strategy/SerializableStrategyTest.php b/test/Strategy/SerializableStrategyTest.php new file mode 100644 index 000000000..f36980de2 --- /dev/null +++ b/test/Strategy/SerializableStrategyTest.php @@ -0,0 +1,53 @@ +setExpectedException('Zend\Stdlib\Exception\InvalidArgumentException'); + $serializerStrategy = new SerializableStrategy(false); + } + + public function testUseBadSerilizerObject() + { + $serializer = Serializer::factory('phpserialize'); + $serializerStrategy = new SerializableStrategy($serializer); + $this->assertEquals($serializer, $serializerStrategy->getSerializer()); + } + + public function testUseBadSerilizerString() + { + $serializerStrategy = new SerializableStrategy('phpserialize'); + $this->assertEquals('Zend\Serializer\Adapter\PhpSerialize', get_class($serializerStrategy->getSerializer())); + } + + public function testCanSerialize() + { + $serializer = Serializer::factory('phpserialize'); + $serializerStrategy = new SerializableStrategy($serializer); + $serialized = $serializerStrategy->extract('foo'); + $this->assertEquals($serialized, 's:3:"foo";'); + } + + public function testCanUnserialize() + { + $serializer = Serializer::factory('phpserialize'); + $serializerStrategy = new SerializableStrategy($serializer); + $serialized = $serializerStrategy->hydrate('s:3:"foo";'); + $this->assertEquals($serialized, 'foo'); + } +} diff --git a/test/TestAsset/ClassMethodsCamelCase.php b/test/TestAsset/ClassMethodsCamelCase.php new file mode 100644 index 000000000..50ccd4ec6 --- /dev/null +++ b/test/TestAsset/ClassMethodsCamelCase.php @@ -0,0 +1,92 @@ +fooBar; + } + + public function setFooBar($value) + { + $this->fooBar = $value; + return $this; + } + + public function getFooBarBaz() + { + return $this->fooBarBaz; + } + + public function setFooBarBaz($value) + { + $this->fooBarBaz = $value; + return $this; + } + + public function getIsFoo() + { + return $this->isFoo; + } + + public function setIsFoo($value) + { + $this->isFoo = $value; + return $this; + } + + public function isBar() + { + return $this->isBar; + } + + public function setIsBar($value) + { + $this->isBar = $value; + return $this; + } + + public function getHasFoo() + { + return $this->hasFoo; + } + + public function setHasFoo($value) + { + $this->hasFoo = $value; + return $this; + } + + public function hasBar() + { + return $this->hasBar; + } + + public function setHasBar($value) + { + $this->hasBar = $value; + return $this; + } +} diff --git a/test/TestAsset/ClassMethodsCamelCaseMissing.php b/test/TestAsset/ClassMethodsCamelCaseMissing.php new file mode 100644 index 000000000..7ad333e26 --- /dev/null +++ b/test/TestAsset/ClassMethodsCamelCaseMissing.php @@ -0,0 +1,44 @@ +fooBar; + } + + public function setFooBar($value) + { + $this->fooBar = $value; + return $this; + } + + public function getFooBarBaz() + { + return $this->fooBarBaz; + } + + /* + * comment to detection verification + * + public function setFooBarBaz($value) + { + $this->fooBarBaz = $value; + return $this; + } + */ +} diff --git a/test/TestAsset/ClassMethodsUnderscore.php b/test/TestAsset/ClassMethodsUnderscore.php new file mode 100644 index 000000000..a51883805 --- /dev/null +++ b/test/TestAsset/ClassMethodsUnderscore.php @@ -0,0 +1,92 @@ +foo_bar; + } + + public function setFooBar($value) + { + $this->foo_bar = $value; + return $this; + } + + public function getFooBarBaz() + { + return $this->foo_bar_baz; + } + + public function setFooBarBaz($value) + { + $this->foo_bar_baz = $value; + return $this; + } + + public function getIsFoo() + { + return $this->is_foo; + } + + public function setIsFoo($value) + { + $this->is_foo = $value; + return $this; + } + + public function isBar() + { + return $this->is_bar; + } + + public function setIsBar($value) + { + $this->is_bar = $value; + return $this; + } + + public function getHasFoo() + { + return $this->has_foo; + } + + public function setHasFoo($value) + { + $this->has_foo = $value; + return $this; + } + + public function hasBar() + { + return $this->has_bar; + } + + public function setHasBar($value) + { + $this->has_bar = $value; + return $this; + } +} diff --git a/test/TestAsset/HydratorStrategy.php b/test/TestAsset/HydratorStrategy.php new file mode 100644 index 000000000..abb7bf47e --- /dev/null +++ b/test/TestAsset/HydratorStrategy.php @@ -0,0 +1,64 @@ +simulatedStorageDevice = array(); + $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(111, 'AAA'); + $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(222, 'BBB'); + $this->simulatedStorageDevice[] = new HydratorStrategyEntityB(333, 'CCC'); + } + + public function extract($value) + { + $result = array(); + foreach ($value as $instance) { + $result[] = $instance->getField1(); + } + return $result; + } + + public function hydrate($value) + { + $result = $value; + if (is_array($value)) { + $result = array(); + foreach ($value as $field1) { + $result[] = $this->findEntity($field1); + } + } + return $result; + } + + private function findEntity($field1) + { + $result = null; + foreach ($this->simulatedStorageDevice as $entity) { + if ($entity->getField1() == $field1) { + $result = $entity; + break; + } + } + return $result; + } +} diff --git a/test/TestAsset/HydratorStrategyEntityA.php b/test/TestAsset/HydratorStrategyEntityA.php new file mode 100644 index 000000000..641d44473 --- /dev/null +++ b/test/TestAsset/HydratorStrategyEntityA.php @@ -0,0 +1,75 @@ +entities = array(); + } + + public function addEntity(HydratorStrategyEntityB $entity) + { + $this->entities[] = $entity; + } + + public function getEntities() + { + return $this->entities; + } + + public function setEntities($entities) + { + $this->entities = $entities; + } + + public function getInputFilter() + { + if (!$this->inputFilter) { + $input = new Input(); + $input->setName('entities'); + $input->setRequired(false); + + $this->inputFilter = new InputFilter(); + $this->inputFilter->add($input); + } + + return $this->inputFilter; + } + + public function setInputFilter(InputFilterInterface $inputFilter) + { + $this->inputFilter = $inputFilter; + } + + // Add the getArrayCopy method so we can test the ArraySerializable hydrator: + public function getArrayCopy() + { + return get_object_vars($this); + } + + // Add the populate method so we can test the ArraySerializable hydrator: + public function populate($data) + { + foreach ($data as $name => $value) { + $this->$name = $value; + } + } +} diff --git a/test/TestAsset/HydratorStrategyEntityB.php b/test/TestAsset/HydratorStrategyEntityB.php new file mode 100644 index 000000000..d31f8c73c --- /dev/null +++ b/test/TestAsset/HydratorStrategyEntityB.php @@ -0,0 +1,46 @@ +field1 = $field1; + $this->field2 = $field2; + } + + public function getField1() + { + return $this->field1; + } + + public function getField2() + { + return $this->field2; + } + + public function setField1($value) + { + $this->field1 = $value; + return $this; + } + + public function setField2($value) + { + $this->field2 = $value; + return $this; + } +} diff --git a/test/TestAsset/Reflection.php b/test/TestAsset/Reflection.php new file mode 100644 index 000000000..97ddc1b12 --- /dev/null +++ b/test/TestAsset/Reflection.php @@ -0,0 +1,30 @@ +fooBar; + } + + public function getFooBarBaz() + { + return $this->fooBarBaz; + } +} diff --git a/test/TestAsset/TestOptions.php b/test/TestAsset/TestOptions.php new file mode 100644 index 000000000..a2fbe9842 --- /dev/null +++ b/test/TestAsset/TestOptions.php @@ -0,0 +1,31 @@ +testField = $value; + } + + public function getTestField() + { + return $this->testField; + } +} diff --git a/test/TestAsset/TestOptionsNoStrict.php b/test/TestAsset/TestOptionsNoStrict.php new file mode 100644 index 000000000..cd1a557ba --- /dev/null +++ b/test/TestAsset/TestOptionsNoStrict.php @@ -0,0 +1,33 @@ +testField = $value; + } + + public function getTestField() + { + return $this->testField; + } +} diff --git a/test/_files/alpha b/test/_files/alpha new file mode 100644 index 000000000..e69de29bb diff --git a/test/_files/beta b/test/_files/beta new file mode 100644 index 000000000..e69de29bb diff --git a/test/_files/delta b/test/_files/delta new file mode 100644 index 000000000..e69de29bb diff --git a/test/_files/gamma b/test/_files/gamma new file mode 100644 index 000000000..e69de29bb From 67985b0537e55af8a13fcda22b792f3b60a4e2c2 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 26 Nov 2012 22:32:42 +0100 Subject: [PATCH 13/63] StringUtils: phpdoc + cs --- src/StringUtils.php | 92 +++++++++++++++++--- src/StringWrapper/AbstractStringWrapper.php | 13 +++ src/StringWrapper/Iconv.php | 13 +++ src/StringWrapper/Intl.php | 13 +++ src/StringWrapper/MbString.php | 13 +++ src/StringWrapper/Native.php | 13 +++ src/StringWrapper/StringWrapperInterface.php | 61 ++++++++++++- 7 files changed, 203 insertions(+), 15 deletions(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index 4aa7da8c7..2af69f43e 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -1,19 +1,45 @@ Date: Tue, 27 Nov 2012 11:38:07 +0100 Subject: [PATCH 14/63] StringUtils: phpdoc + cs --- src/StringWrapper/AbstractStringWrapper.php | 18 ++++++++-- src/StringWrapper/Iconv.php | 34 ++++++++++++++++++ src/StringWrapper/Intl.php | 34 ++++++++++++++++++ src/StringWrapper/MbString.php | 34 ++++++++++++++++++ src/StringWrapper/Native.php | 38 ++++++++++++++++++++ src/StringWrapper/StringWrapperInterface.php | 3 +- 6 files changed, 157 insertions(+), 4 deletions(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index ae849c8a8..9eb122ea6 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -25,21 +25,32 @@ abstract class AbstractStringWrapper implements StringWrapperInterface */ protected $charsets = array(); + /** + * Check if the given charset is supported + * + * @param string $charset + * @return boolean + */ public function isCharsetSupported($charset) { $charset = strtoupper($charset); return in_array($charset, $this->charsets); } + /** + * Get a list of supported charsets + * + * @return string[] + */ public function getSupportedCharsets() { return $this->$charsets; } /** - * Word wrap + * Wraps a string to a given number of characters * - * @param string $string + * @param string $str * @param integer $width * @param string $break * @param boolean $cut @@ -117,7 +128,7 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $cha } /** - * String padding + * Pad a string to a certain length with another string * * @param string $input * @param integer $padLength @@ -167,3 +178,4 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD return $return; } } + diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 56b1f131b..73ba6dcc3 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -46,23 +46,57 @@ public function __construct() } } + /** + * Returns the length of the given string + * + * @param string $str + * @param string $charset + * @return int|false + */ public function strlen($str, $charset = 'UTF-8') { return iconv_strlen($str, $charset); } + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @param string $charset + * @return string|false + */ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') { return iconv_substr($str, $offset, $length, $charset); } + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @param string $charset + * @return int|false + */ public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') { return iconv_strpos($haystack, $needle, $offset, $charset); } + /** + * Convert a string from one character encoding to another + * + * @param string $str + * @param string $toCharset + * @param string $fromCharset + * @return string|false + */ public function convert($str, $toCharset, $fromCharset = 'UTF-8') { return iconv($fromCharset, $toCharset, $str); } } + diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index d0a486b0c..e7e789bc5 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -39,6 +39,13 @@ public function __construct() } } + /** + * Returns the length of the given string + * + * @param string $str + * @param string $charset + * @return int|false + */ public function strlen($str, $charset = 'UTF-8') { if (strcasecmp($charset, 'UTF-8') != 0) { @@ -49,6 +56,15 @@ public function strlen($str, $charset = 'UTF-8') return grapheme_strlen($str); } + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @param string $charset + * @return string|false + */ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') { if (strcasecmp($charset, 'UTF-8') != 0) { @@ -59,6 +75,15 @@ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') return grapheme_substr($str, $offset, $length); } + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @param string $charset + * @return int|false + */ public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') { if (strcasecmp($charset, 'UTF-8') != 0) { @@ -69,6 +94,14 @@ public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') return grapheme_strpos($haystack, $needle, $offset); } + /** + * Convert a string from one character encoding to another + * + * @param string $str + * @param string $toCharset + * @param string $fromCharset + * @return string|false + */ public function convert($str, $toCharset, $fromCharset = 'UTF-8') { if (strcasecmp($toCharset, $fromCharset) != 0) { @@ -79,3 +112,4 @@ public function convert($str, $toCharset, $fromCharset = 'UTF-8') return true; } } + diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index 97fcda503..08119bf43 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -48,23 +48,57 @@ public function __construct() } } + /** + * Returns the length of the given string + * + * @param string $str + * @param string $charset + * @return int|false + */ public function strlen($str, $charset = 'UTF-8') { return mb_strlen($str, $charset); } + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @param string $charset + * @return string|false + */ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') { return mb_substr($str, $offset, $length, $charset); } + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @param string $charset + * @return int|false + */ public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') { return mb_strpos($haystack, $needle, $offset, $charset); } + /** + * Convert a string from one character encoding to another + * + * @param string $str + * @param string $toCharset + * @param string $fromCharset + * @return string|false + */ public function convert($str, $toCharset, $fromCharset = 'UTF-8') { return mb_convert_encoding($str, $toCharset, $fromCharset); } } + diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index b24b2f369..eb6a03ebc 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -19,28 +19,66 @@ */ class Native extends AbstractStringWrapper { + + /** + * Constructor + */ public function __construct() { $this->charsets = StringUtils::getSingleByteCharsets(); } + /** + * Returns the length of the given string + * + * @param string $str + * @param string $charset + * @return int|false + */ public function strlen($str, $charset = 'UTF-8') { return strlen($str); } + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @param string $charset + * @return string|false + */ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') { return substr($str, $offset, $length); } + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @param string $charset + * @return int|false + */ public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') { return strpos($haystack, $needle, $offset); } + /** + * Convert a string from one character encoding to another + * + * @param string $str + * @param string $toCharset + * @param string $fromCharset + * @return string|false + */ public function convert($str, $toCharset, $fromCharset = 'UTF-8') { return false; } } + diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index 6a05b1a10..eb7b80bbb 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -38,7 +38,7 @@ public function getSupportedCharsets(); * * @param string $str * @param string $charset - * @return int + * @return int|false */ public function strlen($str, $charset = 'UTF-8'); @@ -98,3 +98,4 @@ public function wordWrap($str, $width = 75, $break = "\n", $cut = false, $charse */ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT, $charset = 'UTF-8'); } + From 069b5b04a8db038b74438f178b2940f1fd79af88 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Tue, 27 Nov 2012 12:32:42 +0100 Subject: [PATCH 15/63] StringUtils: added tests --- test/StringUtilsTest.php | 79 ++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/test/StringUtilsTest.php b/test/StringUtilsTest.php index c38e6f221..ea7594679 100644 --- a/test/StringUtilsTest.php +++ b/test/StringUtilsTest.php @@ -22,8 +22,8 @@ namespace ZendTest\Stdlib; -use PHPUnit_Framework_TestCase as TestCase, - Zend\Stdlib\StringUtils; +use PHPUnit_Framework_TestCase as TestCase; +use Zend\Stdlib\StringUtils; class StringUtilsTest extends TestCase { @@ -47,24 +47,32 @@ public function tearDown() } - public function singleByCharsets() + public function getSingleByCharsets() { return array( array('AscII'), + array('7bit'), + array('8bit'), array('ISo-8859-1'), - ); - } - - public function nonSingleByteCharsets() - { - return array( - array('UTf-8'), - array('usC-2') + array('ISo-8859-2'), + array('ISo-8859-3'), + array('ISo-8859-4'), + array('ISo-8859-5'), + array('ISo-8859-6'), + array('ISo-8859-7'), + array('ISo-8859-8'), + array('ISo-8859-9'), + array('ISo-8859-10'), + array('ISo-8859-11'), + array('ISo-8859-13'), + array('ISo-8859-14'), + array('ISo-8859-15'), + array('ISo-8859-16'), ); } /** - * @dataProvider singleByCharsets + * @dataProvider getSingleByCharsets * @param string $charset */ public function testIsSingleByteCharsetReturnsTrue($charset) @@ -72,8 +80,18 @@ public function testIsSingleByteCharsetReturnsTrue($charset) $this->assertTrue(StringUtils::isSingleByteCharset($charset)); } + public function getNonSingleByteCharsets() + { + return array( + array('UTf-8'), + array('UTf-16'), + array('usC-2'), + array('CESU-8'), + ); + } + /** - * @dataProvider nonSingleByteCharsets + * @dataProvider getNonSingleByteCharsets * @param string $charset */ public function testIsSingleByteCharsetReturnsFalse($charset) @@ -118,10 +136,41 @@ public function testGetWrapper() $this->assertInstanceOf('Zend\Stdlib\StringWrapper\Iconv', $wrapper); } } catch (Exception $e) { - if (extension_loaded('mbstring') || extension_loaded('iconv') - ) { + if (extension_loaded('mbstring') || extension_loaded('iconv')) { $this->fail("Failed to get mbstring or iconv wrapper for UTF-8 and ISO-8859-1"); } } } + + public function getUtf8StringValidity() + { + return array( + // valid + array('', true), + array("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + . "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + . ' !"#$%&\'()*+,-./0123456789:;<=>?' + . '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_' + . '`abcdefghijklmnopqrstuvwxyz{|}~', + true + ), + + // invalid + array(true, false), + array(123, false), + array(123.45, false), + array("\xFF", false), + array("\x90a", false), + ); + } + + /** + * @dataProvider getUtf8StringValidity + * @param string $str + * @param boolean $valid + */ + public function testIsValidUtf8($str, $valid) + { + $this->assertSame($valid, StringUtils::isValidUtf8($str)); + } } From 1d18478c3a706ddc05ed33209615038277028827 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Tue, 27 Nov 2012 12:33:51 +0100 Subject: [PATCH 16/63] StringUtilsTest: updated phpdoc --- test/StringUtilsTest.php | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/test/StringUtilsTest.php b/test/StringUtilsTest.php index ea7594679..94fcdd895 100644 --- a/test/StringUtilsTest.php +++ b/test/StringUtilsTest.php @@ -1,23 +1,11 @@ Date: Tue, 27 Nov 2012 12:48:25 +0100 Subject: [PATCH 17/63] StringUtils: cs --- src/StringUtils.php | 1 - src/StringWrapper/AbstractStringWrapper.php | 1 - src/StringWrapper/Iconv.php | 1 - src/StringWrapper/Intl.php | 1 - src/StringWrapper/MbString.php | 1 - src/StringWrapper/Native.php | 1 - src/StringWrapper/StringWrapperInterface.php | 1 - 7 files changed, 7 deletions(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index 2af69f43e..a854d4ab1 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -164,4 +164,3 @@ public static function isValidUtf8($str) return is_string($str) && ($str === '' || preg_match('/^./su', $str) == 1); } } - diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 9eb122ea6..62e38a270 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -178,4 +178,3 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD return $return; } } - diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 73ba6dcc3..0e930c57d 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -99,4 +99,3 @@ public function convert($str, $toCharset, $fromCharset = 'UTF-8') return iconv($fromCharset, $toCharset, $str); } } - diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index e7e789bc5..b6954015b 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -112,4 +112,3 @@ public function convert($str, $toCharset, $fromCharset = 'UTF-8') return true; } } - diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index 08119bf43..dfe2fbce4 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -101,4 +101,3 @@ public function convert($str, $toCharset, $fromCharset = 'UTF-8') return mb_convert_encoding($str, $toCharset, $fromCharset); } } - diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index eb6a03ebc..7854fa93a 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -81,4 +81,3 @@ public function convert($str, $toCharset, $fromCharset = 'UTF-8') return false; } } - diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index eb7b80bbb..f78da2e4d 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -98,4 +98,3 @@ public function wordWrap($str, $width = 75, $break = "\n", $cut = false, $charse */ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT, $charset = 'UTF-8'); } - From 7a4f013b8d5af52721486c9e69b47852d5342f98 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 15:13:42 +0100 Subject: [PATCH 18/63] StringUtils: tests + fixes + supported encodings for iconv and mbstring --- src/StringWrapper/AbstractStringWrapper.php | 15 +- src/StringWrapper/Iconv.php | 97 +++++- src/StringWrapper/Intl.php | 3 +- src/StringWrapper/MbString.php | 107 ++++++- src/StringWrapper/Native.php | 7 +- .../StringWrapper/CommonStringWrapperTest.php | 302 ++++++++++++++++++ test/StringWrapper/IconvTest.php | 34 ++ test/StringWrapper/IntlTest.php | 34 ++ test/StringWrapper/MbStringTest.php | 34 ++ test/StringWrapper/NativeTest.php | 24 ++ 10 files changed, 637 insertions(+), 20 deletions(-) create mode 100644 test/StringWrapper/CommonStringWrapperTest.php create mode 100644 test/StringWrapper/IconvTest.php create mode 100644 test/StringWrapper/IntlTest.php create mode 100644 test/StringWrapper/MbStringTest.php create mode 100644 test/StringWrapper/NativeTest.php diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 62e38a270..07298335a 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -10,6 +10,9 @@ namespace Zend\Stdlib\StringWrapper; +use Zend\Stdlib\Exception; +use Zend\Stdlib\StringUtils; + /** * @category Zend * @package Zend_Stdlib @@ -75,7 +78,11 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $cha throw new Exception\InvalidArgumentException('Cannot force cut when width is zero'); } - $charset = strtoupper($charset); + $charset = strtoupper($charset); + if (StringUtils::isSingleByteCharset($charset)) { + return wordwrap($string, $width, $break, $cut); + } + $stringWidth = $this->strlen($string, $charset); $breakWidth = $this->strlen($break, $charset); @@ -139,7 +146,11 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $cha */ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT, $charset = 'UTF-8') { - $charset = strtoupper($charset); + $charset = strtoupper($charset); + if (StringUtils::isSingleByteCharset($charset)) { + return str_pad($input, $padLength, $padString, $padType); + } + $return = ''; $lengthOfPadding = $padLength - $this->strlen($input, $charset); $padStringLength = $this->strlen($padString, $charset); diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 0e930c57d..887097333 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -17,19 +17,102 @@ */ class Iconv extends AbstractStringWrapper { - /** * List of supported character sets (upper case) * * @var string[] - * @link http://php.net/manual/mbstring.supported-encodings.php + * @link http://www.gnu.org/software/libiconv/ */ protected $charsets = array( - 'ASCII', '7BIT', '8BIT', - 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', - 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10', - 'ISO-8859-11', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', - 'UTF-8', // TODO + // European languages + 'ASCII', + 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-7', + 'ISO-8859-9', 'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', + 'KOI8-R', 'KOI8-U', 'KOI8-RU', + 'CP1250', 'CP1251', 'CP1252', 'CP1253', 'CP1254' ,'CP1257', + 'CP850', 'CP866', 'CP1131', + 'MACROMAN', 'MACCENTRALEUROPE', 'MACICELAND', 'MACCROATIAN', 'MACROMANIA', + 'MACCYRILLIC', 'MACUKRAINE', 'MACGREEK', 'MACTURKISH', + 'MACINTOSH', + + // Semitic languages + 'ISO-8859-6', 'ISO-8859-8', + 'CP1255' , 'CP1256', 'CP862', + 'MACHEBREW', 'MACARABIC', + + // Japanese + 'EUC-JP', 'SHIFT_JIS', 'CP932', 'ISO-2022-JP', 'ISO-2022-JP-2', 'ISO-2022-JP-1', + + // Chinese + 'EUC-CN', 'HZ', 'GBK', 'CP936', 'GB18030', 'EUC-TW', 'BIG5', 'CP950', + 'BIG5-HKSCS', 'BIG5-HKSCS:2004', 'BIG5-HKSCS:2001', 'BIG5-HKSCS:1999', + 'ISO-2022-CN', 'ISO-2022-CN-EXT', + + // Korean + 'EUC-KR', 'CP949', 'ISO-2022-KR', 'JOHAB', + + // Armenian + 'ARMSCII-8', + + // Georgian + 'GEORGIAN-ACADEMY', 'GEORGIAN-PS', + + // Tajik + 'KOI8-T', + + // Kazakh + 'PT154', 'RK1048', + + // Thai + 'ISO-8859-11', 'TIS-620', 'CP874', 'MACTHAI', + + // Laotian + 'MULELAO-1', 'CP1133', + + // Vietnamese + 'VISCII', 'TCVN', 'CP1258', + + // Platform specifics + 'HP-ROMAN8', 'NEXTSTEP', + + // Full Unicode + 'UTF-8', + 'UCS-2', 'UCS-2BE', 'UCS-2LE', + 'UCS-4', 'UCS-4BE', 'UCS-4LE', + 'UTF-16', 'UTF-16BE', 'UTF-16LE', + 'UTF-32', 'UTF-32BE', 'UTF-32LE', + 'UTF-7', + 'C99', 'JAVA', + + // Full Unicode, in terms of uint16_t or uint32_t (with machine dependent endianness and alignment) + // 'UCS-2-INTERNAL', 'UCS-4-INTERNAL', + + // Locale dependent, in terms of `char' or `wchar_t' (with machine dependent endianness and alignment, + // and with OS and locale dependent semantics) + // 'char', 'wchar_t', + // '', // The empty encoding name is equivalent to "char": it denotes the locale dependent character encoding. + + // When configured with the option --enable-extra-encodings, + // it also provides support for a few extra encodings: + + // European languages + 'CP437', 'CP737', 'CP775', 'CP852', 'CP853', 'CP855', 'CP857', 'CP858', + 'CP860', 'CP861', 'CP863', 'CP865', 'CP869', 'CP1125', + + // Semitic languages + 'CP864', + + // Japanese + 'EUC-JISX0213', 'Shift_JISX0213', 'ISO-2022-JP-3', + + // Chinese + 'BIG5-2003', // (experimental) + + // Turkmen + 'TDS565', + + // Platform specifics + 'ATARIST', 'RISCOS-LATIN1', ); /** diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index b6954015b..71a9919d9 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -17,7 +17,6 @@ */ class Intl extends AbstractStringWrapper { - /** * List of supported character sets (upper case) * @@ -109,6 +108,6 @@ public function convert($str, $toCharset, $fromCharset = 'UTF-8') return false; } - return true; + return $str; } } diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index dfe2fbce4..60bb257b6 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -17,7 +17,6 @@ */ class MbString extends AbstractStringWrapper { - /** * List of supported character sets (upper case) * @@ -25,13 +24,81 @@ class MbString extends AbstractStringWrapper * @link http://php.net/manual/mbstring.supported-encodings.php */ protected $charsets = array( - 'ASCII', '7BIT', '8BIT', - 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', - 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10', - 'ISO-8859-11', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', - 'UCS-4', 'UCS-4BE', 'UCS-4LE', - 'UCS-2', 'UCS-2BE', 'UCS-2LE', - 'UTF-8', // TODO + 'UCS-4', + 'UCS-4BE', + 'UCS-4LE', + 'UCS-2', + 'UCS-2BE', + 'UCS-2LE', + 'UTF-32', + 'UTF-32BE', + 'UTF-32LE', + 'UTF-16', + 'UTF-16BE', + 'UTF-16LE', + 'UTF-7', + 'UTF7-IMAP', + 'UTF-8', + 'ASCII', + 'EUC-JP', + 'SJIS', + 'EUCJP-WIN', + 'SJIS-WIN', + 'ISO-2022-JP', + 'ISO-2022-JP-MS', + 'CP932', + 'CP51932', + 'SJIS-MAC', 'MACJAPANESE', // ** + 'SJIS-Mobile#DOCOMO', 'SJIS-DOCOMO', // ** + 'SJIS-Mobile#KDDI', 'SJIS-KDDI', // ** + 'SJIS-Mobile#SOFTBANK', 'SJIS-SOFTBANK', // ** + 'UTF-8-Mobile#DOCOMO', 'UTF-8-DOCOMO', // ** + 'UTF-8-Mobile#KDDI-A', // ** + 'UTF-8-Mobile#KDDI-B', 'UTF-8-KDDI', // ** + 'UTF-8-Mobile#SOFTBANK', 'UTF-8-SOFTBANK', // ** + 'ISO-2022-JP-MOBILE#KDDI', 'ISO-2022-JP-KDDI', // ** + 'JIS', + 'JIS-MS', + 'CP50220', + 'CP50220RAW', + 'CP50221', + 'CP50222', + 'ISO-8859-1', + 'ISO-8859-2', + 'ISO-8859-3', + 'ISO-8859-4', + 'ISO-8859-5', + 'ISO-8859-6', + 'ISO-8859-7', + 'ISO-8859-8', + 'ISO-8859-9', + 'ISO-8859-10', + 'ISO-8859-13', + 'ISO-8859-14', + 'ISO-8859-15', + // 'ISO-8859-16', + 'bYTE2BE', + 'bYTE2LE', + 'BYTE4BE', + 'BYTE4LE', + 'BASE64', + 'HTML-ENTITIES', + '7BIT', + '8BIT', + 'EUC-CN', + 'CP936', + 'GB18030', // ** + 'HZ', + 'EUC-TW', + 'CP950', + 'BIG-5', + 'EUC-KR', + 'UHC', 'CP949', + 'ISO-2022-KR', + 'WINDOWS-1251', 'CP1251', + 'WINDOWS-1252', 'CP1252', + 'CP866', 'IBM866', + 'KOI8-R' ); /** @@ -46,6 +113,30 @@ public function __construct() 'PHP extension "mbstring" is required for this wrapper' ); } + + // remove charsets not available before PHP-5.4 + if (version_compare(PHP_VERSION, '5.4', '<')) { + unset( + $this->charsets['SJIS-MAC'], + $this->charsets['MACJAPANESE'], + $this->charsets['SJIS-Mobile#DOCOMO'], + $this->charsets['SJIS-DOCOMO'], + $this->charsets['SJIS-Mobile#KDDI'], + $this->charsets['SJIS-KDDI'], + $this->charsets['SJIS-Mobile#SOFTBANK'], + $this->charsets['SJIS-SOFTBANK'], + $this->charsets['UTF-8-Mobile#DOCOMO'], + $this->charsets['UTF-8-DOCOMO'], + $this->charsets['UTF-8-Mobile#KDDI-A'], + $this->charsets['UTF-8-Mobile#KDDI-B'], + $this->charsets['UTF-8-KDDI'], + $this->charsets['UTF-8-Mobile#SOFTBANK'], + $this->charsets['UTF-8-SOFTBANK'], + $this->charsets['ISO-2022-JP-MOBILE#KDDI'], + $this->charsets['ISO-2022-JP-KDDI'], + $this->charsets['GB18030'] + ); + } } /** diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index 7854fa93a..aee15b736 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -78,6 +78,11 @@ public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') */ public function convert($str, $toCharset, $fromCharset = 'UTF-8') { - return false; + if (strcasecmp($toCharset, $fromCharset) != 0) { + trigger_error("Can't convert '{$fromCharset}' to '{$toCharset}' using intl", E_WARNING); + return false; + } + + return $str; } } diff --git a/test/StringWrapper/CommonStringWrapperTest.php b/test/StringWrapper/CommonStringWrapperTest.php new file mode 100644 index 000000000..ef44b2aef --- /dev/null +++ b/test/StringWrapper/CommonStringWrapperTest.php @@ -0,0 +1,302 @@ +stringWrapper instanceof StringWrapperInterface) ) { + $this->fail(sprintf( + "%s isn't an instance of %s", + get_class($this) . '::stringWrapper', + 'Zend\Stdlib\StringWrapper\StringWrapperInterface' + )); + } + } + + public function strlenProvider() + { + return array( + array('abcdefghijklmnopqrstuvwxyz', 'ascii', 26), + array('abcdefghijklmnopqrstuvwxyz', 'utf-8', 26), + array('äöüß', 'utf-8', 4), + ); + } + + /** + * @dataProvider strlenProvider + * @param string $string + * @param string $charset + * @param mixed $expected + */ + public function testStrlen($str, $charset, $expected) + { + if (!$this->stringWrapper->isCharsetSupported($charset)) { + $this->markTestSkipped( + "Charset {$charset} not supported by " . get_class($this->stringWrapper) + ); + } + + $result = $this->stringWrapper->strlen($str, $charset); + $this->assertSame($expected, $result); + } + + public function substrProvider() + { + return array( + array('abcdefghijkl', 1, 5, 'ascii', 'bcdef'), + array('abcdefghijkl', 1, 5, 'utf-8', 'bcdef'), + array('äöüß', 1, 2, 'utf-8', 'öü'), + ); + } + + /** + * @dataProvider substrProvider + * @param string $str + * @param int $offset + * @param int|null $length + * @param string $charset + * @param mixed $expected + */ + public function testSubstr($str, $offset, $length, $charset, $expected) + { + if (!$this->stringWrapper->isCharsetSupported($charset)) { + $this->markTestSkipped( + "Charset {$charset} not supported by " . get_class($this->stringWrapper) + ); + } + + $result = $this->stringWrapper->substr($str, $offset, $length, $charset); + $this->assertSame($expected, $result); + } + + public function strposProvider() + { + return array( + array('abcdefghijkl', 'g', 3, 'ascii', 6), + array('abcdefghijkl', 'g', 3, 'utf-8', 6), + array('äöüß', 'ü', 1, 'utf-8', 2), + ); + } + + /** + * @dataProvider strposProvider + * @param string $haystack + * @param string $needle + * @param int $offset + * @param string $charset + * @param mixed $expected + */ + public function testStrpos($haystack, $needle, $offset, $charset, $expected) + { + if (!$this->stringWrapper->isCharsetSupported($charset)) { + $this->markTestSkipped( + "Charset {$charset} not supported by " . get_class($this->stringWrapper) + ); + } + + $result = $this->stringWrapper->strpos($haystack, $needle, $offset, $charset); + $this->assertSame($expected, $result); + } + + public function convertProvider() + { + return array( + array('abc', 'ascii', 'ascii', 'abc'), + array('abc', 'utf-8', 'ascii', 'abc'), + array('abc', 'ascii', 'utf-8', 'abc'), + array('€', 'iso-8859-15', 'utf-8', "\xA4"), + array('€', 'iso-8859-16', 'utf-8', "\xA4"), // ISO-8859-16 is wrong @ mbstring + ); + } + + /** + * @dataProvider convertProvider + * @param string $str + * @param string $toCharset + * @param string $fromCharset + * @param mixed $expected + */ + public function testConvert($str, $toCharset, $fromCharset, $expected) + { + if (!$this->stringWrapper->isCharsetSupported($toCharset)) { + $this->markTestSkipped( + "Charset {$toCharset} not supported by " . get_class($this->stringWrapper) + ); + } elseif (!$this->stringWrapper->isCharsetSupported($fromCharset)) { + $this->markTestSkipped( + "Charset {$fromCharset} not supported by " . get_class($this->stringWrapper) + ); + } + + $result = $this->stringWrapper->convert($str, $toCharset, $fromCharset); + $this->assertSame($expected, $result); + } + + public function wordWrapProvider() + { + return array( + // Standard cut tests + array('äbüöcß', 2, ' ', true, 'utf-8', + 'äb üö cß'), + array('äbüöc ß äbüöcß', 2, ' ', true, 'utf-8', + 'äb üö c ß äb üö cß'), + array('Ä very long wöööööööööööörd.', 8, "\n", true, 'utf-8', + "Ä very\nlong\nwööööööö\nööööörd."), + array("Ä very\nlong wöööööööööööörd.", 8, "\n", false, 'utf-8', + "Ä very\nlong\nwöööööööööööörd."), + array("Ä very
long wöö
öööööööö
öörd.", 8, '
', false, 'utf-8', + "Ä very
long wöö
öööööööö
öörd."), + + // Alternative cut tests + array(' äüöäöü', 3, ' ', true, 'utf-8', + ' äüö äöü'), + array('äüöäöü ', 3, ' ', true, 'utf-8', + 'äüö äöü '), + array('äöüäöü ', 3, '-', true, 'utf-8', + 'äöü-äöü-'), + array('äüöäöü ', 3, ' ', true, 'utf-8', + 'äüö äöü '), + array('12345 ', 5, '-', false, 'utf-8', + '12345-'), + array('12345 ', 5, '-', false, 'utf-8', + '12345- '), + array('äüöäöü ', 3, ' ', true, 'utf-8', + 'äüö äöü '), + array('äüöäöü--', 3, '-', true, 'utf-8', + 'äüö-äöü--'), + array("äbü\töcß", 3, ' ', true, 'utf-8', + "äbü \töc ß"), + array("äbü\nößt", 3, ' ', true, 'utf-8', + "äbü \nöß t"), + array("äbü\nößte", 3, "\n", true, 'utf-8', + "äbü\nößt\ne"), + + // Break cut tests + array('foobar-foofoofoo', 8, '-', true, 'ascii', + 'foobar-foofoofo-o'), + array('foobar-foobar', 6, '-', true, 'ascii', + 'foobar-foobar'), + array('foobar-foobar', 7, '-', true, 'ascii', + 'foobar-foobar'), + array('foobar-', 7, '-', true, 'ascii', + 'foobar-'), + array('foobar-foobar', 5, '-', true, 'ascii', + 'fooba-r-fooba-r'), + + // Standard no-cut tests + array('äbüöcß', 2, ' ', false, 'utf-8', + 'äbüöcß'), + array('äbüöc ß äbüöcß', 2, "\n", false, 'utf-8', + "äbüöc\nß\näbüöcß"), + array('äöü äöü äöü', 5, "\n", false, 'utf-8', + "äöü\näöü\näöü"), + + // Break no-cut tests + array('foobar-foofoofoo', 8, '-', false, 'ascii', + 'foobar-foofoofoo'), + array('foobar-foobar', 6, '-', false, 'ascii', + 'foobar-foobar'), + array('foobar-foobar', 7, '-', false, 'ascii', + 'foobar-foobar'), + array('foobar-', 7, '-', false, 'ascii', + 'foobar-'), + array('foobar-foobar', 5, '-', false, 'ascii', + 'foobar-foobar'), + ); + } + + /** + * @dataProvider wordWrapProvider + * @param string $str + * @param integer $width + * @param string $break + * @param boolean $cut + * @param string $charset + * @param mixed $expected + */ + public function testWordWrap($string, $width, $break, $cut, $charset, $expected) + { + if (!$this->stringWrapper->isCharsetSupported($charset)) { + $this->markTestSkipped( + "Charset {$charset} not supported by " . get_class($this->stringWrapper) + ); + } + + $result = $this->stringWrapper->wordWrap($string, $width, $break, $cut, $charset); + $this->assertSame($expected, $result); + } + + public function testWordWrapInvalidArgument() + { + $this->setExpectedException( + 'Zend\Stdlib\Exception\InvalidArgumentException', + "Cannot force cut when width is zero" + ); + $this->stringWrapper->wordWrap('a', 0, "\n", true); + } + + public function strPadProvider() + { + return array( + // single-byte + array('aaa', 5, 'o', STR_PAD_LEFT, 'ascii', 'ooaaa'), + array('aaa', 6, 'o', STR_PAD_BOTH, 'ascii', 'oaaaoo'), + array('aaa', 5, 'o', STR_PAD_RIGHT, 'ascii', 'aaaoo'), + + // multi-byte + array('äää', 5, 'ö', STR_PAD_LEFT, 'utf-8', 'ööäää'), + array('äää', 6, 'ö', STR_PAD_BOTH, 'utf-8', 'öäääöö'), + array('äää', 5, 'ö', STR_PAD_RIGHT, 'utf-8', 'äääöö'), + + // ZF-12186 + array('äääöö', 2, 'ö', STR_PAD_RIGHT, 'utf-8', 'äääöö'), // PadInputLongerThanPadLength + array('äääöö', 5, 'ö', STR_PAD_RIGHT, 'utf-8', 'äääöö'), // PadInputSameAsPadLength + array('äääöö', -2, 'ö', STR_PAD_RIGHT, 'utf-8', 'äääöö'), // PadNegativePadLength + ); + } + + /** + * @dataProvider strPadProvider + * @param string $input + * @param integer $padLength + * @param string $padString + * @param integer $padType + * @param string $charset + * @param mixed $expected + * + * @group ZF-12186 + */ + public function testStrPad($input, $padLength, $padString, $padType, $charset, $expected) + { + if (!$this->stringWrapper->isCharsetSupported($charset)) { + $this->markTestSkipped( + "Charset {$charset} not supported by " . get_class($this->stringWrapper) + ); + } + + $result = $this->stringWrapper->strPad($input, $padLength, $padString, $padType, $charset); + $this->assertSame($expected, $result); + } +} diff --git a/test/StringWrapper/IconvTest.php b/test/StringWrapper/IconvTest.php new file mode 100644 index 000000000..92a83e1c6 --- /dev/null +++ b/test/StringWrapper/IconvTest.php @@ -0,0 +1,34 @@ +fail('Missing expected Zend\Stdlib\Exception\ExtensionNotLoadedException'); + } catch (Exception\ExtensionNotLoadedException $e) { + $this->markTestSkipped('Missing ext/iconv'); + } + } + + $this->stringWrapper = new Iconv(); + parent::setUp(); + } +} diff --git a/test/StringWrapper/IntlTest.php b/test/StringWrapper/IntlTest.php new file mode 100644 index 000000000..f764b3d98 --- /dev/null +++ b/test/StringWrapper/IntlTest.php @@ -0,0 +1,34 @@ +fail('Missing expected Zend\Stdlib\Exception\ExtensionNotLoadedException'); + } catch (Exception\ExtensionNotLoadedException $e) { + $this->markTestSkipped('Missing ext/intl'); + } + } + + $this->stringWrapper = new Intl(); + parent::setUp(); + } +} diff --git a/test/StringWrapper/MbStringTest.php b/test/StringWrapper/MbStringTest.php new file mode 100644 index 000000000..bd6ee7aec --- /dev/null +++ b/test/StringWrapper/MbStringTest.php @@ -0,0 +1,34 @@ +fail('Missing expected Zend\Stdlib\Exception\ExtensionNotLoadedException'); + } catch (Exception\ExtensionNotLoadedException $e) { + $this->markTestSkipped('Missing ext/mbstring'); + } + } + + $this->stringWrapper = new MbString(); + parent::setUp(); + } +} diff --git a/test/StringWrapper/NativeTest.php b/test/StringWrapper/NativeTest.php new file mode 100644 index 000000000..329a19ba3 --- /dev/null +++ b/test/StringWrapper/NativeTest.php @@ -0,0 +1,24 @@ +stringWrapper = new Native(); + parent::setUp(); + } +} From ccbf706dbd67cc87e5df098d9441b79f02843756 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 15:35:05 +0100 Subject: [PATCH 19/63] StringUtils: wording: charset -> encoding --- src/StringUtils.php | 36 +++++----- src/StringWrapper/AbstractStringWrapper.php | 62 ++++++++--------- src/StringWrapper/Iconv.php | 28 ++++---- src/StringWrapper/Intl.php | 36 +++++----- src/StringWrapper/MbString.php | 66 +++++++++---------- src/StringWrapper/Native.php | 24 +++---- src/StringWrapper/StringWrapperInterface.php | 36 +++++----- test/StringUtilsTest.php | 20 +++--- .../StringWrapper/CommonStringWrapperTest.php | 66 +++++++++---------- 9 files changed, 187 insertions(+), 187 deletions(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index a854d4ab1..6aa3f7937 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -36,11 +36,11 @@ abstract class StringUtils protected static $wrapperRegistry; /** - * A list of known single-byte charsets (upper-case) + * A list of known single-byte encodings (upper-case) * * @var string[] */ - protected static $singleByteCharsets = array( + protected static $singleByteEncodings = array( 'ASCII', '7BIT', '8BIT', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10', @@ -106,20 +106,20 @@ public static function unregisterWrapper(StringWrapperInterface $wrapper) } /** - * Get the first string wrapper supporting one or more charsets + * Get the first string wrapper supporting one or more encodings * - * @param string $charset Charset supported by he string wrapper - * @param string $charsetN, ... Unlimited OPTIONAL number of additional charsets + * @param string $encoding Encoding supported by he string wrapper + * @param string $encodingN, ... Unlimited OPTIONAL number of additional encodings * @return StringWrapperInterface - * @throws Exception\RuntimeException If no wrapper supports all given charsets + * @throws Exception\RuntimeException If no wrapper supports all given encodings */ - public static function getWrapper($charset = 'UTF-8') + public static function getWrapper($encoding = 'UTF-8') { - $charsets = func_get_args(); + $$encodings = func_get_args(); foreach (static::getRegisteredWrappers() as $wrapper) { - foreach ($charsets as $charset) { - if (!$wrapper->isCharsetSupported($charset)) { + foreach ($encodings as $encoding) { + if (!$wrapper->isEncodingSupported($encoding)) { continue 2; } } @@ -128,29 +128,29 @@ public static function getWrapper($charset = 'UTF-8') } throw new Exception\RuntimeException( - 'No wrapper found supporting charset(s) ' . implode(', ', $charsets) + 'No wrapper found supporting encoding(s) ' . implode(', ', $encodings) ); } /** - * Get a list of all known single-byte charsets + * Get a list of all known single-byte encodings * * @return string[] */ - public static function getSingleByteCharsets() + public static function getSingleByteEncodings() { - return static::$singleByteCharsets; + return static::$singleByteEncodings; } /** - * Check if a given charset is a known single-byte charset + * Check if a given encoding is a known single-byte encoding * - * @param string $charset + * @param string $encoding * @return boolean */ - public static function isSingleByteCharset($charset) + public static function isSingleByteEncoding($encoding) { - return in_array(strtoupper($charset), static::$singleByteCharsets); + return in_array(strtoupper($encoding), static::$singleByteEncodings); } /** diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 07298335a..1f0bd2bbb 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -26,28 +26,28 @@ abstract class AbstractStringWrapper implements StringWrapperInterface * * @var string[] */ - protected $charsets = array(); + protected $encodings = array(); /** - * Check if the given charset is supported + * Check if the given encoding is supported * - * @param string $charset + * @param string $encoding * @return boolean */ - public function isCharsetSupported($charset) + public function isEncodingSupported($encoding) { - $charset = strtoupper($charset); - return in_array($charset, $this->charsets); + $encoding = strtoupper($encoding); + return in_array($encoding, $this->encodings); } /** - * Get a list of supported charsets + * Get a list of supported encodings * * @return string[] */ - public function getSupportedCharsets() + public function getSupportedEncodings() { - return $this->$charsets; + return $this->$encodings; } /** @@ -57,10 +57,10 @@ public function getSupportedCharsets() * @param integer $width * @param string $break * @param boolean $cut - * @param string $charset + * @param string $encoding * @return string */ - public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $charset = 'UTF-8') + public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $encoding = 'UTF-8') { $string = (string) $string; if ($string === '') { @@ -78,27 +78,27 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $cha throw new Exception\InvalidArgumentException('Cannot force cut when width is zero'); } - $charset = strtoupper($charset); - if (StringUtils::isSingleByteCharset($charset)) { + $encoding = strtoupper($encoding); + if (StringUtils::isSingleByteEncoding($encoding)) { return wordwrap($string, $width, $break, $cut); } - $stringWidth = $this->strlen($string, $charset); - $breakWidth = $this->strlen($break, $charset); + $stringWidth = $this->strlen($string, $encoding); + $breakWidth = $this->strlen($break, $encoding); $result = ''; $lastStart = $lastSpace = 0; for ($current = 0; $current < $stringWidth; $current++) { - $char = $this->substr($string, $current, 1, $charset); + $char = $this->substr($string, $current, 1, $encoding); $possibleBreak = $char; if ($breakWidth !== 1) { - $possibleBreak = $this->substr($string, $current, $breakWidth, $charset); + $possibleBreak = $this->substr($string, $current, $breakWidth, $encoding); } if ($possibleBreak === $break) { - $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth, $charset); + $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth, $encoding); $current += $breakWidth - 1; $lastStart = $lastSpace = $current + 1; continue; @@ -106,7 +106,7 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $cha if ($char === ' ') { if ($current - $lastStart >= $width) { - $result .= $this->substr($string, $lastStart, $current - $lastStart, $charset) . $break; + $result .= $this->substr($string, $lastStart, $current - $lastStart, $encoding) . $break; $lastStart = $current + 1; } @@ -115,20 +115,20 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $cha } if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) { - $result .= $this->substr($string, $lastStart, $current - $lastStart, $charset) . $break; + $result .= $this->substr($string, $lastStart, $current - $lastStart, $encoding) . $break; $lastStart = $lastSpace = $current; continue; } if ($current - $lastStart >= $width && $lastStart < $lastSpace) { - $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart, $charset) . $break; + $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart, $encoding) . $break; $lastStart = $lastSpace = $lastSpace + 1; continue; } } if ($lastStart !== $current) { - $result .= $this->substr($string, $lastStart, $current - $lastStart, $charset); + $result .= $this->substr($string, $lastStart, $current - $lastStart, $encoding); } return $result; @@ -141,19 +141,19 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $cha * @param integer $padLength * @param string $padString * @param integer $padType - * @param string $charset + * @param string $encoding * @return string */ - public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT, $charset = 'UTF-8') + public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT, $encoding = 'UTF-8') { - $charset = strtoupper($charset); - if (StringUtils::isSingleByteCharset($charset)) { + $encoding = strtoupper($encoding); + if (StringUtils::isSingleByteEncoding($encoding)) { return str_pad($input, $padLength, $padString, $padType); } $return = ''; - $lengthOfPadding = $padLength - $this->strlen($input, $charset); - $padStringLength = $this->strlen($padString, $charset); + $lengthOfPadding = $padLength - $this->strlen($input, $encoding); + $padStringLength = $this->strlen($padString, $encoding); if ($padStringLength === 0 || $lengthOfPadding <= 0) { $return = $input; @@ -169,14 +169,14 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2); $lastStringRightLength += $lastStringLength % 2; - $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength, $charset); - $lastStringRight = $this->substr($padString, 0, $lastStringRightLength, $charset); + $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength, $encoding); + $lastStringRight = $this->substr($padString, 0, $lastStringRightLength, $encoding); $return = str_repeat($padString, $repeatCountLeft) . $lastStringLeft . $input . str_repeat($padString, $repeatCountRight) . $lastStringRight; } else { - $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength, $charset); + $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength, $encoding); if ($padType === \STR_PAD_LEFT) { $return = str_repeat($padString, $repeatCount) . $lastString . $input; diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 887097333..01be679da 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -23,7 +23,7 @@ class Iconv extends AbstractStringWrapper * @var string[] * @link http://www.gnu.org/software/libiconv/ */ - protected $charsets = array( + protected $encodings = array( // European languages 'ASCII', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-7', @@ -133,12 +133,12 @@ public function __construct() * Returns the length of the given string * * @param string $str - * @param string $charset + * @param string $encoding * @return int|false */ - public function strlen($str, $charset = 'UTF-8') + public function strlen($str, $encoding = 'UTF-8') { - return iconv_strlen($str, $charset); + return iconv_strlen($str, $encoding); } /** @@ -147,12 +147,12 @@ public function strlen($str, $charset = 'UTF-8') * @param string $str * @param int $offset * @param int|null $length - * @param string $charset + * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') + public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') { - return iconv_substr($str, $offset, $length, $charset); + return iconv_substr($str, $offset, $length, $encoding); } /** @@ -161,24 +161,24 @@ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') * @param string $haystack * @param string $needle * @param int $offset - * @param string $charset + * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') + public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') { - return iconv_strpos($haystack, $needle, $offset, $charset); + return iconv_strpos($haystack, $needle, $offset, $encoding); } /** * Convert a string from one character encoding to another * * @param string $str - * @param string $toCharset - * @param string $fromCharset + * @param string $toEncoding + * @param string $fromEncoding * @return string|false */ - public function convert($str, $toCharset, $fromCharset = 'UTF-8') + public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') { - return iconv($fromCharset, $toCharset, $str); + return iconv($fromEncoding, $toEncoding, $str); } } diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index 71a9919d9..490ce7688 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -22,7 +22,7 @@ class Intl extends AbstractStringWrapper * * @var string[] */ - protected $charsets = array('UTF-8'); + protected $encodings = array('UTF-8'); /** * Constructor @@ -42,13 +42,13 @@ public function __construct() * Returns the length of the given string * * @param string $str - * @param string $charset + * @param string $encoding * @return int|false */ - public function strlen($str, $charset = 'UTF-8') + public function strlen($str, $encoding = 'UTF-8') { - if (strcasecmp($charset, 'UTF-8') != 0) { - trigger_error("Character set '{$charset}' not supported by intl"); + if (strcasecmp($encoding, 'UTF-8') != 0) { + trigger_error("Character set '{$encoding}' not supported by intl"); return false; } @@ -61,13 +61,13 @@ public function strlen($str, $charset = 'UTF-8') * @param string $str * @param int $offset * @param int|null $length - * @param string $charset + * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') + public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') { - if (strcasecmp($charset, 'UTF-8') != 0) { - trigger_error("Character set '{$charset}' not supported by intl"); + if (strcasecmp($encoding, 'UTF-8') != 0) { + trigger_error("Character set '{$encoding}' not supported by intl"); return false; } @@ -80,13 +80,13 @@ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') * @param string $haystack * @param string $needle * @param int $offset - * @param string $charset + * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') + public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') { - if (strcasecmp($charset, 'UTF-8') != 0) { - trigger_error("Character set '{$charset}' not supported by intl"); + if (strcasecmp($encoding, 'UTF-8') != 0) { + trigger_error("Character set '{$encoding}' not supported by intl"); return false; } @@ -97,14 +97,14 @@ public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') * Convert a string from one character encoding to another * * @param string $str - * @param string $toCharset - * @param string $fromCharset + * @param string $toEncoding + * @param string $fromEncoding * @return string|false */ - public function convert($str, $toCharset, $fromCharset = 'UTF-8') + public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') { - if (strcasecmp($toCharset, $fromCharset) != 0) { - trigger_error("Can't convert '{$fromCharset}' to '{$toCharset}' using intl", E_WARNING); + if (strcasecmp($toEncoding, $fromEncoding) != 0) { + trigger_error("Can't convert '{$fromEncoding}' to '{$toEncoding}' using intl", E_WARNING); return false; } diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index 60bb257b6..46b5a88f5 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -23,7 +23,7 @@ class MbString extends AbstractStringWrapper * @var string[] * @link http://php.net/manual/mbstring.supported-encodings.php */ - protected $charsets = array( + protected $encodings = array( 'UCS-4', 'UCS-4BE', 'UCS-4LE', @@ -114,27 +114,27 @@ public function __construct() ); } - // remove charsets not available before PHP-5.4 + // remove encodings not available before PHP-5.4 if (version_compare(PHP_VERSION, '5.4', '<')) { unset( - $this->charsets['SJIS-MAC'], - $this->charsets['MACJAPANESE'], - $this->charsets['SJIS-Mobile#DOCOMO'], - $this->charsets['SJIS-DOCOMO'], - $this->charsets['SJIS-Mobile#KDDI'], - $this->charsets['SJIS-KDDI'], - $this->charsets['SJIS-Mobile#SOFTBANK'], - $this->charsets['SJIS-SOFTBANK'], - $this->charsets['UTF-8-Mobile#DOCOMO'], - $this->charsets['UTF-8-DOCOMO'], - $this->charsets['UTF-8-Mobile#KDDI-A'], - $this->charsets['UTF-8-Mobile#KDDI-B'], - $this->charsets['UTF-8-KDDI'], - $this->charsets['UTF-8-Mobile#SOFTBANK'], - $this->charsets['UTF-8-SOFTBANK'], - $this->charsets['ISO-2022-JP-MOBILE#KDDI'], - $this->charsets['ISO-2022-JP-KDDI'], - $this->charsets['GB18030'] + $this->encodings['SJIS-MAC'], + $this->encodings['MACJAPANESE'], + $this->encodings['SJIS-Mobile#DOCOMO'], + $this->encodings['SJIS-DOCOMO'], + $this->encodings['SJIS-Mobile#KDDI'], + $this->encodings['SJIS-KDDI'], + $this->encodings['SJIS-Mobile#SOFTBANK'], + $this->encodings['SJIS-SOFTBANK'], + $this->encodings['UTF-8-Mobile#DOCOMO'], + $this->encodings['UTF-8-DOCOMO'], + $this->encodings['UTF-8-Mobile#KDDI-A'], + $this->encodings['UTF-8-Mobile#KDDI-B'], + $this->encodings['UTF-8-KDDI'], + $this->encodings['UTF-8-Mobile#SOFTBANK'], + $this->encodings['UTF-8-SOFTBANK'], + $this->encodings['ISO-2022-JP-MOBILE#KDDI'], + $this->encodings['ISO-2022-JP-KDDI'], + $this->encodings['GB18030'] ); } } @@ -143,12 +143,12 @@ public function __construct() * Returns the length of the given string * * @param string $str - * @param string $charset + * @param string $encoding * @return int|false */ - public function strlen($str, $charset = 'UTF-8') + public function strlen($str, $encoding = 'UTF-8') { - return mb_strlen($str, $charset); + return mb_strlen($str, $encoding); } /** @@ -157,12 +157,12 @@ public function strlen($str, $charset = 'UTF-8') * @param string $str * @param int $offset * @param int|null $length - * @param string $charset + * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') + public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') { - return mb_substr($str, $offset, $length, $charset); + return mb_substr($str, $offset, $length, $encoding); } /** @@ -171,24 +171,24 @@ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') * @param string $haystack * @param string $needle * @param int $offset - * @param string $charset + * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') + public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') { - return mb_strpos($haystack, $needle, $offset, $charset); + return mb_strpos($haystack, $needle, $offset, $encoding); } /** * Convert a string from one character encoding to another * * @param string $str - * @param string $toCharset - * @param string $fromCharset + * @param string $toEncoding + * @param string $fromEncoding * @return string|false */ - public function convert($str, $toCharset, $fromCharset = 'UTF-8') + public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') { - return mb_convert_encoding($str, $toCharset, $fromCharset); + return mb_convert_encoding($str, $toEncoding, $fromEncoding); } } diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index aee15b736..ed0bf48f6 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -25,17 +25,17 @@ class Native extends AbstractStringWrapper */ public function __construct() { - $this->charsets = StringUtils::getSingleByteCharsets(); + $this->encodings = StringUtils::getSingleByteEncodings(); } /** * Returns the length of the given string * * @param string $str - * @param string $charset + * @param string $encoding * @return int|false */ - public function strlen($str, $charset = 'UTF-8') + public function strlen($str, $encoding = 'UTF-8') { return strlen($str); } @@ -46,10 +46,10 @@ public function strlen($str, $charset = 'UTF-8') * @param string $str * @param int $offset * @param int|null $length - * @param string $charset + * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') + public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') { return substr($str, $offset, $length); } @@ -60,10 +60,10 @@ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8') * @param string $haystack * @param string $needle * @param int $offset - * @param string $charset + * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') + public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') { return strpos($haystack, $needle, $offset); } @@ -72,14 +72,14 @@ public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8') * Convert a string from one character encoding to another * * @param string $str - * @param string $toCharset - * @param string $fromCharset + * @param string $toEncoding + * @param string $fromEncoding * @return string|false */ - public function convert($str, $toCharset, $fromCharset = 'UTF-8') + public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') { - if (strcasecmp($toCharset, $fromCharset) != 0) { - trigger_error("Can't convert '{$fromCharset}' to '{$toCharset}' using intl", E_WARNING); + if (strcasecmp($toEncoding, $fromEncoding) != 0) { + trigger_error("Can't convert '{$fromEncoding}' to '{$toEncoding}' using intl", E_WARNING); return false; } diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index f78da2e4d..3929fb696 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -19,28 +19,28 @@ interface StringWrapperInterface { /** - * Check if the given charset is supported + * Check if the given encoding is supported * - * @param string $charset + * @param string $encoding * @return boolean */ - public function isCharsetSupported($charset); + public function isEncodingSupported($encoding); /** - * Get a list of supported charsets + * Get a list of supported encodings * * @return string[] */ - public function getSupportedCharsets(); + public function getSupportedEncodings(); /** * Returns the length of the given string * * @param string $str - * @param string $charset + * @param string $encoding * @return int|false */ - public function strlen($str, $charset = 'UTF-8'); + public function strlen($str, $encoding = 'UTF-8'); /** * Returns the portion of string specified by the start and length parameters @@ -48,10 +48,10 @@ public function strlen($str, $charset = 'UTF-8'); * @param string $str * @param int $offset * @param int|null $length - * @param string $charset + * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8'); + public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8'); /** * Find the position of the first occurrence of a substring in a string @@ -59,20 +59,20 @@ public function substr($str, $offset = 0, $length = null, $charset = 'UTF-8'); * @param string $haystack * @param string $needle * @param int $offset - * @param string $charset + * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $charset = 'UTF-8'); + public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8'); /** * Convert a string from one character encoding to another * * @param string $str - * @param string $toCharset - * @param string $fromCharset + * @param string $toEncoding + * @param string $fromEncoding * @return string|false */ - public function convert($str, $toCharset, $fromCharset = 'UTF-8'); + public function convert($str, $toEncoding, $fromEncoding = 'UTF-8'); /** * Wraps a string to a given number of characters @@ -81,10 +81,10 @@ public function convert($str, $toCharset, $fromCharset = 'UTF-8'); * @param integer $width * @param string $break * @param boolean $cut - * @param string $charset + * @param string $encoding * @return string */ - public function wordWrap($str, $width = 75, $break = "\n", $cut = false, $charset = 'UTF-8'); + public function wordWrap($str, $width = 75, $break = "\n", $cut = false, $encoding = 'UTF-8'); /** * Pad a string to a certain length with another string @@ -93,8 +93,8 @@ public function wordWrap($str, $width = 75, $break = "\n", $cut = false, $charse * @param integer $padLength * @param string $padString * @param integer $padType - * @param string $charset + * @param string $encoding * @return string */ - public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT, $charset = 'UTF-8'); + public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT, $encoding = 'UTF-8'); } diff --git a/test/StringUtilsTest.php b/test/StringUtilsTest.php index 94fcdd895..156431dde 100644 --- a/test/StringUtilsTest.php +++ b/test/StringUtilsTest.php @@ -35,7 +35,7 @@ public function tearDown() } - public function getSingleByCharsets() + public function getSingleByEncodings() { return array( array('AscII'), @@ -60,15 +60,15 @@ public function getSingleByCharsets() } /** - * @dataProvider getSingleByCharsets - * @param string $charset + * @dataProvider getSingleByEncodings + * @param string $encoding */ - public function testIsSingleByteCharsetReturnsTrue($charset) + public function testIsSingleByteEncodingReturnsTrue($encoding) { - $this->assertTrue(StringUtils::isSingleByteCharset($charset)); + $this->assertTrue(StringUtils::isSingleByteEncoding($encoding)); } - public function getNonSingleByteCharsets() + public function getNonSingleByteEncodings() { return array( array('UTf-8'), @@ -79,12 +79,12 @@ public function getNonSingleByteCharsets() } /** - * @dataProvider getNonSingleByteCharsets - * @param string $charset + * @dataProvider getNonSingleByteEncodings + * @param string $encoding */ - public function testIsSingleByteCharsetReturnsFalse($charset) + public function testIsSingleByteEncodingReturnsFalse($encoding) { - $this->assertFalse(StringUtils::isSingleByteCharset($charset)); + $this->assertFalse(StringUtils::isSingleByteEncoding($encoding)); } public function testGetWrapper() diff --git a/test/StringWrapper/CommonStringWrapperTest.php b/test/StringWrapper/CommonStringWrapperTest.php index ef44b2aef..4f606a1ae 100644 --- a/test/StringWrapper/CommonStringWrapperTest.php +++ b/test/StringWrapper/CommonStringWrapperTest.php @@ -47,18 +47,18 @@ public function strlenProvider() /** * @dataProvider strlenProvider * @param string $string - * @param string $charset + * @param string $encoding * @param mixed $expected */ - public function testStrlen($str, $charset, $expected) + public function testStrlen($str, $encoding, $expected) { - if (!$this->stringWrapper->isCharsetSupported($charset)) { + if (!$this->stringWrapper->isEncodingSupported($encoding)) { $this->markTestSkipped( - "Charset {$charset} not supported by " . get_class($this->stringWrapper) + "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) ); } - $result = $this->stringWrapper->strlen($str, $charset); + $result = $this->stringWrapper->strlen($str, $encoding); $this->assertSame($expected, $result); } @@ -76,18 +76,18 @@ public function substrProvider() * @param string $str * @param int $offset * @param int|null $length - * @param string $charset + * @param string $encoding * @param mixed $expected */ - public function testSubstr($str, $offset, $length, $charset, $expected) + public function testSubstr($str, $offset, $length, $encoding, $expected) { - if (!$this->stringWrapper->isCharsetSupported($charset)) { + if (!$this->stringWrapper->isEncodingSupported($encoding)) { $this->markTestSkipped( - "Charset {$charset} not supported by " . get_class($this->stringWrapper) + "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) ); } - $result = $this->stringWrapper->substr($str, $offset, $length, $charset); + $result = $this->stringWrapper->substr($str, $offset, $length, $encoding); $this->assertSame($expected, $result); } @@ -105,18 +105,18 @@ public function strposProvider() * @param string $haystack * @param string $needle * @param int $offset - * @param string $charset + * @param string $encoding * @param mixed $expected */ - public function testStrpos($haystack, $needle, $offset, $charset, $expected) + public function testStrpos($haystack, $needle, $offset, $encoding, $expected) { - if (!$this->stringWrapper->isCharsetSupported($charset)) { + if (!$this->stringWrapper->isEncodingSupported($encoding)) { $this->markTestSkipped( - "Charset {$charset} not supported by " . get_class($this->stringWrapper) + "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) ); } - $result = $this->stringWrapper->strpos($haystack, $needle, $offset, $charset); + $result = $this->stringWrapper->strpos($haystack, $needle, $offset, $encoding); $this->assertSame($expected, $result); } @@ -134,23 +134,23 @@ public function convertProvider() /** * @dataProvider convertProvider * @param string $str - * @param string $toCharset - * @param string $fromCharset + * @param string $toEncoding + * @param string $fromEncoding * @param mixed $expected */ - public function testConvert($str, $toCharset, $fromCharset, $expected) + public function testConvert($str, $toEncoding, $fromEncoding, $expected) { - if (!$this->stringWrapper->isCharsetSupported($toCharset)) { + if (!$this->stringWrapper->isEncodingSupported($toEncoding)) { $this->markTestSkipped( - "Charset {$toCharset} not supported by " . get_class($this->stringWrapper) + "Encoding {$toEncoding} not supported by " . get_class($this->stringWrapper) ); - } elseif (!$this->stringWrapper->isCharsetSupported($fromCharset)) { + } elseif (!$this->stringWrapper->isEncodingSupported($fromEncoding)) { $this->markTestSkipped( - "Charset {$fromCharset} not supported by " . get_class($this->stringWrapper) + "Encoding {$fromEncoding} not supported by " . get_class($this->stringWrapper) ); } - $result = $this->stringWrapper->convert($str, $toCharset, $fromCharset); + $result = $this->stringWrapper->convert($str, $toEncoding, $fromEncoding); $this->assertSame($expected, $result); } @@ -233,18 +233,18 @@ public function wordWrapProvider() * @param integer $width * @param string $break * @param boolean $cut - * @param string $charset + * @param string $encoding * @param mixed $expected */ - public function testWordWrap($string, $width, $break, $cut, $charset, $expected) + public function testWordWrap($string, $width, $break, $cut, $encoding, $expected) { - if (!$this->stringWrapper->isCharsetSupported($charset)) { + if (!$this->stringWrapper->isEncodingSupported($encoding)) { $this->markTestSkipped( - "Charset {$charset} not supported by " . get_class($this->stringWrapper) + "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) ); } - $result = $this->stringWrapper->wordWrap($string, $width, $break, $cut, $charset); + $result = $this->stringWrapper->wordWrap($string, $width, $break, $cut, $encoding); $this->assertSame($expected, $result); } @@ -283,20 +283,20 @@ public function strPadProvider() * @param integer $padLength * @param string $padString * @param integer $padType - * @param string $charset + * @param string $encoding * @param mixed $expected * * @group ZF-12186 */ - public function testStrPad($input, $padLength, $padString, $padType, $charset, $expected) + public function testStrPad($input, $padLength, $padString, $padType, $encoding, $expected) { - if (!$this->stringWrapper->isCharsetSupported($charset)) { + if (!$this->stringWrapper->isEncodingSupported($encoding)) { $this->markTestSkipped( - "Charset {$charset} not supported by " . get_class($this->stringWrapper) + "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) ); } - $result = $this->stringWrapper->strPad($input, $padLength, $padString, $padType, $charset); + $result = $this->stringWrapper->strPad($input, $padLength, $padString, $padType, $encoding); $this->assertSame($expected, $result); } } From 77e20ddd17d50bb1398858277df992b42f780b4e Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 15:44:02 +0100 Subject: [PATCH 20/63] fixed wrong typed variable in StringUtils::getWrapper --- src/StringUtils.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index 6aa3f7937..4714a47fc 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -115,7 +115,7 @@ public static function unregisterWrapper(StringWrapperInterface $wrapper) */ public static function getWrapper($encoding = 'UTF-8') { - $$encodings = func_get_args(); + $encodings = func_get_args(); foreach (static::getRegisteredWrappers() as $wrapper) { foreach ($encodings as $encoding) { From f46ba861aa528dab4f6d04474251958561ae88e3 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 16:20:14 +0100 Subject: [PATCH 21/63] StringUtils: cs --- src/StringUtils.php | 7 +++--- src/StringWrapper/Iconv.php | 4 ++-- src/StringWrapper/Intl.php | 2 +- src/StringWrapper/MbString.php | 24 ++++++++++---------- src/StringWrapper/Native.php | 2 +- src/StringWrapper/StringWrapperInterface.php | 2 +- 6 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index 4714a47fc..040ce301f 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -30,14 +30,14 @@ abstract class StringUtils /** * Ordered list of registered string wrapper instances - * + * * @var StringWrapperInterface[] */ protected static $wrapperRegistry; /** * A list of known single-byte encodings (upper-case) - * + * * @var string[] */ protected static $singleByteEncodings = array( @@ -45,9 +45,8 @@ abstract class StringUtils 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10', 'ISO-8859-11', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', - 'CP-1251', 'CP-1252' + 'CP-1251', 'CP-1252', // TODO - ); /** diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 01be679da..3de069ed0 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -112,7 +112,7 @@ class Iconv extends AbstractStringWrapper 'TDS565', // Platform specifics - 'ATARIST', 'RISCOS-LATIN1', + 'ATARIST', 'RISCOS-LATIN1', ); /** @@ -143,7 +143,7 @@ public function strlen($str, $encoding = 'UTF-8') /** * Returns the portion of string specified by the start and length parameters - * + * * @param string $str * @param int $offset * @param int|null $length diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index 490ce7688..0a0d2cac8 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -57,7 +57,7 @@ public function strlen($str, $encoding = 'UTF-8') /** * Returns the portion of string specified by the start and length parameters - * + * * @param string $str * @param int $offset * @param int|null $length diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index 46b5a88f5..8331ba789 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -48,15 +48,15 @@ class MbString extends AbstractStringWrapper 'ISO-2022-JP-MS', 'CP932', 'CP51932', - 'SJIS-MAC', 'MACJAPANESE', // ** - 'SJIS-Mobile#DOCOMO', 'SJIS-DOCOMO', // ** - 'SJIS-Mobile#KDDI', 'SJIS-KDDI', // ** - 'SJIS-Mobile#SOFTBANK', 'SJIS-SOFTBANK', // ** - 'UTF-8-Mobile#DOCOMO', 'UTF-8-DOCOMO', // ** - 'UTF-8-Mobile#KDDI-A', // ** - 'UTF-8-Mobile#KDDI-B', 'UTF-8-KDDI', // ** - 'UTF-8-Mobile#SOFTBANK', 'UTF-8-SOFTBANK', // ** - 'ISO-2022-JP-MOBILE#KDDI', 'ISO-2022-JP-KDDI', // ** + 'SJIS-MAC', 'MACJAPANESE', + 'SJIS-Mobile#DOCOMO', 'SJIS-DOCOMO', + 'SJIS-Mobile#KDDI', 'SJIS-KDDI', + 'SJIS-Mobile#SOFTBANK', 'SJIS-SOFTBANK', + 'UTF-8-Mobile#DOCOMO', 'UTF-8-DOCOMO', + 'UTF-8-Mobile#KDDI-A', + 'UTF-8-Mobile#KDDI-B', 'UTF-8-KDDI', + 'UTF-8-Mobile#SOFTBANK', 'UTF-8-SOFTBANK', + 'ISO-2022-JP-MOBILE#KDDI', 'ISO-2022-JP-KDDI', 'JIS', 'JIS-MS', 'CP50220', @@ -87,7 +87,7 @@ class MbString extends AbstractStringWrapper '8BIT', 'EUC-CN', 'CP936', - 'GB18030', // ** + 'GB18030', 'HZ', 'EUC-TW', 'CP950', @@ -98,7 +98,7 @@ class MbString extends AbstractStringWrapper 'WINDOWS-1251', 'CP1251', 'WINDOWS-1252', 'CP1252', 'CP866', 'IBM866', - 'KOI8-R' + 'KOI8-R', ); /** @@ -153,7 +153,7 @@ public function strlen($str, $encoding = 'UTF-8') /** * Returns the portion of string specified by the start and length parameters - * + * * @param string $str * @param int $offset * @param int|null $length diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index ed0bf48f6..07601ba52 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -42,7 +42,7 @@ public function strlen($str, $encoding = 'UTF-8') /** * Returns the portion of string specified by the start and length parameters - * + * * @param string $str * @param int $offset * @param int|null $length diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index 3929fb696..c46570383 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -44,7 +44,7 @@ public function strlen($str, $encoding = 'UTF-8'); /** * Returns the portion of string specified by the start and length parameters - * + * * @param string $str * @param int $offset * @param int|null $length From caf59c17f321d5e7e994d96ab96cdf8b695bdfb1 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 16:51:40 +0100 Subject: [PATCH 22/63] StringUtils: implemented basic functionality into AbstractStringWrapper::convert --- src/StringWrapper/AbstractStringWrapper.php | 18 ++++++++++++++++++ src/StringWrapper/Intl.php | 18 ------------------ src/StringWrapper/Native.php | 20 +------------------- 3 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 1f0bd2bbb..b8fc2b61b 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -50,6 +50,24 @@ public function getSupportedEncodings() return $this->$encodings; } + /** + * Convert a string from one character encoding to another + * + * @param string $str + * @param string $toEncoding + * @param string $fromEncoding + * @return string|false + */ + public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') + { + if (strcasecmp($toEncoding, $fromEncoding) != 0) { + trigger_error("Can't convert '{$fromEncoding}' to '{$toEncoding}'", E_WARNING); + return false; + } + + return $str; + } + /** * Wraps a string to a given number of characters * diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index 0a0d2cac8..e9c9ae9f5 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -92,22 +92,4 @@ public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') return grapheme_strpos($haystack, $needle, $offset); } - - /** - * Convert a string from one character encoding to another - * - * @param string $str - * @param string $toEncoding - * @param string $fromEncoding - * @return string|false - */ - public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') - { - if (strcasecmp($toEncoding, $fromEncoding) != 0) { - trigger_error("Can't convert '{$fromEncoding}' to '{$toEncoding}' using intl", E_WARNING); - return false; - } - - return $str; - } } diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index 07601ba52..42b8f4ae5 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -67,22 +67,4 @@ public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') { return strpos($haystack, $needle, $offset); } - - /** - * Convert a string from one character encoding to another - * - * @param string $str - * @param string $toEncoding - * @param string $fromEncoding - * @return string|false - */ - public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') - { - if (strcasecmp($toEncoding, $fromEncoding) != 0) { - trigger_error("Can't convert '{$fromEncoding}' to '{$toEncoding}' using intl", E_WARNING); - return false; - } - - return $str; - } -} +} From 1e3bb8471400d2ac6b3c3ed14ef16fa20ea97b0c Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 17:37:30 +0100 Subject: [PATCH 23/63] StringUtils: hopefully a little better encoding list --- src/StringWrapper/AbstractStringWrapper.php | 33 ++++++++++++++++----- src/StringWrapper/Iconv.php | 11 ++++--- src/StringWrapper/Native.php | 18 +++++++++-- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index b8fc2b61b..2ba662966 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -22,32 +22,31 @@ abstract class AbstractStringWrapper implements StringWrapperInterface { /** - * List of supported character sets (upper case) + * List of supported character encodings (upper case) * * @var string[] */ protected $encodings = array(); /** - * Check if the given encoding is supported + * Check if the given character encoding is supported * * @param string $encoding * @return boolean */ public function isEncodingSupported($encoding) { - $encoding = strtoupper($encoding); - return in_array($encoding, $this->encodings); + return in_array(strtoupper($encoding), $this->encodings); } /** - * Get a list of supported encodings + * Get a list of supported character encodings * * @return string[] */ public function getSupportedEncodings() { - return $this->$encodings; + return $this->encodings; } /** @@ -61,7 +60,7 @@ public function getSupportedEncodings() public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') { if (strcasecmp($toEncoding, $fromEncoding) != 0) { - trigger_error("Can't convert '{$fromEncoding}' to '{$toEncoding}'", E_WARNING); + trigger_error("Can't convert '{$fromEncoding}' to '{$toEncoding}'", \E_WARNING); return false; } @@ -78,7 +77,7 @@ public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') * @param string $encoding * @return string */ - public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $encoding = 'UTF-8') + public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $encoding = 'UTF-8') { $string = (string) $string; if ($string === '') { @@ -206,4 +205,22 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD return $return; } + + /** + * Get the internal used name of an encoding + * + * @param string $encoding + * @return string + * @throws Exception\InvalidArgumentException On an unsupported encoding + */ + protected function getInternalEncoding($encoding) + { + $encodingUpper = strtoupper($encoding); + if (!isset($this->encodingMap[$encodingUpper])) { + throw new Exception\InvalidArgumentException( + "Character encoding '{$encoding}' isn't supported by this string wrapper" + ); + } + return $this->encodingMap[$encodingUpper]; + } } diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 3de069ed0..3c97ad083 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -29,19 +29,18 @@ class Iconv extends AbstractStringWrapper 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-7', 'ISO-8859-9', 'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', 'KOI8-R', 'KOI8-U', 'KOI8-RU', - 'CP1250', 'CP1251', 'CP1252', 'CP1253', 'CP1254' ,'CP1257', - 'CP850', 'CP866', 'CP1131', + 'CP1250', 'CP1251', 'CP1252', 'CP1253', 'CP1254', 'CP1257', 'CP850', 'CP866', 'CP1131', 'MACROMAN', 'MACCENTRALEUROPE', 'MACICELAND', 'MACCROATIAN', 'MACROMANIA', - 'MACCYRILLIC', 'MACUKRAINE', 'MACGREEK', 'MACTURKISH', - 'MACINTOSH', + 'MACCYRILLIC', 'MACUKRAINE', 'MACGREEK', 'MACTURKISH', 'MACINTOSH', // Semitic languages 'ISO-8859-6', 'ISO-8859-8', - 'CP1255' , 'CP1256', 'CP862', + 'CP1255', 'CP1256', 'CP862', 'MACHEBREW', 'MACARABIC', // Japanese - 'EUC-JP', 'SHIFT_JIS', 'CP932', 'ISO-2022-JP', 'ISO-2022-JP-2', 'ISO-2022-JP-1', + 'EUC-JP', 'SHIFT_JIS', 'CP932', + 'ISO-2022-JP', 'ISO-2022-JP-2', 'ISO-2022-JP-1', // Chinese 'EUC-CN', 'HZ', 'GBK', 'CP936', 'GB18030', 'EUC-TW', 'BIG5', 'CP950', diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index 42b8f4ae5..d7e13e9b7 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -19,13 +19,25 @@ */ class Native extends AbstractStringWrapper { + /** + * Check if the given encoding is supported + * + * @param string $encoding + * @return boolean + */ + public function isEncodingSupported($encoding) + { + return StringUtils::isSingleByteEncoding($encoding); + } /** - * Constructor + * Get a list of supported character encodings + * + * @return string[] */ - public function __construct() + public function getSupportedEncodings() { - $this->encodings = StringUtils::getSingleByteEncodings(); + return StringUtils::getSingleByteEncodings(); } /** From e415882c88651ea12350fee905adf6e35161a20e Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 17:41:10 +0100 Subject: [PATCH 24/63] StringUtils: hopefully a little better encoding list --- src/StringUtils.php | 14 +++++++------- src/StringWrapper/AbstractStringWrapper.php | 18 ------------------ src/StringWrapper/StringWrapperInterface.php | 4 ++-- 3 files changed, 9 insertions(+), 27 deletions(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index 040ce301f..2b1b227e8 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -36,7 +36,7 @@ abstract class StringUtils protected static $wrapperRegistry; /** - * A list of known single-byte encodings (upper-case) + * A list of known single-byte character encodings (upper-case) * * @var string[] */ @@ -105,12 +105,12 @@ public static function unregisterWrapper(StringWrapperInterface $wrapper) } /** - * Get the first string wrapper supporting one or more encodings + * Get the first string wrapper supporting one or more character encodings * - * @param string $encoding Encoding supported by he string wrapper - * @param string $encodingN, ... Unlimited OPTIONAL number of additional encodings + * @param string $encoding Character encoding supported by he string wrapper + * @param string $encodingN, ... Unlimited OPTIONAL number of additional character encodings * @return StringWrapperInterface - * @throws Exception\RuntimeException If no wrapper supports all given encodings + * @throws Exception\RuntimeException If no wrapper supports all given character encodings */ public static function getWrapper($encoding = 'UTF-8') { @@ -132,7 +132,7 @@ public static function getWrapper($encoding = 'UTF-8') } /** - * Get a list of all known single-byte encodings + * Get a list of all known single-byte character encodings * * @return string[] */ @@ -142,7 +142,7 @@ public static function getSingleByteEncodings() } /** - * Check if a given encoding is a known single-byte encoding + * Check if a given encoding is a known single-byte character encoding * * @param string $encoding * @return boolean diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 2ba662966..ac329357c 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -205,22 +205,4 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD return $return; } - - /** - * Get the internal used name of an encoding - * - * @param string $encoding - * @return string - * @throws Exception\InvalidArgumentException On an unsupported encoding - */ - protected function getInternalEncoding($encoding) - { - $encodingUpper = strtoupper($encoding); - if (!isset($this->encodingMap[$encodingUpper])) { - throw new Exception\InvalidArgumentException( - "Character encoding '{$encoding}' isn't supported by this string wrapper" - ); - } - return $this->encodingMap[$encodingUpper]; - } } diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index c46570383..f3f8ebe15 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -19,7 +19,7 @@ interface StringWrapperInterface { /** - * Check if the given encoding is supported + * Check if the given character encoding is supported * * @param string $encoding * @return boolean @@ -27,7 +27,7 @@ interface StringWrapperInterface public function isEncodingSupported($encoding); /** - * Get a list of supported encodings + * Get a list of supported character encodings * * @return string[] */ From 832179bdfc4125954f0f77fa33311b9e592edea2 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 17:46:58 +0100 Subject: [PATCH 25/63] StringUtils: optimations --- src/StringWrapper/AbstractStringWrapper.php | 49 ++++++++++----------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index ac329357c..bd9e7713f 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -75,7 +75,7 @@ public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') * @param string $break * @param boolean $cut * @param string $encoding - * @return string + * @return string|false */ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $encoding = 'UTF-8') { @@ -168,41 +168,38 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD return str_pad($input, $padLength, $padString, $padType); } - $return = ''; $lengthOfPadding = $padLength - $this->strlen($input, $encoding); $padStringLength = $this->strlen($padString, $encoding); if ($padStringLength === 0 || $lengthOfPadding <= 0) { - $return = $input; - } else { - $repeatCount = floor($lengthOfPadding / $padStringLength); + return $input; + } - if ($padType === \STR_PAD_BOTH) { - $lastStringLeft = ''; - $lastStringRight = ''; - $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2; + $repeatCount = floor($lengthOfPadding / $padStringLength); - $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength; - $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2); - $lastStringRightLength += $lastStringLength % 2; + if ($padType === \STR_PAD_BOTH) { + $lastStringLeft = ''; + $lastStringRight = ''; + $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2; - $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength, $encoding); - $lastStringRight = $this->substr($padString, 0, $lastStringRightLength, $encoding); + $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength; + $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2); + $lastStringRightLength += $lastStringLength % 2; - $return = str_repeat($padString, $repeatCountLeft) . $lastStringLeft - . $input - . str_repeat($padString, $repeatCountRight) . $lastStringRight; - } else { - $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength, $encoding); + $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength, $encoding); + $lastStringRight = $this->substr($padString, 0, $lastStringRightLength, $encoding); - if ($padType === \STR_PAD_LEFT) { - $return = str_repeat($padString, $repeatCount) . $lastString . $input; - } else { - $return = $input . str_repeat($padString, $repeatCount) . $lastString; - } + return str_repeat($padString, $repeatCountLeft) . $lastStringLeft + . $input + . str_repeat($padString, $repeatCountRight) . $lastStringRight; + } else { + $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength, $encoding); + + if ($padType === \STR_PAD_LEFT) { + return str_repeat($padString, $repeatCount) . $lastString . $input; + } else { + return $input . str_repeat($padString, $repeatCount) . $lastString; } } - - return $return; } } From 90c0cc0534e96f8837180e3c3b2bfd0d4e5660dc Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 19:49:28 +0100 Subject: [PATCH 26/63] StringUtils: cs --- src/StringWrapper/Native.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index d7e13e9b7..3aee7f13b 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -79,4 +79,4 @@ public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') { return strpos($haystack, $needle, $offset); } -} +} From 56d536f6990f736ddc0316c228033fbb128760a4 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 29 Nov 2012 21:09:12 +0100 Subject: [PATCH 27/63] StringUtils: MbString wrapper use of 'mb_list_encodings' --- src/StringWrapper/MbString.php | 102 +-------------------------------- 1 file changed, 2 insertions(+), 100 deletions(-) diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index 8331ba789..a17241228 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -23,83 +23,7 @@ class MbString extends AbstractStringWrapper * @var string[] * @link http://php.net/manual/mbstring.supported-encodings.php */ - protected $encodings = array( - 'UCS-4', - 'UCS-4BE', - 'UCS-4LE', - 'UCS-2', - 'UCS-2BE', - 'UCS-2LE', - 'UTF-32', - 'UTF-32BE', - 'UTF-32LE', - 'UTF-16', - 'UTF-16BE', - 'UTF-16LE', - 'UTF-7', - 'UTF7-IMAP', - 'UTF-8', - 'ASCII', - 'EUC-JP', - 'SJIS', - 'EUCJP-WIN', - 'SJIS-WIN', - 'ISO-2022-JP', - 'ISO-2022-JP-MS', - 'CP932', - 'CP51932', - 'SJIS-MAC', 'MACJAPANESE', - 'SJIS-Mobile#DOCOMO', 'SJIS-DOCOMO', - 'SJIS-Mobile#KDDI', 'SJIS-KDDI', - 'SJIS-Mobile#SOFTBANK', 'SJIS-SOFTBANK', - 'UTF-8-Mobile#DOCOMO', 'UTF-8-DOCOMO', - 'UTF-8-Mobile#KDDI-A', - 'UTF-8-Mobile#KDDI-B', 'UTF-8-KDDI', - 'UTF-8-Mobile#SOFTBANK', 'UTF-8-SOFTBANK', - 'ISO-2022-JP-MOBILE#KDDI', 'ISO-2022-JP-KDDI', - 'JIS', - 'JIS-MS', - 'CP50220', - 'CP50220RAW', - 'CP50221', - 'CP50222', - 'ISO-8859-1', - 'ISO-8859-2', - 'ISO-8859-3', - 'ISO-8859-4', - 'ISO-8859-5', - 'ISO-8859-6', - 'ISO-8859-7', - 'ISO-8859-8', - 'ISO-8859-9', - 'ISO-8859-10', - 'ISO-8859-13', - 'ISO-8859-14', - 'ISO-8859-15', - // 'ISO-8859-16', - 'bYTE2BE', - 'bYTE2LE', - 'BYTE4BE', - 'BYTE4LE', - 'BASE64', - 'HTML-ENTITIES', - '7BIT', - '8BIT', - 'EUC-CN', - 'CP936', - 'GB18030', - 'HZ', - 'EUC-TW', - 'CP950', - 'BIG-5', - 'EUC-KR', - 'UHC', 'CP949', - 'ISO-2022-KR', - 'WINDOWS-1251', 'CP1251', - 'WINDOWS-1252', 'CP1252', - 'CP866', 'IBM866', - 'KOI8-R', - ); + protected $encodings = array(); /** * Constructor @@ -114,29 +38,7 @@ public function __construct() ); } - // remove encodings not available before PHP-5.4 - if (version_compare(PHP_VERSION, '5.4', '<')) { - unset( - $this->encodings['SJIS-MAC'], - $this->encodings['MACJAPANESE'], - $this->encodings['SJIS-Mobile#DOCOMO'], - $this->encodings['SJIS-DOCOMO'], - $this->encodings['SJIS-Mobile#KDDI'], - $this->encodings['SJIS-KDDI'], - $this->encodings['SJIS-Mobile#SOFTBANK'], - $this->encodings['SJIS-SOFTBANK'], - $this->encodings['UTF-8-Mobile#DOCOMO'], - $this->encodings['UTF-8-DOCOMO'], - $this->encodings['UTF-8-Mobile#KDDI-A'], - $this->encodings['UTF-8-Mobile#KDDI-B'], - $this->encodings['UTF-8-KDDI'], - $this->encodings['UTF-8-Mobile#SOFTBANK'], - $this->encodings['UTF-8-SOFTBANK'], - $this->encodings['ISO-2022-JP-MOBILE#KDDI'], - $this->encodings['ISO-2022-JP-KDDI'], - $this->encodings['GB18030'] - ); - } + $this->encodings = array_map('strtoupper', mb_list_encodings()); } /** From 7cf106aae74d50aa56082c410ddf8fb7fb9a44a6 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 30 Nov 2012 09:16:08 +0100 Subject: [PATCH 28/63] FIXME: Converting the euro sign from UTF-8 to ISO-8859-16 using the mbstring extension gives a wrong result --- src/StringWrapper/Intl.php | 15 --------------- src/StringWrapper/MbString.php | 6 ++++++ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index e9c9ae9f5..81f154943 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -47,11 +47,6 @@ public function __construct() */ public function strlen($str, $encoding = 'UTF-8') { - if (strcasecmp($encoding, 'UTF-8') != 0) { - trigger_error("Character set '{$encoding}' not supported by intl"); - return false; - } - return grapheme_strlen($str); } @@ -66,11 +61,6 @@ public function strlen($str, $encoding = 'UTF-8') */ public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') { - if (strcasecmp($encoding, 'UTF-8') != 0) { - trigger_error("Character set '{$encoding}' not supported by intl"); - return false; - } - return grapheme_substr($str, $offset, $length); } @@ -85,11 +75,6 @@ public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') */ public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') { - if (strcasecmp($encoding, 'UTF-8') != 0) { - trigger_error("Character set '{$encoding}' not supported by intl"); - return false; - } - return grapheme_strpos($haystack, $needle, $offset); } } diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index a17241228..849f3abc5 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -39,6 +39,12 @@ public function __construct() } $this->encodings = array_map('strtoupper', mb_list_encodings()); + + // FIXME: Converting € (UTF-8) to ISO-8859-16 gives a wrong result + $indexIso885916 = array_search('ISO-8859-16', $this->encodings, true); + if ($indexIso885916 !== false) { + unset($this->encodings[$indexIso885916]); + } } /** From 8f2d7b25aa68a12c6d31451eb012f19dd1fda766 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 31 Dec 2012 16:33:37 +0100 Subject: [PATCH 29/63] Changed API to only check given encoding once and to better support the new Intl-UConverter of PHP 5.5 --- src/StringUtils.php | 57 ++--- src/StringWrapper/AbstractStringWrapper.php | 139 +++++++---- src/StringWrapper/Iconv.php | 34 ++- src/StringWrapper/Intl.php | 24 +- src/StringWrapper/MbString.php | 52 +++-- src/StringWrapper/Native.php | 22 +- src/StringWrapper/StringWrapperInterface.php | 40 ++-- .../StringWrapper/CommonStringWrapperTest.php | 217 ++++++++---------- test/StringWrapper/IconvTest.php | 16 +- test/StringWrapper/IntlTest.php | 16 +- test/StringWrapper/MbStringTest.php | 16 +- test/StringWrapper/NativeTest.php | 13 +- 12 files changed, 378 insertions(+), 268 deletions(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index 2b1b227e8..68ce89bed 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -11,10 +11,6 @@ namespace Zend\Stdlib; use Zend\Stdlib\StringWrapper\StringWrapperInterface; -use Zend\Stdlib\StringWrapper\MbString as MbStringWrapper; -use Zend\Stdlib\StringWrapper\Iconv as IconvWrapper; -use Zend\Stdlib\StringWrapper\Intl as IntlWrapper; -use Zend\Stdlib\StringWrapper\Native as NativeWrapper; /** * Utility class for handling strings of different character encodings @@ -50,9 +46,9 @@ abstract class StringUtils ); /** - * Get registered wrappers + * Get registered wrapper classes * - * @return StringWrapperInterface[] + * @return string[] */ public static function getRegisteredWrappers() { @@ -60,74 +56,71 @@ public static function getRegisteredWrappers() static::$wrapperRegistry = array(); if (extension_loaded('intl')) { - static::$wrapperRegistry[] = new IntlWrapper(); + static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Intl'; } if (extension_loaded('mbstring')) { - static::$wrapperRegistry[] = new MbStringWrapper(); + static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\MbString'; } if (extension_loaded('iconv')) { - static::$wrapperRegistry[] = new IconvWrapper(); + static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Iconv'; } - static::$wrapperRegistry[] = new NativeWrapper(); + static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Native'; } return static::$wrapperRegistry; } /** - * Register a string wrapper + * Register a string wrapper class * - * @param StringWrapperInterface + * @param string $wrapper * @return void */ - public static function registerWrapper(StringWrapperInterface $wrapper) + public static function registerWrapper($wrapper) { + $wrapper = (string) $wrapper; if (!in_array($wrapper, static::$wrapperRegistry, true)) { static::$wrapperRegistry[] = $wrapper; } } /** - * Unregister a string wrapper + * Unregister a string wrapper class * - * @param StringWrapperInterface $wrapper + * @param string $wrapper * @return void */ - public static function unregisterWrapper(StringWrapperInterface $wrapper) + public static function unregisterWrapper($wrapper) { - $index = array_search($wrapper, static::$wrapperRegistry, true); + $index = array_search((string) $wrapper, static::$wrapperRegistry, true); if ($index !== false) { unset(static::$wrapperRegistry[$index]); } } /** - * Get the first string wrapper supporting one or more character encodings + * Get the first string wrapper supporting the given character encoding + * and supports to convert into the given convert encoding. * - * @param string $encoding Character encoding supported by he string wrapper - * @param string $encodingN, ... Unlimited OPTIONAL number of additional character encodings + * @param string $encoding Character encoding to support + * @param string|null $convertEncoding OPTIONAL character encoding to convert in * @return StringWrapperInterface - * @throws Exception\RuntimeException If no wrapper supports all given character encodings + * @throws Exception\RuntimeException If no wrapper supports given character encodings */ - public static function getWrapper($encoding = 'UTF-8') + public static function getWrapper($encoding = 'UTF-8', $convertEncoding = null) { - $encodings = func_get_args(); - - foreach (static::getRegisteredWrappers() as $wrapper) { - foreach ($encodings as $encoding) { - if (!$wrapper->isEncodingSupported($encoding)) { - continue 2; - } + foreach (static::getRegisteredWrappers() as $wrapperClass) { + if ($wrapperClass::isSupported($encoding, $convertEncoding)) { + return new $wrapperClass($encoding, $convertEncoding); } - - return $wrapper; } throw new Exception\RuntimeException( - 'No wrapper found supporting encoding(s) ' . implode(', ', $encodings) + 'No wrapper found supporting "' . $encoding . '"' + . (($convertEncoding !== null) ? ' and "' . $convertEncoding . '"' : '') ); } diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index bd9e7713f..69a658f2a 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -20,51 +20,108 @@ */ abstract class AbstractStringWrapper implements StringWrapperInterface { + /** + * The character encoding working on + * @var string|null + */ + protected $encoding; /** - * List of supported character encodings (upper case) - * - * @var string[] + * An optionally character encoding to convert to + * @var string|null */ - protected $encodings = array(); + protected $convertEncoding; /** - * Check if the given character encoding is supported + * Check if the given character encoding is supported by this wrapper + * and the character encoding to convert to is also supported. * - * @param string $encoding - * @return boolean + * @param string $encoding + * @param string|null $convertEncoding + */ + public static function isSupported($encoding, $convertEncoding = null) + { + $supportedEncodings = static::getSupportedEncodings(); + + if (!in_array(strtoupper($encoding), $supportedEncodings)) { + return false; + } + + if ($convertEncoding !== null && !in_array(strtoupper($convertEncoding), $supportedEncodings)) { + return false; + } + + return true; + } + + /** + * Constructor + * @param string $encoding Character encoding working on + * @param string|null $convertEncoding Character encoding to convert to + * @throws Exception\InvalidArgumentException */ - public function isEncodingSupported($encoding) + public function __construct($encoding, $convertEncoding = null) { - return in_array(strtoupper($encoding), $this->encodings); + $this->setEncoding($encoding, $convertEncoding); } /** - * Get a list of supported character encodings + * Set character encoding working with and convert to * - * @return string[] + * @param string $encoding The character encoding to work with + * @param string|null $convertEncoding The character encoding to convert to + * @return StringWrapperInterface */ - public function getSupportedEncodings() + public function setEncoding($encoding, $convertEncoding) { - return $this->encodings; + $supportedEncodings = static::getSupportedEncodings(); + + $encodingUpper = strtoupper($encoding); + if (!in_array($encodingUpper, $supportedEncodings)) { + throw new Exception\InvalidArgumentException( + 'Wrapper doesn\'t support character encoding "' . $encoding . '"' + ); + } + + + if ($convertEncoding !== null) { + $convertEncodingUpper = strtoupper($convertEncoding); + if (!in_array($convertEncodingUpper, $supportedEncodings)) { + throw new Exception\InvalidArgumentException( + 'Wrapper doesn\'t support character encoding "' . $convertEncoding . '"' + ); + } + + $this->convertEncoding = $convertEncodingUpper; + } else { + $this->convertEncoding = null; + } + $this->encoding = $encodingUpper; + + return $this; } /** * Convert a string from one character encoding to another * - * @param string $str - * @param string $toEncoding - * @param string $fromEncoding + * @param string $str + * @param boolean $backward * @return string|false */ - public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') + public function convert($str, $backward = false) { - if (strcasecmp($toEncoding, $fromEncoding) != 0) { - trigger_error("Can't convert '{$fromEncoding}' to '{$toEncoding}'", \E_WARNING); - return false; + $from = $backward ? $this->convertEncoding : $this->encoding; + $to = $backward ? $this->encoding : $this->convertEncoding; + + if ($to == $from) { + return $str; } - return $str; + throw new Exception\RuntimeException(sprintf( + 'Converting from "%s" to "%s" isn\'t supported by this string wrapper', + $from, + $to + )); } /** @@ -74,10 +131,9 @@ public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') * @param integer $width * @param string $break * @param boolean $cut - * @param string $encoding * @return string|false */ - public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $encoding = 'UTF-8') + public function wordWrap($string, $width = 75, $break = "\n", $cut = false) { $string = (string) $string; if ($string === '') { @@ -95,27 +151,26 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $enc throw new Exception\InvalidArgumentException('Cannot force cut when width is zero'); } - $encoding = strtoupper($encoding); - if (StringUtils::isSingleByteEncoding($encoding)) { + if (StringUtils::isSingleByteEncoding($this->encoding)) { return wordwrap($string, $width, $break, $cut); } - $stringWidth = $this->strlen($string, $encoding); - $breakWidth = $this->strlen($break, $encoding); + $stringWidth = $this->strlen($string); + $breakWidth = $this->strlen($break); $result = ''; $lastStart = $lastSpace = 0; for ($current = 0; $current < $stringWidth; $current++) { - $char = $this->substr($string, $current, 1, $encoding); + $char = $this->substr($string, $current, 1); $possibleBreak = $char; if ($breakWidth !== 1) { - $possibleBreak = $this->substr($string, $current, $breakWidth, $encoding); + $possibleBreak = $this->substr($string, $current, $breakWidth); } if ($possibleBreak === $break) { - $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth, $encoding); + $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth); $current += $breakWidth - 1; $lastStart = $lastSpace = $current + 1; continue; @@ -123,7 +178,7 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $enc if ($char === ' ') { if ($current - $lastStart >= $width) { - $result .= $this->substr($string, $lastStart, $current - $lastStart, $encoding) . $break; + $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; $lastStart = $current + 1; } @@ -132,20 +187,20 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $enc } if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) { - $result .= $this->substr($string, $lastStart, $current - $lastStart, $encoding) . $break; + $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; $lastStart = $lastSpace = $current; continue; } if ($current - $lastStart >= $width && $lastStart < $lastSpace) { - $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart, $encoding) . $break; + $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break; $lastStart = $lastSpace = $lastSpace + 1; continue; } } if ($lastStart !== $current) { - $result .= $this->substr($string, $lastStart, $current - $lastStart, $encoding); + $result .= $this->substr($string, $lastStart, $current - $lastStart); } return $result; @@ -158,18 +213,16 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false, $enc * @param integer $padLength * @param string $padString * @param integer $padType - * @param string $encoding * @return string */ - public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT, $encoding = 'UTF-8') + public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT) { - $encoding = strtoupper($encoding); - if (StringUtils::isSingleByteEncoding($encoding)) { + if (StringUtils::isSingleByteEncoding($this->encoding)) { return str_pad($input, $padLength, $padString, $padType); } - $lengthOfPadding = $padLength - $this->strlen($input, $encoding); - $padStringLength = $this->strlen($padString, $encoding); + $lengthOfPadding = $padLength - $this->strlen($input); + $padStringLength = $this->strlen($padString); if ($padStringLength === 0 || $lengthOfPadding <= 0) { return $input; @@ -186,14 +239,14 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2); $lastStringRightLength += $lastStringLength % 2; - $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength, $encoding); - $lastStringRight = $this->substr($padString, 0, $lastStringRightLength, $encoding); + $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength); + $lastStringRight = $this->substr($padString, 0, $lastStringRightLength); return str_repeat($padString, $repeatCountLeft) . $lastStringLeft . $input . str_repeat($padString, $repeatCountRight) . $lastStringRight; } else { - $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength, $encoding); + $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength); if ($padType === \STR_PAD_LEFT) { return str_repeat($padString, $repeatCount) . $lastString . $input; diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 3c97ad083..f4982fb12 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -10,6 +10,8 @@ namespace Zend\Stdlib\StringWrapper; +use Zend\Stdlib\Exception; + /** * @category Zend * @package Zend_Stdlib @@ -23,7 +25,7 @@ class Iconv extends AbstractStringWrapper * @var string[] * @link http://www.gnu.org/software/libiconv/ */ - protected $encodings = array( + protected static $encodings = array( // European languages 'ASCII', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-7', @@ -114,18 +116,30 @@ class Iconv extends AbstractStringWrapper 'ATARIST', 'RISCOS-LATIN1', ); + /** + * Get a list of supported character encodings + * + * @return string[] + */ + public static function getSupportedEncodings() + { + return static::$encodings; + } + /** * Constructor * * @throws Exception\ExtensionNotLoadedException */ - public function __construct() + public function __construct($encoding, $convertEncoding = null) { if (!extension_loaded('iconv')) { throw new Exception\ExtensionNotLoadedException( 'PHP extension "iconv" is required for this wrapper' ); } + + parent::__construct($encoding, $convertEncoding); } /** @@ -135,9 +149,9 @@ public function __construct() * @param string $encoding * @return int|false */ - public function strlen($str, $encoding = 'UTF-8') + public function strlen($str) { - return iconv_strlen($str, $encoding); + return iconv_strlen($str, $this->encoding); } /** @@ -149,9 +163,9 @@ public function strlen($str, $encoding = 'UTF-8') * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') + public function substr($str, $offset = 0, $length = null) { - return iconv_substr($str, $offset, $length, $encoding); + return iconv_substr($str, $offset, $length, $this->encoding); } /** @@ -163,9 +177,9 @@ public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') + public function strpos($haystack, $needle, $offset = 0) { - return iconv_strpos($haystack, $needle, $offset, $encoding); + return iconv_strpos($haystack, $needle, $offset, $this->encoding); } /** @@ -176,8 +190,10 @@ public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') * @param string $fromEncoding * @return string|false */ - public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') + public function convert($str, $backword = false) { + $fromEncoding = $backword ? $this->convertEncoding : $this->encoding; + $toEncoding = $backword ? $this->encoding : $this->convertEncoding; return iconv($fromEncoding, $toEncoding, $str); } } diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index 81f154943..7b48accd6 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -10,6 +10,8 @@ namespace Zend\Stdlib\StringWrapper; +use Zend\Stdlib\Exception; + /** * @category Zend * @package Zend_Stdlib @@ -22,20 +24,32 @@ class Intl extends AbstractStringWrapper * * @var string[] */ - protected $encodings = array('UTF-8'); + protected static $encodings = array('UTF-8'); + + /** + * Get a list of supported character encodings + * + * @return string[] + */ + public static function getSupportedEncodings() + { + return static::$encodings; + } /** * Constructor * * @throws Exception\ExtensionNotLoadedException */ - public function __construct() + public function __construct($encoding, $convertEncoding = null) { if (!extension_loaded('intl')) { throw new Exception\ExtensionNotLoadedException( 'PHP extension "intl" is required for this wrapper' ); } + + parent::__construct($encoding, $convertEncoding); } /** @@ -45,7 +59,7 @@ public function __construct() * @param string $encoding * @return int|false */ - public function strlen($str, $encoding = 'UTF-8') + public function strlen($str) { return grapheme_strlen($str); } @@ -59,7 +73,7 @@ public function strlen($str, $encoding = 'UTF-8') * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') + public function substr($str, $offset = 0, $length = null) { return grapheme_substr($str, $offset, $length); } @@ -73,7 +87,7 @@ public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') + public function strpos($haystack, $needle, $offset = 0) { return grapheme_strpos($haystack, $needle, $offset); } diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index 849f3abc5..bf72a5a7c 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -10,6 +10,8 @@ namespace Zend\Stdlib\StringWrapper; +use Zend\Stdlib\Exception; + /** * @category Zend * @package Zend_Stdlib @@ -20,17 +22,37 @@ class MbString extends AbstractStringWrapper /** * List of supported character sets (upper case) * - * @var string[] + * @var null|string[] * @link http://php.net/manual/mbstring.supported-encodings.php */ - protected $encodings = array(); + protected static $encodings = null; + + /** + * Get a list of supported character encodings + * + * @return string[] + */ + public static function getSupportedEncodings() + { + if (static::$encodings === null) { + static::$encodings = array_map('strtoupper', mb_list_encodings()); + + // FIXME: Converting € (UTF-8) to ISO-8859-16 gives a wrong result + $indexIso885916 = array_search('ISO-8859-16', static::$encodings, true); + if ($indexIso885916 !== false) { + unset(static::$encodings[$indexIso885916]); + } + } + + return static::$encodings; + } /** * Constructor * * @throws Exception\ExtensionNotLoadedException */ - public function __construct() + public function __construct($encoding, $convertEncoding = null) { if (!extension_loaded('mbstring')) { throw new Exception\ExtensionNotLoadedException( @@ -38,13 +60,7 @@ public function __construct() ); } - $this->encodings = array_map('strtoupper', mb_list_encodings()); - - // FIXME: Converting € (UTF-8) to ISO-8859-16 gives a wrong result - $indexIso885916 = array_search('ISO-8859-16', $this->encodings, true); - if ($indexIso885916 !== false) { - unset($this->encodings[$indexIso885916]); - } + parent::__construct($encoding, $convertEncoding); } /** @@ -54,9 +70,9 @@ public function __construct() * @param string $encoding * @return int|false */ - public function strlen($str, $encoding = 'UTF-8') + public function strlen($str) { - return mb_strlen($str, $encoding); + return mb_strlen($str, $this->encoding); } /** @@ -68,9 +84,9 @@ public function strlen($str, $encoding = 'UTF-8') * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') + public function substr($str, $offset = 0, $length = null) { - return mb_substr($str, $offset, $length, $encoding); + return mb_substr($str, $offset, $length, $this->encoding); } /** @@ -82,9 +98,9 @@ public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') + public function strpos($haystack, $needle, $offset = 0) { - return mb_strpos($haystack, $needle, $offset, $encoding); + return mb_strpos($haystack, $needle, $offset, $this->encoding); } /** @@ -95,8 +111,10 @@ public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') * @param string $fromEncoding * @return string|false */ - public function convert($str, $toEncoding, $fromEncoding = 'UTF-8') + public function convert($str, $backword = false) { + $fromEncoding = $backword ? $this->convertEncoding : $this->encoding; + $toEncoding = $backword ? $this->encoding : $this->convertEncoding; return mb_convert_encoding($str, $toEncoding, $fromEncoding); } } diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index 3aee7f13b..69468bd69 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -19,23 +19,12 @@ */ class Native extends AbstractStringWrapper { - /** - * Check if the given encoding is supported - * - * @param string $encoding - * @return boolean - */ - public function isEncodingSupported($encoding) - { - return StringUtils::isSingleByteEncoding($encoding); - } - /** * Get a list of supported character encodings * * @return string[] */ - public function getSupportedEncodings() + public static function getSupportedEncodings() { return StringUtils::getSingleByteEncodings(); } @@ -44,10 +33,9 @@ public function getSupportedEncodings() * Returns the length of the given string * * @param string $str - * @param string $encoding * @return int|false */ - public function strlen($str, $encoding = 'UTF-8') + public function strlen($str) { return strlen($str); } @@ -58,10 +46,9 @@ public function strlen($str, $encoding = 'UTF-8') * @param string $str * @param int $offset * @param int|null $length - * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') + public function substr($str, $offset = 0, $length = null) { return substr($str, $offset, $length); } @@ -72,10 +59,9 @@ public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8') * @param string $haystack * @param string $needle * @param int $offset - * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8') + public function strpos($haystack, $needle, $offset = 0) { return strpos($haystack, $needle, $offset); } diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index f3f8ebe15..f99dbf73c 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -17,30 +17,37 @@ */ interface StringWrapperInterface { - /** - * Check if the given character encoding is supported + * Check if the given character encoding is supported by this wrapper + * and the character encoding to convert to is also supported. * - * @param string $encoding - * @return boolean + * @param string $encoding + * @param string|null $convertEncoding */ - public function isEncodingSupported($encoding); + public static function isSupported($encoding, $convertEncoding = null); /** * Get a list of supported character encodings * * @return string[] */ - public function getSupportedEncodings(); + public static function getSupportedEncodings(); + + /** + * Constructor + * + * @param string $encoding Character encoding working on + * @param string|null $convertEncoding Character encoding to convert to + */ + public function __construct($encoding, $convertEncoding = null); /** * Returns the length of the given string * * @param string $str - * @param string $encoding * @return int|false */ - public function strlen($str, $encoding = 'UTF-8'); + public function strlen($str); /** * Returns the portion of string specified by the start and length parameters @@ -51,7 +58,7 @@ public function strlen($str, $encoding = 'UTF-8'); * @param string $encoding * @return string|false */ - public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8'); + public function substr($str, $offset = 0, $length = null); /** * Find the position of the first occurrence of a substring in a string @@ -62,17 +69,16 @@ public function substr($str, $offset = 0, $length = null, $encoding = 'UTF-8'); * @param string $encoding * @return int|false */ - public function strpos($haystack, $needle, $offset = 0, $encoding = 'UTF-8'); + public function strpos($haystack, $needle, $offset = 0); /** * Convert a string from one character encoding to another * - * @param string $str - * @param string $toEncoding - * @param string $fromEncoding + * @param string $str + * @param boolean $backward * @return string|false */ - public function convert($str, $toEncoding, $fromEncoding = 'UTF-8'); + public function convert($str, $backward = false); /** * Wraps a string to a given number of characters @@ -81,10 +87,9 @@ public function convert($str, $toEncoding, $fromEncoding = 'UTF-8'); * @param integer $width * @param string $break * @param boolean $cut - * @param string $encoding * @return string */ - public function wordWrap($str, $width = 75, $break = "\n", $cut = false, $encoding = 'UTF-8'); + public function wordWrap($str, $width = 75, $break = "\n", $cut = false); /** * Pad a string to a certain length with another string @@ -93,8 +98,7 @@ public function wordWrap($str, $width = 75, $break = "\n", $cut = false, $encodi * @param integer $padLength * @param string $padString * @param integer $padType - * @param string $encoding * @return string */ - public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT, $encoding = 'UTF-8'); + public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT); } diff --git a/test/StringWrapper/CommonStringWrapperTest.php b/test/StringWrapper/CommonStringWrapperTest.php index 4f606a1ae..6bea2a0d6 100644 --- a/test/StringWrapper/CommonStringWrapperTest.php +++ b/test/StringWrapper/CommonStringWrapperTest.php @@ -17,286 +17,269 @@ abstract class CommonStringWrapperTest extends TestCase { - - /** - * An instance of the string wrapper to test - * @StringWrapperInterface - */ - protected $stringWrapper; - - public function setUp() - { - if ( !($this->stringWrapper instanceof StringWrapperInterface) ) { - $this->fail(sprintf( - "%s isn't an instance of %s", - get_class($this) . '::stringWrapper', - 'Zend\Stdlib\StringWrapper\StringWrapperInterface' - )); - } - } + abstract protected function getWrapper($encoding = null, $convertEncoding = null); public function strlenProvider() { return array( - array('abcdefghijklmnopqrstuvwxyz', 'ascii', 26), - array('abcdefghijklmnopqrstuvwxyz', 'utf-8', 26), - array('äöüß', 'utf-8', 4), + array('ascii', 'abcdefghijklmnopqrstuvwxyz', 26), + array('utf-8', 'abcdefghijklmnopqrstuvwxyz', 26), + array('utf-8', 'äöüß', 4), ); } /** * @dataProvider strlenProvider - * @param string $string * @param string $encoding + * @param string $string * @param mixed $expected */ - public function testStrlen($str, $encoding, $expected) + public function testStrlen($encoding, $str, $expected) { - if (!$this->stringWrapper->isEncodingSupported($encoding)) { - $this->markTestSkipped( - "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) - ); + $wrapper = $this->getWrapper($encoding); + if (!$wrapper) { + $this->markTestSkipped("Encoding {$encoding} not supported"); } - $result = $this->stringWrapper->strlen($str, $encoding); + $result = $wrapper->strlen($str); $this->assertSame($expected, $result); } public function substrProvider() { return array( - array('abcdefghijkl', 1, 5, 'ascii', 'bcdef'), - array('abcdefghijkl', 1, 5, 'utf-8', 'bcdef'), - array('äöüß', 1, 2, 'utf-8', 'öü'), + array('ascii', 'abcdefghijkl', 1, 5, 'bcdef'), + array('utf-8', 'abcdefghijkl', 1, 5, 'bcdef'), + array('utf-8', 'äöüß', 1, 2, 'öü'), ); } /** * @dataProvider substrProvider + * @param string $encoding * @param string $str * @param int $offset * @param int|null $length - * @param string $encoding * @param mixed $expected */ - public function testSubstr($str, $offset, $length, $encoding, $expected) + public function testSubstr($encoding, $str, $offset, $length, $expected) { - if (!$this->stringWrapper->isEncodingSupported($encoding)) { - $this->markTestSkipped( - "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) - ); + $wrapper = $this->getWrapper($encoding); + if (!$wrapper) { + $this->markTestSkipped("Encoding {$encoding} not supported"); } - $result = $this->stringWrapper->substr($str, $offset, $length, $encoding); + $result = $wrapper->substr($str, $offset, $length); $this->assertSame($expected, $result); } public function strposProvider() { return array( - array('abcdefghijkl', 'g', 3, 'ascii', 6), - array('abcdefghijkl', 'g', 3, 'utf-8', 6), - array('äöüß', 'ü', 1, 'utf-8', 2), + array('ascii', 'abcdefghijkl', 'g', 3, 6), + array('utf-8', 'abcdefghijkl', 'g', 3, 6), + array('utf-8', 'äöüß', 'ü', 1, 2), ); } /** * @dataProvider strposProvider + * @param string $encoding * @param string $haystack * @param string $needle * @param int $offset - * @param string $encoding * @param mixed $expected */ - public function testStrpos($haystack, $needle, $offset, $encoding, $expected) + public function testStrpos($encoding, $haystack, $needle, $offset, $expected) { - if (!$this->stringWrapper->isEncodingSupported($encoding)) { - $this->markTestSkipped( - "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) - ); + $wrapper = $this->getWrapper($encoding); + if (!$wrapper) { + $this->markTestSkipped("Encoding {$encoding} not supported"); } - $result = $this->stringWrapper->strpos($haystack, $needle, $offset, $encoding); + $result = $wrapper->strpos($haystack, $needle, $offset); $this->assertSame($expected, $result); } public function convertProvider() { return array( - array('abc', 'ascii', 'ascii', 'abc'), - array('abc', 'utf-8', 'ascii', 'abc'), - array('abc', 'ascii', 'utf-8', 'abc'), - array('€', 'iso-8859-15', 'utf-8', "\xA4"), - array('€', 'iso-8859-16', 'utf-8', "\xA4"), // ISO-8859-16 is wrong @ mbstring + array('ascii', 'ascii', 'abc', 'abc'), + array('ascii', 'utf-8', 'abc', 'abc'), + array('utf-8', 'ascii', 'abc', 'abc'), + array('utf-8', 'iso-8859-15', '€', "\xA4"), + array('utf-8', 'iso-8859-16', '€', "\xA4"), // ISO-8859-16 is wrong @ mbstring ); } /** * @dataProvider convertProvider * @param string $str - * @param string $toEncoding - * @param string $fromEncoding + * @param string $encoding + * @param string $convertEncoding * @param mixed $expected */ - public function testConvert($str, $toEncoding, $fromEncoding, $expected) + public function testConvert($encoding, $convertEncoding, $str, $expected) { - if (!$this->stringWrapper->isEncodingSupported($toEncoding)) { - $this->markTestSkipped( - "Encoding {$toEncoding} not supported by " . get_class($this->stringWrapper) - ); - } elseif (!$this->stringWrapper->isEncodingSupported($fromEncoding)) { - $this->markTestSkipped( - "Encoding {$fromEncoding} not supported by " . get_class($this->stringWrapper) - ); + $wrapper = $this->getWrapper($encoding, $convertEncoding); + if (!$wrapper) { + $this->markTestSkipped("Encoding {$encoding} or {$convertEncoding} not supported"); } - $result = $this->stringWrapper->convert($str, $toEncoding, $fromEncoding); + $result = $wrapper->convert($str); $this->assertSame($expected, $result); + + // backword + $result = $wrapper->convert($expected, true); + $this->assertSame($str, $result); } public function wordWrapProvider() { return array( // Standard cut tests - array('äbüöcß', 2, ' ', true, 'utf-8', + array('utf-8', 'äbüöcß', 2, ' ', true, 'äb üö cß'), - array('äbüöc ß äbüöcß', 2, ' ', true, 'utf-8', + array('utf-8', 'äbüöc ß äbüöcß', 2, ' ', true, 'äb üö c ß äb üö cß'), - array('Ä very long wöööööööööööörd.', 8, "\n", true, 'utf-8', + array('utf-8', 'Ä very long wöööööööööööörd.', 8, "\n", true, "Ä very\nlong\nwööööööö\nööööörd."), - array("Ä very\nlong wöööööööööööörd.", 8, "\n", false, 'utf-8', + array('utf-8', "Ä very\nlong wöööööööööööörd.", 8, "\n", false, "Ä very\nlong\nwöööööööööööörd."), - array("Ä very
long wöö
öööööööö
öörd.", 8, '
', false, 'utf-8', + array('utf-8', "Ä very
long wöö
öööööööö
öörd.", 8, '
', false, "Ä very
long wöö
öööööööö
öörd."), // Alternative cut tests - array(' äüöäöü', 3, ' ', true, 'utf-8', + array('utf-8', ' äüöäöü', 3, ' ', true, ' äüö äöü'), - array('äüöäöü ', 3, ' ', true, 'utf-8', + array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), - array('äöüäöü ', 3, '-', true, 'utf-8', + array('utf-8', 'äöüäöü ', 3, '-', true, 'äöü-äöü-'), - array('äüöäöü ', 3, ' ', true, 'utf-8', + array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), - array('12345 ', 5, '-', false, 'utf-8', + array('utf-8', '12345 ', 5, '-', false, '12345-'), - array('12345 ', 5, '-', false, 'utf-8', + array('utf-8', '12345 ', 5, '-', false, '12345- '), - array('äüöäöü ', 3, ' ', true, 'utf-8', + array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), - array('äüöäöü--', 3, '-', true, 'utf-8', + array('utf-8', 'äüöäöü--', 3, '-', true, 'äüö-äöü--'), - array("äbü\töcß", 3, ' ', true, 'utf-8', + array('utf-8', "äbü\töcß", 3, ' ', true, "äbü \töc ß"), - array("äbü\nößt", 3, ' ', true, 'utf-8', + array('utf-8', "äbü\nößt", 3, ' ', true, "äbü \nöß t"), - array("äbü\nößte", 3, "\n", true, 'utf-8', + array('utf-8', "äbü\nößte", 3, "\n", true, "äbü\nößt\ne"), // Break cut tests - array('foobar-foofoofoo', 8, '-', true, 'ascii', + array('ascii', 'foobar-foofoofoo', 8, '-', true, 'foobar-foofoofo-o'), - array('foobar-foobar', 6, '-', true, 'ascii', + array('ascii', 'foobar-foobar', 6, '-', true, 'foobar-foobar'), - array('foobar-foobar', 7, '-', true, 'ascii', + array('ascii', 'foobar-foobar', 7, '-', true, 'foobar-foobar'), - array('foobar-', 7, '-', true, 'ascii', + array('ascii', 'foobar-', 7, '-', true, 'foobar-'), - array('foobar-foobar', 5, '-', true, 'ascii', + array('ascii', 'foobar-foobar', 5, '-', true, 'fooba-r-fooba-r'), // Standard no-cut tests - array('äbüöcß', 2, ' ', false, 'utf-8', + array('utf-8', 'äbüöcß', 2, ' ', false, 'äbüöcß'), - array('äbüöc ß äbüöcß', 2, "\n", false, 'utf-8', + array('utf-8', 'äbüöc ß äbüöcß', 2, "\n", false, "äbüöc\nß\näbüöcß"), - array('äöü äöü äöü', 5, "\n", false, 'utf-8', + array('utf-8', 'äöü äöü äöü', 5, "\n", false, "äöü\näöü\näöü"), // Break no-cut tests - array('foobar-foofoofoo', 8, '-', false, 'ascii', + array('ascii', 'foobar-foofoofoo', 8, '-', false, 'foobar-foofoofoo'), - array('foobar-foobar', 6, '-', false, 'ascii', + array('ascii', 'foobar-foobar', 6, '-', false, 'foobar-foobar'), - array('foobar-foobar', 7, '-', false, 'ascii', + array('ascii', 'foobar-foobar', 7, '-', false, 'foobar-foobar'), - array('foobar-', 7, '-', false, 'ascii', + array('ascii', 'foobar-', 7, '-', false, 'foobar-'), - array('foobar-foobar', 5, '-', false, 'ascii', + array('ascii', 'foobar-foobar', 5, '-', false, 'foobar-foobar'), ); } /** * @dataProvider wordWrapProvider + * @param string $encoding * @param string $str * @param integer $width * @param string $break * @param boolean $cut - * @param string $encoding * @param mixed $expected */ - public function testWordWrap($string, $width, $break, $cut, $encoding, $expected) + public function testWordWrap($encoding, $string, $width, $break, $cut, $expected) { - if (!$this->stringWrapper->isEncodingSupported($encoding)) { - $this->markTestSkipped( - "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) - ); + $wrapper = $this->getWrapper($encoding); + if (!$wrapper) { + $this->markTestSkipped("Encoding {$encoding} not supported"); } - $result = $this->stringWrapper->wordWrap($string, $width, $break, $cut, $encoding); + $result = $wrapper->wordWrap($string, $width, $break, $cut); $this->assertSame($expected, $result); } public function testWordWrapInvalidArgument() { + $wrapper = $this->getWrapper(); + if (!$wrapper) { + $this->fail("Can't instantiate wrapper"); + } + $this->setExpectedException( 'Zend\Stdlib\Exception\InvalidArgumentException', "Cannot force cut when width is zero" ); - $this->stringWrapper->wordWrap('a', 0, "\n", true); + $wrapper->wordWrap('a', 0, "\n", true); } public function strPadProvider() { return array( // single-byte - array('aaa', 5, 'o', STR_PAD_LEFT, 'ascii', 'ooaaa'), - array('aaa', 6, 'o', STR_PAD_BOTH, 'ascii', 'oaaaoo'), - array('aaa', 5, 'o', STR_PAD_RIGHT, 'ascii', 'aaaoo'), + array('ascii', 'aaa', 5, 'o', STR_PAD_LEFT, 'ooaaa'), + array('ascii', 'aaa', 6, 'o', STR_PAD_BOTH, 'oaaaoo'), + array('ascii', 'aaa', 5, 'o', STR_PAD_RIGHT, 'aaaoo'), // multi-byte - array('äää', 5, 'ö', STR_PAD_LEFT, 'utf-8', 'ööäää'), - array('äää', 6, 'ö', STR_PAD_BOTH, 'utf-8', 'öäääöö'), - array('äää', 5, 'ö', STR_PAD_RIGHT, 'utf-8', 'äääöö'), + array('utf-8', 'äää', 5, 'ö', STR_PAD_LEFT, 'ööäää'), + array('utf-8', 'äää', 6, 'ö', STR_PAD_BOTH, 'öäääöö'), + array('utf-8', 'äää', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), // ZF-12186 - array('äääöö', 2, 'ö', STR_PAD_RIGHT, 'utf-8', 'äääöö'), // PadInputLongerThanPadLength - array('äääöö', 5, 'ö', STR_PAD_RIGHT, 'utf-8', 'äääöö'), // PadInputSameAsPadLength - array('äääöö', -2, 'ö', STR_PAD_RIGHT, 'utf-8', 'äääöö'), // PadNegativePadLength + array('utf-8', 'äääöö', 2, 'ö', STR_PAD_RIGHT, 'äääöö'), // PadInputLongerThanPadLength + array('utf-8', 'äääöö', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), // PadInputSameAsPadLength + array('utf-8', 'äääöö', -2, 'ö', STR_PAD_RIGHT, 'äääöö'), // PadNegativePadLength ); } /** * @dataProvider strPadProvider + * @param string $encoding * @param string $input * @param integer $padLength * @param string $padString * @param integer $padType - * @param string $encoding * @param mixed $expected * * @group ZF-12186 */ - public function testStrPad($input, $padLength, $padString, $padType, $encoding, $expected) + public function testStrPad($encoding, $input, $padLength, $padString, $padType, $expected) { - if (!$this->stringWrapper->isEncodingSupported($encoding)) { - $this->markTestSkipped( - "Encoding {$encoding} not supported by " . get_class($this->stringWrapper) - ); + $wrapper = $this->getWrapper($encoding); + if (!$wrapper) { + $this->markTestSkipped("Encoding {$encoding} not supported"); } - $result = $this->stringWrapper->strPad($input, $padLength, $padString, $padType, $encoding); + $result = $wrapper->strPad($input, $padLength, $padString, $padType); $this->assertSame($expected, $result); } } diff --git a/test/StringWrapper/IconvTest.php b/test/StringWrapper/IconvTest.php index 92a83e1c6..b1f3a0bba 100644 --- a/test/StringWrapper/IconvTest.php +++ b/test/StringWrapper/IconvTest.php @@ -21,14 +21,26 @@ public function setUp() { if (!extension_loaded('iconv')) { try { - new Iconv(); + new Iconv('utf-8'); $this->fail('Missing expected Zend\Stdlib\Exception\ExtensionNotLoadedException'); } catch (Exception\ExtensionNotLoadedException $e) { $this->markTestSkipped('Missing ext/iconv'); } } - $this->stringWrapper = new Iconv(); parent::setUp(); } + + protected function getWrapper($encoding = null, $convertEncoding = null) + { + if ($encoding === null) { + $supportedEncodings = Iconv::getSupportedEncodings(); + $encoding = array_shift($supportedEncodings); + } + + if (!Iconv::isSupported($encoding, $convertEncoding)) { + return false; + } + return new Iconv($encoding, $convertEncoding); + } } diff --git a/test/StringWrapper/IntlTest.php b/test/StringWrapper/IntlTest.php index f764b3d98..ab2ae0402 100644 --- a/test/StringWrapper/IntlTest.php +++ b/test/StringWrapper/IntlTest.php @@ -21,14 +21,26 @@ public function setUp() { if (!extension_loaded('intl')) { try { - new Intl(); + new Intl('utf-8'); $this->fail('Missing expected Zend\Stdlib\Exception\ExtensionNotLoadedException'); } catch (Exception\ExtensionNotLoadedException $e) { $this->markTestSkipped('Missing ext/intl'); } } - $this->stringWrapper = new Intl(); parent::setUp(); } + + protected function getWrapper($encoding = null, $convertEncoding = null) + { + if ($encoding === null) { + $supportedEncodings = Intl::getSupportedEncodings(); + $encoding = array_shift($supportedEncodings); + } + + if (!Intl::isSupported($encoding, $convertEncoding)) { + return false; + } + return new Intl($encoding, $convertEncoding); + } } diff --git a/test/StringWrapper/MbStringTest.php b/test/StringWrapper/MbStringTest.php index bd6ee7aec..fe4a5500d 100644 --- a/test/StringWrapper/MbStringTest.php +++ b/test/StringWrapper/MbStringTest.php @@ -21,14 +21,26 @@ public function setUp() { if (!extension_loaded('mbstring')) { try { - new MbString(); + new MbString('utf-8'); $this->fail('Missing expected Zend\Stdlib\Exception\ExtensionNotLoadedException'); } catch (Exception\ExtensionNotLoadedException $e) { $this->markTestSkipped('Missing ext/mbstring'); } } - $this->stringWrapper = new MbString(); parent::setUp(); } + + protected function getWrapper($encoding = null, $convertEncoding = null) + { + if ($encoding === null) { + $supportedEncodings = MbString::getSupportedEncodings(); + $encoding = array_shift($supportedEncodings); + } + + if (!MbString::isSupported($encoding, $convertEncoding)) { + return false; + } + return new MbString($encoding, $convertEncoding); + } } diff --git a/test/StringWrapper/NativeTest.php b/test/StringWrapper/NativeTest.php index 329a19ba3..8f3b64ccd 100644 --- a/test/StringWrapper/NativeTest.php +++ b/test/StringWrapper/NativeTest.php @@ -16,9 +16,16 @@ class NativeTest extends CommonStringWrapperTest { - public function setUp() + protected function getWrapper($encoding = null, $convertEncoding = null) { - $this->stringWrapper = new Native(); - parent::setUp(); + if ($encoding === null) { + $supportedEncodings = Native::getSupportedEncodings(); + $encoding = array_shift($supportedEncodings); + } + + if (!Native::isSupported($encoding, $convertEncoding)) { + return false; + } + return new Native($encoding, $convertEncoding); } } From fcc4099982a634221ffcfc2b5d3b65e765e5278a Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 31 Dec 2012 17:50:03 +0100 Subject: [PATCH 30/63] Updated consumers after API changes --- src/StringWrapper/AbstractStringWrapper.php | 2 +- src/StringWrapper/StringWrapperInterface.php | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 69a658f2a..89ad28ce6 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -72,7 +72,7 @@ public function __construct($encoding, $convertEncoding = null) * @param string|null $convertEncoding The character encoding to convert to * @return StringWrapperInterface */ - public function setEncoding($encoding, $convertEncoding) + public function setEncoding($encoding, $convertEncoding = null) { $supportedEncodings = static::getSupportedEncodings(); diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index f99dbf73c..bba34fe23 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -41,6 +41,15 @@ public static function getSupportedEncodings(); */ public function __construct($encoding, $convertEncoding = null); + /** + * Set character encoding working with and convert to + * + * @param string $encoding The character encoding to work with + * @param string|null $convertEncoding The character encoding to convert to + * @return StringWrapperInterface + */ + public function setEncoding($encoding, $convertEncoding = null); + /** * Returns the length of the given string * From 3f8e987db50fba3a6c403639f9130ddbdeaf8778 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Wed, 2 Jan 2013 18:34:32 +0100 Subject: [PATCH 31/63] It's 2013 --- src/StringUtils.php | 2 +- src/StringWrapper/AbstractStringWrapper.php | 2 +- src/StringWrapper/Iconv.php | 2 +- src/StringWrapper/Intl.php | 2 +- src/StringWrapper/MbString.php | 2 +- src/StringWrapper/Native.php | 2 +- src/StringWrapper/StringWrapperInterface.php | 2 +- test/StringUtilsTest.php | 2 +- test/StringWrapper/CommonStringWrapperTest.php | 2 +- test/StringWrapper/IconvTest.php | 2 +- test/StringWrapper/IntlTest.php | 2 +- test/StringWrapper/MbStringTest.php | 2 +- test/StringWrapper/NativeTest.php | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index 68ce89bed..031800b70 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib */ diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 89ad28ce6..4b4e8544c 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib */ diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index f4982fb12..946624474 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib */ diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index 7b48accd6..3669e002b 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib */ diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index bf72a5a7c..4ae1f1b1c 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib */ diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index 69468bd69..0f26fcb08 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib */ diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index bba34fe23..35467cef0 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib */ diff --git a/test/StringUtilsTest.php b/test/StringUtilsTest.php index 156431dde..fefed5807 100644 --- a/test/StringUtilsTest.php +++ b/test/StringUtilsTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib */ diff --git a/test/StringWrapper/CommonStringWrapperTest.php b/test/StringWrapper/CommonStringWrapperTest.php index 6bea2a0d6..5ae04708a 100644 --- a/test/StringWrapper/CommonStringWrapperTest.php +++ b/test/StringWrapper/CommonStringWrapperTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib * @subpackage StringWrapper diff --git a/test/StringWrapper/IconvTest.php b/test/StringWrapper/IconvTest.php index b1f3a0bba..2819b6b00 100644 --- a/test/StringWrapper/IconvTest.php +++ b/test/StringWrapper/IconvTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib * @subpackage StringWrapper diff --git a/test/StringWrapper/IntlTest.php b/test/StringWrapper/IntlTest.php index ab2ae0402..efa3fdddb 100644 --- a/test/StringWrapper/IntlTest.php +++ b/test/StringWrapper/IntlTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib * @subpackage StringWrapper diff --git a/test/StringWrapper/MbStringTest.php b/test/StringWrapper/MbStringTest.php index fe4a5500d..01f332bee 100644 --- a/test/StringWrapper/MbStringTest.php +++ b/test/StringWrapper/MbStringTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib * @subpackage StringWrapper diff --git a/test/StringWrapper/NativeTest.php b/test/StringWrapper/NativeTest.php index 8f3b64ccd..9a3716dbd 100644 --- a/test/StringWrapper/NativeTest.php +++ b/test/StringWrapper/NativeTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License * @package Zend_Stdlib * @subpackage StringWrapper From f3be23de92d016517212cb12133502d867d7b0b7 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 3 Jan 2013 15:23:07 +0100 Subject: [PATCH 32/63] else isn't needed, as the previous block returns on completion + removed call to strlen if length of padding is less than or equal 0 --- src/StringWrapper/AbstractStringWrapper.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 4b4e8544c..eebf006fa 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -222,9 +222,12 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD } $lengthOfPadding = $padLength - $this->strlen($input); - $padStringLength = $this->strlen($padString); + if ($lengthOfPadding <= 0) { + return $input; + } - if ($padStringLength === 0 || $lengthOfPadding <= 0) { + $padStringLength = $this->strlen($padString); + if ($padStringLength === 0) { return $input; } @@ -245,14 +248,14 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD return str_repeat($padString, $repeatCountLeft) . $lastStringLeft . $input . str_repeat($padString, $repeatCountRight) . $lastStringRight; - } else { - $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength); + } - if ($padType === \STR_PAD_LEFT) { - return str_repeat($padString, $repeatCount) . $lastString . $input; - } else { - return $input . str_repeat($padString, $repeatCount) . $lastString; - } + $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength); + + if ($padType === \STR_PAD_LEFT) { + return str_repeat($padString, $repeatCount) . $lastString . $input; } + + return $input . str_repeat($padString, $repeatCount) . $lastString; } } From 4e9d332c137ca52dd626eedfb83644d3da13a520 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 3 Jan 2013 15:41:34 +0100 Subject: [PATCH 33/63] StringWrapper::convert() Renamed second argument to and fixed phpdoc --- src/StringWrapper/AbstractStringWrapper.php | 11 +++++------ src/StringWrapper/Iconv.php | 11 +++++------ src/StringWrapper/MbString.php | 11 +++++------ src/StringWrapper/StringWrapperInterface.php | 4 ++-- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index eebf006fa..2f3bc1feb 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -105,18 +105,17 @@ public function setEncoding($encoding, $convertEncoding = null) * Convert a string from one character encoding to another * * @param string $str - * @param boolean $backward + * @param boolean $reverse * @return string|false */ - public function convert($str, $backward = false) + public function convert($str, $reverse = false) { - $from = $backward ? $this->convertEncoding : $this->encoding; - $to = $backward ? $this->encoding : $this->convertEncoding; - - if ($to == $from) { + if ($this->encoding === $this->convertEncoding) { return $str; } + $from = $reverse ? $this->convertEncoding : $this->encoding; + $to = $reverse ? $this->encoding : $this->convertEncoding; throw new Exception\RuntimeException(sprintf( 'Converting from "%s" to "%s" isn\'t supported by this string wrapper', $from, diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 946624474..abbecbd02 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -185,15 +185,14 @@ public function strpos($haystack, $needle, $offset = 0) /** * Convert a string from one character encoding to another * - * @param string $str - * @param string $toEncoding - * @param string $fromEncoding + * @param string $str + * @param boolean $reverse * @return string|false */ - public function convert($str, $backword = false) + public function convert($str, $reverse = false) { - $fromEncoding = $backword ? $this->convertEncoding : $this->encoding; - $toEncoding = $backword ? $this->encoding : $this->convertEncoding; + $fromEncoding = $reverse ? $this->convertEncoding : $this->encoding; + $toEncoding = $reverse ? $this->encoding : $this->convertEncoding; return iconv($fromEncoding, $toEncoding, $str); } } diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index 4ae1f1b1c..72af7fe84 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -106,15 +106,14 @@ public function strpos($haystack, $needle, $offset = 0) /** * Convert a string from one character encoding to another * - * @param string $str - * @param string $toEncoding - * @param string $fromEncoding + * @param string $str + * @param boolean $reverse * @return string|false */ - public function convert($str, $backword = false) + public function convert($str, $reverse = false) { - $fromEncoding = $backword ? $this->convertEncoding : $this->encoding; - $toEncoding = $backword ? $this->encoding : $this->convertEncoding; + $fromEncoding = $reverse ? $this->convertEncoding : $this->encoding; + $toEncoding = $reverse ? $this->encoding : $this->convertEncoding; return mb_convert_encoding($str, $toEncoding, $fromEncoding); } } diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index 35467cef0..f0251d16f 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -84,10 +84,10 @@ public function strpos($haystack, $needle, $offset = 0); * Convert a string from one character encoding to another * * @param string $str - * @param boolean $backward + * @param boolean $reverse * @return string|false */ - public function convert($str, $backward = false); + public function convert($str, $reverse = false); /** * Wraps a string to a given number of characters From b19de9b20b99646fee11d5da83b5eca290df0287 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 3 Jan 2013 15:45:36 +0100 Subject: [PATCH 34/63] phpdoc --- src/StringWrapper/AbstractStringWrapper.php | 2 +- src/StringWrapper/Iconv.php | 2 +- src/StringWrapper/MbString.php | 2 +- src/StringWrapper/StringWrapperInterface.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 2f3bc1feb..9613f372a 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -102,7 +102,7 @@ public function setEncoding($encoding, $convertEncoding = null) } /** - * Convert a string from one character encoding to another + * Convert a string from defined encoding to the defined convert encoding * * @param string $str * @param boolean $reverse diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index abbecbd02..d1aaa03ac 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -183,7 +183,7 @@ public function strpos($haystack, $needle, $offset = 0) } /** - * Convert a string from one character encoding to another + * Convert a string from defined encoding to the defined convert encoding * * @param string $str * @param boolean $reverse diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index 72af7fe84..8d8d49a75 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -104,7 +104,7 @@ public function strpos($haystack, $needle, $offset = 0) } /** - * Convert a string from one character encoding to another + * Convert a string from defined encoding to the defined convert encoding * * @param string $str * @param boolean $reverse diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index f0251d16f..4dc133fb1 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -81,7 +81,7 @@ public function substr($str, $offset = 0, $length = null); public function strpos($haystack, $needle, $offset = 0); /** - * Convert a string from one character encoding to another + * Convert a string from defined encoding to the defined convert encoding * * @param string $str * @param boolean $reverse From 0c8aeba1e5cf8b79fef4dd418863522a8ef86ed9 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 3 Jan 2013 16:19:24 +0100 Subject: [PATCH 35/63] The native string wrapper doesn't support to convert between encodings --- src/StringWrapper/AbstractStringWrapper.php | 3 +- src/StringWrapper/Native.php | 63 +++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 9613f372a..50621cd03 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -102,7 +102,7 @@ public function setEncoding($encoding, $convertEncoding = null) } /** - * Convert a string from defined encoding to the defined convert encoding + * Convert a string from defined character encoding to the defined convert encoding * * @param string $str * @param boolean $reverse @@ -114,6 +114,7 @@ public function convert($str, $reverse = false) return $str; } + var_dump($this->encoding, $this->convertEncoding); $from = $reverse ? $this->convertEncoding : $this->encoding; $to = $reverse ? $this->encoding : $this->convertEncoding; throw new Exception\RuntimeException(sprintf( diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index 0f26fcb08..8ddcf3d6c 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -10,6 +10,7 @@ namespace Zend\Stdlib\StringWrapper; +use Zend\Stdlib\Exception; use Zend\Stdlib\StringUtils; /** @@ -19,6 +20,30 @@ */ class Native extends AbstractStringWrapper { + /** + * Check if the given character encoding is supported by this wrapper + * and the character encoding to convert to is also supported. + * + * @param string $encoding + * @param string|null $convertEncoding + */ + public static function isSupported($encoding, $convertEncoding = null) + { + $encodingUpper = strtoupper($encoding); + $supportedEncodings = static::getSupportedEncodings(); + + if (!in_array($encodingUpper, $supportedEncodings)) { + return false; + } + + // This adapter doesn't support to convert between encodings + if ($convertEncoding !== null && $encodingUpper !== strtoupper($convertEncoding)) { + return false; + } + + return true; + } + /** * Get a list of supported character encodings * @@ -29,6 +54,44 @@ public static function getSupportedEncodings() return StringUtils::getSingleByteEncodings(); } + /** + * Set character encoding working with and convert to + * + * @param string $encoding The character encoding to work with + * @param string|null $convertEncoding The character encoding to convert to + * @return StringWrapperInterface + */ + public function setEncoding($encoding, $convertEncoding = null) + { + $supportedEncodings = static::getSupportedEncodings(); + + $encodingUpper = strtoupper($encoding); + if (!in_array($encodingUpper, $supportedEncodings)) { + throw new Exception\InvalidArgumentException( + 'Wrapper doesn\'t support character encoding "' . $encoding . '"' + ); + } + + if ($encodingUpper !== strtoupper($convertEncoding)) { + $this->convertEncoding = $encodingUpper; + } + + if ($convertEncoding !== null) { + if ($encodingUpper !== strtoupper($convertEncoding)) { + throw new Exception\InvalidArgumentException( + 'Wrapper doesn\'t support to convert between character encodings' + ); + } + + $this->convertEncoding = $encodingUpper; + } else { + $this->convertEncoding = null; + } + $this->encoding = $encodingUpper; + + return $this; + } + /** * Returns the length of the given string * From 6ecb74d29db33ddd54eccf22c277dc03fb7c8583 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 3 Jan 2013 16:24:23 +0100 Subject: [PATCH 36/63] Added note why encodings are typed in case-mix --- test/StringUtilsTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/StringUtilsTest.php b/test/StringUtilsTest.php index fefed5807..7bcde696c 100644 --- a/test/StringUtilsTest.php +++ b/test/StringUtilsTest.php @@ -38,9 +38,10 @@ public function tearDown() public function getSingleByEncodings() { return array( + // case-mix to check case-insensitivity array('AscII'), - array('7bit'), - array('8bit'), + array('7bIt'), + array('8Bit'), array('ISo-8859-1'), array('ISo-8859-2'), array('ISo-8859-3'), From 212a253fcb7b796449919608965d3609a538b61c Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 3 Jan 2013 23:28:04 +0100 Subject: [PATCH 37/63] added methods get[Convert]Encoding() and removed constructor from interface --- src/StringUtils.php | 4 +- src/StringWrapper/AbstractStringWrapper.php | 54 +++++++++++++------- src/StringWrapper/Iconv.php | 26 +++++++--- src/StringWrapper/Intl.php | 4 +- src/StringWrapper/MbString.php | 27 +++++++--- src/StringWrapper/Native.php | 8 +++ src/StringWrapper/StringWrapperInterface.php | 22 +++++--- test/StringWrapper/IconvTest.php | 5 +- test/StringWrapper/IntlTest.php | 5 +- test/StringWrapper/MbStringTest.php | 5 +- test/StringWrapper/NativeTest.php | 5 +- 11 files changed, 115 insertions(+), 50 deletions(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index 031800b70..65e6004cc 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -114,7 +114,9 @@ public static function getWrapper($encoding = 'UTF-8', $convertEncoding = null) { foreach (static::getRegisteredWrappers() as $wrapperClass) { if ($wrapperClass::isSupported($encoding, $convertEncoding)) { - return new $wrapperClass($encoding, $convertEncoding); + $wrapper = new $wrapperClass($encoding, $convertEncoding); + $wrapper->setEncoding($encoding, $convertEncoding); + return $wrapper; } } diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 50621cd03..60e2730be 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -24,7 +24,7 @@ abstract class AbstractStringWrapper implements StringWrapperInterface * The character encoding working on * @var string|null */ - protected $encoding; + protected $encoding = 'UTF-8'; /** * An optionally character encoding to convert to @@ -54,17 +54,6 @@ public static function isSupported($encoding, $convertEncoding = null) return true; } - /** - * Constructor - * @param string $encoding Character encoding working on - * @param string|null $convertEncoding Character encoding to convert to - * @throws Exception\InvalidArgumentException - */ - public function __construct($encoding, $convertEncoding = null) - { - $this->setEncoding($encoding, $convertEncoding); - } - /** * Set character encoding working with and convert to * @@ -101,6 +90,28 @@ public function setEncoding($encoding, $convertEncoding = null) return $this; } + + /** + * Get the defined character encoding to work with + * + * @return string + * @throws Exception\LogicException If no encoding was defined + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Get the defined character encoding to convert to + * + * @return string|null + */ + public function getConvertEncoding() + { + return $this->convertEncoding; + } + /** * Convert a string from defined character encoding to the defined convert encoding * @@ -110,13 +121,20 @@ public function setEncoding($encoding, $convertEncoding = null) */ public function convert($str, $reverse = false) { - if ($this->encoding === $this->convertEncoding) { + $encoding = $this->getEncoding(); + $convertEncoding = $this->getConvertEncoding(); + if ($convertEncoding === null) { + throw new Exception\LogicException( + 'No convert encoding defined' + ); + } + + if ($encoding === $convertEncoding) { return $str; } - var_dump($this->encoding, $this->convertEncoding); - $from = $reverse ? $this->convertEncoding : $this->encoding; - $to = $reverse ? $this->encoding : $this->convertEncoding; + $from = $reverse ? $convertEncoding : $encoding; + $to = $reverse ? $encoding : $convertEncoding; throw new Exception\RuntimeException(sprintf( 'Converting from "%s" to "%s" isn\'t supported by this string wrapper', $from, @@ -151,7 +169,7 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false) throw new Exception\InvalidArgumentException('Cannot force cut when width is zero'); } - if (StringUtils::isSingleByteEncoding($this->encoding)) { + if (StringUtils::isSingleByteEncoding($this->getEncoding())) { return wordwrap($string, $width, $break, $cut); } @@ -217,7 +235,7 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false) */ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT) { - if (StringUtils::isSingleByteEncoding($this->encoding)) { + if (StringUtils::isSingleByteEncoding($this->getEncoding())) { return str_pad($input, $padLength, $padString, $padType); } diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index d1aaa03ac..2588dd185 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -131,15 +131,13 @@ public static function getSupportedEncodings() * * @throws Exception\ExtensionNotLoadedException */ - public function __construct($encoding, $convertEncoding = null) + public function __construct() { if (!extension_loaded('iconv')) { throw new Exception\ExtensionNotLoadedException( 'PHP extension "iconv" is required for this wrapper' ); } - - parent::__construct($encoding, $convertEncoding); } /** @@ -151,7 +149,7 @@ public function __construct($encoding, $convertEncoding = null) */ public function strlen($str) { - return iconv_strlen($str, $this->encoding); + return iconv_strlen($str, $this->getEncoding()); } /** @@ -165,7 +163,7 @@ public function strlen($str) */ public function substr($str, $offset = 0, $length = null) { - return iconv_substr($str, $offset, $length, $this->encoding); + return iconv_substr($str, $offset, $length, $this->getEncoding()); } /** @@ -179,7 +177,7 @@ public function substr($str, $offset = 0, $length = null) */ public function strpos($haystack, $needle, $offset = 0) { - return iconv_strpos($haystack, $needle, $offset, $this->encoding); + return iconv_strpos($haystack, $needle, $offset, $this->getEncoding()); } /** @@ -191,8 +189,20 @@ public function strpos($haystack, $needle, $offset = 0) */ public function convert($str, $reverse = false) { - $fromEncoding = $reverse ? $this->convertEncoding : $this->encoding; - $toEncoding = $reverse ? $this->encoding : $this->convertEncoding; + $encoding = $this->getEncoding(); + $convertEncoding = $this->getConvertEncoding(); + if ($convertEncoding === null) { + throw new Exception\LogicException( + 'No convert encoding defined' + ); + } + + if ($encoding === $convertEncoding) { + return $str; + } + + $fromEncoding = $reverse ? $convertEncoding : $encoding; + $toEncoding = $reverse ? $encoding : $convertEncoding; return iconv($fromEncoding, $toEncoding, $str); } } diff --git a/src/StringWrapper/Intl.php b/src/StringWrapper/Intl.php index 3669e002b..c7eacaa24 100644 --- a/src/StringWrapper/Intl.php +++ b/src/StringWrapper/Intl.php @@ -41,15 +41,13 @@ public static function getSupportedEncodings() * * @throws Exception\ExtensionNotLoadedException */ - public function __construct($encoding, $convertEncoding = null) + public function __construct() { if (!extension_loaded('intl')) { throw new Exception\ExtensionNotLoadedException( 'PHP extension "intl" is required for this wrapper' ); } - - parent::__construct($encoding, $convertEncoding); } /** diff --git a/src/StringWrapper/MbString.php b/src/StringWrapper/MbString.php index 8d8d49a75..62782dab6 100644 --- a/src/StringWrapper/MbString.php +++ b/src/StringWrapper/MbString.php @@ -52,15 +52,13 @@ public static function getSupportedEncodings() * * @throws Exception\ExtensionNotLoadedException */ - public function __construct($encoding, $convertEncoding = null) + public function __construct() { if (!extension_loaded('mbstring')) { throw new Exception\ExtensionNotLoadedException( 'PHP extension "mbstring" is required for this wrapper' ); } - - parent::__construct($encoding, $convertEncoding); } /** @@ -72,7 +70,7 @@ public function __construct($encoding, $convertEncoding = null) */ public function strlen($str) { - return mb_strlen($str, $this->encoding); + return mb_strlen($str, $this->getEncoding()); } /** @@ -86,7 +84,7 @@ public function strlen($str) */ public function substr($str, $offset = 0, $length = null) { - return mb_substr($str, $offset, $length, $this->encoding); + return mb_substr($str, $offset, $length, $this->getEncoding()); } /** @@ -100,7 +98,7 @@ public function substr($str, $offset = 0, $length = null) */ public function strpos($haystack, $needle, $offset = 0) { - return mb_strpos($haystack, $needle, $offset, $this->encoding); + return mb_strpos($haystack, $needle, $offset, $this->getEncoding()); } /** @@ -112,8 +110,21 @@ public function strpos($haystack, $needle, $offset = 0) */ public function convert($str, $reverse = false) { - $fromEncoding = $reverse ? $this->convertEncoding : $this->encoding; - $toEncoding = $reverse ? $this->encoding : $this->convertEncoding; + $encoding = $this->getEncoding(); + $convertEncoding = $this->getConvertEncoding(); + + if ($convertEncoding === null) { + throw new Exception\LogicException( + 'No convert encoding defined' + ); + } + + if ($encoding === $convertEncoding) { + return $str; + } + + $fromEncoding = $reverse ? $convertEncoding : $encoding; + $toEncoding = $reverse ? $encoding : $convertEncoding; return mb_convert_encoding($str, $toEncoding, $fromEncoding); } } diff --git a/src/StringWrapper/Native.php b/src/StringWrapper/Native.php index 8ddcf3d6c..375b46f28 100644 --- a/src/StringWrapper/Native.php +++ b/src/StringWrapper/Native.php @@ -20,6 +20,14 @@ */ class Native extends AbstractStringWrapper { + /** + * The character encoding working on + * (overwritten to change defaut encoding) + * + * @var string + */ + protected $encoding = 'ASCII'; + /** * Check if the given character encoding is supported by this wrapper * and the character encoding to convert to is also supported. diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index 4dc133fb1..401cda3fd 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -33,14 +33,6 @@ public static function isSupported($encoding, $convertEncoding = null); */ public static function getSupportedEncodings(); - /** - * Constructor - * - * @param string $encoding Character encoding working on - * @param string|null $convertEncoding Character encoding to convert to - */ - public function __construct($encoding, $convertEncoding = null); - /** * Set character encoding working with and convert to * @@ -50,6 +42,20 @@ public function __construct($encoding, $convertEncoding = null); */ public function setEncoding($encoding, $convertEncoding = null); + /** + * Get the defined character encoding to work with (upper case) + * + * @return string|null + */ + public function getEncoding(); + + /** + * Get the defined character encoding to convert to (upper case) + * + * @return string|null + */ + public function getConvertEncoding(); + /** * Returns the length of the given string * diff --git a/test/StringWrapper/IconvTest.php b/test/StringWrapper/IconvTest.php index 2819b6b00..ec3b0db24 100644 --- a/test/StringWrapper/IconvTest.php +++ b/test/StringWrapper/IconvTest.php @@ -41,6 +41,9 @@ protected function getWrapper($encoding = null, $convertEncoding = null) if (!Iconv::isSupported($encoding, $convertEncoding)) { return false; } - return new Iconv($encoding, $convertEncoding); + + $wrapper = new Iconv(); + $wrapper->setEncoding($encoding, $convertEncoding); + return $wrapper; } } diff --git a/test/StringWrapper/IntlTest.php b/test/StringWrapper/IntlTest.php index efa3fdddb..d3092f60b 100644 --- a/test/StringWrapper/IntlTest.php +++ b/test/StringWrapper/IntlTest.php @@ -41,6 +41,9 @@ protected function getWrapper($encoding = null, $convertEncoding = null) if (!Intl::isSupported($encoding, $convertEncoding)) { return false; } - return new Intl($encoding, $convertEncoding); + + $wrapper = new Intl(); + $wrapper->setEncoding($encoding, $convertEncoding); + return $wrapper; } } diff --git a/test/StringWrapper/MbStringTest.php b/test/StringWrapper/MbStringTest.php index 01f332bee..d024afaa6 100644 --- a/test/StringWrapper/MbStringTest.php +++ b/test/StringWrapper/MbStringTest.php @@ -41,6 +41,9 @@ protected function getWrapper($encoding = null, $convertEncoding = null) if (!MbString::isSupported($encoding, $convertEncoding)) { return false; } - return new MbString($encoding, $convertEncoding); + + $wrapper = new MbString(); + $wrapper->setEncoding($encoding, $convertEncoding); + return $wrapper; } } diff --git a/test/StringWrapper/NativeTest.php b/test/StringWrapper/NativeTest.php index 9a3716dbd..b54e41daa 100644 --- a/test/StringWrapper/NativeTest.php +++ b/test/StringWrapper/NativeTest.php @@ -26,6 +26,9 @@ protected function getWrapper($encoding = null, $convertEncoding = null) if (!Native::isSupported($encoding, $convertEncoding)) { return false; } - return new Native($encoding, $convertEncoding); + + $wrapper = new Native(); + $wrapper->setEncoding($encoding, $convertEncoding); + return $wrapper; } } From 5f991bfd04937b16a5dbcfad288fa202116bb142 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 3 Jan 2013 23:29:49 +0100 Subject: [PATCH 38/63] fixed phpdoc --- src/StringWrapper/StringWrapperInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index 401cda3fd..888f9c3d6 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -45,7 +45,7 @@ public function setEncoding($encoding, $convertEncoding = null); /** * Get the defined character encoding to work with (upper case) * - * @return string|null + * @return string */ public function getEncoding(); From 0b94b67e570c91ae33435de38fdeb211e41189d9 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 6 Jan 2013 15:16:48 +0100 Subject: [PATCH 39/63] psr --- src/StringWrapper/AbstractStringWrapper.php | 1 - src/StringWrapper/Iconv.php | 149 +++++++++++++++----- 2 files changed, 117 insertions(+), 33 deletions(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 60e2730be..8b19605ae 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -90,7 +90,6 @@ public function setEncoding($encoding, $convertEncoding = null) return $this; } - /** * Get the defined character encoding to work with * diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 2588dd185..d81315790 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -28,83 +28,167 @@ class Iconv extends AbstractStringWrapper protected static $encodings = array( // European languages 'ASCII', - 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-7', - 'ISO-8859-9', 'ISO-8859-10', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', - 'KOI8-R', 'KOI8-U', 'KOI8-RU', - 'CP1250', 'CP1251', 'CP1252', 'CP1253', 'CP1254', 'CP1257', 'CP850', 'CP866', 'CP1131', - 'MACROMAN', 'MACCENTRALEUROPE', 'MACICELAND', 'MACCROATIAN', 'MACROMANIA', - 'MACCYRILLIC', 'MACUKRAINE', 'MACGREEK', 'MACTURKISH', 'MACINTOSH', + 'ISO-8859-1', + 'ISO-8859-2', + 'ISO-8859-3', + 'ISO-8859-4', + 'ISO-8859-5', + 'ISO-8859-7', + 'ISO-8859-9', + 'ISO-8859-10', + 'ISO-8859-13', + 'ISO-8859-14', + 'ISO-8859-15', + 'ISO-8859-16', + 'KOI8-R', + 'KOI8-U', + 'KOI8-RU', + 'CP1250', + 'CP1251', + 'CP1252', + 'CP1253', + 'CP1254', + 'CP1257', + 'CP850', + 'CP866', + 'CP1131', + 'MACROMAN', + 'MACCENTRALEUROPE', + 'MACICELAND', + 'MACCROATIAN', + 'MACROMANIA', + 'MACCYRILLIC', + 'MACUKRAINE', + 'MACGREEK', + 'MACTURKISH', + 'MACINTOSH', // Semitic languages - 'ISO-8859-6', 'ISO-8859-8', - 'CP1255', 'CP1256', 'CP862', - 'MACHEBREW', 'MACARABIC', + 'ISO-8859-6', + 'ISO-8859-8', + 'CP1255', + 'CP1256', + 'CP862', + 'MACHEBREW', + 'MACARABIC', // Japanese - 'EUC-JP', 'SHIFT_JIS', 'CP932', - 'ISO-2022-JP', 'ISO-2022-JP-2', 'ISO-2022-JP-1', + 'EUC-JP', + 'SHIFT_JIS', + 'CP932', + 'ISO-2022-JP', + 'ISO-2022-JP-2', + 'ISO-2022-JP-1', // Chinese - 'EUC-CN', 'HZ', 'GBK', 'CP936', 'GB18030', 'EUC-TW', 'BIG5', 'CP950', - 'BIG5-HKSCS', 'BIG5-HKSCS:2004', 'BIG5-HKSCS:2001', 'BIG5-HKSCS:1999', - 'ISO-2022-CN', 'ISO-2022-CN-EXT', + 'EUC-CN', + 'HZ', + 'GBK', + 'CP936', + 'GB18030', + 'EUC-TW', + 'BIG5', + 'CP950', + 'BIG5-HKSCS', + 'BIG5-HKSCS:2004', + 'BIG5-HKSCS:2001', + 'BIG5-HKSCS:1999', + 'ISO-2022-CN', + 'ISO-2022-CN-EXT', // Korean - 'EUC-KR', 'CP949', 'ISO-2022-KR', 'JOHAB', + 'EUC-KR', + 'CP949', + 'ISO-2022-KR', + 'JOHAB', // Armenian 'ARMSCII-8', // Georgian - 'GEORGIAN-ACADEMY', 'GEORGIAN-PS', + 'GEORGIAN-ACADEMY', + 'GEORGIAN-PS', // Tajik 'KOI8-T', // Kazakh - 'PT154', 'RK1048', + 'PT154', + 'RK1048', // Thai - 'ISO-8859-11', 'TIS-620', 'CP874', 'MACTHAI', + 'ISO-8859-11', + 'TIS-620', + 'CP874', + 'MACTHAI', // Laotian - 'MULELAO-1', 'CP1133', + 'MULELAO-1', + 'CP1133', // Vietnamese - 'VISCII', 'TCVN', 'CP1258', + 'VISCII', + 'TCVN', + 'CP1258', // Platform specifics - 'HP-ROMAN8', 'NEXTSTEP', + 'HP-ROMAN8', + 'NEXTSTEP', // Full Unicode 'UTF-8', - 'UCS-2', 'UCS-2BE', 'UCS-2LE', - 'UCS-4', 'UCS-4BE', 'UCS-4LE', - 'UTF-16', 'UTF-16BE', 'UTF-16LE', - 'UTF-32', 'UTF-32BE', 'UTF-32LE', + 'UCS-2', + 'UCS-2BE', + 'UCS-2LE', + 'UCS-4', + 'UCS-4BE', + 'UCS-4LE', + 'UTF-16', + 'UTF-16BE', + 'UTF-16LE', + 'UTF-32', + 'UTF-32BE', + 'UTF-32LE', 'UTF-7', - 'C99', 'JAVA', + 'C99', + 'JAVA', // Full Unicode, in terms of uint16_t or uint32_t (with machine dependent endianness and alignment) - // 'UCS-2-INTERNAL', 'UCS-4-INTERNAL', + // 'UCS-2-INTERNAL', + // 'UCS-4-INTERNAL', // Locale dependent, in terms of `char' or `wchar_t' (with machine dependent endianness and alignment, // and with OS and locale dependent semantics) - // 'char', 'wchar_t', + // 'char', + // 'wchar_t', // '', // The empty encoding name is equivalent to "char": it denotes the locale dependent character encoding. // When configured with the option --enable-extra-encodings, // it also provides support for a few extra encodings: // European languages - 'CP437', 'CP737', 'CP775', 'CP852', 'CP853', 'CP855', 'CP857', 'CP858', - 'CP860', 'CP861', 'CP863', 'CP865', 'CP869', 'CP1125', + 'CP437', + 'CP737', + 'CP775', + 'CP852', + 'CP853', + 'CP855', + 'CP857', + 'CP858', + 'CP860', + 'CP861', + 'CP863', + 'CP865', + 'CP869', + 'CP1125', // Semitic languages 'CP864', // Japanese - 'EUC-JISX0213', 'Shift_JISX0213', 'ISO-2022-JP-3', + 'EUC-JISX0213', + 'Shift_JISX0213', + 'ISO-2022-JP-3', // Chinese 'BIG5-2003', // (experimental) @@ -113,7 +197,8 @@ class Iconv extends AbstractStringWrapper 'TDS565', // Platform specifics - 'ATARIST', 'RISCOS-LATIN1', + 'ATARIST', + 'RISCOS-LATIN1', ); /** From f48fd28848c1783a2ebdc0b19c8bb69b56a0087b Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 6 Jan 2013 15:21:56 +0100 Subject: [PATCH 40/63] added StringUtils::resetRegisteredWrappers() for testing purposes --- src/StringUtils.php | 12 +++++++++++- test/StringUtilsTest.php | 17 +---------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/StringUtils.php b/src/StringUtils.php index 65e6004cc..47e362692 100644 --- a/src/StringUtils.php +++ b/src/StringUtils.php @@ -29,7 +29,7 @@ abstract class StringUtils * * @var StringWrapperInterface[] */ - protected static $wrapperRegistry; + protected static $wrapperRegistry = null; /** * A list of known single-byte character encodings (upper-case) @@ -101,6 +101,16 @@ public static function unregisterWrapper($wrapper) } } + /** + * Reset all registered wrappers so the default wrappers will be used + * + * @return void + */ + public static function resetRegisteredWrappers() + { + static::$wrapperRegistry = null; + } + /** * Get the first string wrapper supporting the given character encoding * and supports to convert into the given convert encoding. diff --git a/test/StringUtilsTest.php b/test/StringUtilsTest.php index 7bcde696c..bb27a59bf 100644 --- a/test/StringUtilsTest.php +++ b/test/StringUtilsTest.php @@ -15,24 +15,9 @@ class StringUtilsTest extends TestCase { - - protected $bufferedWrappers; - - public function setUp() - { - $this->bufferedWrappers = StringUtils::getRegisteredWrappers(); - } - public function tearDown() { - // reset registered wrappers - foreach (StringUtils::getRegisteredWrappers() as $wrapper) { - StringUtils::unregisterWrapper($wrapper); - } - foreach ($this->bufferedWrappers as $wrapper) { - StringUtils::registerWrapper($wrapper); - } - + StringUtils::resetRegisteredWrappers(); } public function getSingleByEncodings() From 2e6bd008637da6ce8a73114944ad1a0db2e6e0bf Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 6 Jan 2013 15:24:40 +0100 Subject: [PATCH 41/63] Global namespace not needed for constants --- src/StringWrapper/AbstractStringWrapper.php | 6 +++--- src/StringWrapper/StringWrapperInterface.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 8b19605ae..5fb8e85b5 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -232,7 +232,7 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false) * @param integer $padType * @return string */ - public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT) + public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT) { if (StringUtils::isSingleByteEncoding($this->getEncoding())) { return str_pad($input, $padLength, $padString, $padType); @@ -250,7 +250,7 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD $repeatCount = floor($lengthOfPadding / $padStringLength); - if ($padType === \STR_PAD_BOTH) { + if ($padType === STR_PAD_BOTH) { $lastStringLeft = ''; $lastStringRight = ''; $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2; @@ -269,7 +269,7 @@ public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength); - if ($padType === \STR_PAD_LEFT) { + if ($padType === STR_PAD_LEFT) { return str_repeat($padString, $repeatCount) . $lastString . $input; } diff --git a/src/StringWrapper/StringWrapperInterface.php b/src/StringWrapper/StringWrapperInterface.php index 888f9c3d6..bcba9ec48 100644 --- a/src/StringWrapper/StringWrapperInterface.php +++ b/src/StringWrapper/StringWrapperInterface.php @@ -115,5 +115,5 @@ public function wordWrap($str, $width = 75, $break = "\n", $cut = false); * @param integer $padType * @return string */ - public function strPad($input, $padLength, $padString = ' ', $padType = \STR_PAD_RIGHT); + public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT); } From e145bfab82b770743212c12e3d5d7954e528aef3 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 6 Jan 2013 15:31:14 +0100 Subject: [PATCH 42/63] File and class level docblocks --- src/Exception/ExtensionNotLoadedException.php | 15 +++++++++++++++ src/Exception/RuntimeException.php | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/Exception/ExtensionNotLoadedException.php b/src/Exception/ExtensionNotLoadedException.php index 40ceaf4ee..2270b5e00 100644 --- a/src/Exception/ExtensionNotLoadedException.php +++ b/src/Exception/ExtensionNotLoadedException.php @@ -1,7 +1,22 @@ Date: Sun, 6 Jan 2013 15:34:47 +0100 Subject: [PATCH 43/63] Removed not neccessary variable comversion as there is no strict comparison on it --- src/StringWrapper/AbstractStringWrapper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/StringWrapper/AbstractStringWrapper.php b/src/StringWrapper/AbstractStringWrapper.php index 5fb8e85b5..933482c73 100644 --- a/src/StringWrapper/AbstractStringWrapper.php +++ b/src/StringWrapper/AbstractStringWrapper.php @@ -163,7 +163,6 @@ public function wordWrap($string, $width = 75, $break = "\n", $cut = false) } $width = (int) $width; - $cut = (bool) $cut; if ($width === 0 && $cut) { throw new Exception\InvalidArgumentException('Cannot force cut when width is zero'); } From 9e2e9319b8c0b7e02c8c9a41da5c41afdef64f32 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 6 Jan 2013 16:03:05 +0100 Subject: [PATCH 44/63] Added short describtions on tests using data providers --- .../StringWrapper/CommonStringWrapperTest.php | 120 ++++++++++++------ 1 file changed, 80 insertions(+), 40 deletions(-) diff --git a/test/StringWrapper/CommonStringWrapperTest.php b/test/StringWrapper/CommonStringWrapperTest.php index 5ae04708a..cc58f9a70 100644 --- a/test/StringWrapper/CommonStringWrapperTest.php +++ b/test/StringWrapper/CommonStringWrapperTest.php @@ -138,77 +138,107 @@ public function wordWrapProvider() { return array( // Standard cut tests - array('utf-8', 'äbüöcß', 2, ' ', true, + array('Word wrap cut single-line', + 'utf-8', 'äbüöcß', 2, ' ', true, 'äb üö cß'), - array('utf-8', 'äbüöc ß äbüöcß', 2, ' ', true, + array('Word wrap cut multi-line', + 'utf-8', 'äbüöc ß äbüöcß', 2, ' ', true, 'äb üö c ß äb üö cß'), - array('utf-8', 'Ä very long wöööööööööööörd.', 8, "\n", true, + array('Word wrap cut multi-line short words', + 'utf-8', 'Ä very long wöööööööööööörd.', 8, "\n", true, "Ä very\nlong\nwööööööö\nööööörd."), - array('utf-8', "Ä very\nlong wöööööööööööörd.", 8, "\n", false, + array('Word wrap cut multi-line with previous new lines', + 'utf-8', "Ä very\nlong wöööööööööööörd.", 8, "\n", false, "Ä very\nlong\nwöööööööööööörd."), - array('utf-8', "Ä very
long wöö
öööööööö
öörd.", 8, '
', false, + array('Word wrap long break', + 'utf-8', "Ä very
long wöö
öööööööö
öörd.", 8, '
', false, "Ä very
long wöö
öööööööö
öörd."), // Alternative cut tests - array('utf-8', ' äüöäöü', 3, ' ', true, + array('Word wrap cut beginning single space', + 'utf-8', ' äüöäöü', 3, ' ', true, ' äüö äöü'), - array('utf-8', 'äüöäöü ', 3, ' ', true, + array('Word wrap cut ending single space', + 'utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), - array('utf-8', 'äöüäöü ', 3, '-', true, + array('Word wrap cut ending single space with non space divider', + 'utf-8', 'äöüäöü ', 3, '-', true, 'äöü-äöü-'), - array('utf-8', 'äüöäöü ', 3, ' ', true, + array('Word wrap cut ending two spaces', + 'utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), - array('utf-8', '12345 ', 5, '-', false, + array('Word wrap no cut ending single space', + 'utf-8', '12345 ', 5, '-', false, '12345-'), - array('utf-8', '12345 ', 5, '-', false, + array('Word wrap no cut ending two spaces', + 'utf-8', '12345 ', 5, '-', false, '12345- '), - array('utf-8', 'äüöäöü ', 3, ' ', true, + array('Word wrap cut ending three spaces', + 'utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), - array('utf-8', 'äüöäöü--', 3, '-', true, + array('Word wrap cut ending two breaks', + 'utf-8', 'äüöäöü--', 3, '-', true, 'äüö-äöü--'), - array('utf-8', "äbü\töcß", 3, ' ', true, + array('Word wrap cut tab', + 'utf-8', "äbü\töcß", 3, ' ', true, "äbü \töc ß"), - array('utf-8', "äbü\nößt", 3, ' ', true, + array('Word wrap cut new-line with space', + 'utf-8', "äbü\nößt", 3, ' ', true, "äbü \nöß t"), - array('utf-8', "äbü\nößte", 3, "\n", true, + array('Word wrap cut new-line with new-line', + 'utf-8', "äbü\nößte", 3, "\n", true, "äbü\nößt\ne"), // Break cut tests - array('ascii', 'foobar-foofoofoo', 8, '-', true, + array('Word wrap cut break before', + 'ascii', 'foobar-foofoofoo', 8, '-', true, 'foobar-foofoofo-o'), - array('ascii', 'foobar-foobar', 6, '-', true, + array('Word wrap cut break with', + 'ascii', 'foobar-foobar', 6, '-', true, 'foobar-foobar'), - array('ascii', 'foobar-foobar', 7, '-', true, + array('Word wrap cut break within', + 'ascii', 'foobar-foobar', 7, '-', true, 'foobar-foobar'), - array('ascii', 'foobar-', 7, '-', true, + array('Word wrap cut break within end', + 'ascii', 'foobar-', 7, '-', true, 'foobar-'), - array('ascii', 'foobar-foobar', 5, '-', true, + array('Word wrap cut break after', + 'ascii', 'foobar-foobar', 5, '-', true, 'fooba-r-fooba-r'), // Standard no-cut tests - array('utf-8', 'äbüöcß', 2, ' ', false, + array('Word wrap no cut single-line', + 'utf-8', 'äbüöcß', 2, ' ', false, 'äbüöcß'), - array('utf-8', 'äbüöc ß äbüöcß', 2, "\n", false, + array('Word wrap no cut multi-line', + 'utf-8', 'äbüöc ß äbüöcß', 2, "\n", false, "äbüöc\nß\näbüöcß"), - array('utf-8', 'äöü äöü äöü', 5, "\n", false, + array('Word wrap no cut multi-word', + 'utf-8', 'äöü äöü äöü', 5, "\n", false, "äöü\näöü\näöü"), // Break no-cut tests - array('ascii', 'foobar-foofoofoo', 8, '-', false, + array('Word wrap no cut break before', + 'ascii', 'foobar-foofoofoo', 8, '-', false, 'foobar-foofoofoo'), - array('ascii', 'foobar-foobar', 6, '-', false, + array('Word wrap no cut break with', + 'ascii', 'foobar-foobar', 6, '-', false, 'foobar-foobar'), - array('ascii', 'foobar-foobar', 7, '-', false, + array('Word wrap no cut break within', + 'ascii', 'foobar-foobar', 7, '-', false, 'foobar-foobar'), - array('ascii', 'foobar-', 7, '-', false, + array('Word wrap no cut break within end', + 'ascii', 'foobar-', 7, '-', false, 'foobar-'), - array('ascii', 'foobar-foobar', 5, '-', false, + array('Word wrap no cut break after', + 'ascii', 'foobar-foobar', 5, '-', false, 'foobar-foobar'), ); } /** * @dataProvider wordWrapProvider + * @param string $shortDesc * @param string $encoding * @param string $str * @param integer $width @@ -216,7 +246,7 @@ public function wordWrapProvider() * @param boolean $cut * @param mixed $expected */ - public function testWordWrap($encoding, $string, $width, $break, $cut, $expected) + public function testWordWrap($shortDesc, $encoding, $string, $width, $break, $cut, $expected) { $wrapper = $this->getWrapper($encoding); if (!$wrapper) { @@ -245,24 +275,34 @@ public function strPadProvider() { return array( // single-byte - array('ascii', 'aaa', 5, 'o', STR_PAD_LEFT, 'ooaaa'), - array('ascii', 'aaa', 6, 'o', STR_PAD_BOTH, 'oaaaoo'), - array('ascii', 'aaa', 5, 'o', STR_PAD_RIGHT, 'aaaoo'), + array('Left padding - single byte', + 'ascii', 'aaa', 5, 'o', STR_PAD_LEFT, 'ooaaa'), + array('Center padding - single byte', + 'ascii', 'aaa', 6, 'o', STR_PAD_BOTH, 'oaaaoo'), + array('Right padding - single byte', + 'ascii', 'aaa', 5, 'o', STR_PAD_RIGHT, 'aaaoo'), // multi-byte - array('utf-8', 'äää', 5, 'ö', STR_PAD_LEFT, 'ööäää'), - array('utf-8', 'äää', 6, 'ö', STR_PAD_BOTH, 'öäääöö'), - array('utf-8', 'äää', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), + array('Left padding - multi-byte', + 'utf-8', 'äää', 5, 'ö', STR_PAD_LEFT, 'ööäää'), + array('Center padding - multi byte', + 'utf-8', 'äää', 6, 'ö', STR_PAD_BOTH, 'öäääöö'), + array('Right padding - multi-byte', + 'utf-8', 'äää', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), // ZF-12186 - array('utf-8', 'äääöö', 2, 'ö', STR_PAD_RIGHT, 'äääöö'), // PadInputLongerThanPadLength - array('utf-8', 'äääöö', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), // PadInputSameAsPadLength - array('utf-8', 'äääöö', -2, 'ö', STR_PAD_RIGHT, 'äääöö'), // PadNegativePadLength + array('Input longer than pad length', + 'utf-8', 'äääöö', 2, 'ö', STR_PAD_RIGHT, 'äääöö'), + array('Input same as pad length', + 'utf-8', 'äääöö', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), + array('Negative pad length', + 'utf-8', 'äääöö', -2, 'ö', STR_PAD_RIGHT, 'äääöö'), ); } /** * @dataProvider strPadProvider + * @param string $shortDesc * @param string $encoding * @param string $input * @param integer $padLength @@ -272,7 +312,7 @@ public function strPadProvider() * * @group ZF-12186 */ - public function testStrPad($encoding, $input, $padLength, $padString, $padType, $expected) + public function testStrPad($shortDesc, $encoding, $input, $padLength, $padString, $padType, $expected) { $wrapper = $this->getWrapper($encoding); if (!$wrapper) { From 8ee4281ed02a9555f6a37b44f7a4bfd4ae29332b Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 6 Jan 2013 18:22:32 +0100 Subject: [PATCH 45/63] added comment for a commented out block --- src/StringWrapper/Iconv.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index d81315790..118b5e082 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -153,15 +153,17 @@ class Iconv extends AbstractStringWrapper 'C99', 'JAVA', + /* Commented out because that's internal encodings not existing in real world // Full Unicode, in terms of uint16_t or uint32_t (with machine dependent endianness and alignment) - // 'UCS-2-INTERNAL', - // 'UCS-4-INTERNAL', + 'UCS-2-INTERNAL', + 'UCS-4-INTERNAL', // Locale dependent, in terms of `char' or `wchar_t' (with machine dependent endianness and alignment, // and with OS and locale dependent semantics) - // 'char', - // 'wchar_t', - // '', // The empty encoding name is equivalent to "char": it denotes the locale dependent character encoding. + 'char', + 'wchar_t', + '', // The empty encoding name is equivalent to "char": it denotes the locale dependent character encoding. + */ // When configured with the option --enable-extra-encodings, // it also provides support for a few extra encodings: From 54016c4292f43b7fbbf39c4aefbf7eb97efe3da4 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 6 Jan 2013 20:44:51 +0100 Subject: [PATCH 46/63] Use array keys as description for data provider --- .../StringWrapper/CommonStringWrapperTest.php | 190 ++++++++---------- 1 file changed, 81 insertions(+), 109 deletions(-) diff --git a/test/StringWrapper/CommonStringWrapperTest.php b/test/StringWrapper/CommonStringWrapperTest.php index cc58f9a70..454809b33 100644 --- a/test/StringWrapper/CommonStringWrapperTest.php +++ b/test/StringWrapper/CommonStringWrapperTest.php @@ -138,107 +138,80 @@ public function wordWrapProvider() { return array( // Standard cut tests - array('Word wrap cut single-line', - 'utf-8', 'äbüöcß', 2, ' ', true, - 'äb üö cß'), - array('Word wrap cut multi-line', - 'utf-8', 'äbüöc ß äbüöcß', 2, ' ', true, - 'äb üö c ß äb üö cß'), - array('Word wrap cut multi-line short words', - 'utf-8', 'Ä very long wöööööööööööörd.', 8, "\n", true, - "Ä very\nlong\nwööööööö\nööööörd."), - array('Word wrap cut multi-line with previous new lines', - 'utf-8', "Ä very\nlong wöööööööööööörd.", 8, "\n", false, - "Ä very\nlong\nwöööööööööööörd."), - array('Word wrap long break', - 'utf-8', "Ä very
long wöö
öööööööö
öörd.", 8, '
', false, - "Ä very
long wöö
öööööööö
öörd."), + 'word-wrap-cut-single-line' => + array('utf-8', 'äbüöcß', 2, ' ', true, 'äb üö cß'), + 'word-wrap-cut-multi-line' => + array('utf-8', 'äbüöc ß äbüöcß', 2, ' ', true, 'äb üö c ß äb üö cß'), + 'word-wrap-cut-multi-line-short-words' => + array('utf-8', 'Ä very long wöööööööööööörd.', 8, "\n", true, + "Ä very\nlong\nwööööööö\nööööörd."), + 'word-wrap-cut-multi-line-with-previous-new-lines' => + array('utf-8', "Ä very\nlong wöööööööööööörd.", 8, "\n", false, + "Ä very\nlong\nwöööööööööööörd."), + 'word-wrap-long-break' => + array('utf-8', "Ä very
long wöö
öööööööö
öörd.", 8, '
', false, + "Ä very
long wöö
öööööööö
öörd."), // Alternative cut tests - array('Word wrap cut beginning single space', - 'utf-8', ' äüöäöü', 3, ' ', true, - ' äüö äöü'), - array('Word wrap cut ending single space', - 'utf-8', 'äüöäöü ', 3, ' ', true, - 'äüö äöü '), - array('Word wrap cut ending single space with non space divider', - 'utf-8', 'äöüäöü ', 3, '-', true, - 'äöü-äöü-'), - array('Word wrap cut ending two spaces', - 'utf-8', 'äüöäöü ', 3, ' ', true, - 'äüö äöü '), - array('Word wrap no cut ending single space', - 'utf-8', '12345 ', 5, '-', false, - '12345-'), - array('Word wrap no cut ending two spaces', - 'utf-8', '12345 ', 5, '-', false, - '12345- '), - array('Word wrap cut ending three spaces', - 'utf-8', 'äüöäöü ', 3, ' ', true, - 'äüö äöü '), - array('Word wrap cut ending two breaks', - 'utf-8', 'äüöäöü--', 3, '-', true, - 'äüö-äöü--'), - array('Word wrap cut tab', - 'utf-8', "äbü\töcß", 3, ' ', true, - "äbü \töc ß"), - array('Word wrap cut new-line with space', - 'utf-8', "äbü\nößt", 3, ' ', true, - "äbü \nöß t"), - array('Word wrap cut new-line with new-line', - 'utf-8', "äbü\nößte", 3, "\n", true, - "äbü\nößt\ne"), + 'word-wrap-cut-beginning-single-space' => + array('utf-8', ' äüöäöü', 3, ' ', true, ' äüö äöü'), + 'word-wrap-cut-ending-single-space' => + array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), + 'word-wrap-cut-ending-single-space-with-non-space-divider' => + array('utf-8', 'äöüäöü ', 3, '-', true, 'äöü-äöü-'), + 'word-wrap-cut-ending-two-spaces' => + array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), + 'word-wrap-no-cut-ending-single-space' => + array('utf-8', '12345 ', 5, '-', false, '12345-'), + 'word-wrap-no-cut-ending-two-spaces' => + array('utf-8', '12345 ', 5, '-', false, '12345- '), + 'word-wrap-cut-ending-three-spaces' => + array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), + 'word-wrap-cut-ending-two-breaks' => + array('utf-8', 'äüöäöü--', 3, '-', true, 'äüö-äöü--'), + 'word-wrap-cut-tab' => + array('utf-8', "äbü\töcß", 3, ' ', true, "äbü \töc ß"), + 'word-wrap-cut-new-line-with-space' => + array('utf-8', "äbü\nößt", 3, ' ', true, "äbü \nöß t"), + 'word-wrap-cut-new-line-with-new-line' => + array('utf-8', "äbü\nößte", 3, "\n", true, "äbü\nößt\ne"), // Break cut tests - array('Word wrap cut break before', - 'ascii', 'foobar-foofoofoo', 8, '-', true, - 'foobar-foofoofo-o'), - array('Word wrap cut break with', - 'ascii', 'foobar-foobar', 6, '-', true, - 'foobar-foobar'), - array('Word wrap cut break within', - 'ascii', 'foobar-foobar', 7, '-', true, - 'foobar-foobar'), - array('Word wrap cut break within end', - 'ascii', 'foobar-', 7, '-', true, - 'foobar-'), - array('Word wrap cut break after', - 'ascii', 'foobar-foobar', 5, '-', true, - 'fooba-r-fooba-r'), + 'word-wrap-cut-break-before' => + array('ascii', 'foobar-foofoofoo', 8, '-', true, 'foobar-foofoofo-o'), + 'word-wrap-cut-break-with' => + array('ascii', 'foobar-foobar', 6, '-', true, 'foobar-foobar'), + 'word-wrap-cut-break-within' => + array('ascii', 'foobar-foobar', 7, '-', true, 'foobar-foobar'), + 'word-wrap-cut-break-within-end' => + array('ascii', 'foobar-', 7, '-', true, 'foobar-'), + 'word-wrap-cut-break-after' => + array('ascii', 'foobar-foobar', 5, '-', true, 'fooba-r-fooba-r'), // Standard no-cut tests - array('Word wrap no cut single-line', - 'utf-8', 'äbüöcß', 2, ' ', false, - 'äbüöcß'), - array('Word wrap no cut multi-line', - 'utf-8', 'äbüöc ß äbüöcß', 2, "\n", false, - "äbüöc\nß\näbüöcß"), - array('Word wrap no cut multi-word', - 'utf-8', 'äöü äöü äöü', 5, "\n", false, - "äöü\näöü\näöü"), + 'word-wrap-no-cut-single-line' => + array('utf-8', 'äbüöcß', 2, ' ', false, 'äbüöcß'), + 'word-wrap-no-cut-multi-line' => + array('utf-8', 'äbüöc ß äbüöcß', 2, "\n", false, "äbüöc\nß\näbüöcß"), + 'word-wrap-no-cut-multi-word' => + array('utf-8', 'äöü äöü äöü', 5, "\n", false, "äöü\näöü\näöü"), // Break no-cut tests - array('Word wrap no cut break before', - 'ascii', 'foobar-foofoofoo', 8, '-', false, - 'foobar-foofoofoo'), - array('Word wrap no cut break with', - 'ascii', 'foobar-foobar', 6, '-', false, - 'foobar-foobar'), - array('Word wrap no cut break within', - 'ascii', 'foobar-foobar', 7, '-', false, - 'foobar-foobar'), - array('Word wrap no cut break within end', - 'ascii', 'foobar-', 7, '-', false, - 'foobar-'), - array('Word wrap no cut break after', - 'ascii', 'foobar-foobar', 5, '-', false, - 'foobar-foobar'), + 'word-wrap-no-cut-break-before' => + array('ascii', 'foobar-foofoofoo', 8, '-', false, 'foobar-foofoofoo'), + 'word-wrap-no-cut-break-with' => + array('ascii', 'foobar-foobar', 6, '-', false, 'foobar-foobar'), + 'word-wrap-no-cut-break-within' => + array('ascii', 'foobar-foobar', 7, '-', false, 'foobar-foobar'), + 'word-wrap-no-cut-break-within-end' => + array('ascii', 'foobar-', 7, '-', false, 'foobar-'), + 'word-wrap-no-cut-break-after' => + array('ascii', 'foobar-foobar', 5, '-', false, 'foobar-foobar'), ); } /** * @dataProvider wordWrapProvider - * @param string $shortDesc * @param string $encoding * @param string $str * @param integer $width @@ -246,7 +219,7 @@ public function wordWrapProvider() * @param boolean $cut * @param mixed $expected */ - public function testWordWrap($shortDesc, $encoding, $string, $width, $break, $cut, $expected) + public function testWordWrap($encoding, $string, $width, $break, $cut, $expected) { $wrapper = $this->getWrapper($encoding); if (!$wrapper) { @@ -275,34 +248,33 @@ public function strPadProvider() { return array( // single-byte - array('Left padding - single byte', - 'ascii', 'aaa', 5, 'o', STR_PAD_LEFT, 'ooaaa'), - array('Center padding - single byte', - 'ascii', 'aaa', 6, 'o', STR_PAD_BOTH, 'oaaaoo'), - array('Right padding - single byte', - 'ascii', 'aaa', 5, 'o', STR_PAD_RIGHT, 'aaaoo'), + 'left-padding_single-byte' => + array('ascii', 'aaa', 5, 'o', STR_PAD_LEFT, 'ooaaa'), + 'center-padding_single-byte' => + array('ascii', 'aaa', 6, 'o', STR_PAD_BOTH, 'oaaaoo'), + 'right-padding_single-byte' => + array('ascii', 'aaa', 5, 'o', STR_PAD_RIGHT, 'aaaoo'), // multi-byte - array('Left padding - multi-byte', - 'utf-8', 'äää', 5, 'ö', STR_PAD_LEFT, 'ööäää'), - array('Center padding - multi byte', - 'utf-8', 'äää', 6, 'ö', STR_PAD_BOTH, 'öäääöö'), - array('Right padding - multi-byte', - 'utf-8', 'äää', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), + 'left-padding_multi-byte' => + array('utf-8', 'äää', 5, 'ö', STR_PAD_LEFT, 'ööäää'), + 'center-padding_multi-byte' => + array('utf-8', 'äää', 6, 'ö', STR_PAD_BOTH, 'öäääöö'), + 'right-padding_multi-byte' => + array('utf-8', 'äää', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), // ZF-12186 - array('Input longer than pad length', - 'utf-8', 'äääöö', 2, 'ö', STR_PAD_RIGHT, 'äääöö'), - array('Input same as pad length', - 'utf-8', 'äääöö', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), - array('Negative pad length', - 'utf-8', 'äääöö', -2, 'ö', STR_PAD_RIGHT, 'äääöö'), + 'input-longer-than-pad-length' => + array('utf-8', 'äääöö', 2, 'ö', STR_PAD_RIGHT, 'äääöö'), + 'input-same-as-pad-length' => + array('utf-8', 'äääöö', 5, 'ö', STR_PAD_RIGHT, 'äääöö'), + 'negative-pad-length' => + array('utf-8', 'äääöö', -2, 'ö', STR_PAD_RIGHT, 'äääöö'), ); } /** * @dataProvider strPadProvider - * @param string $shortDesc * @param string $encoding * @param string $input * @param integer $padLength @@ -312,7 +284,7 @@ public function strPadProvider() * * @group ZF-12186 */ - public function testStrPad($shortDesc, $encoding, $input, $padLength, $padString, $padType, $expected) + public function testStrPad($encoding, $input, $padLength, $padString, $padType, $expected) { $wrapper = $this->getWrapper($encoding); if (!$wrapper) { From 874aec176dc49e288664fd4d578d6a371ef53d2a Mon Sep 17 00:00:00 2001 From: ingo Date: Mon, 7 Jan 2013 00:59:43 +0100 Subject: [PATCH 47/63] Unit tests and error handling --- src/Hydrator/ClassMethods.php | 2 - src/Hydrator/Filter/FilterComposite.php | 41 ++++++++++- test/TestAsset/FilterCompositeTest.php | 90 +++++++++++++++++++------ 3 files changed, 110 insertions(+), 23 deletions(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index 003424512..bff9f3fe7 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -78,7 +78,6 @@ public function setOptions($options) public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys) { $this->underscoreSeparatedKeys = $underscoreSeparatedKeys; - return $this; } @@ -88,7 +87,6 @@ public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys) public function getUnderscoreSeparatedKeys() { return $this->underscoreSeparatedKeys; - } /** diff --git a/src/Hydrator/Filter/FilterComposite.php b/src/Hydrator/Filter/FilterComposite.php index 87f3efcf1..e21e8af06 100644 --- a/src/Hydrator/Filter/FilterComposite.php +++ b/src/Hydrator/Filter/FilterComposite.php @@ -9,6 +9,8 @@ */ namespace Zend\Stdlib\Hydrator\Filter; +use Zend\Stdlib\Exception\InvalidArgumentException; + /** * @category Zend * @package Zend_Stdlib @@ -36,9 +38,39 @@ class FilterComposite implements FilterInterface /** * Define default Filter + * + * @throws InvalidArgumentException */ public function __construct($orFilter = array(), $andFilter = array()) { + array_walk($orFilter, + function($value, $key) { + if( + !is_callable($value) && + !$value instanceof FilterInterface + ) { + throw new InvalidArgumentException( + 'The value of ' . $key . ' should be either a callable or ' . + 'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface' + ); + } + } + ); + + array_walk($andFilter, + function($value, $key) { + if( + !is_callable($value) && + !$value instanceof FilterInterface + ) { + throw new InvalidArgumentException( + 'The value of ' . $key . ' should be either a callable or ' . + 'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface' + ); + } + } + ); + $this->orFilter = new \ArrayObject($orFilter); $this->andFilter = new \ArrayObject($andFilter); } @@ -62,6 +94,7 @@ public function __construct($orFilter = array(), $andFilter = array()) * @param string $name * @param callable|FilterInterface $filter * @param int $condition Can be either FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND + * @throws InvalidArgumentException */ public function addFilter($name, $filter, $condition = self::CONDITION_OR) { @@ -71,10 +104,14 @@ public function addFilter($name, $filter, $condition = self::CONDITION_OR) ) { if ($condition === self::CONDITION_OR) { $this->orFilter[$name] = $filter; - } - if ($condition === self::CONDITION_AND) { + } elseif ($condition === self::CONDITION_AND) { $this->andFilter[$name] = $filter; } + } else { + throw new InvalidArgumentException( + 'The value of ' . $name . ' should be either a callable or ' . + 'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface' + ); } } diff --git a/test/TestAsset/FilterCompositeTest.php b/test/TestAsset/FilterCompositeTest.php index 9eaa21e5e..6efbbfaa7 100644 --- a/test/TestAsset/FilterCompositeTest.php +++ b/test/TestAsset/FilterCompositeTest.php @@ -12,56 +12,56 @@ use Zend\Stdlib\Hydrator\Filter\FilterComposite; -class ValidationCompositeTest extends \PHPUnit_Framework_TestCase +class FilterCompositeTest extends \PHPUnit_Framework_TestCase { - protected $validatorComposite; + protected $filterComposite; public function setUp() { - $this->validatorComposite = new FilterComposite(); + $this->filterComposite = new FilterComposite(); } public function testValidationAdd() { - $this->assertTrue($this->validatorComposite->filter("foo")); - $this->validatorComposite->addFilter("has", + $this->assertTrue($this->filterComposite->filter("foo")); + $this->filterComposite->addFilter("has", function($property) { return false; } ); - $this->assertFalse($this->validatorComposite->filter("foo")); + $this->assertFalse($this->filterComposite->filter("foo")); } public function testValidationRemove() { - $this->validatorComposite->addFilter("has", + $this->filterComposite->addFilter("has", function($property) { return false; } ); - $this->assertFalse($this->validatorComposite->filter("foo")); - $this->validatorComposite->removeFilter("has"); - $this->assertTrue($this->validatorComposite->filter("foo")); + $this->assertFalse($this->filterComposite->filter("foo")); + $this->filterComposite->removeFilter("has"); + $this->assertTrue($this->filterComposite->filter("foo")); } public function testValidationHas() { - $this->validatorComposite->addFilter("has", + $this->filterComposite->addFilter("has", function($property) { return false; } ); - $this->assertFalse($this->validatorComposite->filter("foo")); - $this->assertTrue($this->validatorComposite->hasFilter("has")); + $this->assertFalse($this->filterComposite->filter("foo")); + $this->assertTrue($this->filterComposite->hasFilter("has")); } public function testComplexValidation() { - $this->validatorComposite->addFilter("has", new \Zend\Stdlib\Hydrator\Filter\HasFilter()); - $this->validatorComposite->addFilter("get", new \Zend\Stdlib\Hydrator\Filter\GetFilter()); - $this->validatorComposite->addFilter("is", new \Zend\Stdlib\Hydrator\Filter\IsFilter()); + $this->filterComposite->addFilter("has", new \Zend\Stdlib\Hydrator\Filter\HasFilter()); + $this->filterComposite->addFilter("get", new \Zend\Stdlib\Hydrator\Filter\GetFilter()); + $this->filterComposite->addFilter("is", new \Zend\Stdlib\Hydrator\Filter\IsFilter()); - $this->validatorComposite->addFilter("exclude", + $this->filterComposite->addFilter("exclude", function($property) { $method = substr($property, strpos($property, '::')); @@ -73,7 +73,59 @@ function($property) { }, FilterComposite::CONDITION_AND ); - $this->assertTrue($this->validatorComposite->filter('getFooBar')); - $this->assertFalse($this->validatorComposite->filter('getServiceLocator')); + $this->assertTrue($this->filterComposite->filter('getFooBar')); + $this->assertFalse($this->filterComposite->filter('getServiceLocator')); + } + + public function testConstructorInjection() + { + $andCondition = array( + 'servicelocator' => function($property) { + if($property === 'getServiceLocator') { + return false; + } + return true; + }, + 'foobar' => function($property) { + if($property === 'getFooBar') { + return false; + } + return true; + } + ); + $orCondition = array( + 'has' => new \Zend\Stdlib\Hydrator\Filter\HasFilter(), + 'get' => new \Zend\Stdlib\Hydrator\Filter\GetFilter() + ); + $filterComposite = new FilterComposite($orCondition, $andCondition); + + $this->assertFalse($filterComposite->filter('getFooBar')); + $this->assertFalse($filterComposite->filter('geTFooBar')); + $this->assertFalse($filterComposite->filter('getServiceLocator')); + $this->assertTrue($filterComposite->filter('getFoo')); + $this->assertTrue($filterComposite->filter('hasFoo')); + } + + /** + * @expectedException Zend\Stdlib\Exception\InvalidArgumentException + * @expectedExceptionMessage The value of test should be either a callable + * or an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface + */ + public function testInvalidParameterConstructorInjection() + { + $andCondition = array('foo' => 'bar'); + $orCondition = array('test' => 'blubb'); + + new FilterComposite($orCondition, $andCondition); + } + + /** + * @expectedException Zend\Stdlib\Exception\InvalidArgumentException + * @expectedExceptionMessage The value of foo should be either a callable + * or an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface + */ + public function testInvalidFilterInjection() + { + $this->filterComposite->addFilter('foo', 'bar'); } } From b3909fb68e45275d418db422f7a9d3faadac1d60 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jan 2013 20:28:07 +0100 Subject: [PATCH 48/63] Make sure StringWrapper::convert don't substring return value on invalid character + test --- src/StringWrapper/Iconv.php | 5 ++++- test/StringWrapper/CommonStringWrapperTest.php | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/StringWrapper/Iconv.php b/src/StringWrapper/Iconv.php index 118b5e082..0cc8464eb 100644 --- a/src/StringWrapper/Iconv.php +++ b/src/StringWrapper/Iconv.php @@ -290,6 +290,9 @@ public function convert($str, $reverse = false) $fromEncoding = $reverse ? $convertEncoding : $encoding; $toEncoding = $reverse ? $encoding : $convertEncoding; - return iconv($fromEncoding, $toEncoding, $str); + + // automatically add "//IGNORE" to not stop converting on invalid characters + // invalid characters triggers a notice anyway + return iconv($fromEncoding, $toEncoding . '//IGNORE', $str); } } diff --git a/test/StringWrapper/CommonStringWrapperTest.php b/test/StringWrapper/CommonStringWrapperTest.php index 454809b33..8fe180ba3 100644 --- a/test/StringWrapper/CommonStringWrapperTest.php +++ b/test/StringWrapper/CommonStringWrapperTest.php @@ -12,6 +12,7 @@ namespace ZendTest\Stdlib\StringWrapper; use PHPUnit_Framework_TestCase as TestCase; +use Zend\Stdlib\ErrorHandler; use Zend\Stdlib\Exception; use Zend\Stdlib\StringWrapper\StringWrapperInterface; @@ -134,6 +135,22 @@ public function testConvert($encoding, $convertEncoding, $str, $expected) $this->assertSame($str, $result); } + public function testConvertDontSubstringsOnInvalidCharacter() + { + $wrapper = $this->getWrapper('UTF-8', 'ASCII'); + if (!$wrapper) { + $this->markTestSkipped("Converting UTF-8 to ASCII not supported"); + } + + // NOTE: This call could trigger a notice/warning/error + // but that isn't part of this test + ErrorHandler::start(E_NOTICE); + $result = $wrapper->convert($wrapper->convert("foo \xDEx bar"), true); + ErrorHandler::stop(); + + $this->assertSame("foo x bar", $result); + } + public function wordWrapProvider() { return array( From 7392f83af171070f33393b74206724b7a33aa535 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jan 2013 20:29:56 +0100 Subject: [PATCH 49/63] removed unneccissary 'word-wrap-' prefix --- .../StringWrapper/CommonStringWrapperTest.php | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/test/StringWrapper/CommonStringWrapperTest.php b/test/StringWrapper/CommonStringWrapperTest.php index 8fe180ba3..3640431d8 100644 --- a/test/StringWrapper/CommonStringWrapperTest.php +++ b/test/StringWrapper/CommonStringWrapperTest.php @@ -155,74 +155,74 @@ public function wordWrapProvider() { return array( // Standard cut tests - 'word-wrap-cut-single-line' => + 'cut-single-line' => array('utf-8', 'äbüöcß', 2, ' ', true, 'äb üö cß'), - 'word-wrap-cut-multi-line' => + 'cut-multi-line' => array('utf-8', 'äbüöc ß äbüöcß', 2, ' ', true, 'äb üö c ß äb üö cß'), - 'word-wrap-cut-multi-line-short-words' => + 'cut-multi-line-short-words' => array('utf-8', 'Ä very long wöööööööööööörd.', 8, "\n", true, "Ä very\nlong\nwööööööö\nööööörd."), - 'word-wrap-cut-multi-line-with-previous-new-lines' => + 'cut-multi-line-with-previous-new-lines' => array('utf-8', "Ä very\nlong wöööööööööööörd.", 8, "\n", false, "Ä very\nlong\nwöööööööööööörd."), - 'word-wrap-long-break' => + 'long-break' => array('utf-8', "Ä very
long wöö
öööööööö
öörd.", 8, '
', false, "Ä very
long wöö
öööööööö
öörd."), // Alternative cut tests - 'word-wrap-cut-beginning-single-space' => + 'cut-beginning-single-space' => array('utf-8', ' äüöäöü', 3, ' ', true, ' äüö äöü'), - 'word-wrap-cut-ending-single-space' => + 'cut-ending-single-space' => array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), - 'word-wrap-cut-ending-single-space-with-non-space-divider' => + 'cut-ending-single-space-with-non-space-divider' => array('utf-8', 'äöüäöü ', 3, '-', true, 'äöü-äöü-'), - 'word-wrap-cut-ending-two-spaces' => + 'cut-ending-two-spaces' => array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), - 'word-wrap-no-cut-ending-single-space' => + 'no-cut-ending-single-space' => array('utf-8', '12345 ', 5, '-', false, '12345-'), - 'word-wrap-no-cut-ending-two-spaces' => + 'no-cut-ending-two-spaces' => array('utf-8', '12345 ', 5, '-', false, '12345- '), - 'word-wrap-cut-ending-three-spaces' => + 'cut-ending-three-spaces' => array('utf-8', 'äüöäöü ', 3, ' ', true, 'äüö äöü '), - 'word-wrap-cut-ending-two-breaks' => + 'cut-ending-two-breaks' => array('utf-8', 'äüöäöü--', 3, '-', true, 'äüö-äöü--'), - 'word-wrap-cut-tab' => + 'cut-tab' => array('utf-8', "äbü\töcß", 3, ' ', true, "äbü \töc ß"), - 'word-wrap-cut-new-line-with-space' => + 'cut-new-line-with-space' => array('utf-8', "äbü\nößt", 3, ' ', true, "äbü \nöß t"), - 'word-wrap-cut-new-line-with-new-line' => + 'cut-new-line-with-new-line' => array('utf-8', "äbü\nößte", 3, "\n", true, "äbü\nößt\ne"), // Break cut tests - 'word-wrap-cut-break-before' => + 'cut-break-before' => array('ascii', 'foobar-foofoofoo', 8, '-', true, 'foobar-foofoofo-o'), - 'word-wrap-cut-break-with' => + 'cut-break-with' => array('ascii', 'foobar-foobar', 6, '-', true, 'foobar-foobar'), - 'word-wrap-cut-break-within' => + 'cut-break-within' => array('ascii', 'foobar-foobar', 7, '-', true, 'foobar-foobar'), - 'word-wrap-cut-break-within-end' => + 'cut-break-within-end' => array('ascii', 'foobar-', 7, '-', true, 'foobar-'), - 'word-wrap-cut-break-after' => + 'cut-break-after' => array('ascii', 'foobar-foobar', 5, '-', true, 'fooba-r-fooba-r'), // Standard no-cut tests - 'word-wrap-no-cut-single-line' => + 'no-cut-single-line' => array('utf-8', 'äbüöcß', 2, ' ', false, 'äbüöcß'), - 'word-wrap-no-cut-multi-line' => + 'no-cut-multi-line' => array('utf-8', 'äbüöc ß äbüöcß', 2, "\n", false, "äbüöc\nß\näbüöcß"), - 'word-wrap-no-cut-multi-word' => + 'no-cut-multi-word' => array('utf-8', 'äöü äöü äöü', 5, "\n", false, "äöü\näöü\näöü"), // Break no-cut tests - 'word-wrap-no-cut-break-before' => + 'no-cut-break-before' => array('ascii', 'foobar-foofoofoo', 8, '-', false, 'foobar-foofoofoo'), - 'word-wrap-no-cut-break-with' => + 'no-cut-break-with' => array('ascii', 'foobar-foobar', 6, '-', false, 'foobar-foobar'), - 'word-wrap-no-cut-break-within' => + 'no-cut-break-within' => array('ascii', 'foobar-foobar', 7, '-', false, 'foobar-foobar'), - 'word-wrap-no-cut-break-within-end' => + 'no-cut-break-within-end' => array('ascii', 'foobar-', 7, '-', false, 'foobar-'), - 'word-wrap-no-cut-break-after' => + 'no-cut-break-after' => array('ascii', 'foobar-foobar', 5, '-', false, 'foobar-foobar'), ); } From 85dd79a63ff5bf36a3400965c390104e2b9c0cd9 Mon Sep 17 00:00:00 2001 From: ingo Date: Tue, 8 Jan 2013 00:38:56 +0100 Subject: [PATCH 50/63] Fixed reviews --- src/Hydrator/ClassMethods.php | 10 +++--- src/Hydrator/Filter/FilterComposite.php | 47 ++++++++++++++----------- test/HydratorTest.php | 2 +- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index bff9f3fe7..54d3be736 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -10,11 +10,11 @@ namespace Zend\Stdlib\Hydrator; -use Zend\Stdlib\Exception, - Zend\Stdlib\Hydrator\Filter\FilterComposite, - Zend\Stdlib\Hydrator\Filter\IsFilter, - Zend\Stdlib\Hydrator\Filter\GetFilter, - Zend\Stdlib\Hydrator\Filter\HasFilter; +use Zend\Stdlib\Exception; +use Zend\Stdlib\Hydrator\Filter\FilterComposite; +use Zend\Stdlib\Hydrator\Filter\GetFilter; +use Zend\Stdlib\Hydrator\Filter\HasFilter; +use Zend\Stdlib\Hydrator\Filter\IsFilter; /** * @category Zend diff --git a/src/Hydrator/Filter/FilterComposite.php b/src/Hydrator/Filter/FilterComposite.php index e21e8af06..03767936b 100644 --- a/src/Hydrator/Filter/FilterComposite.php +++ b/src/Hydrator/Filter/FilterComposite.php @@ -9,6 +9,7 @@ */ namespace Zend\Stdlib\Hydrator\Filter; +use ArrayObject; use Zend\Stdlib\Exception\InvalidArgumentException; /** @@ -19,11 +20,12 @@ class FilterComposite implements FilterInterface { /** - * @var \ArrayObject + * @var ArrayObject */ protected $orFilter; + /** - * @var \ArrayObject + * @var ArrayObject */ protected $andFilter; @@ -31,6 +33,7 @@ class FilterComposite implements FilterInterface * Constant to add with "or" conditition */ const CONDITION_OR = 1; + /** * Constant to add with "and" conditition */ @@ -46,8 +49,8 @@ public function __construct($orFilter = array(), $andFilter = array()) array_walk($orFilter, function($value, $key) { if( - !is_callable($value) && - !$value instanceof FilterInterface + !is_callable($value) + && !$value instanceof FilterInterface ) { throw new InvalidArgumentException( 'The value of ' . $key . ' should be either a callable or ' . @@ -60,8 +63,8 @@ function($value, $key) { array_walk($andFilter, function($value, $key) { if( - !is_callable($value) && - !$value instanceof FilterInterface + !is_callable($value) + && !$value instanceof FilterInterface ) { throw new InvalidArgumentException( 'The value of ' . $key . ' should be either a callable or ' . @@ -71,8 +74,8 @@ function($value, $key) { } ); - $this->orFilter = new \ArrayObject($orFilter); - $this->andFilter = new \ArrayObject($andFilter); + $this->orFilter = new ArrayObject($orFilter); + $this->andFilter = new ArrayObject($andFilter); } /** @@ -95,30 +98,31 @@ function($value, $key) { * @param callable|FilterInterface $filter * @param int $condition Can be either FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND * @throws InvalidArgumentException + * @return FilterComposite */ public function addFilter($name, $filter, $condition = self::CONDITION_OR) { - if ( - is_callable($filter) || - $filter instanceof FilterInterface - ) { - if ($condition === self::CONDITION_OR) { - $this->orFilter[$name] = $filter; - } elseif ($condition === self::CONDITION_AND) { - $this->andFilter[$name] = $filter; - } - } else { + if ( !is_callable($filter) && !($filter instanceof FilterInterface) ) { throw new InvalidArgumentException( 'The value of ' . $name . ' should be either a callable or ' . 'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface' ); } + + if ($condition === self::CONDITION_OR) { + $this->orFilter[$name] = $filter; + } elseif ($condition === self::CONDITION_AND) { + $this->andFilter[$name] = $filter; + } + + return $this; } /** * Remove a filter from the composition * * @param $name string Identifier for the filter + * @return FilterComposite */ public function removeFilter($name) { @@ -129,6 +133,8 @@ public function removeFilter($name) if( isset($this->andFilter[$name])) { unset($this->andFilter[$name]); } + + return $this; } /** @@ -139,8 +145,7 @@ public function removeFilter($name) */ public function hasFilter($name) { - return - isset($this->orFilter[$name]) || isset($this->andFilter[$name]); + return isset($this->orFilter[$name]) || isset($this->andFilter[$name]); } /** @@ -170,6 +175,7 @@ public function filter($property) $returnValue = true; break; } + continue; } else { if ( $filter->filter($property) === true) { $returnValue = true; @@ -184,6 +190,7 @@ public function filter($property) if( $filter($property) === false) { return false; } + continue; } else { if( $filter->filter($property) === false) { return false; diff --git a/test/HydratorTest.php b/test/HydratorTest.php index d16193ef0..4f178daf2 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -274,7 +274,7 @@ public function testHydratorClassMethodsManipulateFilter() $this->assertFalse(isset($datas['hasBar'])); //method is hasBar } - public function testHydratorClassMethodsWithCostumFilter() + public function testHydratorClassMethodsWithCustomFilter() { $hydrator = new ClassMethods(false); $datas = $hydrator->extract($this->classMethodsCamelCase); From 02528a748582445a594aaac0fc5ae3fcc40b0d65 Mon Sep 17 00:00:00 2001 From: ingo Date: Tue, 8 Jan 2013 01:11:17 +0100 Subject: [PATCH 51/63] Moved filter implementation to abstract hydrator --- src/Hydrator/AbstractHydrator.php | 61 +++++++++++++++++++++++++++++++ src/Hydrator/ClassMethods.php | 58 ----------------------------- 2 files changed, 61 insertions(+), 58 deletions(-) diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php index 056ade4b0..5d5dd56a4 100644 --- a/src/Hydrator/AbstractHydrator.php +++ b/src/Hydrator/AbstractHydrator.php @@ -12,6 +12,7 @@ use ArrayObject; use Zend\Stdlib\Exception; +use Zend\Stdlib\Hydrator\Filter\FilterComposite; use Zend\Stdlib\Hydrator\StrategyEnabledInterface; use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; @@ -29,12 +30,19 @@ abstract class AbstractHydrator implements HydratorInterface, StrategyEnabledInt */ protected $strategies; + /** + * Composite to filter the methods, that need to be hydrated + * @var Filter\FilterComposite + */ + protected $filterComposite; + /** * Initializes a new instance of this class. */ public function __construct() { $this->strategies = new ArrayObject(); + $this->filterComposite = new FilterComposite(); } /** @@ -128,4 +136,57 @@ public function hydrateValue($name, $value) } return $value; } + + /** + * Add a new filter to take care of what needs to be hydrated. + * To exclude e.g. the method getServiceLocator: + * + * + * $composite->addFilter("servicelocator", + * function($property) { + * list($class, $method) = explode('::', $property); + * if ($method === 'getServiceLocator') { + * return false; + * } + * return true; + * }, FilterComposite::CONDITION_AND + * ); + * + * + * @param string $name Index in the composite + * @param callable|Zend\Stdlib\Hydrator\Filter\FilterInterface $filter + * @param int $condition + * @return Filter\FilterComposite + */ + public function addFilter($name, $filter, $condition = FilterComposite::CONDITION_OR) + { + return $this->filterComposite->addFilter($name, $filter, $condition); + } + + /** + * Check whether a specific filter exists at key $name or not + * + * @param string $name Index in the composite + * @return bool + */ + public function hasFilter($name) + { + return $this->filterComposite->hasFilter($name); + } + + /** + * Remove a filter from the composition. + * To not extract "has" methods, you simply need to unregister it + * + * + * $filterComposite->removeFilter('has'); + * + * + * @param $name + * @return Filter\FilterComposite + */ + public function removeFilter($name) + { + return $this->filterComposite->removeFilter($name); + } } diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index 54d3be736..4cb37c4e4 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -11,7 +11,6 @@ namespace Zend\Stdlib\Hydrator; use Zend\Stdlib\Exception; -use Zend\Stdlib\Hydrator\Filter\FilterComposite; use Zend\Stdlib\Hydrator\Filter\GetFilter; use Zend\Stdlib\Hydrator\Filter\HasFilter; use Zend\Stdlib\Hydrator\Filter\IsFilter; @@ -29,12 +28,6 @@ class ClassMethods extends AbstractHydrator implements HydratorOptionsInterface */ protected $underscoreSeparatedKeys = true; - /** - * Composite to filter the methods, that need to be hydrated - * @var Filter\FilterComposite - */ - protected $filterComposite; - /** * Define if extract values will use camel case or name with underscore * @param boolean|array $underscoreSeparatedKeys @@ -44,7 +37,6 @@ public function __construct($underscoreSeparatedKeys = true) parent::__construct(); $this->setUnderscoreSeparatedKeys($underscoreSeparatedKeys); - $this->filterComposite = new FilterComposite(); $this->filterComposite->addFilter("is", new IsFilter()); $this->filterComposite->addFilter("has", new HasFilter()); $this->filterComposite->addFilter("get", new GetFilter()); @@ -174,54 +166,4 @@ public function hydrate(array $data, $object) return $object; } - /** - * Add a new filter to take care of what needs to be hydrated. - * To exclude e.g. the method getServiceLocator: - * - * - * $composite->addFilter("servicelocator", - * function($property) { - * list($class, $method) = explode('::', $property); - * if ($method === 'getServiceLocator') { - * return false; - * } - * return true; - * }, FilterComposite::CONDITION_AND - * ); - * - * - * @param string $name Index in the composite - * @param callable|Zend\Stdlib\Hydrator\Filter\FilterInterface $filter - * @param int $condition - */ - public function addFilter($name, $filter, $condition = FilterComposite::CONDITION_OR) - { - $this->filterComposite->addFilter($name, $filter, $condition); - } - - /** - * Check whether a specific filter exists at key $name or not - * - * @param string $name Index in the composite - * @return bool - */ - public function hasFilter($name) - { - return $this->filterComposite->hasFilter($name); - } - - /** - * Remove a filter from the composition. - * To not extract "has" methods, you simply need to unregister it - * - * - * $filterComposite->removeFilter('has'); - * - * - * @param $name - */ - public function removeFilter($name) - { - $this->filterComposite->removeFilter($name); - } } From 09d682ec4c2d3c88a706cf96463ae3697d9dc3a3 Mon Sep 17 00:00:00 2001 From: ingo Date: Tue, 8 Jan 2013 22:09:42 +0100 Subject: [PATCH 52/63] Fixed complex composite --- src/Hydrator/Filter/FilterComposite.php | 11 ++++-- test/TestAsset/FilterCompositeTest.php | 49 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/Hydrator/Filter/FilterComposite.php b/src/Hydrator/Filter/FilterComposite.php index 03767936b..00a99477a 100644 --- a/src/Hydrator/Filter/FilterComposite.php +++ b/src/Hydrator/Filter/FilterComposite.php @@ -158,16 +158,21 @@ public function hasFilter($name) */ public function filter($property) { + $andCount = count($this->andFilter); + $orCount = count($this->orFilter); // return true if no filters are registered if ( - count($this->orFilter) === 0 && - count($this->andFilter) === 0 + $orCount === 0 && + $andCount === 0 ) { return true; + } elseif ($orCount === 0 && $andCount !== 0) { + $returnValue = true; + } else { + $returnValue = false; } // Check if 1 from the or filters return true - $returnValue = false; foreach($this->orFilter as $filter) { if (is_callable($filter)) { if( $filter($property) === true) diff --git a/test/TestAsset/FilterCompositeTest.php b/test/TestAsset/FilterCompositeTest.php index 6efbbfaa7..cf278afac 100644 --- a/test/TestAsset/FilterCompositeTest.php +++ b/test/TestAsset/FilterCompositeTest.php @@ -106,6 +106,55 @@ public function testConstructorInjection() $this->assertTrue($filterComposite->filter('hasFoo')); } + public function testWithOnlyAndFiltersAdded() + { + $filter = new FilterComposite(); + $filter->addFilter("foobarbaz", function($property) { + return true; + }, FilterComposite::CONDITION_AND); + $filter->addFilter("foobar", function($property) { + return true; + }, FilterComposite::CONDITION_AND); + $this->assertTrue($filter->filter("foo")); + } + + public function testWithOnlyOrFiltersAdded() + { + $filter = new FilterComposite(); + $filter->addFilter("foobarbaz", function($property) { + return true; + }); + $filter->addFilter("foobar", function($property) { + return false; + }); + $this->assertTrue($filter->filter("foo")); + } + + public function testWithComplexCompositeAdded() + { + $filter1 = new FilterComposite(); + $filter1->addFilter("foobarbaz", function($property) { + return true; + }); + $filter1->addFilter("foobar", function($property) { + return false; + }); + $filter2 = new FilterComposite(); + $filter2->addFilter("bar", function($property) { + return true; + }, FilterComposite::CONDITION_AND); + $filter2->addFilter("barblubb", function($property) { + return true; + }, FilterComposite::CONDITION_AND); + $this->assertTrue($filter1->filter("foo")); + $this->assertTrue($filter2->filter("foo")); + $filter1->addFilter("bar", $filter2); + $this->assertTrue($filter1->filter("blubb")); + + $filter1->addFilter("blubb", function($property) { return false; }, FilterComposite::CONDITION_AND); + $this->assertFalse($filter1->filter("test")); + } + /** * @expectedException Zend\Stdlib\Exception\InvalidArgumentException * @expectedExceptionMessage The value of test should be either a callable From d23d89d0cbeb2b122e88f765c6790bd041773605 Mon Sep 17 00:00:00 2001 From: ingo Date: Tue, 8 Jan 2013 23:37:41 +0100 Subject: [PATCH 53/63] Added filter to arrayserializable --- src/Hydrator/AbstractHydrator.php | 10 +++++ src/Hydrator/ArraySerializable.php | 9 ++++- test/HydratorTest.php | 59 ++++++++++++++++++++++++++++ test/TestAsset/ArraySerializable.php | 54 +++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 test/TestAsset/ArraySerializable.php diff --git a/src/Hydrator/AbstractHydrator.php b/src/Hydrator/AbstractHydrator.php index 5d5dd56a4..19ac954d7 100644 --- a/src/Hydrator/AbstractHydrator.php +++ b/src/Hydrator/AbstractHydrator.php @@ -137,6 +137,16 @@ public function hydrateValue($name, $value) return $value; } + /** + * Get the filter instance + * + * @return Filter\FilterComposite + */ + public function getFilter() + { + return $this->filterComposite; + } + /** * Add a new filter to take care of what needs to be hydrated. * To exclude e.g. the method getServiceLocator: diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php index fbe214db9..da16c4981 100644 --- a/src/Hydrator/ArraySerializable.php +++ b/src/Hydrator/ArraySerializable.php @@ -39,9 +39,14 @@ public function extract($object) $self = $this; $data = $object->getArrayCopy(); - array_walk($data, function (&$value, $name) use ($self) { - $value = $self->extractValue($name, $value); + array_walk($data, function (&$value, $name) use ($self, &$data) { + if (!$self->getFilter()->filter($name)) { + unset($data[$name]); + } else { + $value = $self->extractValue($name, $value); + } }); + #var_dump($data); return $data; } diff --git a/test/HydratorTest.php b/test/HydratorTest.php index 4f178daf2..44dc16f3a 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -293,4 +293,63 @@ function($property) { $datas = $hydrator->extract($this->classMethodsCamelCase); $this->assertFalse(isset($datas['hasFoo'])); } + + public function testArraySerializableFilter() + { + $hydrator = new \Zend\Stdlib\Hydrator\ArraySerializable(); + $serializable = new \ZendTest\Stdlib\TestAsset\ArraySerializable(); + $this->assertSame( + array( + "foo" => "bar", + "bar" => "foo", + "blubb" => "baz", + "quo" => "blubb" + ), + $hydrator->extract($serializable) + ); + + $hydrator->addFilter("foo", function($property) { + if ($property == "foo") { + return false; + } + return true; + }); + + $this->assertSame( + array( + "bar" => "foo", + "blubb" => "baz", + "quo" => "blubb" + ), + $hydrator->extract($serializable) + ); + + $hydrator->addFilter("len", function($property) { + if (strlen($property) !== 3) { + return false; + } + return true; + }, FilterComposite::CONDITION_AND); + + $this->assertSame( + array( + "bar" => "foo", + "quo" => "blubb" + ), + $hydrator->extract($serializable) + ); + + $hydrator->removeFilter("len"); + $hydrator->removeFilter("foo"); + + $this->assertSame( + array( + "foo" => "bar", + "bar" => "foo", + "blubb" => "baz", + "quo" => "blubb" + ), + $hydrator->extract($serializable) + ); + } } diff --git a/test/TestAsset/ArraySerializable.php b/test/TestAsset/ArraySerializable.php new file mode 100644 index 000000000..498099c5f --- /dev/null +++ b/test/TestAsset/ArraySerializable.php @@ -0,0 +1,54 @@ +data = array( + "foo" => "bar", + "bar" => "foo", + "blubb" => "baz", + "quo" => "blubb" + ); + } + + /** + * Exchange internal values from provided array + * + * @param array $array + * @return void + */ + public function exchangeArray(array $array) + { + $this->data = $array; + } + + /** + * Return an array representation of the object + * + * @return array + */ + public function getArrayCopy() + { + return $this->data; + } +} + From d7c2600e4a5325687463998af21465b5080f1250 Mon Sep 17 00:00:00 2001 From: ingo Date: Tue, 8 Jan 2013 23:54:00 +0100 Subject: [PATCH 54/63] Filter feature to object property hydrator --- src/Hydrator/ObjectProperty.php | 8 +++++-- test/HydratorTest.php | 20 +++++++++++++++--- test/TestAsset/ObjectProperty.php | 35 +++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 test/TestAsset/ObjectProperty.php diff --git a/src/Hydrator/ObjectProperty.php b/src/Hydrator/ObjectProperty.php index a77e1e792..dd5f1a0dd 100644 --- a/src/Hydrator/ObjectProperty.php +++ b/src/Hydrator/ObjectProperty.php @@ -38,8 +38,12 @@ public function extract($object) $self = $this; $data = get_object_vars($object); - array_walk($data, function (&$value, $name) use ($self) { - $value = $self->extractValue($name, $value); + array_walk($data, function (&$value, $name) use ($self, &$data) { + if (!$self->getFilter()->filter($name)) { + unset($data[$name]); + } else { + $value = $self->extractValue($name, $value); + } }); return $data; } diff --git a/test/HydratorTest.php b/test/HydratorTest.php index 44dc16f3a..f51b09355 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -12,14 +12,19 @@ use Zend\Stdlib\Hydrator\ClassMethods; use Zend\Stdlib\Hydrator\Reflection; +use Zend\Stdlib\Hydrator\ObjectProperty; +use Zend\Stdlib\Hydrator\ArraySerializable; use Zend\Stdlib\Hydrator\Filter\FilterComposite; use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCase; use ZendTest\Stdlib\TestAsset\ClassMethodsUnderscore; use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCaseMissing; use ZendTest\Stdlib\TestAsset\Reflection as ReflectionAsset; +use ZendTest\Stdlib\TestAsset\ObjectProperty as ObjectPropertyAsset; +use ZendTest\Stdlib\TestAsset\ArraySerializable as ArraySerializableAsset; use Zend\Stdlib\Hydrator\Strategy\DefaultStrategy; use Zend\Stdlib\Hydrator\Strategy\SerializableStrategy; + /** * @category Zend * @package Zend_Stdlib @@ -294,10 +299,11 @@ function($property) { $this->assertFalse(isset($datas['hasFoo'])); } - public function testArraySerializableFilter() + /** + * @dataProvider filterProvider + */ + public function testArraySerializableFilter($hydrator, $serializable) { - $hydrator = new \Zend\Stdlib\Hydrator\ArraySerializable(); - $serializable = new \ZendTest\Stdlib\TestAsset\ArraySerializable(); $this->assertSame( array( "foo" => "bar", @@ -352,4 +358,12 @@ public function testArraySerializableFilter() $hydrator->extract($serializable) ); } + + public function filterProvider() + { + return array( + array(new ObjectProperty(), new ObjectPropertyAsset), + array(new ArraySerializable(), new ArraySerializableAsset) + ); + } } diff --git a/test/TestAsset/ObjectProperty.php b/test/TestAsset/ObjectProperty.php new file mode 100644 index 000000000..6b73900ee --- /dev/null +++ b/test/TestAsset/ObjectProperty.php @@ -0,0 +1,35 @@ +foo = "bar"; + $this->bar = "foo"; + $this->blubb = "baz"; + $this->quo = "blubb"; + } + +} + From 7be4274ae18df4782c40a104aeb62c5655fcb819 Mon Sep 17 00:00:00 2001 From: ingo Date: Tue, 8 Jan 2013 23:56:33 +0100 Subject: [PATCH 55/63] Fixed code style --- src/Hydrator/Filter/FilterComposite.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Hydrator/Filter/FilterComposite.php b/src/Hydrator/Filter/FilterComposite.php index 00a99477a..cae986bc0 100644 --- a/src/Hydrator/Filter/FilterComposite.php +++ b/src/Hydrator/Filter/FilterComposite.php @@ -162,8 +162,8 @@ public function filter($property) $orCount = count($this->orFilter); // return true if no filters are registered if ( - $orCount === 0 && - $andCount === 0 + $orCount === 0 + && $andCount === 0 ) { return true; } elseif ($orCount === 0 && $andCount !== 0) { From bbbe6bf42d455e8835c324f7db3f6bf4c85e1786 Mon Sep 17 00:00:00 2001 From: ingo Date: Wed, 9 Jan 2013 00:37:25 +0100 Subject: [PATCH 56/63] Added filter to reflection --- src/Hydrator/Reflection.php | 3 +++ test/HydratorTest.php | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Hydrator/Reflection.php b/src/Hydrator/Reflection.php index b372665d1..d46abce7d 100644 --- a/src/Hydrator/Reflection.php +++ b/src/Hydrator/Reflection.php @@ -37,6 +37,9 @@ public function extract($object) $result = array(); foreach (self::getReflProperties($object) as $property) { $propertyName = $property->getName(); + if (!$this->filterComposite->filter($propertyName)) { + continue; + } $value = $property->getValue($object); $result[$propertyName] = $this->extractValue($propertyName, $value); diff --git a/test/HydratorTest.php b/test/HydratorTest.php index f51b09355..17ceef560 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -19,6 +19,7 @@ use ZendTest\Stdlib\TestAsset\ClassMethodsUnderscore; use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCaseMissing; use ZendTest\Stdlib\TestAsset\Reflection as ReflectionAsset; +use ZendTest\Stdlib\TestAsset\ReflectionFilter; use ZendTest\Stdlib\TestAsset\ObjectProperty as ObjectPropertyAsset; use ZendTest\Stdlib\TestAsset\ArraySerializable as ArraySerializableAsset; use Zend\Stdlib\Hydrator\Strategy\DefaultStrategy; @@ -363,7 +364,8 @@ public function filterProvider() { return array( array(new ObjectProperty(), new ObjectPropertyAsset), - array(new ArraySerializable(), new ArraySerializableAsset) + array(new ArraySerializable(), new ArraySerializableAsset), + array(new Reflection(), new ReflectionFilter) ); } } From e822d1f216155ccaa50821ebdf212f21bd082b3a Mon Sep 17 00:00:00 2001 From: ingo Date: Wed, 9 Jan 2013 01:09:12 +0100 Subject: [PATCH 57/63] Added number of parameter filter. Fixed zendframework/zf2#3352 --- src/Hydrator/ClassMethods.php | 3 + src/Hydrator/Filter/FilterInterface.php | 7 +++ .../Filter/NumberOfParameterFilter.php | 60 +++++++++++++++++++ test/HydratorTest.php | 17 ++++++ .../ClassMethodsInvalidParameter.php | 43 +++++++++++++ test/TestAsset/ReflectionFilter.php | 35 +++++++++++ 6 files changed, 165 insertions(+) create mode 100644 src/Hydrator/Filter/NumberOfParameterFilter.php create mode 100644 test/TestAsset/ClassMethodsInvalidParameter.php create mode 100644 test/TestAsset/ReflectionFilter.php diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index 4cb37c4e4..d78dfb847 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -11,9 +11,11 @@ namespace Zend\Stdlib\Hydrator; use Zend\Stdlib\Exception; +use Zend\Stdlib\Hydrator\Filter\FilterComposite; use Zend\Stdlib\Hydrator\Filter\GetFilter; use Zend\Stdlib\Hydrator\Filter\HasFilter; use Zend\Stdlib\Hydrator\Filter\IsFilter; +use Zend\Stdlib\Hydrator\Filter\NumberOfParameterFilter; /** * @category Zend @@ -40,6 +42,7 @@ public function __construct($underscoreSeparatedKeys = true) $this->filterComposite->addFilter("is", new IsFilter()); $this->filterComposite->addFilter("has", new HasFilter()); $this->filterComposite->addFilter("get", new GetFilter()); + $this->filterComposite->addFilter("parameter", new NumberOfParameterFilter(), FilterComposite::CONDITION_AND); } /** diff --git a/src/Hydrator/Filter/FilterInterface.php b/src/Hydrator/Filter/FilterInterface.php index 961ac6102..fe70feb84 100644 --- a/src/Hydrator/Filter/FilterInterface.php +++ b/src/Hydrator/Filter/FilterInterface.php @@ -16,5 +16,12 @@ */ interface FilterInterface { + /** + * Should return true, if the given filter + * does not match + * + * @param string $property The name of the property + * @return bool + */ public function filter($property); } diff --git a/src/Hydrator/Filter/NumberOfParameterFilter.php b/src/Hydrator/Filter/NumberOfParameterFilter.php new file mode 100644 index 000000000..2a0479b5a --- /dev/null +++ b/src/Hydrator/Filter/NumberOfParameterFilter.php @@ -0,0 +1,60 @@ +numberOfParameters = 0; + } + + /** + * @param string $property the name of the property + * @throws InvalidArgumentException + */ + public function filter($property) + { + try { + $reflectionMethod = new ReflectionMethod($property); + } catch( ReflectionException $exception) { + throw new InvalidArgumentException( + "Method $property doesn't exist" + ); + } + + if ($reflectionMethod->getNumberOfParameters() !== $this->numberOfParameters) { + return false; + } + + return true; + } +} + diff --git a/test/HydratorTest.php b/test/HydratorTest.php index 17ceef560..261c6b146 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -18,6 +18,7 @@ use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCase; use ZendTest\Stdlib\TestAsset\ClassMethodsUnderscore; use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCaseMissing; +use ZendTest\Stdlib\TestAsset\ClassMethodsInvalidParameter; use ZendTest\Stdlib\TestAsset\Reflection as ReflectionAsset; use ZendTest\Stdlib\TestAsset\ReflectionFilter; use ZendTest\Stdlib\TestAsset\ObjectProperty as ObjectPropertyAsset; @@ -50,6 +51,11 @@ class HydratorTest extends \PHPUnit_Framework_TestCase */ protected $classMethodsUnderscore; + /** + * @var ClassMethodsInvalidParameter + */ + protected $classMethodsInvalidParameter; + /** * @var ReflectionAsset */ @@ -61,6 +67,7 @@ public function setUp() $this->classMethodsCamelCaseMissing = new ClassMethodsCamelCaseMissing(); $this->classMethodsUnderscore = new ClassMethodsUnderscore(); $this->reflection = new ReflectionAsset; + $this->classMethodsInvalidParameter = new ClassMethodsInvalidParameter(); } public function testInitiateValues() @@ -368,4 +375,14 @@ public function filterProvider() array(new Reflection(), new ReflectionFilter) ); } + + public function testHydratorClassMethodsWithInvalidNumberOfParameters() + { + $hydrator = new ClassMethods(false); + $datas = $hydrator->extract($this->classMethodsInvalidParameter); + + $this->assertTrue($datas['hasBar']); + $this->assertEquals('Bar', $datas['foo']); + $this->assertFalse($datas['isBla']); + } } diff --git a/test/TestAsset/ClassMethodsInvalidParameter.php b/test/TestAsset/ClassMethodsInvalidParameter.php new file mode 100644 index 000000000..cf9338865 --- /dev/null +++ b/test/TestAsset/ClassMethodsInvalidParameter.php @@ -0,0 +1,43 @@ +foo = "bar"; + $this->bar = "foo"; + $this->blubb = "baz"; + $this->quo = "blubb"; + } + +} + From 25fa34ad67c1bbb67eadcdabcceed53c72d803ad Mon Sep 17 00:00:00 2001 From: ingo Date: Fri, 11 Jan 2013 01:20:50 +0100 Subject: [PATCH 58/63] Implemented FilterProviderInterface and MethodMatchFilter --- src/Hydrator/ClassMethods.php | 19 ++++- .../Filter/FilterProviderInterface.php | 25 +++++++ src/Hydrator/Filter/MethodMatchFilter.php | 53 ++++++++++++++ test/HydratorTest.php | 11 +++ .../ClassMethodsFilterProviderInterface.php | 70 +++++++++++++++++++ 5 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 src/Hydrator/Filter/FilterProviderInterface.php create mode 100644 src/Hydrator/Filter/MethodMatchFilter.php create mode 100644 test/TestAsset/ClassMethodsFilterProviderInterface.php diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index d78dfb847..0c6ffb142 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -12,6 +12,8 @@ use Zend\Stdlib\Exception; use Zend\Stdlib\Hydrator\Filter\FilterComposite; +use Zend\Stdlib\Hydrator\Filter\FilterProviderInterface; +use Zend\Stdlib\Hydrator\Filter\MethodMatchFilter; use Zend\Stdlib\Hydrator\Filter\GetFilter; use Zend\Stdlib\Hydrator\Filter\HasFilter; use Zend\Stdlib\Hydrator\Filter\IsFilter; @@ -101,6 +103,21 @@ public function extract($object) )); } + $filter = null; + if ($object instanceof FilterProviderInterface) { + $filter = $object->getFilter(); + if ($filter instanceof FilterComposite) + { + $filter->addFilter( + "getfilter", + new MethodMatchFilter("getFilter"), + FilterComposite::CONDITION_AND + ); + } + } else { + $filter = $this->filterComposite; + } + $transform = function ($letters) { $letter = array_shift($letters); return '_' . strtolower($letter); @@ -110,7 +127,7 @@ public function extract($object) foreach ($methods as $method) { if ( - !$this->filterComposite->filter( + !$filter->filter( get_class($object) . '::' . $method ) ) { diff --git a/src/Hydrator/Filter/FilterProviderInterface.php b/src/Hydrator/Filter/FilterProviderInterface.php new file mode 100644 index 000000000..562b6fb6f --- /dev/null +++ b/src/Hydrator/Filter/FilterProviderInterface.php @@ -0,0 +1,25 @@ +method = $method; + $this->exclude = $exclude; + } + + public function filter($property) + { + $pos = strpos($property, '::'); + if ($pos !== false) { + $pos += 2; + } else { + $pos = 0; + } + if (substr($property, $pos) === $this->method) { + return $this->exclude ? false : true; + } + return $this->exclude ? true : false; + } +} diff --git a/test/HydratorTest.php b/test/HydratorTest.php index 261c6b146..f67259c6f 100644 --- a/test/HydratorTest.php +++ b/test/HydratorTest.php @@ -16,6 +16,7 @@ use Zend\Stdlib\Hydrator\ArraySerializable; use Zend\Stdlib\Hydrator\Filter\FilterComposite; use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCase; +use ZendTest\Stdlib\TestAsset\ClassMethodsFilterProviderInterface; use ZendTest\Stdlib\TestAsset\ClassMethodsUnderscore; use ZendTest\Stdlib\TestAsset\ClassMethodsCamelCaseMissing; use ZendTest\Stdlib\TestAsset\ClassMethodsInvalidParameter; @@ -385,4 +386,14 @@ public function testHydratorClassMethodsWithInvalidNumberOfParameters() $this->assertEquals('Bar', $datas['foo']); $this->assertFalse($datas['isBla']); } + + public function testObjectBasedFilters() + { + $hydrator = new ClassMethods(false); + $foo = new ClassMethodsFilterProviderInterface(); + $data = $hydrator->extract($foo); + $this->assertFalse(array_key_exists("filter", $data)); + $this->assertSame("bar", $data["foo"]); + $this->assertSame("foo", $data["bar"]); + } } diff --git a/test/TestAsset/ClassMethodsFilterProviderInterface.php b/test/TestAsset/ClassMethodsFilterProviderInterface.php new file mode 100644 index 000000000..b24b8210a --- /dev/null +++ b/test/TestAsset/ClassMethodsFilterProviderInterface.php @@ -0,0 +1,70 @@ +addFilter("get", new GetFilter()); + $excludes = new FilterComposite(); + $excludes->addFilter( + "servicemanager", + new MethodMatchFilter("getServiceManager"), + FilterComposite::CONDITION_AND + ); + $excludes->addFilter( + "eventmanager", + new MethodMatchFilter("getEventManager"), + FilterComposite::CONDITION_AND + ); + $filterComposite->addFilter("excludes", $excludes, FilterComposite::CONDITION_AND); + + return $filterComposite; + } +} From 86896f80c9ff95c87e7f56619734a9307f021eea Mon Sep 17 00:00:00 2001 From: ingo Date: Fri, 11 Jan 2013 02:02:27 +0100 Subject: [PATCH 59/63] Simplified code --- src/Hydrator/ClassMethods.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index 0c6ffb142..2255b232c 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -105,15 +105,10 @@ public function extract($object) $filter = null; if ($object instanceof FilterProviderInterface) { - $filter = $object->getFilter(); - if ($filter instanceof FilterComposite) - { - $filter->addFilter( - "getfilter", - new MethodMatchFilter("getFilter"), - FilterComposite::CONDITION_AND - ); - } + $filter = new FilterComposite( + array($object->getFilter()), + array(new MethodMatchFilter("getFilter")) + ); } else { $filter = $this->filterComposite; } From a9ddfc98c20c9ab629bb61826aa404146ad1a141 Mon Sep 17 00:00:00 2001 From: ingo Date: Sat, 12 Jan 2013 20:25:15 +0100 Subject: [PATCH 60/63] Removed dump --- src/Hydrator/ArraySerializable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Hydrator/ArraySerializable.php b/src/Hydrator/ArraySerializable.php index da16c4981..8332a983b 100644 --- a/src/Hydrator/ArraySerializable.php +++ b/src/Hydrator/ArraySerializable.php @@ -46,7 +46,7 @@ public function extract($object) $value = $self->extractValue($name, $value); } }); - #var_dump($data); + return $data; } From 32ec458d09cc21f0d25ce2f1f3f68390ebcbae26 Mon Sep 17 00:00:00 2001 From: ingo Date: Sun, 13 Jan 2013 21:51:46 +0100 Subject: [PATCH 61/63] CS fixes --- src/Hydrator/ClassMethods.php | 14 +++++---- src/Hydrator/Filter/FilterComposite.php | 30 ++++++++----------- .../Filter/NumberOfParameterFilter.php | 1 - 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/Hydrator/ClassMethods.php b/src/Hydrator/ClassMethods.php index 2255b232c..42681737d 100644 --- a/src/Hydrator/ClassMethods.php +++ b/src/Hydrator/ClassMethods.php @@ -48,7 +48,7 @@ public function __construct($underscoreSeparatedKeys = true) } /** - * @param array|\Traversable $options + * @param array|\Traversable $options * @return ClassMethods * @throws Exception\InvalidArgumentException */ @@ -69,12 +69,13 @@ public function setOptions($options) } /** - * @param boolean $underscoreSeparatedKeys + * @param boolean $underscoreSeparatedKeys * @return ClassMethods */ public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys) { $this->underscoreSeparatedKeys = $underscoreSeparatedKeys; + return $this; } @@ -91,7 +92,7 @@ public function getUnderscoreSeparatedKeys() * * Extracts the getter/setter of the given $object. * - * @param object $object + * @param object $object * @return array * @throws Exception\BadMethodCallException for a non-object $object */ @@ -115,6 +116,7 @@ public function extract($object) $transform = function ($letters) { $letter = array_shift($letters); + return '_' . strtolower($letter); }; $attributes = array(); @@ -149,8 +151,8 @@ public function extract($object) * * Hydrates an object by getter/setter methods of the object. * - * @param array $data - * @param object $object + * @param array $data + * @param object $object * @return object * @throws Exception\BadMethodCallException for a non-object $object */ @@ -164,6 +166,7 @@ public function hydrate(array $data, $object) $transform = function ($letters) { $letter = substr(array_shift($letters), 1, 1); + return ucfirst($letter); }; @@ -178,6 +181,7 @@ public function hydrate(array $data, $object) $object->$method($value); } } + return $object; } diff --git a/src/Hydrator/Filter/FilterComposite.php b/src/Hydrator/Filter/FilterComposite.php index cae986bc0..7531d5bd1 100644 --- a/src/Hydrator/Filter/FilterComposite.php +++ b/src/Hydrator/Filter/FilterComposite.php @@ -48,7 +48,7 @@ public function __construct($orFilter = array(), $andFilter = array()) { array_walk($orFilter, function($value, $key) { - if( + if ( !is_callable($value) && !$value instanceof FilterInterface ) { @@ -62,7 +62,7 @@ function($value, $key) { array_walk($andFilter, function($value, $key) { - if( + if ( !is_callable($value) && !$value instanceof FilterInterface ) { @@ -94,9 +94,9 @@ function($value, $key) { * ); * * - * @param string $name - * @param callable|FilterInterface $filter - * @param int $condition Can be either FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND + * @param string $name + * @param callable|FilterInterface $filter + * @param int $condition Can be either FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND * @throws InvalidArgumentException * @return FilterComposite */ @@ -126,11 +126,11 @@ public function addFilter($name, $filter, $condition = self::CONDITION_OR) */ public function removeFilter($name) { - if( isset($this->orFilter[$name])) { + if (isset($this->orFilter[$name])) { unset($this->orFilter[$name]); } - if( isset($this->andFilter[$name])) { + if (isset($this->andFilter[$name])) { unset($this->andFilter[$name]); } @@ -161,10 +161,7 @@ public function filter($property) $andCount = count($this->andFilter); $orCount = count($this->orFilter); // return true if no filters are registered - if ( - $orCount === 0 - && $andCount === 0 - ) { + if ($orCount === 0 && $andCount === 0) { return true; } elseif ($orCount === 0 && $andCount !== 0) { $returnValue = true; @@ -173,10 +170,9 @@ public function filter($property) } // Check if 1 from the or filters return true - foreach($this->orFilter as $filter) { + foreach ($this->orFilter as $filter) { if (is_callable($filter)) { - if( $filter($property) === true) - { + if ( $filter($property) === true) { $returnValue = true; break; } @@ -190,14 +186,14 @@ public function filter($property) } // Check if all of the and condition return true - foreach($this->andFilter as $filter) { + foreach ($this->andFilter as $filter) { if (is_callable($filter)) { - if( $filter($property) === false) { + if ($filter($property) === false) { return false; } continue; } else { - if( $filter->filter($property) === false) { + if ($filter->filter($property) === false) { return false; } } diff --git a/src/Hydrator/Filter/NumberOfParameterFilter.php b/src/Hydrator/Filter/NumberOfParameterFilter.php index 2a0479b5a..3c2e0b94a 100644 --- a/src/Hydrator/Filter/NumberOfParameterFilter.php +++ b/src/Hydrator/Filter/NumberOfParameterFilter.php @@ -57,4 +57,3 @@ public function filter($property) return true; } } - From 196c1dad9b74b13defbb97ab09cba6707db3b9db Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 18 Jan 2013 15:09:18 -0600 Subject: [PATCH 62/63] [zendframework/zf2#3230] CS fixes - Trailing whitespace --- src/Hydrator/Strategy/ClosureStrategy.php | 10 +++++----- test/HydratorClosureStrategyTest.php | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Hydrator/Strategy/ClosureStrategy.php b/src/Hydrator/Strategy/ClosureStrategy.php index 9c1a694a7..002ca9f70 100644 --- a/src/Hydrator/Strategy/ClosureStrategy.php +++ b/src/Hydrator/Strategy/ClosureStrategy.php @@ -25,7 +25,7 @@ class ClosureStrategy implements StrategyInterface * @var callable */ protected $extractFunc = null; - + /** * Function, used in hydrate method, default: * function($value) { @@ -34,7 +34,7 @@ class ClosureStrategy implements StrategyInterface * @var callable */ protected $hydrateFunc = null; - + /** * You can describe how your values will extract and hydrate, like this: * $hydrator->addStrategy('category', new ClosureStrategy( @@ -45,9 +45,9 @@ class ClosureStrategy implements StrategyInterface * return new Category((int)$value); * } * )); - * + * * @param callable $extractFunc - anonymous function, that extract values - * from object + * from object * @param callable $hydrateFunc - anonymous function, that hydrate values * into object */ @@ -77,7 +77,7 @@ public function __construct($extractFunc = null, $hydrateFunc = null) }; } } - + /** * Converts the given value so that it can be extracted by the hydrator. * diff --git a/test/HydratorClosureStrategyTest.php b/test/HydratorClosureStrategyTest.php index fd8601dae..ae4d227ef 100644 --- a/test/HydratorClosureStrategyTest.php +++ b/test/HydratorClosureStrategyTest.php @@ -21,7 +21,7 @@ */ class HydratorClosureStrategyTest extends \PHPUnit_Framework_TestCase { - + /** * The hydrator that is used during testing. * @@ -33,7 +33,7 @@ public function setUp() { $this->hydrator = new ObjectProperty(); } - + public function testAddingStrategy() { $this->assertAttributeCount(0, 'strategies', $this->hydrator); @@ -42,12 +42,12 @@ public function testAddingStrategy() $this->assertAttributeCount(1, 'strategies', $this->hydrator); } - + public function testCheckStrategyEmpty() { $this->assertFalse($this->hydrator->hasStrategy('myStrategy')); } - + public function testCheckStrategyNotEmpty() { $this->hydrator->addStrategy('myStrategy', new ClosureStrategy()); @@ -88,14 +88,14 @@ function($value) { }, null )); - + $entity = new TestAsset\HydratorClosureStrategyEntity(111, 'world'); $values = $this->hydrator->extract($entity); - + $this->assertEquals(111, $values['field1']); $this->assertEquals('hello, world!', $values['field2']); } - + public function testHydratingObjects() { $this->hydrator->addStrategy('field2', new ClosureStrategy( @@ -110,17 +110,17 @@ function($value) { return new TestAsset\HydratorClosureStrategyEntity($value, sprintf('111%s', $value)); } )); - + $entity = new TestAsset\HydratorClosureStrategyEntity(111, 'world'); - + $values = $this->hydrator->extract($entity); $values['field3'] = 333; $this->assertCount(2, (array)$entity); $this->hydrator->hydrate($values, $entity); $this->assertCount(3, (array)$entity); - + $this->assertInstanceOf('ZendTest\Stdlib\TestAsset\HydratorClosureStrategyEntity', $entity->field3); } - + } From 04b932a1fb216b3933a7d8eebcf63beec708893a Mon Sep 17 00:00:00 2001 From: radnan Date: Mon, 21 Jan 2013 17:44:00 -0600 Subject: [PATCH 63/63] string/int safe inArray implementation --- src/ArrayUtils.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/ArrayUtils.php b/src/ArrayUtils.php index b2870efe0..ff4bb67db 100644 --- a/src/ArrayUtils.php +++ b/src/ArrayUtils.php @@ -164,6 +164,36 @@ public static function isHashTable($value, $allowEmpty = false) return (array_values($value) !== $value); } + /** + * Checks if a value exists in an array. + * + * Due to "foo" == 0 === TRUE with in_array when strict = false, an option + * has been added to prevent this. When $strict = 0/false, the most secure + * non-strict check is implemented. if $strict = -1, the default in_array + * non-strict behaviour is used. + * + * @param mixed $needle + * @param array $haystack + * @param int|bool $strict + * @return bool + */ + public static function inArray($needle, array $haystack, $strict = false) + { + if (!$strict) { + if (is_int($needle) || is_float($needle)) { + $needle = (string) $needle; + } + if (is_string($needle)) { + foreach ($haystack as &$h) { + if (is_int($h) || is_float($h)) { + $h = (string) $h; + } + } + } + } + return in_array($needle, $haystack, $strict); + } + /** * Convert an iterator to an array. *