This is a drop-in replacement for our use-case due to laminas-zendframework-bridge.
<file>lib/system/api/symfony/polyfill-php72/README.md</file>
<file>lib/system/api/symfony/polyfill-php72/bootstrap.php</file>
<file>lib/system/api/symfony/polyfill-php72/composer.json</file>
+ <file>lib/system/api/zend/ProgressBar/Adapter/AbstractAdapter.php</file>
+ <file>lib/system/api/zend/ProgressBar/Adapter/Console.php</file>
+ <file>lib/system/api/zend/ProgressBar/Adapter/Exception/ExceptionInterface.php</file>
+ <file>lib/system/api/zend/ProgressBar/Adapter/Exception/InvalidArgumentException.php</file>
+ <file>lib/system/api/zend/ProgressBar/Adapter/Exception/RuntimeException.php</file>
+ <file>lib/system/api/zend/ProgressBar/Adapter/JsPull.php</file>
+ <file>lib/system/api/zend/ProgressBar/Adapter/JsPush.php</file>
+ <file>lib/system/api/zend/ProgressBar/Exception/ExceptionInterface.php</file>
+ <file>lib/system/api/zend/ProgressBar/Exception/InvalidArgumentException.php</file>
+ <file>lib/system/api/zend/ProgressBar/Exception/OutOfRangeException.php</file>
+ <file>lib/system/api/zend/ProgressBar/Exception/RuntimeException.php</file>
+ <file>lib/system/api/zend/ProgressBar/ProgressBar.php</file>
+ <file>lib/system/api/zend/ProgressBar/composer.json</file>
<file>lib/system/auth/UserAuth.class.php</file>
<file>lib/system/auth/UserAuthEmail.class.php</file>
<file>lib/system/background/job/DownloadRankImageJob.class.php</file>
"guzzlehttp/guzzle": "^7.3.0",
"paragonie/constant_time_encoding": "^2.3",
"laminas/laminas-diactoros": "^2.4",
- "laminas/laminas-httphandlerrunner": "^1.2"
+ "laminas/laminas-httphandlerrunner": "^1.2",
+ "laminas/laminas-progressbar": "^2.7"
}
}
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "b3aeea343e2f7ee79bb2d9a6b8a86799",
+ "content-hash": "f0cae9f94fb82f90b140ebbc23a4366d",
"packages": [
{
"name": "chrisjean/php-ico",
],
"time": "2020-06-03T15:52:17+00:00"
},
+ {
+ "name": "laminas/laminas-progressbar",
+ "version": "2.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laminas/laminas-progressbar.git",
+ "reference": "15f9e983276462f30d7d38660dc7488c6e3df34b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laminas/laminas-progressbar/zipball/15f9e983276462f30d7d38660dc7488c6e3df34b",
+ "reference": "15f9e983276462f30d7d38660dc7488c6e3df34b",
+ "shasum": ""
+ },
+ "require": {
+ "laminas/laminas-stdlib": "^3.2.1",
+ "laminas/laminas-zendframework-bridge": "^1.0",
+ "php": "^5.6 || ^7.0"
+ },
+ "replace": {
+ "zendframework/zend-progressbar": "self.version"
+ },
+ "require-dev": {
+ "laminas/laminas-coding-standard": "~1.0.0",
+ "laminas/laminas-json": "^2.6.1",
+ "laminas/laminas-session": "^2.8.5",
+ "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4"
+ },
+ "suggest": {
+ "laminas/laminas-json": "Laminas\\Json component",
+ "laminas/laminas-session": "To support progressbar persistent"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7.x-dev",
+ "dev-develop": "2.8.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Laminas\\ProgressBar\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Create and update progress bars in different environments",
+ "homepage": "https://laminas.dev",
+ "keywords": [
+ "laminas",
+ "progressbar"
+ ],
+ "support": {
+ "chat": "https://laminas.dev/chat",
+ "docs": "https://docs.laminas.dev/laminas-progressbar/",
+ "forum": "https://discourse.laminas.dev",
+ "issues": "https://github.com/laminas/laminas-progressbar/issues",
+ "rss": "https://github.com/laminas/laminas-progressbar/releases.atom",
+ "source": "https://github.com/laminas/laminas-progressbar"
+ },
+ "time": "2019-12-31T17:38:44+00:00"
+ },
+ {
+ "name": "laminas/laminas-stdlib",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laminas/laminas-stdlib.git",
+ "reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/2b18347625a2f06a1a485acfbc870f699dbe51c6",
+ "reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6",
+ "shasum": ""
+ },
+ "require": {
+ "laminas/laminas-zendframework-bridge": "^1.0",
+ "php": "^5.6 || ^7.0"
+ },
+ "replace": {
+ "zendframework/zend-stdlib": "self.version"
+ },
+ "require-dev": {
+ "laminas/laminas-coding-standard": "~1.0.0",
+ "phpbench/phpbench": "^0.13",
+ "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2.x-dev",
+ "dev-develop": "3.3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Laminas\\Stdlib\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "SPL extensions, array utilities, error handlers, and more",
+ "homepage": "https://laminas.dev",
+ "keywords": [
+ "laminas",
+ "stdlib"
+ ],
+ "support": {
+ "chat": "https://laminas.dev/chat",
+ "docs": "https://docs.laminas.dev/laminas-stdlib/",
+ "forum": "https://discourse.laminas.dev",
+ "issues": "https://github.com/laminas/laminas-stdlib/issues",
+ "rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
+ "source": "https://github.com/laminas/laminas-stdlib"
+ },
+ "time": "2019-12-31T17:51:15+00:00"
+ },
{
"name": "laminas/laminas-zendframework-bridge",
"version": "1.1.1",
'Laminas\\HttpHandlerRunner\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-httphandlerrunner/src/Exception/ExceptionInterface.php',
'Laminas\\HttpHandlerRunner\\Exception\\InvalidEmitterException' => $vendorDir . '/laminas/laminas-httphandlerrunner/src/Exception/InvalidEmitterException.php',
'Laminas\\HttpHandlerRunner\\RequestHandlerRunner' => $vendorDir . '/laminas/laminas-httphandlerrunner/src/RequestHandlerRunner.php',
+ 'Laminas\\ProgressBar\\Adapter\\AbstractAdapter' => $vendorDir . '/laminas/laminas-progressbar/src/Adapter/AbstractAdapter.php',
+ 'Laminas\\ProgressBar\\Adapter\\Console' => $vendorDir . '/laminas/laminas-progressbar/src/Adapter/Console.php',
+ 'Laminas\\ProgressBar\\Adapter\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-progressbar/src/Adapter/Exception/ExceptionInterface.php',
+ 'Laminas\\ProgressBar\\Adapter\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-progressbar/src/Adapter/Exception/InvalidArgumentException.php',
+ 'Laminas\\ProgressBar\\Adapter\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-progressbar/src/Adapter/Exception/RuntimeException.php',
+ 'Laminas\\ProgressBar\\Adapter\\JsPull' => $vendorDir . '/laminas/laminas-progressbar/src/Adapter/JsPull.php',
+ 'Laminas\\ProgressBar\\Adapter\\JsPush' => $vendorDir . '/laminas/laminas-progressbar/src/Adapter/JsPush.php',
+ 'Laminas\\ProgressBar\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-progressbar/src/Exception/ExceptionInterface.php',
+ 'Laminas\\ProgressBar\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-progressbar/src/Exception/InvalidArgumentException.php',
+ 'Laminas\\ProgressBar\\Exception\\OutOfRangeException' => $vendorDir . '/laminas/laminas-progressbar/src/Exception/OutOfRangeException.php',
+ 'Laminas\\ProgressBar\\Exception\\PhpEnvironmentException' => $vendorDir . '/laminas/laminas-progressbar/src/Exception/PhpEnvironmentException.php',
+ 'Laminas\\ProgressBar\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-progressbar/src/Exception/RuntimeException.php',
+ 'Laminas\\ProgressBar\\ProgressBar' => $vendorDir . '/laminas/laminas-progressbar/src/ProgressBar.php',
+ 'Laminas\\ProgressBar\\Upload\\AbstractUploadHandler' => $vendorDir . '/laminas/laminas-progressbar/src/Upload/AbstractUploadHandler.php',
+ 'Laminas\\ProgressBar\\Upload\\ApcProgress' => $vendorDir . '/laminas/laminas-progressbar/src/Upload/ApcProgress.php',
+ 'Laminas\\ProgressBar\\Upload\\SessionProgress' => $vendorDir . '/laminas/laminas-progressbar/src/Upload/SessionProgress.php',
+ 'Laminas\\ProgressBar\\Upload\\UploadHandlerInterface' => $vendorDir . '/laminas/laminas-progressbar/src/Upload/UploadHandlerInterface.php',
+ 'Laminas\\ProgressBar\\Upload\\UploadProgress' => $vendorDir . '/laminas/laminas-progressbar/src/Upload/UploadProgress.php',
+ 'Laminas\\Stdlib\\AbstractOptions' => $vendorDir . '/laminas/laminas-stdlib/src/AbstractOptions.php',
+ 'Laminas\\Stdlib\\ArrayObject' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayObject.php',
+ 'Laminas\\Stdlib\\ArraySerializableInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ArraySerializableInterface.php',
+ 'Laminas\\Stdlib\\ArrayStack' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayStack.php',
+ 'Laminas\\Stdlib\\ArrayUtils' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils.php',
+ 'Laminas\\Stdlib\\ArrayUtils\\MergeRemoveKey' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php',
+ 'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKey' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php',
+ 'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKeyInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php',
+ 'Laminas\\Stdlib\\ConsoleHelper' => $vendorDir . '/laminas/laminas-stdlib/src/ConsoleHelper.php',
+ 'Laminas\\Stdlib\\DispatchableInterface' => $vendorDir . '/laminas/laminas-stdlib/src/DispatchableInterface.php',
+ 'Laminas\\Stdlib\\ErrorHandler' => $vendorDir . '/laminas/laminas-stdlib/src/ErrorHandler.php',
+ 'Laminas\\Stdlib\\Exception\\BadMethodCallException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php',
+ 'Laminas\\Stdlib\\Exception\\DomainException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/DomainException.php',
+ 'Laminas\\Stdlib\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php',
+ 'Laminas\\Stdlib\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php',
+ 'Laminas\\Stdlib\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php',
+ 'Laminas\\Stdlib\\Exception\\LogicException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/LogicException.php',
+ 'Laminas\\Stdlib\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-stdlib/src/Exception/RuntimeException.php',
+ 'Laminas\\Stdlib\\FastPriorityQueue' => $vendorDir . '/laminas/laminas-stdlib/src/FastPriorityQueue.php',
+ 'Laminas\\Stdlib\\Glob' => $vendorDir . '/laminas/laminas-stdlib/src/Glob.php',
+ 'Laminas\\Stdlib\\Guard\\AllGuardsTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php',
+ 'Laminas\\Stdlib\\Guard\\ArrayOrTraversableGuardTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php',
+ 'Laminas\\Stdlib\\Guard\\EmptyGuardTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php',
+ 'Laminas\\Stdlib\\Guard\\NullGuardTrait' => $vendorDir . '/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php',
+ 'Laminas\\Stdlib\\InitializableInterface' => $vendorDir . '/laminas/laminas-stdlib/src/InitializableInterface.php',
+ 'Laminas\\Stdlib\\JsonSerializable' => $vendorDir . '/laminas/laminas-stdlib/src/JsonSerializable.php',
+ 'Laminas\\Stdlib\\Message' => $vendorDir . '/laminas/laminas-stdlib/src/Message.php',
+ 'Laminas\\Stdlib\\MessageInterface' => $vendorDir . '/laminas/laminas-stdlib/src/MessageInterface.php',
+ 'Laminas\\Stdlib\\ParameterObjectInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ParameterObjectInterface.php',
+ 'Laminas\\Stdlib\\Parameters' => $vendorDir . '/laminas/laminas-stdlib/src/Parameters.php',
+ 'Laminas\\Stdlib\\ParametersInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ParametersInterface.php',
+ 'Laminas\\Stdlib\\PriorityList' => $vendorDir . '/laminas/laminas-stdlib/src/PriorityList.php',
+ 'Laminas\\Stdlib\\PriorityQueue' => $vendorDir . '/laminas/laminas-stdlib/src/PriorityQueue.php',
+ 'Laminas\\Stdlib\\Request' => $vendorDir . '/laminas/laminas-stdlib/src/Request.php',
+ 'Laminas\\Stdlib\\RequestInterface' => $vendorDir . '/laminas/laminas-stdlib/src/RequestInterface.php',
+ 'Laminas\\Stdlib\\Response' => $vendorDir . '/laminas/laminas-stdlib/src/Response.php',
+ 'Laminas\\Stdlib\\ResponseInterface' => $vendorDir . '/laminas/laminas-stdlib/src/ResponseInterface.php',
+ 'Laminas\\Stdlib\\SplPriorityQueue' => $vendorDir . '/laminas/laminas-stdlib/src/SplPriorityQueue.php',
+ 'Laminas\\Stdlib\\SplQueue' => $vendorDir . '/laminas/laminas-stdlib/src/SplQueue.php',
+ 'Laminas\\Stdlib\\SplStack' => $vendorDir . '/laminas/laminas-stdlib/src/SplStack.php',
+ 'Laminas\\Stdlib\\StringUtils' => $vendorDir . '/laminas/laminas-stdlib/src/StringUtils.php',
+ 'Laminas\\Stdlib\\StringWrapper\\AbstractStringWrapper' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php',
+ 'Laminas\\Stdlib\\StringWrapper\\Iconv' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/Iconv.php',
+ 'Laminas\\Stdlib\\StringWrapper\\Intl' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/Intl.php',
+ 'Laminas\\Stdlib\\StringWrapper\\MbString' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/MbString.php',
+ 'Laminas\\Stdlib\\StringWrapper\\Native' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/Native.php',
+ 'Laminas\\Stdlib\\StringWrapper\\StringWrapperInterface' => $vendorDir . '/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php',
'Laminas\\ZendFrameworkBridge\\Autoloader' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/Autoloader.php',
'Laminas\\ZendFrameworkBridge\\ConfigPostProcessor' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php',
'Laminas\\ZendFrameworkBridge\\Module' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/Module.php',
'Pelago\\Emogrifier\\' => array($vendorDir . '/pelago/emogrifier/src'),
'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
'Laminas\\ZendFrameworkBridge\\' => array($vendorDir . '/laminas/laminas-zendframework-bridge/src'),
+ 'Laminas\\Stdlib\\' => array($vendorDir . '/laminas/laminas-stdlib/src'),
+ 'Laminas\\ProgressBar\\' => array($vendorDir . '/laminas/laminas-progressbar/src'),
'Laminas\\HttpHandlerRunner\\' => array($vendorDir . '/laminas/laminas-httphandlerrunner/src'),
'Laminas\\Diactoros\\' => array($vendorDir . '/laminas/laminas-diactoros/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'L' =>
array (
'Laminas\\ZendFrameworkBridge\\' => 28,
+ 'Laminas\\Stdlib\\' => 15,
+ 'Laminas\\ProgressBar\\' => 20,
'Laminas\\HttpHandlerRunner\\' => 26,
'Laminas\\Diactoros\\' => 18,
),
array (
0 => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src',
),
+ 'Laminas\\Stdlib\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/laminas/laminas-stdlib/src',
+ ),
+ 'Laminas\\ProgressBar\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/laminas/laminas-progressbar/src',
+ ),
'Laminas\\HttpHandlerRunner\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-httphandlerrunner/src',
'Laminas\\HttpHandlerRunner\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-httphandlerrunner/src/Exception/ExceptionInterface.php',
'Laminas\\HttpHandlerRunner\\Exception\\InvalidEmitterException' => __DIR__ . '/..' . '/laminas/laminas-httphandlerrunner/src/Exception/InvalidEmitterException.php',
'Laminas\\HttpHandlerRunner\\RequestHandlerRunner' => __DIR__ . '/..' . '/laminas/laminas-httphandlerrunner/src/RequestHandlerRunner.php',
+ 'Laminas\\ProgressBar\\Adapter\\AbstractAdapter' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Adapter/AbstractAdapter.php',
+ 'Laminas\\ProgressBar\\Adapter\\Console' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Adapter/Console.php',
+ 'Laminas\\ProgressBar\\Adapter\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Adapter/Exception/ExceptionInterface.php',
+ 'Laminas\\ProgressBar\\Adapter\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Adapter/Exception/InvalidArgumentException.php',
+ 'Laminas\\ProgressBar\\Adapter\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Adapter/Exception/RuntimeException.php',
+ 'Laminas\\ProgressBar\\Adapter\\JsPull' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Adapter/JsPull.php',
+ 'Laminas\\ProgressBar\\Adapter\\JsPush' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Adapter/JsPush.php',
+ 'Laminas\\ProgressBar\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Exception/ExceptionInterface.php',
+ 'Laminas\\ProgressBar\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Exception/InvalidArgumentException.php',
+ 'Laminas\\ProgressBar\\Exception\\OutOfRangeException' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Exception/OutOfRangeException.php',
+ 'Laminas\\ProgressBar\\Exception\\PhpEnvironmentException' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Exception/PhpEnvironmentException.php',
+ 'Laminas\\ProgressBar\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Exception/RuntimeException.php',
+ 'Laminas\\ProgressBar\\ProgressBar' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/ProgressBar.php',
+ 'Laminas\\ProgressBar\\Upload\\AbstractUploadHandler' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Upload/AbstractUploadHandler.php',
+ 'Laminas\\ProgressBar\\Upload\\ApcProgress' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Upload/ApcProgress.php',
+ 'Laminas\\ProgressBar\\Upload\\SessionProgress' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Upload/SessionProgress.php',
+ 'Laminas\\ProgressBar\\Upload\\UploadHandlerInterface' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Upload/UploadHandlerInterface.php',
+ 'Laminas\\ProgressBar\\Upload\\UploadProgress' => __DIR__ . '/..' . '/laminas/laminas-progressbar/src/Upload/UploadProgress.php',
+ 'Laminas\\Stdlib\\AbstractOptions' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/AbstractOptions.php',
+ 'Laminas\\Stdlib\\ArrayObject' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayObject.php',
+ 'Laminas\\Stdlib\\ArraySerializableInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArraySerializableInterface.php',
+ 'Laminas\\Stdlib\\ArrayStack' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayStack.php',
+ 'Laminas\\Stdlib\\ArrayUtils' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils.php',
+ 'Laminas\\Stdlib\\ArrayUtils\\MergeRemoveKey' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php',
+ 'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKey' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKey.php',
+ 'Laminas\\Stdlib\\ArrayUtils\\MergeReplaceKeyInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php',
+ 'Laminas\\Stdlib\\ConsoleHelper' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ConsoleHelper.php',
+ 'Laminas\\Stdlib\\DispatchableInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/DispatchableInterface.php',
+ 'Laminas\\Stdlib\\ErrorHandler' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ErrorHandler.php',
+ 'Laminas\\Stdlib\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/BadMethodCallException.php',
+ 'Laminas\\Stdlib\\Exception\\DomainException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/DomainException.php',
+ 'Laminas\\Stdlib\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/ExceptionInterface.php',
+ 'Laminas\\Stdlib\\Exception\\ExtensionNotLoadedException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/ExtensionNotLoadedException.php',
+ 'Laminas\\Stdlib\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/InvalidArgumentException.php',
+ 'Laminas\\Stdlib\\Exception\\LogicException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/LogicException.php',
+ 'Laminas\\Stdlib\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Exception/RuntimeException.php',
+ 'Laminas\\Stdlib\\FastPriorityQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/FastPriorityQueue.php',
+ 'Laminas\\Stdlib\\Glob' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Glob.php',
+ 'Laminas\\Stdlib\\Guard\\AllGuardsTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php',
+ 'Laminas\\Stdlib\\Guard\\ArrayOrTraversableGuardTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/ArrayOrTraversableGuardTrait.php',
+ 'Laminas\\Stdlib\\Guard\\EmptyGuardTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/EmptyGuardTrait.php',
+ 'Laminas\\Stdlib\\Guard\\NullGuardTrait' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Guard/NullGuardTrait.php',
+ 'Laminas\\Stdlib\\InitializableInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/InitializableInterface.php',
+ 'Laminas\\Stdlib\\JsonSerializable' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/JsonSerializable.php',
+ 'Laminas\\Stdlib\\Message' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Message.php',
+ 'Laminas\\Stdlib\\MessageInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/MessageInterface.php',
+ 'Laminas\\Stdlib\\ParameterObjectInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ParameterObjectInterface.php',
+ 'Laminas\\Stdlib\\Parameters' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Parameters.php',
+ 'Laminas\\Stdlib\\ParametersInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ParametersInterface.php',
+ 'Laminas\\Stdlib\\PriorityList' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/PriorityList.php',
+ 'Laminas\\Stdlib\\PriorityQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/PriorityQueue.php',
+ 'Laminas\\Stdlib\\Request' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Request.php',
+ 'Laminas\\Stdlib\\RequestInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/RequestInterface.php',
+ 'Laminas\\Stdlib\\Response' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/Response.php',
+ 'Laminas\\Stdlib\\ResponseInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/ResponseInterface.php',
+ 'Laminas\\Stdlib\\SplPriorityQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/SplPriorityQueue.php',
+ 'Laminas\\Stdlib\\SplQueue' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/SplQueue.php',
+ 'Laminas\\Stdlib\\SplStack' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/SplStack.php',
+ 'Laminas\\Stdlib\\StringUtils' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringUtils.php',
+ 'Laminas\\Stdlib\\StringWrapper\\AbstractStringWrapper' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php',
+ 'Laminas\\Stdlib\\StringWrapper\\Iconv' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/Iconv.php',
+ 'Laminas\\Stdlib\\StringWrapper\\Intl' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/Intl.php',
+ 'Laminas\\Stdlib\\StringWrapper\\MbString' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/MbString.php',
+ 'Laminas\\Stdlib\\StringWrapper\\Native' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/Native.php',
+ 'Laminas\\Stdlib\\StringWrapper\\StringWrapperInterface' => __DIR__ . '/..' . '/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php',
'Laminas\\ZendFrameworkBridge\\Autoloader' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/Autoloader.php',
'Laminas\\ZendFrameworkBridge\\ConfigPostProcessor' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php',
'Laminas\\ZendFrameworkBridge\\Module' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/Module.php',
],
"install-path": "../laminas/laminas-httphandlerrunner"
},
+ {
+ "name": "laminas/laminas-progressbar",
+ "version": "2.7.0",
+ "version_normalized": "2.7.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laminas/laminas-progressbar.git",
+ "reference": "15f9e983276462f30d7d38660dc7488c6e3df34b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laminas/laminas-progressbar/zipball/15f9e983276462f30d7d38660dc7488c6e3df34b",
+ "reference": "15f9e983276462f30d7d38660dc7488c6e3df34b",
+ "shasum": ""
+ },
+ "require": {
+ "laminas/laminas-stdlib": "^3.2.1",
+ "laminas/laminas-zendframework-bridge": "^1.0",
+ "php": "^5.6 || ^7.0"
+ },
+ "replace": {
+ "zendframework/zend-progressbar": "self.version"
+ },
+ "require-dev": {
+ "laminas/laminas-coding-standard": "~1.0.0",
+ "laminas/laminas-json": "^2.6.1",
+ "laminas/laminas-session": "^2.8.5",
+ "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4"
+ },
+ "suggest": {
+ "laminas/laminas-json": "Laminas\\Json component",
+ "laminas/laminas-session": "To support progressbar persistent"
+ },
+ "time": "2019-12-31T17:38:44+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7.x-dev",
+ "dev-develop": "2.8.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Laminas\\ProgressBar\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Create and update progress bars in different environments",
+ "homepage": "https://laminas.dev",
+ "keywords": [
+ "laminas",
+ "progressbar"
+ ],
+ "support": {
+ "chat": "https://laminas.dev/chat",
+ "docs": "https://docs.laminas.dev/laminas-progressbar/",
+ "forum": "https://discourse.laminas.dev",
+ "issues": "https://github.com/laminas/laminas-progressbar/issues",
+ "rss": "https://github.com/laminas/laminas-progressbar/releases.atom",
+ "source": "https://github.com/laminas/laminas-progressbar"
+ },
+ "install-path": "../laminas/laminas-progressbar"
+ },
+ {
+ "name": "laminas/laminas-stdlib",
+ "version": "3.2.1",
+ "version_normalized": "3.2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laminas/laminas-stdlib.git",
+ "reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/2b18347625a2f06a1a485acfbc870f699dbe51c6",
+ "reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6",
+ "shasum": ""
+ },
+ "require": {
+ "laminas/laminas-zendframework-bridge": "^1.0",
+ "php": "^5.6 || ^7.0"
+ },
+ "replace": {
+ "zendframework/zend-stdlib": "self.version"
+ },
+ "require-dev": {
+ "laminas/laminas-coding-standard": "~1.0.0",
+ "phpbench/phpbench": "^0.13",
+ "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2"
+ },
+ "time": "2019-12-31T17:51:15+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2.x-dev",
+ "dev-develop": "3.3.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Laminas\\Stdlib\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "SPL extensions, array utilities, error handlers, and more",
+ "homepage": "https://laminas.dev",
+ "keywords": [
+ "laminas",
+ "stdlib"
+ ],
+ "support": {
+ "chat": "https://laminas.dev/chat",
+ "docs": "https://docs.laminas.dev/laminas-stdlib/",
+ "forum": "https://discourse.laminas.dev",
+ "issues": "https://github.com/laminas/laminas-stdlib/issues",
+ "rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
+ "source": "https://github.com/laminas/laminas-stdlib"
+ },
+ "install-path": "../laminas/laminas-stdlib"
+ },
{
"name": "laminas/laminas-zendframework-bridge",
"version": "1.1.1",
'reference' => 'e1a5dad040e0043135e8095ee27d1fbf6fb640e1',
'dev_requirement' => false,
),
+ 'laminas/laminas-progressbar' => array(
+ 'pretty_version' => '2.7.0',
+ 'version' => '2.7.0.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../laminas/laminas-progressbar',
+ 'aliases' => array(),
+ 'reference' => '15f9e983276462f30d7d38660dc7488c6e3df34b',
+ 'dev_requirement' => false,
+ ),
+ 'laminas/laminas-stdlib' => array(
+ 'pretty_version' => '3.2.1',
+ 'version' => '3.2.1.0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../laminas/laminas-stdlib',
+ 'aliases' => array(),
+ 'reference' => '2b18347625a2f06a1a485acfbc870f699dbe51c6',
+ 'dev_requirement' => false,
+ ),
'laminas/laminas-zendframework-bridge' => array(
'pretty_version' => '1.1.1',
'version' => '1.1.1.0',
0 => '^1.1.0',
),
),
+ 'zendframework/zend-progressbar' => array(
+ 'dev_requirement' => false,
+ 'replaced' => array(
+ 0 => '2.7.0',
+ ),
+ ),
+ 'zendframework/zend-stdlib' => array(
+ 'dev_requirement' => false,
+ 'replaced' => array(
+ 0 => '3.2.1',
+ ),
+ ),
),
);
--- /dev/null
+# Changelog
+
+All notable changes to this project will be documented in this file, in reverse chronological order by release.
+
+## 2.7.0 - 2019-10-17
+
+### Added
+
+- [zendframework/zend-progressbar#27](https://github.com/zendframework/zend-progressbar/pull/27) adds support for PHP 7.3.
+
+### Changed
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- [zendframework/zend-progressbar#27](https://github.com/zendframework/zend-progressbar/pull/27) removes support for laminas-stdlib v2 releases.
+
+### Fixed
+
+- Nothing.
+
+## 2.6.0 - 2018-04-30
+
+### Added
+
+- [zendframework/zend-progressbar#25](https://github.com/zendframework/zend-progressbar/pull/25) adds support for PHP 7.1 and 7.2.
+
+- [zendframework/zend-progressbar#17](https://github.com/zendframework/zend-progressbar/pull/17) adds and
+ publishes the documentation to https://docs.laminas.dev/laminas-progressbar/
+
+### Changed
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- [zendframework/zend-progressbar#25](https://github.com/zendframework/zend-progressbar/pull/25) removes support for PHP 5.5.
+
+- [zendframework/zend-progressbar#25](https://github.com/zendframework/zend-progressbar/pull/25) removes support for HHVM.
+
+### Fixed
+
+- Nothing.
+
+## 2.5.2 - 2016-03-01
+
+### Added
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- [zendframework/zend-progressbar#10](https://github.com/zendframework/zend-progressbar/pull/10) updates
+ dependencies to allow forward-compatibility with laminas-stdlib 3.
--- /dev/null
+Copyright (c) 2019, Laminas Foundation.
+All rights reserved. (https://getlaminas.org/)
--- /dev/null
+Copyright (c) 2019, Laminas Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+- Neither the name of Laminas Foundation nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+# laminas-progressbar
+
+[![Build Status](https://travis-ci.org/laminas/laminas-progressbar.svg?branch=master)](https://travis-ci.org/laminas/laminas-progressbar)
+[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-progressbar/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-progressbar?branch=master)
+
+laminas-progressbar is a component to create and update progress bars in different
+environments. It consists of a single backend, which outputs the progress through
+one of the multiple adapters. On every update, it takes an absolute value and
+optionally a status message, and then calls the adapter with some precalculated
+values like percentage and estimated time left.
+
+## Installation
+
+Run the following to install this library:
+
+```bash
+$ composer require laminas/laminas-progressbar
+```
+
+## Documentation
+
+Browse the documentation online at https://docs.laminas.dev/laminas-progressbar/
+
+## Support
+
+* [Issues](https://github.com/laminas/laminas-progressbar/issues/)
+* [Chat](https://laminas.dev/chat/)
+* [Forum](https://discourse.laminas.dev/)
--- /dev/null
+{
+ "name": "laminas/laminas-progressbar",
+ "description": "Create and update progress bars in different environments",
+ "license": "BSD-3-Clause",
+ "keywords": [
+ "laminas",
+ "progressbar"
+ ],
+ "homepage": "https://laminas.dev",
+ "support": {
+ "docs": "https://docs.laminas.dev/laminas-progressbar/",
+ "issues": "https://github.com/laminas/laminas-progressbar/issues",
+ "source": "https://github.com/laminas/laminas-progressbar",
+ "rss": "https://github.com/laminas/laminas-progressbar/releases.atom",
+ "chat": "https://laminas.dev/chat",
+ "forum": "https://discourse.laminas.dev"
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7.x-dev",
+ "dev-develop": "2.8.x-dev"
+ }
+ },
+ "require": {
+ "php": "^5.6 || ^7.0",
+ "laminas/laminas-stdlib": "^3.2.1",
+ "laminas/laminas-zendframework-bridge": "^1.0"
+ },
+ "require-dev": {
+ "laminas/laminas-coding-standard": "~1.0.0",
+ "laminas/laminas-json": "^2.6.1",
+ "laminas/laminas-session": "^2.8.5",
+ "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4"
+ },
+ "suggest": {
+ "laminas/laminas-json": "Laminas\\Json component",
+ "laminas/laminas-session": "To support progressbar persistent"
+ },
+ "autoload": {
+ "psr-4": {
+ "Laminas\\ProgressBar\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "LaminasTest\\ProgressBar\\": "test/"
+ }
+ },
+ "scripts": {
+ "check": [
+ "@cs-check",
+ "@test"
+ ],
+ "cs-check": "phpcs",
+ "cs-fix": "phpcbf",
+ "test": "phpunit --colors=always",
+ "test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
+ },
+ "replace": {
+ "zendframework/zend-progressbar": "self.version"
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Adapter;
+
+use Laminas\Stdlib\ArrayUtils;
+use Traversable;
+
+/**
+ * Abstract class for Laminas\ProgressBar Adapters
+ */
+abstract class AbstractAdapter
+{
+ /**
+ * Option keys to skip when calling setOptions()
+ *
+ * @var array
+ */
+ protected $skipOptions = [
+ 'options',
+ 'config',
+ ];
+
+ /**
+ * Create a new adapter
+ *
+ * $options may be either be an array or a Laminas\Config object which
+ * specifies adapter related options.
+ *
+ * @param array|Traversable $options
+ */
+ public function __construct($options = null)
+ {
+ if ($options instanceof Traversable) {
+ $options = ArrayUtils::iteratorToArray($options);
+ }
+ if (is_array($options)) {
+ $this->setOptions($options);
+ }
+ }
+
+ /**
+ * Set options via an array
+ *
+ * @param array $options
+ * @return AbstractAdapter
+ */
+ public function setOptions(array $options)
+ {
+ foreach ($options as $key => $value) {
+ if (in_array(strtolower($key), $this->skipOptions)) {
+ continue;
+ }
+
+ $method = 'set' . ucfirst($key);
+ if (method_exists($this, $method)) {
+ $this->$method($value);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Notify the adapter about an update
+ *
+ * @param float $current Current progress value
+ * @param float $max Max progress value
+ * @param float $percent Current percent value
+ * @param int $timeTaken Taken time in seconds
+ * @param int $timeRemaining Remaining time in seconds
+ * @param string $text Status text
+ * @return void
+ */
+ abstract public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text);
+
+ /**
+ * Called when the progress is explicitly finished
+ *
+ * @return void
+ */
+ abstract public function finish();
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Adapter;
+
+use Laminas\Stdlib\ErrorHandler;
+use Laminas\Stdlib\StringUtils;
+
+/**
+ * Laminas\ProgressBar\Adapter\Console offers a text-based progressbar for console
+ * applications
+ */
+class Console extends AbstractAdapter
+{
+ /**
+ * Percentage value of the progress
+ */
+ const ELEMENT_PERCENT = 'ELEMENT_PERCENT';
+
+ /**
+ * Visual value of the progress
+ */
+ const ELEMENT_BAR = 'ELEMENT_BAR';
+
+ /**
+ * ETA of the progress
+ */
+ const ELEMENT_ETA = 'ELEMENT_ETA';
+
+ /**
+ * Text part of the progress
+ */
+ const ELEMENT_TEXT = 'ELEMENT_TEXT';
+
+ /**
+ * Finish action: End of Line
+ */
+ const FINISH_ACTION_EOL = 'FINISH_ACTION_EOL';
+
+ /**
+ * Finish action: Clear Line
+ */
+ const FINISH_ACTION_CLEAR_LINE = 'FINISH_ACTION_CLEAR_LINE';
+
+ /**
+ * Finish action: None
+ */
+ const FINISH_ACTION_NONE = 'FINISH_ACTION_NONE';
+
+ /**
+ * Width of the progressbar
+ *
+ * @var int
+ */
+ protected $width = null;
+
+ /**
+ * Elements to display
+ *
+ * @var array
+ */
+ protected $elements = [
+ self::ELEMENT_PERCENT,
+ self::ELEMENT_BAR,
+ self::ELEMENT_ETA,
+ ];
+
+ /**
+ * Which action to do at finish call
+ *
+ * @var string
+ */
+ protected $finishAction = self::FINISH_ACTION_EOL;
+
+ /**
+ * Width of the bar element
+ *
+ * @var int
+ */
+ protected $barWidth;
+
+ /**
+ * Left character(s) within the bar
+ *
+ * @var string
+ */
+ protected $barLeftChar = '#';
+
+ /**
+ * Indicator character(s) within the bar
+ *
+ * @var string
+ */
+ protected $barIndicatorChar = '';
+
+ /**
+ * Right character(s) within the bar
+ *
+ * @var string
+ */
+ protected $barRightChar = '-';
+
+ /**
+ * Output-stream, when STDOUT is not defined (e.g. in CGI) or set manually
+ *
+ * @var resource
+ */
+ protected $outputStream = null;
+
+ /**
+ * Width of the text element
+ *
+ * @var string
+ */
+ protected $textWidth = 20;
+
+ /**
+ * Whether the output started yet or not
+ *
+ * @var bool
+ */
+ protected $outputStarted = false;
+
+ /**
+ * Charset of text element
+ *
+ * @var string
+ */
+ protected $charset = 'utf-8';
+
+ /**
+ * Defined by Laminas\ProgressBar adapter
+ *
+ * @param array|\Traversable $options
+ */
+ public function __construct($options = null)
+ {
+ // Call parent constructor with options
+ parent::__construct($options);
+
+ // Check if a width was set, else use auto width
+ if ($this->width === null) {
+ $this->setWidth();
+ }
+ }
+
+ /**
+ * Close local stdout, when open
+ */
+ public function __destruct()
+ {
+ if ($this->outputStream !== null) {
+ fclose($this->outputStream);
+ }
+ }
+
+ /**
+ * Set a different output-stream
+ *
+ * @param string $resource
+ * @throws Exception\RuntimeException
+ * @return \Laminas\ProgressBar\Adapter\Console
+ */
+ public function setOutputStream($resource)
+ {
+ ErrorHandler::start();
+ $stream = fopen($resource, 'w');
+ $error = ErrorHandler::stop();
+
+ if ($stream === false) {
+ throw new Exception\RuntimeException('Unable to open stream', 0, $error);
+ }
+
+ if ($this->outputStream !== null) {
+ fclose($this->outputStream);
+ }
+
+ $this->outputStream = $stream;
+ }
+
+ /**
+ * Get the current output stream
+ *
+ * @return resource
+ */
+ public function getOutputStream()
+ {
+ if ($this->outputStream === null) {
+ if (! defined('STDOUT')) {
+ $this->outputStream = fopen('php://stdout', 'w');
+ } else {
+ return STDOUT;
+ }
+ }
+
+ return $this->outputStream;
+ }
+
+ /**
+ * Set the width of the progressbar
+ *
+ * @param int $width
+ * @return \Laminas\ProgressBar\Adapter\Console
+ */
+ public function setWidth($width = null)
+ {
+ if ($width === null || ! is_int($width)) {
+ if (substr(PHP_OS, 0, 3) === 'WIN') {
+ // We have to default to 79 on windows, because the windows
+ // terminal always has a fixed width of 80 characters and the
+ // cursor is counted to the line, else windows would line break
+ // after every update.
+ $this->width = 79;
+ } else {
+ // Set the default width of 80
+ $this->width = 80;
+
+ // Try to determine the width through stty
+ ErrorHandler::start();
+ if (preg_match('#\d+ (\d+)#', shell_exec('stty size'), $match) === 1) {
+ $this->width = (int) $match[1];
+ } elseif (preg_match('#columns = (\d+);#', shell_exec('stty'), $match) === 1) {
+ $this->width = (int) $match[1];
+ }
+ ErrorHandler::stop();
+ }
+ } else {
+ $this->width = (int) $width;
+ }
+
+ $this->_calculateBarWidth();
+
+ return $this;
+ }
+
+ /**
+ * Set the elements to display with the progressbar
+ *
+ * @param array $elements
+ * @throws \Laminas\ProgressBar\Adapter\Exception\InvalidArgumentException When an invalid element is found
+ * in the array
+ * @return \Laminas\ProgressBar\Adapter\Console
+ */
+ public function setElements(array $elements)
+ {
+ $allowedElements = [self::ELEMENT_PERCENT,
+ self::ELEMENT_BAR,
+ self::ELEMENT_ETA,
+ self::ELEMENT_TEXT];
+
+ if (count(array_diff($elements, $allowedElements)) > 0) {
+ throw new Exception\InvalidArgumentException('Invalid element found in $elements array');
+ }
+
+ $this->elements = $elements;
+
+ $this->_calculateBarWidth();
+
+ return $this;
+ }
+
+ /**
+ * Set the left-hand character for the bar
+ *
+ * @param string $char
+ * @throws \Laminas\ProgressBar\Adapter\Exception\InvalidArgumentException When character is empty
+ * @return \Laminas\ProgressBar\Adapter\Console
+ */
+ public function setBarLeftChar($char)
+ {
+ if (empty($char)) {
+ throw new Exception\InvalidArgumentException('Character may not be empty');
+ }
+
+ $this->barLeftChar = (string) $char;
+
+ return $this;
+ }
+
+ /**
+ * Set the right-hand character for the bar
+ *
+ * @param string $char
+ * @throws \Laminas\ProgressBar\Adapter\Exception\InvalidArgumentException When character is empty
+ * @return \Laminas\ProgressBar\Adapter\Console
+ */
+ public function setBarRightChar($char)
+ {
+ if (empty($char)) {
+ throw new Exception\InvalidArgumentException('Character may not be empty');
+ }
+
+ $this->barRightChar = (string) $char;
+
+ return $this;
+ }
+
+ /**
+ * Set the indicator character for the bar
+ *
+ * @param string $char
+ * @return \Laminas\ProgressBar\Adapter\Console
+ */
+ public function setBarIndicatorChar($char)
+ {
+ $this->barIndicatorChar = (string) $char;
+
+ return $this;
+ }
+
+ /**
+ * Set the width of the text element
+ *
+ * @param int $width
+ * @return \Laminas\ProgressBar\Adapter\Console
+ */
+ public function setTextWidth($width)
+ {
+ $this->textWidth = (int) $width;
+
+ $this->_calculateBarWidth();
+
+ return $this;
+ }
+
+ /**
+ * Set the charset of the text element
+ *
+ * @param string $charset
+ */
+ public function setCharset($charset)
+ {
+ $this->charset = $charset;
+ }
+
+ /**
+ * Set the finish action
+ *
+ * @param string $action
+ * @throws \Laminas\ProgressBar\Adapter\Exception\InvalidArgumentException When an invalid action is specified
+ * @return \Laminas\ProgressBar\Adapter\Console
+ */
+ public function setFinishAction($action)
+ {
+ $allowedActions = [self::FINISH_ACTION_CLEAR_LINE,
+ self::FINISH_ACTION_EOL,
+ self::FINISH_ACTION_NONE];
+
+ if (! in_array($action, $allowedActions)) {
+ throw new Exception\InvalidArgumentException('Invalid finish action specified');
+ }
+
+ $this->finishAction = $action;
+
+ return $this;
+ }
+
+ /**
+ * Defined by Laminas\ProgressBar\Adapter\AbstractAdapter
+ *
+ * @param float $current Current progress value
+ * @param float $max Max progress value
+ * @param float $percent Current percent value
+ * @param int $timeTaken Taken time in seconds
+ * @param int $timeRemaining Remaining time in seconds
+ * @param string $text Status text
+ * @return void
+ */
+ public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
+ {
+ // See if we must clear the line
+ if ($this->outputStarted) {
+ $data = str_repeat("\x08", $this->width);
+ } else {
+ $data = '';
+ $this->outputStarted = true;
+ }
+
+ // Build all elements
+ $renderedElements = [];
+
+ foreach ($this->elements as $element) {
+ switch ($element) {
+ case self::ELEMENT_BAR:
+ $visualWidth = $this->barWidth - 2;
+ $bar = '[';
+
+ $indicatorWidth = strlen($this->barIndicatorChar);
+
+ $doneWidth = min($visualWidth - $indicatorWidth, round($visualWidth * $percent));
+ if ($doneWidth > 0) {
+ $bar .= substr(
+ str_repeat($this->barLeftChar, ceil($doneWidth / strlen($this->barLeftChar))),
+ 0,
+ $doneWidth
+ );
+ }
+
+ $bar .= $this->barIndicatorChar;
+
+ $leftWidth = $visualWidth - $doneWidth - $indicatorWidth;
+ if ($leftWidth > 0) {
+ $bar .= substr(
+ str_repeat($this->barRightChar, ceil($leftWidth / strlen($this->barRightChar))),
+ 0,
+ $leftWidth
+ );
+ }
+
+ $bar .= ']';
+
+ $renderedElements[] = $bar;
+ break;
+
+ case self::ELEMENT_PERCENT:
+ $renderedElements[] = str_pad(round($percent * 100), 3, ' ', STR_PAD_LEFT) . '%';
+ break;
+
+ case self::ELEMENT_ETA:
+ // In the first 5 seconds we don't get accurate results,
+ // this skipping technique is found in many progressbar
+ // implementations.
+ if ($timeTaken < 5) {
+ $renderedElements[] = str_repeat(' ', 12);
+ break;
+ }
+
+ if ($timeRemaining === null || $timeRemaining > 86400) {
+ $etaFormatted = '??:??:??';
+ } else {
+ $hours = floor($timeRemaining / 3600);
+ $minutes = floor(($timeRemaining % 3600) / 60);
+ $seconds = ($timeRemaining % 3600 % 60);
+
+ $etaFormatted = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
+ }
+
+ $renderedElements[] = 'ETA ' . $etaFormatted;
+ break;
+
+ case self::ELEMENT_TEXT:
+ $wrapper = StringUtils::getWrapper($this->charset);
+ $renderedElements[] = $wrapper->strPad(
+ $wrapper->substr($text, 0, $this->textWidth),
+ $this->textWidth,
+ ' ',
+ STR_PAD_RIGHT
+ );
+ break;
+ }
+ }
+
+ $data .= implode(' ', $renderedElements);
+
+ // Output line data
+ $this->_outputData($data);
+ }
+
+ /**
+ * Defined by Laminas\ProgressBar\Adapter\AbstractAdapter
+ *
+ * @return void
+ */
+ public function finish()
+ {
+ switch ($this->finishAction) {
+ case self::FINISH_ACTION_EOL:
+ $this->_outputData(PHP_EOL);
+ break;
+
+ case self::FINISH_ACTION_CLEAR_LINE:
+ if ($this->outputStarted) {
+ $data = str_repeat("\x08", $this->width)
+ . str_repeat(' ', $this->width)
+ . str_repeat("\x08", $this->width);
+
+ $this->_outputData($data);
+ }
+ break;
+
+ case self::FINISH_ACTION_NONE:
+ break;
+ }
+ }
+
+ /**
+ * Calculate the bar width when other elements changed
+ *
+ * @return void
+ */
+ // @codingStandardsIgnoreStart
+ protected function _calculateBarWidth()
+ {
+ // @codingStandardsIgnoreEnd
+ if (in_array(self::ELEMENT_BAR, $this->elements)) {
+ $barWidth = $this->width;
+
+ if (in_array(self::ELEMENT_PERCENT, $this->elements)) {
+ $barWidth -= 4;
+ }
+
+ if (in_array(self::ELEMENT_ETA, $this->elements)) {
+ $barWidth -= 12;
+ }
+
+ if (in_array(self::ELEMENT_TEXT, $this->elements)) {
+ $barWidth -= $this->textWidth;
+ }
+
+ $this->barWidth = $barWidth - (count($this->elements) - 1);
+ }
+ }
+
+ /**
+ * Outputs given data to STDOUT.
+ *
+ * This split-off is required for unit-testing.
+ *
+ * @param string $data
+ * @return void
+ */
+ // @codingStandardsIgnoreStart
+ protected function _outputData($data)
+ {
+ // @codingStandardsIgnoreEnd
+ fwrite($this->getOutputStream(), $data);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Adapter\Exception;
+
+use Laminas\ProgressBar\Exception\ExceptionInterface as ProgressBarException;
+
+/**
+ * Exception class for Laminas\ProgressBar\Adapter
+ */
+interface ExceptionInterface extends ProgressBarException
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Adapter\Exception;
+
+use Laminas\ProgressBar\Exception;
+
+/**
+ * Exception for Laminas\Progressbar component.
+ */
+class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Adapter\Exception;
+
+use Laminas\ProgressBar\Exception;
+
+/**
+ * Exception for Laminas\Progressbar component.
+ */
+class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Adapter;
+
+use Laminas\Json\Json;
+
+/**
+ * Laminas\ProgressBar\Adapter\JsPull offers a simple method for updating a
+ * progressbar in a browser.
+ */
+class JsPull extends AbstractAdapter
+{
+ /**
+ * Whether to exit after json data send or not
+ *
+ * @var bool
+ */
+ protected $exitAfterSend = true;
+
+ /**
+ * Set whether to exit after json data send or not
+ *
+ * @param bool $exitAfterSend
+ * @return \Laminas\ProgressBar\Adapter\JsPull
+ */
+ public function setExitAfterSend($exitAfterSend)
+ {
+ $this->exitAfterSend = $exitAfterSend;
+ }
+
+ /**
+ * Defined by Laminas\ProgressBar\Adapter\AbstractAdapter
+ *
+ * @param float $current Current progress value
+ * @param float $max Max progress value
+ * @param float $percent Current percent value
+ * @param int $timeTaken Taken time in seconds
+ * @param int $timeRemaining Remaining time in seconds
+ * @param string $text Status text
+ * @return void
+ */
+ public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
+ {
+ $arguments = [
+ 'current' => $current,
+ 'max' => $max,
+ 'percent' => ($percent * 100),
+ 'timeTaken' => $timeTaken,
+ 'timeRemaining' => $timeRemaining,
+ 'text' => $text,
+ 'finished' => false
+ ];
+
+ $data = Json::encode($arguments);
+
+ // Output the data
+ $this->_outputData($data);
+ }
+
+ /**
+ * Defined by Laminas\ProgressBar\Adapter\AbstractAdapter
+ *
+ * @return void
+ */
+ public function finish()
+ {
+ $data = Json::encode(['finished' => true]);
+
+ $this->_outputData($data);
+ }
+
+ /**
+ * Outputs given data the user agent.
+ *
+ * This split-off is required for unit-testing.
+ *
+ * @param string $data
+ * @return void
+ */
+ // @codingStandardsIgnoreStart
+ protected function _outputData($data)
+ {
+ // @codingStandardsIgnoreEnd
+ echo $data;
+
+ if ($this->exitAfterSend) {
+ exit;
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Adapter;
+
+use Laminas\Json\Json;
+
+/**
+ * Laminas\ProgressBar\Adapter\JsPush offers a simple method for updating a
+ * progressbar in a browser.
+ */
+class JsPush extends AbstractAdapter
+{
+ /**
+ * Name of the JavaScript method to call on update
+ *
+ * @var string
+ */
+ protected $updateMethodName = 'Laminas\ProgressBar\ProgressBar\Update';
+
+ /**
+ * Name of the JavaScript method to call on finish
+ *
+ * @var string
+ */
+ protected $finishMethodName;
+
+ /**
+ * Set the update method name
+ *
+ * @param string $methodName
+ * @return \Laminas\ProgressBar\Adapter\JsPush
+ */
+ public function setUpdateMethodName($methodName)
+ {
+ $this->updateMethodName = $methodName;
+
+ return $this;
+ }
+
+ /**
+ * Set the finish method name
+ *
+ * @param string $methodName
+ * @return \Laminas\ProgressBar\Adapter\JsPush
+ */
+ public function setFinishMethodName($methodName)
+ {
+ $this->finishMethodName = $methodName;
+
+ return $this;
+ }
+
+ /**
+ * Defined by Laminas\ProgressBar\Adapter\AbstractAdapter
+ *
+ * @param float $current Current progress value
+ * @param float $max Max progress value
+ * @param float $percent Current percent value
+ * @param int $timeTaken Taken time in seconds
+ * @param int $timeRemaining Remaining time in seconds
+ * @param string $text Status text
+ * @return void
+ */
+ public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
+ {
+ $arguments = [
+ 'current' => $current,
+ 'max' => $max,
+ 'percent' => ($percent * 100),
+ 'timeTaken' => $timeTaken,
+ 'timeRemaining' => $timeRemaining,
+ 'text' => $text
+ ];
+
+ $data = '<script type="text/javascript">'
+ . 'parent.' . $this->updateMethodName . '(' . Json::encode($arguments) . ');'
+ . '</script>';
+
+ // Output the data
+ $this->_outputData($data);
+ }
+
+ /**
+ * Defined by Laminas\ProgressBar\Adapter\AbstractAdapter
+ *
+ * @return void
+ */
+ public function finish()
+ {
+ if ($this->finishMethodName === null) {
+ return;
+ }
+
+ $data = '<script type="text/javascript">'
+ . 'parent.' . $this->finishMethodName . '();'
+ . '</script>';
+
+ $this->_outputData($data);
+ }
+
+ /**
+ * Outputs given data the user agent.
+ *
+ * This split-off is required for unit-testing.
+ *
+ * @param string $data
+ * @return void
+ */
+ // @codingStandardsIgnoreStart
+ protected function _outputData($data)
+ {
+ // @codingStandardsIgnoreEnd
+ // 1024 padding is required for Safari, while 256 padding is required
+ // for Internet Explorer. The <br /> is required so Safari actually
+ // executes the <script />
+ echo str_pad($data . '<br />', 1024, ' ', STR_PAD_RIGHT) . "\n";
+
+ flush();
+ ob_flush();
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Exception;
+
+/**
+ * Exception class for Laminas\ProgressBar
+ */
+interface ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Exception;
+
+/**
+ * Exception for Laminas\Progressbar component.
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Exception;
+
+/**
+ * Exception for Laminas\Progressbar component.
+ */
+class OutOfRangeException extends \OutOfRangeException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Exception;
+
+class PhpEnvironmentException extends RuntimeException
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Exception;
+
+/**
+ * Exception for Laminas\Progressbar component.
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar;
+
+use Laminas\Session;
+
+/**
+ * Laminas\ProgressBar offers an interface for multiple environments.
+ */
+class ProgressBar
+{
+ /**
+ * Min value
+ *
+ * @var float
+ */
+ protected $min;
+
+ /**
+ * Max value
+ *
+ * @var float
+ */
+ protected $max;
+
+ /**
+ * Current value
+ *
+ * @var float
+ */
+ protected $current;
+
+ /**
+ * Start time of the progressbar, required for ETA
+ *
+ * @var int
+ */
+ protected $startTime;
+
+ /**
+ * Current status text
+ *
+ * @var string
+ */
+ protected $statusText = null;
+
+ /**
+ * Adapter for the output
+ *
+ * @var \Laminas\ProgressBar\Adapter\AbstractAdapter
+ */
+ protected $adapter;
+
+ /**
+ * Namespace for keeping the progressbar persistent
+ *
+ * @var string
+ */
+ protected $persistenceNamespace = null;
+
+ /**
+ * Create a new progressbar backend.
+ *
+ * @param Adapter\AbstractAdapter $adapter
+ * @param float|int $min
+ * @param float|int $max
+ * @param string|null $persistenceNamespace
+ * @throws Exception\OutOfRangeException When $min is greater than $max
+ */
+ public function __construct(Adapter\AbstractAdapter $adapter, $min = 0, $max = 100, $persistenceNamespace = null)
+ {
+ // Check min/max values and set them
+ if ($min > $max) {
+ throw new Exception\OutOfRangeException('$max must be greater than $min');
+ }
+
+ $this->min = (float) $min;
+ $this->max = (float) $max;
+ $this->current = (float) $min;
+
+ // See if we have to open a session namespace
+ if ($persistenceNamespace !== null) {
+ $this->persistenceNamespace = new Session\Container($persistenceNamespace);
+ }
+
+ // Set adapter
+ $this->adapter = $adapter;
+
+ // Track the start time
+ $this->startTime = time();
+
+ // See If a persistenceNamespace exists and handle accordingly
+ if ($this->persistenceNamespace !== null) {
+ if (isset($this->persistenceNamespace->isSet)) {
+ $this->startTime = $this->persistenceNamespace->startTime;
+ $this->current = $this->persistenceNamespace->current;
+ $this->statusText = $this->persistenceNamespace->statusText;
+ } else {
+ $this->persistenceNamespace->isSet = true;
+ $this->persistenceNamespace->startTime = $this->startTime;
+ $this->persistenceNamespace->current = $this->current;
+ $this->persistenceNamespace->statusText = $this->statusText;
+ }
+ } else {
+ $this->update();
+ }
+ }
+
+ /**
+ * Get the current adapter
+ *
+ * @return Adapter\AbstractAdapter
+ */
+ public function getAdapter()
+ {
+ return $this->adapter;
+ }
+
+ /**
+ * Update the progressbar
+ *
+ * @param float $value
+ * @param string $text
+ * @return void
+ */
+ public function update($value = null, $text = null)
+ {
+ // Update value if given
+ if ($value !== null) {
+ $this->current = min($this->max, max($this->min, $value));
+ }
+
+ // Update text if given
+ if ($text !== null) {
+ $this->statusText = $text;
+ }
+
+ // See if we have to update a namespace
+ if ($this->persistenceNamespace !== null) {
+ $this->persistenceNamespace->current = $this->current;
+ $this->persistenceNamespace->statusText = $this->statusText;
+ }
+
+ // Calculate percent
+ if ($this->min === $this->max) {
+ $percent = false;
+ } else {
+ $percent = (float) ($this->current - $this->min) / ($this->max - $this->min);
+ }
+
+ // Calculate ETA
+ $timeTaken = time() - $this->startTime;
+
+ if ($percent === .0 || $percent === false) {
+ $timeRemaining = null;
+ } else {
+ $timeRemaining = round(((1 / $percent) * $timeTaken) - $timeTaken);
+ }
+
+ // Poll the adapter
+ $this->adapter->notify($this->current, $this->max, $percent, $timeTaken, $timeRemaining, $this->statusText);
+ }
+
+ /**
+ * Update the progressbar to the next value
+ *
+ * @param int $diff
+ * @param string $text
+ * @return void
+ */
+ public function next($diff = 1, $text = null)
+ {
+ $this->update(max($this->min, min($this->max, $this->current + $diff)), $text);
+ }
+
+ /**
+ * Call the adapters finish() behaviour
+ *
+ * @return void
+ */
+ public function finish()
+ {
+ if ($this->persistenceNamespace !== null) {
+ unset($this->persistenceNamespace->isSet);
+ }
+
+ $this->adapter->finish();
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Upload;
+
+use Laminas\ProgressBar\Adapter\AbstractAdapter as AbstractProgressAdapter;
+use Laminas\ProgressBar\Exception;
+use Laminas\ProgressBar\ProgressBar;
+use Laminas\Stdlib\ArrayUtils;
+use Traversable;
+
+/**
+ * Abstract class for Upload Progress Handlers
+ */
+abstract class AbstractUploadHandler implements UploadHandlerInterface
+{
+ /**
+ * @var string
+ */
+ protected $sessionNamespace = 'Laminas\ProgressBar\Upload\AbstractUploadHandler';
+
+ /**
+ * @var AbstractProgressAdapter|ProgressBar
+ */
+ protected $progressAdapter;
+
+ /**
+ * @param array|Traversable $options Optional options
+ * @throws Exception\InvalidArgumentException
+ */
+ public function __construct($options = [])
+ {
+ if (! empty($options)) {
+ $this->setOptions($options);
+ }
+ }
+
+ /**
+ * Set options for a upload handler. Accepted options are:
+ * - session_namespace: session namespace for upload progress
+ * - progress_adapter: progressbar adapter to use for updating progress
+ *
+ * @param array|Traversable $options
+ * @return AbstractUploadHandler
+ * @throws Exception\InvalidArgumentException
+ */
+ public function setOptions($options)
+ {
+ if ($options instanceof Traversable) {
+ $options = ArrayUtils::iteratorToArray($options);
+ } elseif (! is_array($options)) {
+ throw new Exception\InvalidArgumentException(
+ 'The options parameter must be an array or a Traversable'
+ );
+ }
+
+ if (isset($options['session_namespace'])) {
+ $this->setSessionNamespace($options['session_namespace']);
+ }
+ if (isset($options['progress_adapter'])) {
+ $this->setProgressAdapter($options['progress_adapter']);
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param string $sessionNamespace
+ * @return AbstractUploadHandler|UploadHandlerInterface
+ */
+ public function setSessionNamespace($sessionNamespace)
+ {
+ $this->sessionNamespace = $sessionNamespace;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSessionNamespace()
+ {
+ return $this->sessionNamespace;
+ }
+
+ /**
+ * @param AbstractProgressAdapter|ProgressBar $progressAdapter
+ * @return AbstractUploadHandler|UploadHandlerInterface
+ */
+ public function setProgressAdapter($progressAdapter)
+ {
+ $this->progressAdapter = $progressAdapter;
+ return $this;
+ }
+
+ /**
+ * @return AbstractProgressAdapter|ProgressBar
+ */
+ public function getProgressAdapter()
+ {
+ return $this->progressAdapter;
+ }
+
+ /**
+ * @param string $id
+ * @return array
+ */
+ public function getProgress($id)
+ {
+ $status = [
+ 'total' => 0,
+ 'current' => 0,
+ 'rate' => 0,
+ 'message' => 'No upload in progress',
+ 'done' => true
+ ];
+ if (empty($id)) {
+ return $status;
+ }
+
+ $newStatus = $this->getUploadProgress($id);
+ if (false === $newStatus) {
+ return $status;
+ }
+ $status = $newStatus;
+ if ('' === $status['message']) {
+ $status['message'] = $this->toByteString($status['current']) .
+ " - " . $this->toByteString($status['total']);
+ }
+ $status['id'] = $id;
+
+ $adapter = $this->getProgressAdapter();
+ if (isset($adapter)) {
+ if ($adapter instanceof AbstractProgressAdapter) {
+ $adapter = new ProgressBar($adapter, 0, $status['total'], $this->getSessionNamespace());
+ $this->setProgressAdapter($adapter);
+ }
+
+ if (! $adapter instanceof ProgressBar) {
+ throw new Exception\RuntimeException('Unknown Adapter type given');
+ }
+
+ if ($status['done']) {
+ $adapter->finish();
+ } else {
+ $adapter->update($status['current'], $status['message']);
+ }
+ }
+
+ return $status;
+ }
+
+ /**
+ * @param string $id
+ * @return array|bool
+ */
+ abstract protected function getUploadProgress($id);
+
+ /**
+ * Returns the formatted size
+ *
+ * @param int $size
+ * @return string
+ */
+ protected function toByteString($size)
+ {
+ $sizes = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+ for ($i = 0; $size >= 1024 && $i < 9; $i++) {
+ $size /= 1024;
+ }
+
+ return round($size, 2) . $sizes[$i];
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Upload;
+
+use Laminas\ProgressBar\Exception;
+
+/**
+ * Progress Bar Upload Handler for the APC extension
+ */
+class ApcProgress extends AbstractUploadHandler
+{
+ /**
+ * @param string $id
+ * @return array|bool
+ * @throws Exception\PhpEnvironmentException
+ */
+ protected function getUploadProgress($id)
+ {
+ if (! $this->isApcAvailable()) {
+ throw new Exception\PhpEnvironmentException('APC extension is not installed');
+ }
+
+ $uploadInfo = apc_fetch(ini_get('apc.rfc1867_prefix') . $id);
+ if (! is_array($uploadInfo)) {
+ return false;
+ }
+
+ $status = [
+ 'total' => 0,
+ 'current' => 0,
+ 'rate' => 0,
+ 'message' => '',
+ 'done' => false
+ ];
+ $status = $uploadInfo + $status;
+ if (! empty($status['cancel_upload'])) {
+ $status['done'] = true;
+ $status['message'] = 'The upload has been canceled';
+ }
+
+ return $status;
+ }
+
+ /**
+ * Checks for the APC extension
+ *
+ * @return bool
+ */
+ public function isApcAvailable()
+ {
+ return (bool) ini_get('apc.enabled')
+ && (bool) ini_get('apc.rfc1867')
+ && is_callable('apc_fetch');
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Upload;
+
+use Laminas\ProgressBar\Exception;
+
+/**
+ * Progress Bar Upload Handler for PHP 5.4+ Session Upload Progress handling
+ */
+class SessionProgress extends AbstractUploadHandler
+{
+ /**
+ * @param string $id
+ * @return array|bool
+ * @throws Exception\PhpEnvironmentException
+ */
+ protected function getUploadProgress($id)
+ {
+ if (! $this->isSessionUploadProgressAvailable()) {
+ throw new Exception\PhpEnvironmentException(
+ 'Session Upload Progress is not available'
+ );
+ }
+
+ $sessionKey = ini_get('session.upload_progress.prefix') . $id;
+ $uploadInfo = (isset($_SESSION[$sessionKey])) ? $_SESSION[$sessionKey] : null;
+ if (! is_array($uploadInfo)) {
+ return false;
+ }
+
+ $status = [
+ 'total' => 0,
+ 'current' => 0,
+ 'rate' => 0,
+ 'message' => '',
+ 'done' => false,
+ ];
+ $status = $uploadInfo + $status;
+ $status['total'] = $status['content_length'];
+ $status['current'] = $status['bytes_processed'];
+
+ $time = time() - $status['start_time'];
+ $status['rate'] = ($time > 0) ? $status['bytes_processed'] / $time : 0;
+
+ if (! empty($status['cancel_upload'])) {
+ $status['done'] = true;
+ $status['message'] = 'The upload has been canceled';
+ }
+
+ return $status;
+ }
+
+ /**
+ * Checks if Session Upload Progress is available
+ *
+ * @return bool
+ */
+ public function isSessionUploadProgressAvailable()
+ {
+ return (bool) ini_get('session.upload_progress.enabled');
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Upload;
+
+/**
+ * Interface for Upload Progress Handlers
+ */
+interface UploadHandlerInterface
+{
+ /**
+ * @param string $id
+ * @return array
+ */
+ public function getProgress($id);
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-progressbar for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-progressbar/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-progressbar/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\ProgressBar\Upload;
+
+use Laminas\ProgressBar\Exception;
+
+/**
+ * Progress Bar Upload Handler for the UploadProgress extension
+ */
+class UploadProgress extends AbstractUploadHandler
+{
+ /**
+ * @param string $id
+ * @return array|bool
+ * @throws Exception\PhpEnvironmentException
+ */
+ protected function getUploadProgress($id)
+ {
+ if (! $this->isUploadProgressAvailable()) {
+ throw new Exception\PhpEnvironmentException(
+ 'UploadProgress extension is not installed'
+ );
+ }
+
+ $uploadInfo = uploadprogress_get_info($id);
+ if (! is_array($uploadInfo)) {
+ return false;
+ }
+
+ $status = [
+ 'total' => 0,
+ 'current' => 0,
+ 'rate' => 0,
+ 'message' => '',
+ 'done' => false
+ ];
+ $status = $uploadInfo + $status;
+ $status['total'] = $status['bytes_total'];
+ $status['current'] = $status['bytes_uploaded'];
+ $status['rate'] = $status['speed_average'];
+ if ($status['total'] == $status['current']) {
+ $status['done'] = true;
+ }
+
+ return $status;
+ }
+
+ /**
+ * Checks for the UploadProgress extension
+ *
+ * @return bool
+ */
+ public function isUploadProgressAvailable()
+ {
+ return is_callable('uploadprogress_get_info');
+ }
+}
--- /dev/null
+# Changelog
+
+All notable changes to this project will be documented in this file, in reverse chronological order by release.
+
+## 3.2.1 - 2018-08-28
+
+### Added
+
+- Nothing.
+
+### Changed
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- [zendframework/zend-stdlib#92](https://github.com/zendframework/zend-stdlib/pull/92) fixes serialization of `SplPriorityQueue` by ensuring its `$serial`
+ property is also serialized.
+
+- [zendframework/zend-stdlib#91](https://github.com/zendframework/zend-stdlib/pull/91) fixes behavior in the `ArrayObject` implementation that was not
+ compatible with PHP 7.3.
+
+## 3.2.0 - 2018-04-30
+
+### Added
+
+- [zendframework/zend-stdlib#87](https://github.com/zendframework/zend-stdlib/pull/87) adds support for PHP 7.2.
+
+### Changed
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- [zendframework/zend-stdlib#87](https://github.com/zendframework/zend-stdlib/pull/87) removes support for HHVM.
+
+### Fixed
+
+- Nothing.
+
+## 3.1.1 - 2018-04-12
+
+### Added
+
+- Nothing.
+
+### Changed
+
+- [zendframework/zend-stdlib#67](https://github.com/zendframework/zend-stdlib/pull/67) changes the typehint of the `$content` property
+ of the `Message` class to indicate it is a string. All known implementations
+ already assumed this.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- [zendframework/zend-stdlib#60](https://github.com/zendframework/zend-stdlib/pull/60) fixes an issue whereby calling `remove()` would
+ incorrectly re-calculate the maximum priority stored in the queue.
+
+- [zendframework/zend-stdlib#60](https://github.com/zendframework/zend-stdlib/pull/60) fixes an infinite loop condition that can occur when
+ inserting an item at 0 priority.
+
+## 3.1.0 - 2016-09-13
+
+### Added
+
+- [zendframework/zend-stdlib#63](https://github.com/zendframework/zend-stdlib/pull/63) adds a new
+ `Laminas\Stdlib\ConsoleHelper` class, providing minimal support for writing
+ output to `STDOUT` and `STDERR`, with optional colorization, when the console
+ supports that feature.
+
+### Deprecated
+
+- [zendframework/zend-stdlib#38](https://github.com/zendframework/zend-stdlib/pull/38) deprecates
+ `Laminas\Stdlib\JsonSerializable`, as all supported version of PHP now support
+ it.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- Nothing.
+
+## 3.0.1 - 2016-04-12
+
+### Added
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- [zendframework/zend-stdlib#59](https://github.com/zendframework/zend-stdlib/pull/59) fixes a notice
+ when defining the `Laminas\Json\Json::GLOB_BRACE` constant on systems using
+ non-gcc glob implementations.
+
+## 3.0.0 - 2016-02-03
+
+### Added
+
+- [zendframework/zend-stdlib#51](https://github.com/zendframework/zend-stdlib/pull/51) adds PHP 7 as a
+ supported PHP version.
+- [zendframework/zend-stdlib#51](https://github.com/zendframework/zend-stdlib/pull/51) adds a migration
+ document from v2 to v3. Hint: if you use hydrators, you need to be using
+ laminas-hydrator instead!
+- [zendframework/zend-stdlib#51](https://github.com/zendframework/zend-stdlib/pull/51) adds automated
+ documentation builds to gh-pages.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- [zendframework/zend-stdlib#33](https://github.com/zendframework/zend-stdlib/pull/33) - removed
+ deprecated classes
+ - *All Hydrator classes* see zendframework/zend-stdlib#22.
+ - `Laminas\Stdlib\CallbackHandler` see zendframework/zend-stdlib#35
+- [zendframework/zend-stdlib#37](https://github.com/zendframework/zend-stdlib/pull/37) - removed
+ deprecated classes and polyfills:
+ - `Laminas\Stdlib\DateTime`; this had been deprecated since 2.5, and only
+ existed as a polyfill for the `createFromISO8601()` support, now standard
+ in all PHP versions we support.
+ - `Laminas\Stdlib\Exception\InvalidCallbackException`, which was unused since zendframework/zend-stdlib#33.
+ - `Laminas\Stdlib\Guard\GuardUtils`, which duplicated `Laminas\Stdlib\Guard\AllGuardsTrait`
+ to allow usage with pre-PHP 5.4 versions.
+ - `src/compatibility/autoload.php`, which has been dprecated since 2.5.
+- [zendframework/zend-stdlib#37](https://github.com/zendframework/zend-stdlib/pull/37) - removed
+ unneeded dependencies:
+ - laminas-config (used only in testing ArrayUtils, and the test was redundant)
+ - laminas-serializer (no longer used)
+- [zendframework/zend-stdlib#51](https://github.com/zendframework/zend-stdlib/pull/51) removes the
+ documentation for hydrators, as those are part of the laminas-hydrator
+ component.
+
+### Fixed
+
+- Nothing.
+
+## 2.7.4 - 2015-10-15
+
+### Added
+
+- Nothing.
+
+### Deprecated
+
+- [zendframework/zend-stdlib#35](https://github.com/zendframework/zend-stdlib/pull/35) deprecates
+ `Laminas\Stdlib\CallbackHandler`, as the one component that used it,
+ laminas-eventmanager, will no longer depend on it starting in v3.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- Nothing.
+
+## 2.7.3 - 2015-09-24
+
+### Added
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- [zendframework/zend-stdlib#27](https://github.com/zendframework/zend-stdlib/pull/27) fixes a race
+ condition in the `FastPriorityQueue::remove()` logic that occurs when removing
+ items iteratively from the same priority of a queue.
+
+## 2.7.2 - 2015-09-23
+
+### Added
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- [zendframework/zend-stdlib#26](https://github.com/zendframework/zend-stdlib/pull/26) fixes a subtle
+ inheritance issue with deprecation in the hydrators, and updates the
+ `HydratorInterface` to also extend the laminas-hydrator `HydratorInterface` to
+ ensure LSP is preserved.
+
+## 2.7.1 - 2015-09-22
+
+### Added
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- [zendframework/zend-stdlib#24](https://github.com/zendframework/zend-stdlib/pull/24) fixes an import in
+ `FastPriorityQueue` to alias `SplPriorityQueue` in order to disambiguate with
+ the local override present in the component.
+
+## 2.7.0 - 2015-09-22
+
+### Added
+
+- [zendframework/zend-stdlib#19](https://github.com/zendframework/zend-stdlib/pull/19) adds a new
+ `FastPriorityQueue` implementation. It follows the same signature as
+ `SplPriorityQueue`, but uses a performance-optimized algorithm:
+
+ - inserts are 2x faster than `SplPriorityQueue` and 3x faster than the
+ `Laminas\Stdlib\PriorityQueue` implementation.
+ - extracts are 4x faster than `SplPriorityQueue` and 4-5x faster than the
+ `Laminas\Stdlib\PriorityQueue` implementation.
+
+ The intention is to use this as a drop-in replacement in the
+ `laminas-eventmanager` component to provide performance benefits.
+
+### Deprecated
+
+- [zendframework/zend-stdlib#20](https://github.com/zendframework/zend-stdlib/pull/20) deprecates *all
+ hydrator* classes, in favor of the new [laminas-hydrator](https://github.com/laminas/laminas-hydrator)
+ component. All classes were updated to extend their laminas-hydrator equivalents,
+ and marked as `@deprecated`, indicating the equivalent class from the other
+ repository.
+
+ Users *should* immediately start changing their code to use the laminas-hydrator
+ equivalents; in most cases, this can be as easy as removing the `Stdlib`
+ namespace from import statements or hydrator configuration. Hydrators will be
+ removed entirely from laminas-stdlib in v3.0, and all future updates to hydrators
+ will occur in the laminas-hydrator library.
+
+ Changes with backwards compatibility implications:
+
+ - Users implementing `Laminas\Stdlib\Hydrator\HydratorAwareInterface` will need to
+ update their `setHydrator()` implementation to typehint on
+ `Laminas\Hydrator\HydratorInterface`. This can be done by changing the import
+ statement for that interface as follows:
+
+ ```php
+ // Replace this:
+ use Laminas\Stdlib\Hydrator\HydratorInterface;
+ // with this:
+ use Laminas\Hydrator\HydratorInterface;
+ ```
+
+ If you are not using imports, change the typehint within the signature itself:
+
+ ```php
+ // Replace this:
+ public function setHydrator(\Laminas\Stdlib\Hydrator\HydratorInterface $hydrator)
+ // with this:
+ public function setHydrator(\Laminas\Hydrator\HydratorInterface $hydrator)
+ ```
+
+ If you are using `Laminas\Stdlib\Hydrator\HydratorAwareTrait`, no changes are
+ necessary, unless you override that method.
+
+ - If you were catching hydrator-generated exceptions, these were previously in
+ the `Laminas\Stdlib\Exception` namespace. You will need to update your code to
+ catch exceptions in the `Laminas\Hydrator\Exception` namespace.
+
+ - Users who *do* migrate to laminas-hydrator may end up in a situation where
+ their code will not work with existing libraries that are still type-hinting
+ on the laminas-stdlib interfaces. We will be attempting to address that ASAP,
+ but the deprecation within laminas-stdlib is necessary as a first step.
+
+ In the meantime, you can write hydrators targeting laminas-stdlib still in
+ order to guarantee compatibility.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- Nothing.
+
+## 2.6.0 - 2015-07-21
+
+### Added
+
+- [zendframework/zend-stdlib#13](https://github.com/zendframework/zend-stdlib/pull/13) adds
+ `Laminas\Stdlib\Hydrator\Iterator`, which provides mechanisms for hydrating
+ objects when iterating a traversable. This allows creating generic collection
+ resultsets; the original idea was pulled from
+ [PhlyMongo](https://github.com/phly/PhlyMongo), where it was used to hydrate
+ collections retrieved from MongoDB.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- Nothing.
+
+## 2.5.2 - 2015-07-21
+
+### Added
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- [zendframework/zend-stdlib#9](https://github.com/zendframework/zend-stdlib/pull/9) fixes an issue with
+ count incrementation during insert in PriorityList, ensuring that incrementation only
+ occurs when the item inserted was not previously present in the list.
+
+## 2.4.4 - 2015-07-21
+
+### Added
+
+- Nothing.
+
+### Deprecated
+
+- Nothing.
+
+### Removed
+
+- Nothing.
+
+### Fixed
+
+- [zendframework/zend-stdlib#9](https://github.com/zendframework/zend-stdlib/pull/9) fixes an issue with
+ count incrementation during insert in PriorityList, ensuring that incrementation only
+ occurs when the item inserted was not previously present in the list.
--- /dev/null
+Copyright (c) 2019, Laminas Foundation.
+All rights reserved. (https://getlaminas.org/)
--- /dev/null
+Copyright (c) 2019, Laminas Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+- Neither the name of Laminas Foundation nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+# laminas-stdlib
+
+[![Build Status](https://travis-ci.org/laminas/laminas-stdlib.svg?branch=master)](https://travis-ci.org/laminas/laminas-stdlib)
+[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-stdlib/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-stdlib?branch=master)
+
+`Laminas\Stdlib` is a set of components that implements general purpose utility
+class for different scopes like:
+
+- array utilities functions;
+- general messaging systems;
+- string wrappers;
+- etc.
+
+---
+
+- File issues at https://github.com/laminas/laminas-stdlib/issues
+- Documentation is at https://docs.laminas.dev/laminas-stdlib/
+
+## Benchmarks
+
+We provide scripts for benchmarking laminas-stdlib using the
+[PHPBench](https://github.com/phpbench/phpbench) framework; these can be
+found in the `benchmark/` directory.
+
+To execute the benchmarks you can run the following command:
+
+```bash
+$ vendor/bin/phpbench run --report=aggregate
+```
--- /dev/null
+{
+ "name": "laminas/laminas-stdlib",
+ "description": "SPL extensions, array utilities, error handlers, and more",
+ "license": "BSD-3-Clause",
+ "keywords": [
+ "laminas",
+ "stdlib"
+ ],
+ "homepage": "https://laminas.dev",
+ "support": {
+ "docs": "https://docs.laminas.dev/laminas-stdlib/",
+ "issues": "https://github.com/laminas/laminas-stdlib/issues",
+ "source": "https://github.com/laminas/laminas-stdlib",
+ "rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
+ "chat": "https://laminas.dev/chat",
+ "forum": "https://discourse.laminas.dev"
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2.x-dev",
+ "dev-develop": "3.3.x-dev"
+ }
+ },
+ "require": {
+ "php": "^5.6 || ^7.0",
+ "laminas/laminas-zendframework-bridge": "^1.0"
+ },
+ "require-dev": {
+ "laminas/laminas-coding-standard": "~1.0.0",
+ "phpbench/phpbench": "^0.13",
+ "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2"
+ },
+ "autoload": {
+ "psr-4": {
+ "Laminas\\Stdlib\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "LaminasTest\\Stdlib\\": "test/",
+ "LaminasBench\\Stdlib\\": "benchmark/"
+ }
+ },
+ "scripts": {
+ "check": [
+ "@cs-check",
+ "@test"
+ ],
+ "cs-check": "phpcs",
+ "cs-fix": "phpcbf",
+ "test": "phpunit --colors=always",
+ "test-coverage": "phpunit --colors=always --coverage-clover clover.xml"
+ },
+ "replace": {
+ "zendframework/zend-stdlib": "self.version"
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Traversable;
+
+abstract class AbstractOptions implements ParameterObjectInterface
+{
+ // @codingStandardsIgnoreStart
+ /**
+ * We use the __ prefix to avoid collisions with properties in
+ * user-implementations.
+ *
+ * @var bool
+ */
+ protected $__strictMode__ = true;
+ // @codingStandardsIgnoreEnd
+
+ /**
+ * Constructor
+ *
+ * @param array|Traversable|null $options
+ */
+ public function __construct($options = null)
+ {
+ if (null !== $options) {
+ $this->setFromArray($options);
+ }
+ }
+
+ /**
+ * Set one or more configuration properties
+ *
+ * @param array|Traversable|AbstractOptions $options
+ * @throws Exception\InvalidArgumentException
+ * @return AbstractOptions Provides fluent interface
+ */
+ public function setFromArray($options)
+ {
+ if ($options instanceof self) {
+ $options = $options->toArray();
+ }
+
+ if (! is_array($options) && ! $options instanceof Traversable) {
+ throw new Exception\InvalidArgumentException(
+ sprintf(
+ 'Parameter provided to %s must be an %s, %s or %s',
+ __METHOD__,
+ 'array',
+ 'Traversable',
+ 'Laminas\Stdlib\AbstractOptions'
+ )
+ );
+ }
+
+ foreach ($options as $key => $value) {
+ $this->__set($key, $value);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Cast to array
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $array = [];
+ $transform = function ($letters) {
+ $letter = array_shift($letters);
+ return '_' . strtolower($letter);
+ };
+ foreach ($this as $key => $value) {
+ if ($key === '__strictMode__') {
+ continue;
+ }
+ $normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key);
+ $array[$normalizedKey] = $value;
+ }
+ return $array;
+ }
+
+ /**
+ * Set a configuration property
+ *
+ * @see ParameterObject::__set()
+ * @param string $key
+ * @param mixed $value
+ * @throws Exception\BadMethodCallException
+ * @return void
+ */
+ public function __set($key, $value)
+ {
+ $setter = 'set' . str_replace('_', '', $key);
+
+ if (is_callable([$this, $setter])) {
+ $this->{$setter}($value);
+
+ return;
+ }
+
+ if ($this->__strictMode__) {
+ throw new Exception\BadMethodCallException(sprintf(
+ 'The option "%s" does not have a callable "%s" ("%s") setter method which must be defined',
+ $key,
+ 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))),
+ $setter
+ ));
+ }
+ }
+
+ /**
+ * Get a configuration property
+ *
+ * @see ParameterObject::__get()
+ * @param string $key
+ * @throws Exception\BadMethodCallException
+ * @return mixed
+ */
+ public function __get($key)
+ {
+ $getter = 'get' . str_replace('_', '', $key);
+
+ if (is_callable([$this, $getter])) {
+ return $this->{$getter}();
+ }
+
+ throw new Exception\BadMethodCallException(sprintf(
+ 'The option "%s" does not have a callable "%s" getter method which must be defined',
+ $key,
+ 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)))
+ ));
+ }
+
+ /**
+ * Test if a configuration property is null
+ * @see ParameterObject::__isset()
+ * @param string $key
+ * @return bool
+ */
+ public function __isset($key)
+ {
+ $getter = 'get' . str_replace('_', '', $key);
+
+ return method_exists($this, $getter) && null !== $this->__get($key);
+ }
+
+ /**
+ * Set a configuration property to NULL
+ *
+ * @see ParameterObject::__unset()
+ * @param string $key
+ * @throws Exception\InvalidArgumentException
+ * @return void
+ */
+ public function __unset($key)
+ {
+ try {
+ $this->__set($key, null);
+ } catch (Exception\BadMethodCallException $e) {
+ throw new Exception\InvalidArgumentException(
+ 'The class property $' . $key . ' cannot be unset as'
+ . ' NULL is an invalid value for it',
+ 0,
+ $e
+ );
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use ArrayAccess;
+use Countable;
+use IteratorAggregate;
+use Serializable;
+
+/**
+ * Custom framework ArrayObject implementation
+ *
+ * Extends version-specific "abstract" implementation.
+ */
+class ArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable
+{
+ /**
+ * Properties of the object have their normal functionality
+ * when accessed as list (var_dump, foreach, etc.).
+ */
+ const STD_PROP_LIST = 1;
+
+ /**
+ * Entries can be accessed as properties (read and write).
+ */
+ const ARRAY_AS_PROPS = 2;
+
+ /**
+ * @var array
+ */
+ protected $storage;
+
+ /**
+ * @var int
+ */
+ protected $flag;
+
+ /**
+ * @var string
+ */
+ protected $iteratorClass;
+
+ /**
+ * @var array
+ */
+ protected $protectedProperties;
+
+ /**
+ * Constructor
+ *
+ * @param array $input
+ * @param int $flags
+ * @param string $iteratorClass
+ */
+ public function __construct($input = [], $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator')
+ {
+ $this->setFlags($flags);
+ $this->storage = $input;
+ $this->setIteratorClass($iteratorClass);
+ $this->protectedProperties = array_keys(get_object_vars($this));
+ }
+
+ /**
+ * Returns whether the requested key exists
+ *
+ * @param mixed $key
+ * @return bool
+ */
+ public function __isset($key)
+ {
+ if ($this->flag == self::ARRAY_AS_PROPS) {
+ return $this->offsetExists($key);
+ }
+ if (in_array($key, $this->protectedProperties)) {
+ throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ return isset($this->$key);
+ }
+
+ /**
+ * Sets the value at the specified key to value
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @return void
+ */
+ public function __set($key, $value)
+ {
+ if ($this->flag == self::ARRAY_AS_PROPS) {
+ return $this->offsetSet($key, $value);
+ }
+ if (in_array($key, $this->protectedProperties)) {
+ throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
+ }
+ $this->$key = $value;
+ }
+
+ /**
+ * Unsets the value at the specified key
+ *
+ * @param mixed $key
+ * @return void
+ */
+ public function __unset($key)
+ {
+ if ($this->flag == self::ARRAY_AS_PROPS) {
+ return $this->offsetUnset($key);
+ }
+ if (in_array($key, $this->protectedProperties)) {
+ throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
+ }
+ unset($this->$key);
+ }
+
+ /**
+ * Returns the value at the specified key by reference
+ *
+ * @param mixed $key
+ * @return mixed
+ */
+ public function &__get($key)
+ {
+ $ret = null;
+ if ($this->flag == self::ARRAY_AS_PROPS) {
+ $ret =& $this->offsetGet($key);
+
+ return $ret;
+ }
+ if (in_array($key, $this->protectedProperties)) {
+ throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
+ }
+
+ return $this->$key;
+ }
+
+ /**
+ * Appends the value
+ *
+ * @param mixed $value
+ * @return void
+ */
+ public function append($value)
+ {
+ $this->storage[] = $value;
+ }
+
+ /**
+ * Sort the entries by value
+ *
+ * @return void
+ */
+ public function asort()
+ {
+ asort($this->storage);
+ }
+
+ /**
+ * Get the number of public properties in the ArrayObject
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->storage);
+ }
+
+ /**
+ * Exchange the array for another one.
+ *
+ * @param array|ArrayObject $data
+ * @return array
+ */
+ public function exchangeArray($data)
+ {
+ if (! is_array($data) && ! is_object($data)) {
+ throw new Exception\InvalidArgumentException(
+ 'Passed variable is not an array or object, using empty array instead'
+ );
+ }
+
+ if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) {
+ $data = $data->getArrayCopy();
+ }
+ if (! is_array($data)) {
+ $data = (array) $data;
+ }
+
+ $storage = $this->storage;
+
+ $this->storage = $data;
+
+ return $storage;
+ }
+
+ /**
+ * Creates a copy of the ArrayObject.
+ *
+ * @return array
+ */
+ public function getArrayCopy()
+ {
+ return $this->storage;
+ }
+
+ /**
+ * Gets the behavior flags.
+ *
+ * @return int
+ */
+ public function getFlags()
+ {
+ return $this->flag;
+ }
+
+ /**
+ * Create a new iterator from an ArrayObject instance
+ *
+ * @return \Iterator
+ */
+ public function getIterator()
+ {
+ $class = $this->iteratorClass;
+
+ return new $class($this->storage);
+ }
+
+ /**
+ * Gets the iterator classname for the ArrayObject.
+ *
+ * @return string
+ */
+ public function getIteratorClass()
+ {
+ return $this->iteratorClass;
+ }
+
+ /**
+ * Sort the entries by key
+ *
+ * @return void
+ */
+ public function ksort()
+ {
+ ksort($this->storage);
+ }
+
+ /**
+ * Sort an array using a case insensitive "natural order" algorithm
+ *
+ * @return void
+ */
+ public function natcasesort()
+ {
+ natcasesort($this->storage);
+ }
+
+ /**
+ * Sort entries using a "natural order" algorithm
+ *
+ * @return void
+ */
+ public function natsort()
+ {
+ natsort($this->storage);
+ }
+
+ /**
+ * Returns whether the requested key exists
+ *
+ * @param mixed $key
+ * @return bool
+ */
+ public function offsetExists($key)
+ {
+ return isset($this->storage[$key]);
+ }
+
+ /**
+ * Returns the value at the specified key
+ *
+ * @param mixed $key
+ * @return mixed
+ */
+ public function &offsetGet($key)
+ {
+ $ret = null;
+ if (! $this->offsetExists($key)) {
+ return $ret;
+ }
+ $ret =& $this->storage[$key];
+
+ return $ret;
+ }
+
+ /**
+ * Sets the value at the specified key to value
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @return void
+ */
+ public function offsetSet($key, $value)
+ {
+ $this->storage[$key] = $value;
+ }
+
+ /**
+ * Unsets the value at the specified key
+ *
+ * @param mixed $key
+ * @return void
+ */
+ public function offsetUnset($key)
+ {
+ if ($this->offsetExists($key)) {
+ unset($this->storage[$key]);
+ }
+ }
+
+ /**
+ * Serialize an ArrayObject
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return serialize(get_object_vars($this));
+ }
+
+ /**
+ * Sets the behavior flags
+ *
+ * @param int $flags
+ * @return void
+ */
+ public function setFlags($flags)
+ {
+ $this->flag = $flags;
+ }
+
+ /**
+ * Sets the iterator classname for the ArrayObject
+ *
+ * @param string $class
+ * @return void
+ */
+ public function setIteratorClass($class)
+ {
+ if (class_exists($class)) {
+ $this->iteratorClass = $class;
+
+ return ;
+ }
+
+ if (strpos($class, '\\') === 0) {
+ $class = '\\' . $class;
+ if (class_exists($class)) {
+ $this->iteratorClass = $class;
+
+ return ;
+ }
+ }
+
+ throw new Exception\InvalidArgumentException('The iterator class does not exist');
+ }
+
+ /**
+ * Sort the entries with a user-defined comparison function and maintain key association
+ *
+ * @param callable $function
+ * @return void
+ */
+ public function uasort($function)
+ {
+ if (is_callable($function)) {
+ uasort($this->storage, $function);
+ }
+ }
+
+ /**
+ * Sort the entries by keys using a user-defined comparison function
+ *
+ * @param callable $function
+ * @return void
+ */
+ public function uksort($function)
+ {
+ if (is_callable($function)) {
+ uksort($this->storage, $function);
+ }
+ }
+
+ /**
+ * Unserialize an ArrayObject
+ *
+ * @param string $data
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ $ar = unserialize($data);
+ $this->protectedProperties = array_keys(get_object_vars($this));
+
+ $this->setFlags($ar['flag']);
+ $this->exchangeArray($ar['storage']);
+ $this->setIteratorClass($ar['iteratorClass']);
+
+ foreach ($ar as $k => $v) {
+ switch ($k) {
+ case 'flag':
+ $this->setFlags($v);
+ break;
+ case 'storage':
+ $this->exchangeArray($v);
+ break;
+ case 'iteratorClass':
+ $this->setIteratorClass($v);
+ break;
+ case 'protectedProperties':
+ break;
+ default:
+ $this->__set($k, $v);
+ }
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+interface ArraySerializableInterface
+{
+ /**
+ * Exchange internal values from provided array
+ *
+ * @param array $array
+ * @return void
+ */
+ public function exchangeArray(array $array);
+
+ /**
+ * Return an array representation of the object
+ *
+ * @return array
+ */
+ public function getArrayCopy();
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use ArrayIterator;
+use ArrayObject as PhpArrayObject;
+
+/**
+ * ArrayObject that acts as a stack with regards to iteration
+ */
+class ArrayStack extends PhpArrayObject
+{
+ /**
+ * Retrieve iterator
+ *
+ * Retrieve an array copy of the object, reverse its order, and return an
+ * ArrayIterator with that reversed array.
+ *
+ * @return ArrayIterator
+ */
+ public function getIterator()
+ {
+ $array = $this->getArrayCopy();
+ return new ArrayIterator(array_reverse($array));
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Laminas\Stdlib\ArrayUtils\MergeRemoveKey;
+use Laminas\Stdlib\ArrayUtils\MergeReplaceKeyInterface;
+use Traversable;
+
+/**
+ * Utility class for testing and manipulation of PHP arrays.
+ *
+ * Declared abstract, as we have no need for instantiation.
+ */
+abstract class ArrayUtils
+{
+ /**
+ * Compatibility Flag for ArrayUtils::filter
+ */
+ const ARRAY_FILTER_USE_BOTH = 1;
+
+ /**
+ * Compatibility Flag for ArrayUtils::filter
+ */
+ const ARRAY_FILTER_USE_KEY = 2;
+
+ /**
+ * Test whether an array contains one or more string keys
+ *
+ * @param mixed $value
+ * @param bool $allowEmpty Should an empty array() return true
+ * @return bool
+ */
+ public static function hasStringKeys($value, $allowEmpty = false)
+ {
+ if (! is_array($value)) {
+ return false;
+ }
+
+ if (! $value) {
+ return $allowEmpty;
+ }
+
+ return count(array_filter(array_keys($value), 'is_string')) > 0;
+ }
+
+ /**
+ * Test whether an array contains one or more integer keys
+ *
+ * @param mixed $value
+ * @param bool $allowEmpty Should an empty array() return true
+ * @return bool
+ */
+ public static function hasIntegerKeys($value, $allowEmpty = false)
+ {
+ if (! is_array($value)) {
+ return false;
+ }
+
+ if (! $value) {
+ return $allowEmpty;
+ }
+
+ return count(array_filter(array_keys($value), 'is_int')) > 0;
+ }
+
+ /**
+ * Test whether an array contains one or more numeric keys.
+ *
+ * A numeric key can be one of the following:
+ * - an integer 1,
+ * - a string with a number '20'
+ * - a string with negative number: '-1000'
+ * - a float: 2.2120, -78.150999
+ * - a string with float: '4000.99999', '-10.10'
+ *
+ * @param mixed $value
+ * @param bool $allowEmpty Should an empty array() return true
+ * @return bool
+ */
+ public static function hasNumericKeys($value, $allowEmpty = false)
+ {
+ if (! is_array($value)) {
+ return false;
+ }
+
+ if (! $value) {
+ return $allowEmpty;
+ }
+
+ return count(array_filter(array_keys($value), 'is_numeric')) > 0;
+ }
+
+ /**
+ * Test whether an array is a list
+ *
+ * A list is a collection of values assigned to continuous integer keys
+ * starting at 0 and ending at count() - 1.
+ *
+ * For example:
+ * <code>
+ * $list = array('a', 'b', 'c', 'd');
+ * $list = array(
+ * 0 => 'foo',
+ * 1 => 'bar',
+ * 2 => array('foo' => 'baz'),
+ * );
+ * </code>
+ *
+ * @param mixed $value
+ * @param bool $allowEmpty Is an empty list a valid list?
+ * @return bool
+ */
+ public static function isList($value, $allowEmpty = false)
+ {
+ if (! is_array($value)) {
+ return false;
+ }
+
+ if (! $value) {
+ return $allowEmpty;
+ }
+
+ return (array_values($value) === $value);
+ }
+
+ /**
+ * Test whether an array is a hash table.
+ *
+ * An array is a hash table if:
+ *
+ * 1. Contains one or more non-integer keys, or
+ * 2. Integer keys are non-continuous or misaligned (not starting with 0)
+ *
+ * For example:
+ * <code>
+ * $hash = array(
+ * 'foo' => 15,
+ * 'bar' => false,
+ * );
+ * $hash = array(
+ * 1995 => 'Birth of PHP',
+ * 2009 => 'PHP 5.3.0',
+ * 2012 => 'PHP 5.4.0',
+ * );
+ * $hash = array(
+ * 'formElement,
+ * 'options' => array( 'debug' => true ),
+ * );
+ * </code>
+ *
+ * @param mixed $value
+ * @param bool $allowEmpty Is an empty array() a valid hash table?
+ * @return bool
+ */
+ public static function isHashTable($value, $allowEmpty = false)
+ {
+ if (! is_array($value)) {
+ return false;
+ }
+
+ if (! $value) {
+ return $allowEmpty;
+ }
+
+ 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.
+ *
+ * Converts an iterator to an array. The $recursive flag, on by default,
+ * hints whether or not you want to do so recursively.
+ *
+ * @param array|Traversable $iterator The array or Traversable object to convert
+ * @param bool $recursive Recursively check all nested structures
+ * @throws Exception\InvalidArgumentException if $iterator is not an array or a Traversable object
+ * @return array
+ */
+ public static function iteratorToArray($iterator, $recursive = true)
+ {
+ if (! is_array($iterator) && ! $iterator instanceof Traversable) {
+ throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object');
+ }
+
+ if (! $recursive) {
+ if (is_array($iterator)) {
+ return $iterator;
+ }
+
+ return iterator_to_array($iterator);
+ }
+
+ if (method_exists($iterator, 'toArray')) {
+ return $iterator->toArray();
+ }
+
+ $array = [];
+ foreach ($iterator as $key => $value) {
+ if (is_scalar($value)) {
+ $array[$key] = $value;
+ continue;
+ }
+
+ if ($value instanceof Traversable) {
+ $array[$key] = static::iteratorToArray($value, $recursive);
+ continue;
+ }
+
+ if (is_array($value)) {
+ $array[$key] = static::iteratorToArray($value, $recursive);
+ continue;
+ }
+
+ $array[$key] = $value;
+ }
+
+ return $array;
+ }
+
+ /**
+ * Merge two arrays together.
+ *
+ * If an integer key exists in both arrays and preserveNumericKeys is false, the value
+ * from the second array will be appended to the first array. If both values are arrays, they
+ * are merged together, else the value of the second array overwrites the one of the first array.
+ *
+ * @param array $a
+ * @param array $b
+ * @param bool $preserveNumericKeys
+ * @return array
+ */
+ public static function merge(array $a, array $b, $preserveNumericKeys = false)
+ {
+ foreach ($b as $key => $value) {
+ if ($value instanceof MergeReplaceKeyInterface) {
+ $a[$key] = $value->getData();
+ } elseif (isset($a[$key]) || array_key_exists($key, $a)) {
+ if ($value instanceof MergeRemoveKey) {
+ unset($a[$key]);
+ } elseif (! $preserveNumericKeys && is_int($key)) {
+ $a[] = $value;
+ } elseif (is_array($value) && is_array($a[$key])) {
+ $a[$key] = static::merge($a[$key], $value, $preserveNumericKeys);
+ } else {
+ $a[$key] = $value;
+ }
+ } else {
+ if (! $value instanceof MergeRemoveKey) {
+ $a[$key] = $value;
+ }
+ }
+ }
+
+ return $a;
+ }
+
+ /**
+ * @deprecated Since 3.2.0; use the native array_filter methods
+ *
+ * @param array $data
+ * @param callable $callback
+ * @param null|int $flag
+ * @return array
+ * @throws Exception\InvalidArgumentException
+ */
+ public static function filter(array $data, $callback, $flag = null)
+ {
+ if (! is_callable($callback)) {
+ throw new Exception\InvalidArgumentException(sprintf(
+ 'Second parameter of %s must be callable',
+ __METHOD__
+ ));
+ }
+
+ return array_filter($data, $callback, $flag);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\ArrayUtils;
+
+final class MergeRemoveKey
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\ArrayUtils;
+
+final class MergeReplaceKey implements MergeReplaceKeyInterface
+{
+ /**
+ * @var mixed
+ */
+ protected $data;
+
+ /**
+ * @param mixed $data
+ */
+ public function __construct($data)
+ {
+ $this->data = $data;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getData()
+ {
+ return $this->data;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\ArrayUtils;
+
+/**
+ * Marker interface: can be used to replace keys completely in {@see ArrayUtils::merge()} operations
+ */
+interface MergeReplaceKeyInterface
+{
+ /**
+ * @return mixed
+ */
+ public function getData();
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+/**
+ * Utilities for console tooling.
+ *
+ * Provides the following facilities:
+ *
+ * - Colorize strings using markup (e.g., `<info>message</info>`,
+ * `<error>message</error>`)
+ * - Write output to a specified stream, optionally with colorization.
+ * - Write a line of output to a specified stream, optionally with
+ * colorization, using the system EOL sequence..
+ * - Write an error message to STDERR.
+ *
+ * Colorization will only occur when expected sequences are discovered, and
+ * then, only if the console terminal allows it.
+ *
+ * Essentially, provides the bare minimum to allow you to provide messages to
+ * the current console.
+ */
+class ConsoleHelper
+{
+ const COLOR_GREEN = "\033[32m";
+ const COLOR_RED = "\033[31m";
+ const COLOR_RESET = "\033[0m";
+
+ const HIGHLIGHT_INFO = 'info';
+ const HIGHLIGHT_ERROR = 'error';
+
+ private $highlightMap = [
+ self::HIGHLIGHT_INFO => self::COLOR_GREEN,
+ self::HIGHLIGHT_ERROR => self::COLOR_RED,
+ ];
+
+ /**
+ * @var string Exists only for testing.
+ */
+ private $eol = PHP_EOL;
+
+ /**
+ * @var resource Exists only for testing.
+ */
+ private $stderr = STDERR;
+
+ /**
+ * @var bool
+ */
+ private $supportsColor;
+
+ /**
+ * @param resource $resource
+ */
+ public function __construct($resource = STDOUT)
+ {
+ $this->supportsColor = $this->detectColorCapabilities($resource);
+ }
+
+ /**
+ * Colorize a string for use with the terminal.
+ *
+ * Takes strings formatted as `<key>string</key>` and formats them per the
+ * $highlightMap; if color support is disabled, simply removes the formatting
+ * tags.
+ *
+ * @param string $string
+ * @return string
+ */
+ public function colorize($string)
+ {
+ $reset = $this->supportsColor ? self::COLOR_RESET : '';
+ foreach ($this->highlightMap as $key => $color) {
+ $pattern = sprintf('#<%s>(.*?)</%s>#s', $key, $key);
+ $color = $this->supportsColor ? $color : '';
+ $string = preg_replace($pattern, $color . '$1' . $reset, $string);
+ }
+ return $string;
+ }
+
+ /**
+ * @param string $string
+ * @param bool $colorize Whether or not to colorize the string
+ * @param resource $resource Defaults to STDOUT
+ * @return void
+ */
+ public function write($string, $colorize = true, $resource = STDOUT)
+ {
+ if ($colorize) {
+ $string = $this->colorize($string);
+ }
+
+ $string = $this->formatNewlines($string);
+
+ fwrite($resource, $string);
+ }
+
+ /**
+ * @param string $string
+ * @param bool $colorize Whether or not to colorize the line
+ * @param resource $resource Defaults to STDOUT
+ * @return void
+ */
+ public function writeLine($string, $colorize = true, $resource = STDOUT)
+ {
+ $this->write($string . $this->eol, $colorize, $resource);
+ }
+
+ /**
+ * Emit an error message.
+ *
+ * Wraps the message in `<error></error>`, and passes it to `writeLine()`,
+ * using STDERR as the resource; emits an additional empty line when done,
+ * also to STDERR.
+ *
+ * @param string $message
+ * @return void
+ */
+ public function writeErrorMessage($message)
+ {
+ $this->writeLine(sprintf('<error>%s</error>', $message), true, $this->stderr);
+ $this->writeLine('', false, $this->stderr);
+ }
+
+ /**
+ * @param resource $resource
+ * @return bool
+ */
+ private function detectColorCapabilities($resource = STDOUT)
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ // Windows
+ return false !== getenv('ANSICON')
+ || 'ON' === getenv('ConEmuANSI')
+ || 'xterm' === getenv('TERM');
+ }
+
+ return function_exists('posix_isatty') && posix_isatty($resource);
+ }
+
+ /**
+ * Ensure newlines are appropriate for the current terminal.
+ *
+ * @param string
+ * @return string
+ */
+ private function formatNewlines($string)
+ {
+ $string = str_replace($this->eol, "\0PHP_EOL\0", $string);
+ $string = preg_replace("/(\r\n|\n|\r)/", $this->eol, $string);
+ return str_replace("\0PHP_EOL\0", $this->eol, $string);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+interface DispatchableInterface
+{
+ /**
+ * Dispatch a request
+ *
+ * @param RequestInterface $request
+ * @param null|ResponseInterface $response
+ * @return Response|mixed
+ */
+ public function dispatch(RequestInterface $request, ResponseInterface $response = null);
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use ErrorException;
+
+/**
+ * ErrorHandler that can be used to catch internal PHP errors
+ * and convert to an ErrorException instance.
+ */
+abstract class ErrorHandler
+{
+ /**
+ * Active stack
+ *
+ * @var array
+ */
+ protected static $stack = [];
+
+ /**
+ * Check if this error handler is active
+ *
+ * @return bool
+ */
+ public static function started()
+ {
+ return (bool) static::getNestedLevel();
+ }
+
+ /**
+ * Get the current nested level
+ *
+ * @return int
+ */
+ public static function getNestedLevel()
+ {
+ return count(static::$stack);
+ }
+
+ /**
+ * Starting the error handler
+ *
+ * @param int $errorLevel
+ */
+ public static function start($errorLevel = \E_WARNING)
+ {
+ if (! static::$stack) {
+ set_error_handler([get_called_class(), 'addError'], $errorLevel);
+ }
+
+ static::$stack[] = null;
+ }
+
+ /**
+ * Stopping the error handler
+ *
+ * @param bool $throw Throw the ErrorException if any
+ * @return null|ErrorException
+ * @throws ErrorException If an error has been caught and $throw is true
+ */
+ public static function stop($throw = false)
+ {
+ $errorException = null;
+
+ if (static::$stack) {
+ $errorException = array_pop(static::$stack);
+
+ if (! static::$stack) {
+ restore_error_handler();
+ }
+
+ if ($errorException && $throw) {
+ throw $errorException;
+ }
+ }
+
+ return $errorException;
+ }
+
+ /**
+ * Stop all active handler
+ *
+ * @return void
+ */
+ public static function clean()
+ {
+ if (static::$stack) {
+ restore_error_handler();
+ }
+
+ static::$stack = [];
+ }
+
+ /**
+ * Add an error to the stack
+ *
+ * @param int $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param int $errline
+ * @return void
+ */
+ public static function addError($errno, $errstr = '', $errfile = '', $errline = 0)
+ {
+ $stack = & static::$stack[count(static::$stack) - 1];
+ $stack = new ErrorException($errstr, 0, $errno, $errfile, $errline, $stack);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Exception;
+
+/**
+ * Bad method call exception
+ */
+class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Exception;
+
+/**
+ * Domain exception
+ */
+class DomainException extends \DomainException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Exception;
+
+/**
+ * Exception marker interface
+ */
+interface ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Exception;
+
+/**
+ * Extension not loaded exception
+ */
+class ExtensionNotLoadedException extends RuntimeException
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Exception;
+
+/**
+ * Invalid Argument Exception
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Exception;
+
+/**
+ * Logic exception
+ */
+class LogicException extends \LogicException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Exception;
+
+/**
+ * Runtime exception
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Countable;
+use Iterator;
+use Serializable;
+use SplPriorityQueue as PhpSplPriorityQueue;
+
+/**
+ * This is an efficient implementation of an integer priority queue in PHP
+ *
+ * This class acts like a queue with insert() and extract(), removing the
+ * elements from the queue and it also acts like an Iterator without removing
+ * the elements. This behaviour can be used in mixed scenarios with high
+ * performance boost.
+ */
+class FastPriorityQueue implements Iterator, Countable, Serializable
+{
+ const EXTR_DATA = PhpSplPriorityQueue::EXTR_DATA;
+ const EXTR_PRIORITY = PhpSplPriorityQueue::EXTR_PRIORITY;
+ const EXTR_BOTH = PhpSplPriorityQueue::EXTR_BOTH;
+
+ /**
+ * @var integer
+ */
+ protected $extractFlag = self::EXTR_DATA;
+
+ /**
+ * Elements of the queue, divided by priorities
+ *
+ * @var array
+ */
+ protected $values = [];
+
+ /**
+ * Array of priorities
+ *
+ * @var array
+ */
+ protected $priorities = [];
+
+ /**
+ * Array of priorities used for the iteration
+ *
+ * @var array
+ */
+ protected $subPriorities = [];
+
+ /**
+ * Max priority
+ *
+ * @var integer|null
+ */
+ protected $maxPriority = null;
+
+ /**
+ * Total number of elements in the queue
+ *
+ * @var integer
+ */
+ protected $count = 0;
+
+ /**
+ * Index of the current element in the queue
+ *
+ * @var integer
+ */
+ protected $index = 0;
+
+ /**
+ * Sub index of the current element in the same priority level
+ *
+ * @var integer
+ */
+ protected $subIndex = 0;
+
+ /**
+ * Insert an element in the queue with a specified priority
+ *
+ * @param mixed $value
+ * @param integer $priority
+ */
+ public function insert($value, $priority)
+ {
+ if (! is_int($priority)) {
+ throw new Exception\InvalidArgumentException('The priority must be an integer');
+ }
+ $this->values[$priority][] = $value;
+ if (! isset($this->priorities[$priority])) {
+ $this->priorities[$priority] = $priority;
+ $this->maxPriority = $this->maxPriority === null ? $priority : max($priority, $this->maxPriority);
+ }
+ ++$this->count;
+ }
+
+ /**
+ * Extract an element in the queue according to the priority and the
+ * order of insertion
+ *
+ * @return mixed
+ */
+ public function extract()
+ {
+ if (! $this->valid()) {
+ return false;
+ }
+ $value = $this->current();
+ $this->nextAndRemove();
+ return $value;
+ }
+
+ /**
+ * Remove an item from the queue
+ *
+ * This is different than {@link extract()}; its purpose is to dequeue an
+ * item.
+ *
+ * Note: this removes the first item matching the provided item found. If
+ * the same item has been added multiple times, it will not remove other
+ * instances.
+ *
+ * @param mixed $datum
+ * @return bool False if the item was not found, true otherwise.
+ */
+ public function remove($datum)
+ {
+ $currentIndex = $this->index;
+ $currentSubIndex = $this->subIndex;
+ $currentPriority = $this->maxPriority;
+
+ $this->rewind();
+ while ($this->valid()) {
+ if (current($this->values[$this->maxPriority]) === $datum) {
+ $index = key($this->values[$this->maxPriority]);
+ unset($this->values[$this->maxPriority][$index]);
+
+ // The `next()` method advances the internal array pointer, so we need to use the `reset()` function,
+ // otherwise we would lose all elements before the place the pointer points.
+ reset($this->values[$this->maxPriority]);
+
+ $this->index = $currentIndex;
+ $this->subIndex = $currentSubIndex;
+
+ // If the array is empty we need to destroy the unnecessary priority,
+ // otherwise we would end up with an incorrect value of `$this->count`
+ // {@see \Laminas\Stdlib\FastPriorityQueue::nextAndRemove()}.
+ if (empty($this->values[$this->maxPriority])) {
+ unset($this->values[$this->maxPriority]);
+ unset($this->priorities[$this->maxPriority]);
+ if ($this->maxPriority === $currentPriority) {
+ $this->subIndex = 0;
+ }
+ }
+
+ $this->maxPriority = empty($this->priorities) ? null : max($this->priorities);
+ --$this->count;
+ return true;
+ }
+ $this->next();
+ }
+ return false;
+ }
+
+ /**
+ * Get the total number of elements in the queue
+ *
+ * @return integer
+ */
+ public function count()
+ {
+ return $this->count;
+ }
+
+ /**
+ * Get the current element in the queue
+ *
+ * @return mixed
+ */
+ public function current()
+ {
+ switch ($this->extractFlag) {
+ case self::EXTR_DATA:
+ return current($this->values[$this->maxPriority]);
+ case self::EXTR_PRIORITY:
+ return $this->maxPriority;
+ case self::EXTR_BOTH:
+ return [
+ 'data' => current($this->values[$this->maxPriority]),
+ 'priority' => $this->maxPriority
+ ];
+ }
+ }
+
+ /**
+ * Get the index of the current element in the queue
+ *
+ * @return integer
+ */
+ public function key()
+ {
+ return $this->index;
+ }
+
+ /**
+ * Set the iterator pointer to the next element in the queue
+ * removing the previous element
+ */
+ protected function nextAndRemove()
+ {
+ $key = key($this->values[$this->maxPriority]);
+
+ if (false === next($this->values[$this->maxPriority])) {
+ unset($this->priorities[$this->maxPriority]);
+ unset($this->values[$this->maxPriority]);
+ $this->maxPriority = empty($this->priorities) ? null : max($this->priorities);
+ $this->subIndex = -1;
+ } else {
+ unset($this->values[$this->maxPriority][$key]);
+ }
+ ++$this->index;
+ ++$this->subIndex;
+ --$this->count;
+ }
+
+ /**
+ * Set the iterator pointer to the next element in the queue
+ * without removing the previous element
+ */
+ public function next()
+ {
+ if (false === next($this->values[$this->maxPriority])) {
+ unset($this->subPriorities[$this->maxPriority]);
+ reset($this->values[$this->maxPriority]);
+ $this->maxPriority = empty($this->subPriorities) ? null : max($this->subPriorities);
+ $this->subIndex = -1;
+ }
+ ++$this->index;
+ ++$this->subIndex;
+ }
+
+ /**
+ * Check if the current iterator is valid
+ *
+ * @return boolean
+ */
+ public function valid()
+ {
+ return isset($this->values[$this->maxPriority]);
+ }
+
+ /**
+ * Rewind the current iterator
+ */
+ public function rewind()
+ {
+ $this->subPriorities = $this->priorities;
+ $this->maxPriority = empty($this->priorities) ? 0 : max($this->priorities);
+ $this->index = 0;
+ $this->subIndex = 0;
+ }
+
+ /**
+ * Serialize to an array
+ *
+ * Array will be priority => data pairs
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $array = [];
+ foreach (clone $this as $item) {
+ $array[] = $item;
+ }
+ return $array;
+ }
+
+ /**
+ * Serialize
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ $clone = clone $this;
+ $clone->setExtractFlags(self::EXTR_BOTH);
+
+ $data = [];
+ foreach ($clone as $item) {
+ $data[] = $item;
+ }
+
+ return serialize($data);
+ }
+
+ /**
+ * Deserialize
+ *
+ * @param string $data
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ foreach (unserialize($data) as $item) {
+ $this->insert($item['data'], $item['priority']);
+ }
+ }
+
+ /**
+ * Set the extract flag
+ *
+ * @param integer $flag
+ */
+ public function setExtractFlags($flag)
+ {
+ switch ($flag) {
+ case self::EXTR_DATA:
+ case self::EXTR_PRIORITY:
+ case self::EXTR_BOTH:
+ $this->extractFlag = $flag;
+ break;
+ default:
+ throw new Exception\InvalidArgumentException("The extract flag specified is not valid");
+ }
+ }
+
+ /**
+ * Check if the queue is empty
+ *
+ * @return boolean
+ */
+ public function isEmpty()
+ {
+ return empty($this->values);
+ }
+
+ /**
+ * Does the queue contain the given datum?
+ *
+ * @param mixed $datum
+ * @return bool
+ */
+ public function contains($datum)
+ {
+ foreach ($this->values as $values) {
+ if (in_array($datum, $values)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Does the queue have an item with the given priority?
+ *
+ * @param int $priority
+ * @return bool
+ */
+ public function hasPriority($priority)
+ {
+ return isset($this->values[$priority]);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+/**
+ * Wrapper for glob with fallback if GLOB_BRACE is not available.
+ */
+abstract class Glob
+{
+ /**#@+
+ * Glob constants.
+ */
+ const GLOB_MARK = 0x01;
+ const GLOB_NOSORT = 0x02;
+ const GLOB_NOCHECK = 0x04;
+ const GLOB_NOESCAPE = 0x08;
+ const GLOB_BRACE = 0x10;
+ const GLOB_ONLYDIR = 0x20;
+ const GLOB_ERR = 0x40;
+ /**#@-*/
+
+ /**
+ * Find pathnames matching a pattern.
+ *
+ * @see http://docs.php.net/glob
+ * @param string $pattern
+ * @param int $flags
+ * @param bool $forceFallback
+ * @return array
+ * @throws Exception\RuntimeException
+ */
+ public static function glob($pattern, $flags = 0, $forceFallback = false)
+ {
+ if (! defined('GLOB_BRACE') || $forceFallback) {
+ return static::fallbackGlob($pattern, $flags);
+ }
+
+ return static::systemGlob($pattern, $flags);
+ }
+
+ /**
+ * Use the glob function provided by the system.
+ *
+ * @param string $pattern
+ * @param int $flags
+ * @return array
+ * @throws Exception\RuntimeException
+ */
+ protected static function systemGlob($pattern, $flags)
+ {
+ if ($flags) {
+ $flagMap = [
+ self::GLOB_MARK => GLOB_MARK,
+ self::GLOB_NOSORT => GLOB_NOSORT,
+ self::GLOB_NOCHECK => GLOB_NOCHECK,
+ self::GLOB_NOESCAPE => GLOB_NOESCAPE,
+ self::GLOB_BRACE => defined('GLOB_BRACE') ? GLOB_BRACE : 0,
+ self::GLOB_ONLYDIR => GLOB_ONLYDIR,
+ self::GLOB_ERR => GLOB_ERR,
+ ];
+
+ $globFlags = 0;
+
+ foreach ($flagMap as $internalFlag => $globFlag) {
+ if ($flags & $internalFlag) {
+ $globFlags |= $globFlag;
+ }
+ }
+ } else {
+ $globFlags = 0;
+ }
+
+ ErrorHandler::start();
+ $res = glob($pattern, $globFlags);
+ $err = ErrorHandler::stop();
+ if ($res === false) {
+ throw new Exception\RuntimeException("glob('{$pattern}', {$globFlags}) failed", 0, $err);
+ }
+ return $res;
+ }
+
+ /**
+ * Expand braces manually, then use the system glob.
+ *
+ * @param string $pattern
+ * @param int $flags
+ * @return array
+ * @throws Exception\RuntimeException
+ */
+ protected static function fallbackGlob($pattern, $flags)
+ {
+ if (! $flags & self::GLOB_BRACE) {
+ return static::systemGlob($pattern, $flags);
+ }
+
+ $flags &= ~self::GLOB_BRACE;
+ $length = strlen($pattern);
+ $paths = [];
+
+ if ($flags & self::GLOB_NOESCAPE) {
+ $begin = strpos($pattern, '{');
+ } else {
+ $begin = 0;
+
+ while (true) {
+ if ($begin === $length) {
+ $begin = false;
+ break;
+ } elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) {
+ $begin++;
+ } elseif ($pattern[$begin] === '{') {
+ break;
+ }
+
+ $begin++;
+ }
+ }
+
+ if ($begin === false) {
+ return static::systemGlob($pattern, $flags);
+ }
+
+ $next = static::nextBraceSub($pattern, $begin + 1, $flags);
+
+ if ($next === null) {
+ return static::systemGlob($pattern, $flags);
+ }
+
+ $rest = $next;
+
+ while ($pattern[$rest] !== '}') {
+ $rest = static::nextBraceSub($pattern, $rest + 1, $flags);
+
+ if ($rest === null) {
+ return static::systemGlob($pattern, $flags);
+ }
+ }
+
+ $p = $begin + 1;
+
+ while (true) {
+ $subPattern = substr($pattern, 0, $begin)
+ . substr($pattern, $p, $next - $p)
+ . substr($pattern, $rest + 1);
+
+ $result = static::fallbackGlob($subPattern, $flags | self::GLOB_BRACE);
+
+ if ($result) {
+ $paths = array_merge($paths, $result);
+ }
+
+ if ($pattern[$next] === '}') {
+ break;
+ }
+
+ $p = $next + 1;
+ $next = static::nextBraceSub($pattern, $p, $flags);
+ }
+
+ return array_unique($paths);
+ }
+
+ /**
+ * Find the end of the sub-pattern in a brace expression.
+ *
+ * @param string $pattern
+ * @param int $begin
+ * @param int $flags
+ * @return int|null
+ */
+ protected static function nextBraceSub($pattern, $begin, $flags)
+ {
+ $length = strlen($pattern);
+ $depth = 0;
+ $current = $begin;
+
+ while ($current < $length) {
+ if (! $flags & self::GLOB_NOESCAPE && $pattern[$current] === '\\') {
+ if (++$current === $length) {
+ break;
+ }
+
+ $current++;
+ } else {
+ if (($pattern[$current] === '}' && $depth-- === 0) || ($pattern[$current] === ',' && $depth === 0)) {
+ break;
+ } elseif ($pattern[$current++] === '{') {
+ $depth++;
+ }
+ }
+ }
+
+ return ($current < $length ? $current : null);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Guard;
+
+/**
+ * An aggregate for all guard traits
+ */
+trait AllGuardsTrait
+{
+ use ArrayOrTraversableGuardTrait;
+ use EmptyGuardTrait;
+ use NullGuardTrait;
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Guard;
+
+use Traversable;
+
+/**
+ * Provide a guard method for array or Traversable data
+ */
+trait ArrayOrTraversableGuardTrait
+{
+ /**
+ * Verifies that the data is an array or Traversable
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ protected function guardForArrayOrTraversable(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = 'Laminas\Stdlib\Exception\InvalidArgumentException'
+ ) {
+ if (! is_array($data) && ! ($data instanceof Traversable)) {
+ $message = sprintf(
+ "%s must be an array or Traversable, [%s] given",
+ $dataName,
+ is_object($data) ? get_class($data) : gettype($data)
+ );
+ throw new $exceptionClass($message);
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Guard;
+
+/**
+ * Provide a guard method against empty data
+ */
+trait EmptyGuardTrait
+{
+ /**
+ * Verify that the data is not empty
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ protected function guardAgainstEmpty(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = 'Laminas\Stdlib\Exception\InvalidArgumentException'
+ ) {
+ if (empty($data)) {
+ $message = sprintf('%s cannot be empty', $dataName);
+ throw new $exceptionClass($message);
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\Guard;
+
+/**
+ * Provide a guard method against null data
+ */
+trait NullGuardTrait
+{
+ /**
+ * Verify that the data is not null
+ *
+ * @param mixed $data the data to verify
+ * @param string $dataName the data name
+ * @param string $exceptionClass FQCN for the exception
+ * @throws \Exception
+ */
+ protected function guardAgainstNull(
+ $data,
+ $dataName = 'Argument',
+ $exceptionClass = 'Laminas\Stdlib\Exception\InvalidArgumentException'
+ ) {
+ if (null === $data) {
+ $message = sprintf('%s cannot be null', $dataName);
+ throw new $exceptionClass($message);
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+/**
+ * Interface to allow objects to have initialization logic
+ */
+interface InitializableInterface
+{
+ /**
+ * Init an object
+ *
+ * @return void
+ */
+ public function init();
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+/**
+ * @deprecated Since 3.1.0; use the native JsonSerializable interface
+ */
+interface JsonSerializable extends \JsonSerializable
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Traversable;
+
+class Message implements MessageInterface
+{
+ /**
+ * @var array
+ */
+ protected $metadata = [];
+
+ /**
+ * @var mixed
+ */
+ protected $content = '';
+
+ /**
+ * Set message metadata
+ *
+ * Non-destructive setting of message metadata; always adds to the metadata, never overwrites
+ * the entire metadata container.
+ *
+ * @param string|int|array|Traversable $spec
+ * @param mixed $value
+ * @throws Exception\InvalidArgumentException
+ * @return Message
+ */
+ public function setMetadata($spec, $value = null)
+ {
+ if (is_scalar($spec)) {
+ $this->metadata[$spec] = $value;
+ return $this;
+ }
+ if (! is_array($spec) && ! $spec instanceof Traversable) {
+ throw new Exception\InvalidArgumentException(sprintf(
+ 'Expected a string, array, or Traversable argument in first position; received "%s"',
+ (is_object($spec) ? get_class($spec) : gettype($spec))
+ ));
+ }
+ foreach ($spec as $key => $value) {
+ $this->metadata[$key] = $value;
+ }
+ return $this;
+ }
+
+ /**
+ * Retrieve all metadata or a single metadatum as specified by key
+ *
+ * @param null|string|int $key
+ * @param null|mixed $default
+ * @throws Exception\InvalidArgumentException
+ * @return mixed
+ */
+ public function getMetadata($key = null, $default = null)
+ {
+ if (null === $key) {
+ return $this->metadata;
+ }
+
+ if (! is_scalar($key)) {
+ throw new Exception\InvalidArgumentException('Non-scalar argument provided for key');
+ }
+
+ if (array_key_exists($key, $this->metadata)) {
+ return $this->metadata[$key];
+ }
+
+ return $default;
+ }
+
+ /**
+ * Set message content
+ *
+ * @param mixed $value
+ * @return Message
+ */
+ public function setContent($value)
+ {
+ $this->content = $value;
+ return $this;
+ }
+
+ /**
+ * Get message content
+ *
+ * @return mixed
+ */
+ public function getContent()
+ {
+ return $this->content;
+ }
+
+ /**
+ * @return string
+ */
+ public function toString()
+ {
+ $request = '';
+ foreach ($this->getMetadata() as $key => $value) {
+ $request .= sprintf(
+ "%s: %s\r\n",
+ (string) $key,
+ (string) $value
+ );
+ }
+ $request .= "\r\n" . $this->getContent();
+ return $request;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+interface MessageInterface
+{
+ /**
+ * Set metadata
+ *
+ * @param string|int|array|\Traversable $spec
+ * @param mixed $value
+ */
+ public function setMetadata($spec, $value = null);
+
+ /**
+ * Get metadata
+ *
+ * @param null|string|int $key
+ * @return mixed
+ */
+ public function getMetadata($key = null);
+
+ /**
+ * Set content
+ *
+ * @param mixed $content
+ * @return mixed
+ */
+ public function setContent($content);
+
+ /**
+ * Get content
+ *
+ * @return mixed
+ */
+ public function getContent();
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+interface ParameterObjectInterface
+{
+ /**
+ * @param string $key
+ * @param mixed $value
+ * @return void
+ */
+ public function __set($key, $value);
+
+ /**
+ * @param string $key
+ * @return mixed
+ */
+ public function __get($key);
+
+ /**
+ * @param string $key
+ * @return bool
+ */
+ public function __isset($key);
+
+ /**
+ * @param string $key
+ * @return void
+ */
+ public function __unset($key);
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use ArrayObject as PhpArrayObject;
+
+class Parameters extends PhpArrayObject implements ParametersInterface
+{
+ /**
+ * Constructor
+ *
+ * Enforces that we have an array, and enforces parameter access to array
+ * elements.
+ *
+ * @param array $values
+ */
+ public function __construct(array $values = null)
+ {
+ if (null === $values) {
+ $values = [];
+ }
+ parent::__construct($values, ArrayObject::ARRAY_AS_PROPS);
+ }
+
+ /**
+ * Populate from native PHP array
+ *
+ * @param array $values
+ * @return void
+ */
+ public function fromArray(array $values)
+ {
+ $this->exchangeArray($values);
+ }
+
+ /**
+ * Populate from query string
+ *
+ * @param string $string
+ * @return void
+ */
+ public function fromString($string)
+ {
+ $array = [];
+ parse_str($string, $array);
+ $this->fromArray($array);
+ }
+
+ /**
+ * Serialize to native PHP array
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ return $this->getArrayCopy();
+ }
+
+ /**
+ * Serialize to query string
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return http_build_query($this->toArray());
+ }
+
+ /**
+ * Retrieve by key
+ *
+ * Returns null if the key does not exist.
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function offsetGet($name)
+ {
+ if ($this->offsetExists($name)) {
+ return parent::offsetGet($name);
+ }
+ return;
+ }
+
+ /**
+ * @param string $name
+ * @param mixed $default optional default value
+ * @return mixed
+ */
+ public function get($name, $default = null)
+ {
+ if ($this->offsetExists($name)) {
+ return parent::offsetGet($name);
+ }
+ return $default;
+ }
+
+ /**
+ * @param string $name
+ * @param mixed $value
+ * @return Parameters
+ */
+ public function set($name, $value)
+ {
+ $this[$name] = $value;
+ return $this;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use ArrayAccess;
+use Countable;
+use Serializable;
+use Traversable;
+
+/*
+ * Basically, an ArrayObject. You could simply define something like:
+ * class QueryParams extends ArrayObject implements Parameters {}
+ * and have 90% of the functionality
+ */
+interface ParametersInterface extends ArrayAccess, Countable, Serializable, Traversable
+{
+ /**
+ * Constructor
+ *
+ * @param array $values
+ */
+ public function __construct(array $values = null);
+
+ /**
+ * From array
+ *
+ * Allow deserialization from standard array
+ *
+ * @param array $values
+ * @return mixed
+ */
+ public function fromArray(array $values);
+
+ /**
+ * From string
+ *
+ * Allow deserialization from raw body; e.g., for PUT requests
+ *
+ * @param $string
+ * @return mixed
+ */
+ public function fromString($string);
+
+ /**
+ * To array
+ *
+ * Allow serialization back to standard array
+ *
+ * @return mixed
+ */
+ public function toArray();
+
+ /**
+ * To string
+ *
+ * Allow serialization to query format; e.g., for PUT or POST requests
+ *
+ * @return mixed
+ */
+ public function toString();
+
+ /**
+ * Get
+ *
+ * @param string $name
+ * @param mixed|null $default
+ * @return mixed
+ */
+ public function get($name, $default = null);
+
+ /**
+ * Set
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return ParametersInterface
+ */
+ public function set($name, $value);
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Countable;
+use Iterator;
+
+class PriorityList implements Iterator, Countable
+{
+ const EXTR_DATA = 0x00000001;
+ const EXTR_PRIORITY = 0x00000002;
+ const EXTR_BOTH = 0x00000003;
+ /**
+ * Internal list of all items.
+ *
+ * @var array[]
+ */
+ protected $items = [];
+
+ /**
+ * Serial assigned to items to preserve LIFO.
+ *
+ * @var int
+ */
+ protected $serial = 0;
+
+ /**
+ * Serial order mode
+ * @var integer
+ */
+ protected $isLIFO = 1;
+
+ /**
+ * Internal counter to avoid usage of count().
+ *
+ * @var int
+ */
+ protected $count = 0;
+
+ /**
+ * Whether the list was already sorted.
+ *
+ * @var bool
+ */
+ protected $sorted = false;
+
+ /**
+ * Insert a new item.
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param int $priority
+ *
+ * @return void
+ */
+ public function insert($name, $value, $priority = 0)
+ {
+ if (! isset($this->items[$name])) {
+ $this->count++;
+ }
+
+ $this->sorted = false;
+
+ $this->items[$name] = [
+ 'data' => $value,
+ 'priority' => (int) $priority,
+ 'serial' => $this->serial++,
+ ];
+ }
+
+ /**
+ * @param string $name
+ * @param int $priority
+ *
+ * @return $this
+ *
+ * @throws \Exception
+ */
+ public function setPriority($name, $priority)
+ {
+ if (! isset($this->items[$name])) {
+ throw new \Exception("item $name not found");
+ }
+
+ $this->items[$name]['priority'] = (int) $priority;
+ $this->sorted = false;
+
+ return $this;
+ }
+
+ /**
+ * Remove a item.
+ *
+ * @param string $name
+ * @return void
+ */
+ public function remove($name)
+ {
+ if (isset($this->items[$name])) {
+ $this->count--;
+ }
+
+ unset($this->items[$name]);
+ }
+
+ /**
+ * Remove all items.
+ *
+ * @return void
+ */
+ public function clear()
+ {
+ $this->items = [];
+ $this->serial = 0;
+ $this->count = 0;
+ $this->sorted = false;
+ }
+
+ /**
+ * Get a item.
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function get($name)
+ {
+ if (! isset($this->items[$name])) {
+ return;
+ }
+
+ return $this->items[$name]['data'];
+ }
+
+ /**
+ * Sort all items.
+ *
+ * @return void
+ */
+ protected function sort()
+ {
+ if (! $this->sorted) {
+ uasort($this->items, [$this, 'compare']);
+ $this->sorted = true;
+ }
+ }
+
+ /**
+ * Compare the priority of two items.
+ *
+ * @param array $item1,
+ * @param array $item2
+ * @return int
+ */
+ protected function compare(array $item1, array $item2)
+ {
+ return ($item1['priority'] === $item2['priority'])
+ ? ($item1['serial'] > $item2['serial'] ? -1 : 1) * $this->isLIFO
+ : ($item1['priority'] > $item2['priority'] ? -1 : 1);
+ }
+
+ /**
+ * Get/Set serial order mode
+ *
+ * @param bool|null $flag
+ *
+ * @return bool
+ */
+ public function isLIFO($flag = null)
+ {
+ if ($flag !== null) {
+ $isLifo = $flag === true ? 1 : -1;
+
+ if ($isLifo !== $this->isLIFO) {
+ $this->isLIFO = $isLifo;
+ $this->sorted = false;
+ }
+ }
+
+ return 1 === $this->isLIFO;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function rewind()
+ {
+ $this->sort();
+ reset($this->items);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function current()
+ {
+ $this->sorted || $this->sort();
+ $node = current($this->items);
+
+ return $node ? $node['data'] : false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function key()
+ {
+ $this->sorted || $this->sort();
+ return key($this->items);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function next()
+ {
+ $node = next($this->items);
+
+ return $node ? $node['data'] : false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function valid()
+ {
+ return current($this->items) !== false;
+ }
+
+ /**
+ * @return self
+ */
+ public function getIterator()
+ {
+ return clone $this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function count()
+ {
+ return $this->count;
+ }
+
+ /**
+ * Return list as array
+ *
+ * @param int $flag
+ *
+ * @return array
+ */
+ public function toArray($flag = self::EXTR_DATA)
+ {
+ $this->sort();
+
+ if ($flag == self::EXTR_BOTH) {
+ return $this->items;
+ }
+
+ return array_map(
+ function ($item) use ($flag) {
+ return ($flag == PriorityList::EXTR_PRIORITY) ? $item['priority'] : $item['data'];
+ },
+ $this->items
+ );
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Countable;
+use IteratorAggregate;
+use Serializable;
+
+/**
+ * Re-usable, serializable priority queue implementation
+ *
+ * SplPriorityQueue acts as a heap; on iteration, each item is removed from the
+ * queue. If you wish to re-use such a queue, you need to clone it first. This
+ * makes for some interesting issues if you wish to delete items from the queue,
+ * or, as already stated, iterate over it multiple times.
+ *
+ * This class aggregates items for the queue itself, but also composes an
+ * "inner" iterator in the form of an SplPriorityQueue object for performing
+ * the actual iteration.
+ */
+class PriorityQueue implements Countable, IteratorAggregate, Serializable
+{
+ const EXTR_DATA = 0x00000001;
+ const EXTR_PRIORITY = 0x00000002;
+ const EXTR_BOTH = 0x00000003;
+
+ /**
+ * Inner queue class to use for iteration
+ * @var string
+ */
+ protected $queueClass = 'Laminas\Stdlib\SplPriorityQueue';
+
+ /**
+ * Actual items aggregated in the priority queue. Each item is an array
+ * with keys "data" and "priority".
+ * @var array
+ */
+ protected $items = [];
+
+ /**
+ * Inner queue object
+ * @var SplPriorityQueue
+ */
+ protected $queue;
+
+ /**
+ * Insert an item into the queue
+ *
+ * Priority defaults to 1 (low priority) if none provided.
+ *
+ * @param mixed $data
+ * @param int $priority
+ * @return PriorityQueue
+ */
+ public function insert($data, $priority = 1)
+ {
+ $priority = (int) $priority;
+ $this->items[] = [
+ 'data' => $data,
+ 'priority' => $priority,
+ ];
+ $this->getQueue()->insert($data, $priority);
+ return $this;
+ }
+
+ /**
+ * Remove an item from the queue
+ *
+ * This is different than {@link extract()}; its purpose is to dequeue an
+ * item.
+ *
+ * This operation is potentially expensive, as it requires
+ * re-initialization and re-population of the inner queue.
+ *
+ * Note: this removes the first item matching the provided item found. If
+ * the same item has been added multiple times, it will not remove other
+ * instances.
+ *
+ * @param mixed $datum
+ * @return bool False if the item was not found, true otherwise.
+ */
+ public function remove($datum)
+ {
+ $found = false;
+ foreach ($this->items as $key => $item) {
+ if ($item['data'] === $datum) {
+ $found = true;
+ break;
+ }
+ }
+ if ($found) {
+ unset($this->items[$key]);
+ $this->queue = null;
+
+ if (! $this->isEmpty()) {
+ $queue = $this->getQueue();
+ foreach ($this->items as $item) {
+ $queue->insert($item['data'], $item['priority']);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Is the queue empty?
+ *
+ * @return bool
+ */
+ public function isEmpty()
+ {
+ return (0 === $this->count());
+ }
+
+ /**
+ * How many items are in the queue?
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->items);
+ }
+
+ /**
+ * Peek at the top node in the queue, based on priority.
+ *
+ * @return mixed
+ */
+ public function top()
+ {
+ return $this->getIterator()->top();
+ }
+
+ /**
+ * Extract a node from the inner queue and sift up
+ *
+ * @return mixed
+ */
+ public function extract()
+ {
+ return $this->getQueue()->extract();
+ }
+
+ /**
+ * Retrieve the inner iterator
+ *
+ * SplPriorityQueue acts as a heap, which typically implies that as items
+ * are iterated, they are also removed. This does not work for situations
+ * where the queue may be iterated multiple times. As such, this class
+ * aggregates the values, and also injects an SplPriorityQueue. This method
+ * retrieves the inner queue object, and clones it for purposes of
+ * iteration.
+ *
+ * @return SplPriorityQueue
+ */
+ public function getIterator()
+ {
+ $queue = $this->getQueue();
+ return clone $queue;
+ }
+
+ /**
+ * Serialize the data structure
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return serialize($this->items);
+ }
+
+ /**
+ * Unserialize a string into a PriorityQueue object
+ *
+ * Serialization format is compatible with {@link Laminas\Stdlib\SplPriorityQueue}
+ *
+ * @param string $data
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ foreach (unserialize($data) as $item) {
+ $this->insert($item['data'], $item['priority']);
+ }
+ }
+
+ /**
+ * Serialize to an array
+ *
+ * By default, returns only the item data, and in the order registered (not
+ * sorted). You may provide one of the EXTR_* flags as an argument, allowing
+ * the ability to return priorities or both data and priority.
+ *
+ * @param int $flag
+ * @return array
+ */
+ public function toArray($flag = self::EXTR_DATA)
+ {
+ switch ($flag) {
+ case self::EXTR_BOTH:
+ return $this->items;
+ case self::EXTR_PRIORITY:
+ return array_map(function ($item) {
+ return $item['priority'];
+ }, $this->items);
+ case self::EXTR_DATA:
+ default:
+ return array_map(function ($item) {
+ return $item['data'];
+ }, $this->items);
+ }
+ }
+
+ /**
+ * Specify the internal queue class
+ *
+ * Please see {@link getIterator()} for details on the necessity of an
+ * internal queue class. The class provided should extend SplPriorityQueue.
+ *
+ * @param string $class
+ * @return PriorityQueue
+ */
+ public function setInternalQueueClass($class)
+ {
+ $this->queueClass = (string) $class;
+ return $this;
+ }
+
+ /**
+ * Does the queue contain the given datum?
+ *
+ * @param mixed $datum
+ * @return bool
+ */
+ public function contains($datum)
+ {
+ foreach ($this->items as $item) {
+ if ($item['data'] === $datum) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Does the queue have an item with the given priority?
+ *
+ * @param int $priority
+ * @return bool
+ */
+ public function hasPriority($priority)
+ {
+ foreach ($this->items as $item) {
+ if ($item['priority'] === $priority) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the inner priority queue instance
+ *
+ * @throws Exception\DomainException
+ * @return SplPriorityQueue
+ */
+ protected function getQueue()
+ {
+ if (null === $this->queue) {
+ $this->queue = new $this->queueClass();
+ if (! $this->queue instanceof \SplPriorityQueue) {
+ throw new Exception\DomainException(sprintf(
+ 'PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"',
+ get_class($this->queue)
+ ));
+ }
+ }
+ return $this->queue;
+ }
+
+ /**
+ * Add support for deep cloning
+ *
+ * @return void
+ */
+ public function __clone()
+ {
+ if (null !== $this->queue) {
+ $this->queue = clone $this->queue;
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+class Request extends Message implements RequestInterface
+{
+ // generic request implementation
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+interface RequestInterface extends MessageInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+class Response extends Message implements ResponseInterface
+{
+ // generic response implementation
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+interface ResponseInterface extends MessageInterface
+{
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Serializable;
+
+/**
+ * Serializable version of SplPriorityQueue
+ *
+ * Also, provides predictable heap order for datums added with the same priority
+ * (i.e., they will be emitted in the same order they are enqueued).
+ */
+class SplPriorityQueue extends \SplPriorityQueue implements Serializable
+{
+ /**
+ * @var int Seed used to ensure queue order for items of the same priority
+ */
+ protected $serial = PHP_INT_MAX;
+
+ /**
+ * Insert a value with a given priority
+ *
+ * Utilizes {@var $serial} to ensure that values of equal priority are
+ * emitted in the same order in which they are inserted.
+ *
+ * @param mixed $datum
+ * @param mixed $priority
+ * @return void
+ */
+ public function insert($datum, $priority)
+ {
+ if (! is_array($priority)) {
+ $priority = [$priority, $this->serial--];
+ }
+ parent::insert($datum, $priority);
+ }
+
+ /**
+ * Serialize to an array
+ *
+ * Array will be priority => data pairs
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $array = [];
+ foreach (clone $this as $item) {
+ $array[] = $item;
+ }
+ return $array;
+ }
+
+ /**
+ * Serialize
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ $clone = clone $this;
+ $clone->setExtractFlags(self::EXTR_BOTH);
+
+ $data = [];
+ foreach ($clone as $item) {
+ $data[] = $item;
+ }
+
+ return serialize($data);
+ }
+
+ /**
+ * Deserialize
+ *
+ * @param string $data
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ $this->serial = PHP_INT_MAX;
+ foreach (unserialize($data) as $item) {
+ $this->serial--;
+ $this->insert($item['data'], $item['priority']);
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Serializable;
+
+/**
+ * Serializable version of SplQueue
+ */
+class SplQueue extends \SplQueue implements Serializable
+{
+ /**
+ * Return an array representing the queue
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $array = [];
+ foreach ($this as $item) {
+ $array[] = $item;
+ }
+ return $array;
+ }
+
+ /**
+ * Serialize
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return serialize($this->toArray());
+ }
+
+ /**
+ * Unserialize
+ *
+ * @param string $data
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ foreach (unserialize($data) as $item) {
+ $this->push($item);
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Serializable;
+
+/**
+ * Serializable version of SplStack
+ */
+class SplStack extends \SplStack implements Serializable
+{
+ /**
+ * Serialize to an array representing the stack
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $array = [];
+ foreach ($this as $item) {
+ $array[] = $item;
+ }
+ return $array;
+ }
+
+ /**
+ * Serialize
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return serialize($this->toArray());
+ }
+
+ /**
+ * Unserialize
+ *
+ * @param string $data
+ * @return void
+ */
+ public function unserialize($data)
+ {
+ foreach (unserialize($data) as $item) {
+ $this->unshift($item);
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib;
+
+use Laminas\Stdlib\StringWrapper\StringWrapperInterface;
+
+/**
+ * Utility class for handling strings of different character encodings
+ * using available PHP extensions.
+ *
+ * Declared abstract, as we have no need for instantiation.
+ */
+abstract class StringUtils
+{
+ /**
+ * Ordered list of registered string wrapper instances
+ *
+ * @var StringWrapperInterface[]
+ */
+ protected static $wrapperRegistry = null;
+
+ /**
+ * A list of known single-byte character encodings (upper-case)
+ *
+ * @var string[]
+ */
+ protected static $singleByteEncodings = [
+ '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',
+ 'CP-1251', 'CP-1252',
+ // TODO
+ ];
+
+ /**
+ * Is PCRE compiled with Unicode support?
+ *
+ * @var bool
+ **/
+ protected static $hasPcreUnicodeSupport = null;
+
+ /**
+ * Get registered wrapper classes
+ *
+ * @return string[]
+ */
+ public static function getRegisteredWrappers()
+ {
+ if (static::$wrapperRegistry === null) {
+ static::$wrapperRegistry = [];
+
+ if (extension_loaded('intl')) {
+ static::$wrapperRegistry[] = 'Laminas\Stdlib\StringWrapper\Intl';
+ }
+
+ if (extension_loaded('mbstring')) {
+ static::$wrapperRegistry[] = 'Laminas\Stdlib\StringWrapper\MbString';
+ }
+
+ if (extension_loaded('iconv')) {
+ static::$wrapperRegistry[] = 'Laminas\Stdlib\StringWrapper\Iconv';
+ }
+
+ static::$wrapperRegistry[] = 'Laminas\Stdlib\StringWrapper\Native';
+ }
+
+ return static::$wrapperRegistry;
+ }
+
+ /**
+ * Register a string wrapper class
+ *
+ * @param string $wrapper
+ * @return void
+ */
+ public static function registerWrapper($wrapper)
+ {
+ $wrapper = (string) $wrapper;
+ if (! in_array($wrapper, static::$wrapperRegistry, true)) {
+ static::$wrapperRegistry[] = $wrapper;
+ }
+ }
+
+ /**
+ * Unregister a string wrapper class
+ *
+ * @param string $wrapper
+ * @return void
+ */
+ public static function unregisterWrapper($wrapper)
+ {
+ $index = array_search((string) $wrapper, static::$wrapperRegistry, true);
+ if ($index !== false) {
+ unset(static::$wrapperRegistry[$index]);
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @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 given character encodings
+ */
+ public static function getWrapper($encoding = 'UTF-8', $convertEncoding = null)
+ {
+ foreach (static::getRegisteredWrappers() as $wrapperClass) {
+ if ($wrapperClass::isSupported($encoding, $convertEncoding)) {
+ $wrapper = new $wrapperClass($encoding, $convertEncoding);
+ $wrapper->setEncoding($encoding, $convertEncoding);
+ return $wrapper;
+ }
+ }
+
+ throw new Exception\RuntimeException(
+ 'No wrapper found supporting "' . $encoding . '"'
+ . (($convertEncoding !== null) ? ' and "' . $convertEncoding . '"' : '')
+ );
+ }
+
+ /**
+ * Get a list of all known single-byte character encodings
+ *
+ * @return string[]
+ */
+ public static function getSingleByteEncodings()
+ {
+ return static::$singleByteEncodings;
+ }
+
+ /**
+ * Check if a given encoding is a known single-byte character encoding
+ *
+ * @param string $encoding
+ * @return bool
+ */
+ public static function isSingleByteEncoding($encoding)
+ {
+ return in_array(strtoupper($encoding), static::$singleByteEncodings);
+ }
+
+ /**
+ * Check if a given string is valid UTF-8 encoded
+ *
+ * @param string $str
+ * @return bool
+ */
+ public static function isValidUtf8($str)
+ {
+ return is_string($str) && ($str === '' || preg_match('/^./su', $str) == 1);
+ }
+
+ /**
+ * Is PCRE compiled with Unicode support?
+ *
+ * @return bool
+ */
+ public static function hasPcreUnicodeSupport()
+ {
+ if (static::$hasPcreUnicodeSupport === null) {
+ ErrorHandler::start();
+ static::$hasPcreUnicodeSupport = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1;
+ ErrorHandler::stop();
+ }
+ return static::$hasPcreUnicodeSupport;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\StringWrapper;
+
+use Laminas\Stdlib\Exception;
+use Laminas\Stdlib\StringUtils;
+
+abstract class AbstractStringWrapper implements StringWrapperInterface
+{
+ /**
+ * The character encoding working on
+ * @var string|null
+ */
+ protected $encoding = 'UTF-8';
+
+ /**
+ * An optionally character encoding to convert to
+ * @var string|null
+ */
+ protected $convertEncoding;
+
+ /**
+ * 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
+ * @return bool
+ */
+ 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;
+ }
+
+ /**
+ * 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 ($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;
+ }
+
+ /**
+ * 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
+ *
+ * @param string $str
+ * @param bool $reverse
+ * @return string|false
+ */
+ public function convert($str, $reverse = false)
+ {
+ $encoding = $this->getEncoding();
+ $convertEncoding = $this->getConvertEncoding();
+ if ($convertEncoding === null) {
+ throw new Exception\LogicException(
+ 'No convert encoding defined'
+ );
+ }
+
+ if ($encoding === $convertEncoding) {
+ return $str;
+ }
+
+ $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,
+ $to
+ ));
+ }
+
+ /**
+ * Wraps a string to a given number of characters
+ *
+ * @param string $string
+ * @param int $width
+ * @param string $break
+ * @param bool $cut
+ * @return string|false
+ */
+ public function wordWrap($string, $width = 75, $break = "\n", $cut = false)
+ {
+ $string = (string) $string;
+ if ($string === '') {
+ return '';
+ }
+
+ $break = (string) $break;
+ if ($break === '') {
+ throw new Exception\InvalidArgumentException('Break string cannot be empty');
+ }
+
+ $width = (int) $width;
+ if ($width === 0 && $cut) {
+ throw new Exception\InvalidArgumentException('Cannot force cut when width is zero');
+ }
+
+ if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
+ return wordwrap($string, $width, $break, $cut);
+ }
+
+ $stringWidth = $this->strlen($string);
+ $breakWidth = $this->strlen($break);
+
+ $result = '';
+ $lastStart = $lastSpace = 0;
+
+ for ($current = 0; $current < $stringWidth; $current++) {
+ $char = $this->substr($string, $current, 1);
+
+ $possibleBreak = $char;
+ if ($breakWidth !== 1) {
+ $possibleBreak = $this->substr($string, $current, $breakWidth);
+ }
+
+ if ($possibleBreak === $break) {
+ $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth);
+ $current += $breakWidth - 1;
+ $lastStart = $lastSpace = $current + 1;
+ continue;
+ }
+
+ if ($char === ' ') {
+ if ($current - $lastStart >= $width) {
+ $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
+ $lastStart = $current + 1;
+ }
+
+ $lastSpace = $current;
+ continue;
+ }
+
+ if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) {
+ $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) . $break;
+ $lastStart = $lastSpace = $lastSpace + 1;
+ continue;
+ }
+ }
+
+ if ($lastStart !== $current) {
+ $result .= $this->substr($string, $lastStart, $current - $lastStart);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Pad a string to a certain length with another string
+ *
+ * @param string $input
+ * @param int $padLength
+ * @param string $padString
+ * @param int $padType
+ * @return string
+ */
+ public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT)
+ {
+ if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
+ return str_pad($input, $padLength, $padString, $padType);
+ }
+
+ $lengthOfPadding = $padLength - $this->strlen($input);
+ if ($lengthOfPadding <= 0) {
+ return $input;
+ }
+
+ $padStringLength = $this->strlen($padString);
+ if ($padStringLength === 0) {
+ return $input;
+ }
+
+ $repeatCount = floor($lengthOfPadding / $padStringLength);
+
+ if ($padType === STR_PAD_BOTH) {
+ $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2;
+
+ $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength;
+ $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2);
+ $lastStringRightLength += $lastStringLength % 2;
+
+ $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength);
+ $lastStringRight = $this->substr($padString, 0, $lastStringRightLength);
+
+ return str_repeat($padString, $repeatCountLeft) . $lastStringLeft
+ . $input
+ . str_repeat($padString, $repeatCountRight) . $lastStringRight;
+ }
+
+ $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;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\StringWrapper;
+
+use Laminas\Stdlib\Exception;
+
+class Iconv extends AbstractStringWrapper
+{
+ /**
+ * List of supported character sets (upper case)
+ *
+ * @var string[]
+ * @link http://www.gnu.org/software/libiconv/
+ */
+ protected static $encodings = [
+ // 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',
+
+ /* 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',
+
+ // 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',
+ ];
+
+ /**
+ * Get a list of supported character encodings
+ *
+ * @return string[]
+ */
+ public static function getSupportedEncodings()
+ {
+ return static::$encodings;
+ }
+
+ /**
+ * Constructor
+ *
+ * @throws Exception\ExtensionNotLoadedException
+ */
+ public function __construct()
+ {
+ if (! extension_loaded('iconv')) {
+ throw new Exception\ExtensionNotLoadedException(
+ 'PHP extension "iconv" is required for this wrapper'
+ );
+ }
+ }
+
+ /**
+ * Returns the length of the given string
+ *
+ * @param string $str
+ * @return int|false
+ */
+ public function strlen($str)
+ {
+ return iconv_strlen($str, $this->getEncoding());
+ }
+
+ /**
+ * Returns the portion of string specified by the start and length parameters
+ *
+ * @param string $str
+ * @param int $offset
+ * @param int|null $length
+ * @return string|false
+ */
+ public function substr($str, $offset = 0, $length = null)
+ {
+ return iconv_substr($str, $offset, $length, $this->getEncoding());
+ }
+
+ /**
+ * Find the position of the first occurrence of a substring in a string
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @param int $offset
+ * @return int|false
+ */
+ public function strpos($haystack, $needle, $offset = 0)
+ {
+ return iconv_strpos($haystack, $needle, $offset, $this->getEncoding());
+ }
+
+ /**
+ * Convert a string from defined encoding to the defined convert encoding
+ *
+ * @param string $str
+ * @param bool $reverse
+ * @return string|false
+ */
+ public function convert($str, $reverse = false)
+ {
+ $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;
+
+ // automatically add "//IGNORE" to not stop converting on invalid characters
+ // invalid characters triggers a notice anyway
+ return iconv($fromEncoding, $toEncoding . '//IGNORE', $str);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\StringWrapper;
+
+use Laminas\Stdlib\Exception;
+
+class Intl extends AbstractStringWrapper
+{
+ /**
+ * List of supported character sets (upper case)
+ *
+ * @var string[]
+ */
+ protected static $encodings = ['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()
+ {
+ if (! extension_loaded('intl')) {
+ throw new Exception\ExtensionNotLoadedException(
+ 'PHP extension "intl" is required for this wrapper'
+ );
+ }
+ }
+
+ /**
+ * Returns the length of the given string
+ *
+ * @param string $str
+ * @return int|false
+ */
+ public function strlen($str)
+ {
+ 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
+ * @return string|false
+ */
+ public function substr($str, $offset = 0, $length = null)
+ {
+ // Due fix of PHP #62759 The third argument returns an empty string if is 0 or null.
+ if ($length !== null) {
+ return grapheme_substr($str, $offset, $length);
+ }
+
+ return grapheme_substr($str, $offset);
+ }
+
+ /**
+ * Find the position of the first occurrence of a substring in a string
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @param int $offset
+ * @return int|false
+ */
+ public function strpos($haystack, $needle, $offset = 0)
+ {
+ return grapheme_strpos($haystack, $needle, $offset);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\StringWrapper;
+
+use Laminas\Stdlib\Exception;
+
+class MbString extends AbstractStringWrapper
+{
+ /**
+ * List of supported character sets (upper case)
+ *
+ * @var null|string[]
+ * @link http://php.net/manual/mbstring.supported-encodings.php
+ */
+ 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()
+ {
+ if (! extension_loaded('mbstring')) {
+ throw new Exception\ExtensionNotLoadedException(
+ 'PHP extension "mbstring" is required for this wrapper'
+ );
+ }
+ }
+
+ /**
+ * Returns the length of the given string
+ *
+ * @param string $str
+ * @return int|false
+ */
+ public function strlen($str)
+ {
+ return mb_strlen($str, $this->getEncoding());
+ }
+
+ /**
+ * Returns the portion of string specified by the start and length parameters
+ *
+ * @param string $str
+ * @param int $offset
+ * @param int|null $length
+ * @return string|false
+ */
+ public function substr($str, $offset = 0, $length = null)
+ {
+ return mb_substr($str, $offset, $length, $this->getEncoding());
+ }
+
+ /**
+ * Find the position of the first occurrence of a substring in a string
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @param int $offset
+ * @return int|false
+ */
+ public function strpos($haystack, $needle, $offset = 0)
+ {
+ return mb_strpos($haystack, $needle, $offset, $this->getEncoding());
+ }
+
+ /**
+ * Convert a string from defined encoding to the defined convert encoding
+ *
+ * @param string $str
+ * @param bool $reverse
+ * @return string|false
+ */
+ public function convert($str, $reverse = false)
+ {
+ $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);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\StringWrapper;
+
+use Laminas\Stdlib\Exception;
+use Laminas\Stdlib\StringUtils;
+
+class Native extends AbstractStringWrapper
+{
+ /**
+ * The character encoding working on
+ * (overwritten to change default 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.
+ *
+ * @param string $encoding
+ * @param string|null $convertEncoding
+ * @return bool
+ */
+ 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
+ *
+ * @return string[]
+ */
+ 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
+ *
+ * @param string $str
+ * @return int|false
+ */
+ public function strlen($str)
+ {
+ 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
+ * @return string|false
+ */
+ public function substr($str, $offset = 0, $length = null)
+ {
+ 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
+ * @return int|false
+ */
+ public function strpos($haystack, $needle, $offset = 0)
+ {
+ return strpos($haystack, $needle, $offset);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * @see https://github.com/laminas/laminas-stdlib for the canonical source repository
+ * @copyright https://github.com/laminas/laminas-stdlib/blob/master/COPYRIGHT.md
+ * @license https://github.com/laminas/laminas-stdlib/blob/master/LICENSE.md New BSD License
+ */
+
+namespace Laminas\Stdlib\StringWrapper;
+
+interface StringWrapperInterface
+{
+ /**
+ * 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);
+
+ /**
+ * Get a list of supported character encodings
+ *
+ * @return string[]
+ */
+ public static function getSupportedEncodings();
+
+ /**
+ * 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);
+
+ /**
+ * Get the defined character encoding to work with (upper case)
+ *
+ * @return string
+ */
+ 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
+ *
+ * @param string $str
+ * @return int|false
+ */
+ public function strlen($str);
+
+ /**
+ * Returns the portion of string specified by the start and length parameters
+ *
+ * @param string $str
+ * @param int $offset
+ * @param int|null $length
+ * @return string|false
+ */
+ public function substr($str, $offset = 0, $length = null);
+
+ /**
+ * Find the position of the first occurrence of a substring in a string
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @param int $offset
+ * @return int|false
+ */
+ public function strpos($haystack, $needle, $offset = 0);
+
+ /**
+ * Convert a string from defined encoding to the defined convert encoding
+ *
+ * @param string $str
+ * @param bool $reverse
+ * @return string|false
+ */
+ public function convert($str, $reverse = false);
+
+ /**
+ * Wraps a string to a given number of characters
+ *
+ * @param string $str
+ * @param int $width
+ * @param string $break
+ * @param bool $cut
+ * @return string
+ */
+ public function wordWrap($str, $width = 75, $break = "\n", $cut = false);
+
+ /**
+ * Pad a string to a certain length with another string
+ *
+ * @param string $input
+ * @param int $padLength
+ * @param string $padString
+ * @param int $padType
+ * @return string
+ */
+ public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT);
+}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Adapter;
-
-use Traversable;
-use Zend\Stdlib\ArrayUtils;
-
-/**
- * Abstract class for Zend_ProgressBar_Adapters
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-abstract class AbstractAdapter
-{
- /**
- * Option keys to skip when calling setOptions()
- *
- * @var array
- */
- protected $skipOptions = array(
- 'options',
- 'config',
- );
-
- /**
- * Create a new adapter
- *
- * $options may be either be an array or a Zend_Config object which
- * specifies adapter related options.
- *
- * @param array|Traversable $options
- */
- public function __construct($options = null)
- {
- if ($options instanceof Traversable) {
- $options = ArrayUtils::iteratorToArray($options);
- }
- if (is_array($options)) {
- $this->setOptions($options);
- }
- }
-
- /**
- * Set options via an array
- *
- * @param array $options
- * @return AbstractAdapter
- */
- public function setOptions(array $options)
- {
- foreach ($options as $key => $value) {
- if (in_array(strtolower($key), $this->skipOptions)) {
- continue;
- }
-
- $method = 'set' . ucfirst($key);
- if (method_exists($this, $method)) {
- $this->$method($value);
- }
- }
-
- return $this;
- }
-
- /**
- * Notify the adapter about an update
- *
- * @param float $current Current progress value
- * @param float $max Max progress value
- * @param float $percent Current percent value
- * @param integer $timeTaken Taken time in seconds
- * @param integer $timeRemaining Remaining time in seconds
- * @param string $text Status text
- * @return void
- */
- abstract public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text);
-
- /**
- * Called when the progress is explicitly finished
- *
- * @return void
- */
- abstract public function finish();
-}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Adapter;
-
-use Zend\ProgressBar\Adapter\Exception;
-use Zend\Stdlib\ErrorHandler;
-
-/**
- * Zend_ProgressBar_Adapter_Console offers a text-based progressbar for console
- * applications
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-class Console extends AbstractAdapter
-{
- /**
- * Percentage value of the progress
- */
- const ELEMENT_PERCENT = 'ELEMENT_PERCENT';
-
- /**
- * Visual value of the progress
- */
- const ELEMENT_BAR = 'ELEMENT_BAR';
-
- /**
- * ETA of the progress
- */
- const ELEMENT_ETA = 'ELEMENT_ETA';
-
- /**
- * Text part of the progress
- */
- const ELEMENT_TEXT = 'ELEMENT_TEXT';
-
- /**
- * Finish action: End of Line
- */
- const FINISH_ACTION_EOL = 'FINISH_ACTION_EOL';
-
- /**
- * Finish action: Clear Line
- */
- const FINISH_ACTION_CLEAR_LINE = 'FINISH_ACTION_CLEAR_LINE';
-
- /**
- * Finish action: None
- */
- const FINISH_ACTION_NONE = 'FINISH_ACTION_NONE';
-
- /**
- * Width of the progressbar
- *
- * @var integer
- */
- protected $width = null;
-
- /**
- * Elements to display
- *
- * @var array
- */
- protected $elements = array(self::ELEMENT_PERCENT,
- self::ELEMENT_BAR,
- self::ELEMENT_ETA);
-
- /**
- * Which action to do at finish call
- *
- * @var string
- */
- protected $finishAction = self::FINISH_ACTION_EOL;
-
- /**
- * Width of the bar element
- *
- * @var integer
- */
- protected $barWidth;
-
- /**
- * Left character(s) within the bar
- *
- * @var string
- */
- protected $barLeftChar = '#';
-
- /**
- * Indicator character(s) within the bar
- *
- * @var string
- */
- protected $barIndicatorChar = '';
-
- /**
- * Right character(s) within the bar
- *
- * @var string
- */
- protected $barRightChar = '-';
-
- /**
- * Output-stream, when STDOUT is not defined (e.g. in CGI) or set manually
- *
- * @var resource
- */
- protected $outputStream = null;
-
- /**
- * Width of the text element
- *
- * @var string
- */
- protected $textWidth = 20;
-
- /**
- * Whether the output started yet or not
- *
- * @var boolean
- */
- protected $outputStarted = false;
-
- /**
- * Charset of text element
- *
- * @var string
- */
- protected $charset = 'utf-8';
-
- /**
- * Defined by Zend_ProgressBar_Adapter
- *
- * @param array|\Traversable $options
- */
- public function __construct($options = null)
- {
- // Call parent constructor with options
- parent::__construct($options);
-
- // Check if a width was set, else use auto width
- if ($this->width === null) {
- $this->setWidth();
- }
- }
-
- /**
- * Close local stdout, when open
- */
- public function __destruct()
- {
- if ($this->outputStream !== null) {
- fclose($this->outputStream);
- }
- }
-
- /**
- * Set a different output-stream
- *
- * @param string $resource
- * @throws Exception\RuntimeException
- * @return \Zend\ProgressBar\Adapter\Console
- */
- public function setOutputStream($resource)
- {
- ErrorHandler::start();
- $stream = fopen($resource, 'w');
- $error = ErrorHandler::stop();
-
- if ($stream === false) {
- throw new Exception\RuntimeException('Unable to open stream', 0, $error);
- }
-
- if ($this->outputStream !== null) {
- fclose($this->outputStream);
- }
-
- $this->outputStream = $stream;
- }
-
- /**
- * Get the current output stream
- *
- * @return resource
- */
- public function getOutputStream()
- {
- if ($this->outputStream === null) {
- if (!defined('STDOUT')) {
- $this->outputStream = fopen('php://stdout', 'w');
- } else {
- return STDOUT;
- }
- }
-
- return $this->outputStream;
- }
-
- /**
- * Set the width of the progressbar
- *
- * @param integer $width
- * @return \Zend\ProgressBar\Adapter\Console
- */
- public function setWidth($width = null)
- {
- if ($width === null || !is_integer($width)) {
- if (substr(PHP_OS, 0, 3) === 'WIN') {
- // We have to default to 79 on windows, because the windows
- // terminal always has a fixed width of 80 characters and the
- // cursor is counted to the line, else windows would line break
- // after every update.
- $this->width = 79;
- } else {
- // Set the default width of 80
- $this->width = 80;
-
- // Try to determine the width through stty
- ErrorHandler::start();
- if (preg_match('#\d+ (\d+)#', shell_exec('stty size'), $match) === 1) {
- $this->width = (int) $match[1];
- } elseif (preg_match('#columns = (\d+);#', shell_exec('stty'), $match) === 1) {
- $this->width = (int) $match[1];
- }
- ErrorHandler::stop();
- }
- } else {
- $this->width = (int) $width;
- }
-
- $this->_calculateBarWidth();
-
- return $this;
- }
-
- /**
- * Set the elements to display with the progressbar
- *
- * @param array $elements
- * @throws \Zend\ProgressBar\Adapter\Exception\InvalidArgumentException When an invalid element is found in the array
- * @return \Zend\ProgressBar\Adapter\Console
- */
- public function setElements(array $elements)
- {
- $allowedElements = array(self::ELEMENT_PERCENT,
- self::ELEMENT_BAR,
- self::ELEMENT_ETA,
- self::ELEMENT_TEXT);
-
- if (count(array_diff($elements, $allowedElements)) > 0) {
- throw new Exception\InvalidArgumentException('Invalid element found in $elements array');
- }
-
- $this->elements = $elements;
-
- $this->_calculateBarWidth();
-
- return $this;
- }
-
- /**
- * Set the left-hand character for the bar
- *
- * @param string $char
- * @throws \Zend\ProgressBar\Adapter\Exception\InvalidArgumentException When character is empty
- * @return \Zend\ProgressBar\Adapter\Console
- */
- public function setBarLeftChar($char)
- {
- if (empty($char)) {
- throw new Exception\InvalidArgumentException('Character may not be empty');
- }
-
- $this->barLeftChar = (string) $char;
-
- return $this;
- }
-
- /**
- * Set the right-hand character for the bar
- *
- * @param string $char
- * @throws \Zend\ProgressBar\Adapter\Exception\InvalidArgumentException When character is empty
- * @return \Zend\ProgressBar\Adapter\Console
- */
- public function setBarRightChar($char)
- {
- if (empty($char)) {
- throw new Exception\InvalidArgumentException('Character may not be empty');
- }
-
- $this->barRightChar = (string) $char;
-
- return $this;
- }
-
- /**
- * Set the indicator character for the bar
- *
- * @param string $char
- * @return \Zend\ProgressBar\Adapter\Console
- */
- public function setBarIndicatorChar($char)
- {
- $this->barIndicatorChar = (string) $char;
-
- return $this;
- }
-
- /**
- * Set the width of the text element
- *
- * @param integer $width
- * @return \Zend\ProgressBar\Adapter\Console
- */
- public function setTextWidth($width)
- {
- $this->textWidth = (int) $width;
-
- $this->_calculateBarWidth();
-
- return $this;
- }
-
- /**
- * Set the charset of the text element
- *
- * @param string $charset
- */
- public function setCharset($charset)
- {
- $this->charset = $charset;
- }
-
- /**
- * Set the finish action
- *
- * @param string $action
- * @throws \Zend\ProgressBar\Adapter\Exception\InvalidArgumentException When an invalid action is specified
- * @return \Zend\ProgressBar\Adapter\Console
- */
- public function setFinishAction($action)
- {
- $allowedActions = array(self::FINISH_ACTION_CLEAR_LINE,
- self::FINISH_ACTION_EOL,
- self::FINISH_ACTION_NONE);
-
- if (!in_array($action, $allowedActions)) {
- throw new Exception\InvalidArgumentException('Invalid finish action specified');
- }
-
- $this->finishAction = $action;
-
- return $this;
- }
-
- /**
- * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
- *
- * @param float $current Current progress value
- * @param float $max Max progress value
- * @param float $percent Current percent value
- * @param integer $timeTaken Taken time in seconds
- * @param integer $timeRemaining Remaining time in seconds
- * @param string $text Status text
- * @return void
- */
- public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
- {
- // See if we must clear the line
- if ($this->outputStarted) {
- $data = str_repeat("\x08", $this->width);
- } else {
- $data = '';
- $this->outputStarted = true;
- }
-
- // Build all elements
- $renderedElements = array();
-
- foreach ($this->elements as $element) {
- switch ($element) {
- case self::ELEMENT_BAR:
- $visualWidth = $this->barWidth - 2;
- $bar = '[';
-
- $indicatorWidth = strlen($this->barIndicatorChar);
-
- $doneWidth = min($visualWidth - $indicatorWidth, round($visualWidth * $percent));
- if ($doneWidth > 0) {
- $bar .= substr(str_repeat($this->barLeftChar, ceil($doneWidth / strlen($this->barLeftChar))), 0, $doneWidth);
- }
-
- $bar .= $this->barIndicatorChar;
-
- $leftWidth = $visualWidth - $doneWidth - $indicatorWidth;
- if ($leftWidth > 0) {
- $bar .= substr(str_repeat($this->barRightChar, ceil($leftWidth / strlen($this->barRightChar))), 0, $leftWidth);
- }
-
- $bar .= ']';
-
- $renderedElements[] = $bar;
- break;
-
- case self::ELEMENT_PERCENT:
- $renderedElements[] = str_pad(round($percent * 100), 3, ' ', STR_PAD_LEFT) . '%';
- break;
-
- case self::ELEMENT_ETA:
- // In the first 5 seconds we don't get accurate results,
- // this skipping technique is found in many progressbar
- // implementations.
- if ($timeTaken < 5) {
- $renderedElements[] = str_repeat(' ', 12);
- break;
- }
-
- if ($timeRemaining === null || $timeRemaining > 86400) {
- $etaFormatted = '??:??:??';
- } else {
- $hours = floor($timeRemaining / 3600);
- $minutes = floor(($timeRemaining % 3600) / 60);
- $seconds = ($timeRemaining % 3600 % 60);
-
- $etaFormatted = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
- }
-
- $renderedElements[] = 'ETA ' . $etaFormatted;
- break;
-
- case self::ELEMENT_TEXT:
- $renderedElements[] = \Zend\Text\MultiByte::strPad(substr($text, 0, $this->textWidth), $this->textWidth, ' ', STR_PAD_RIGHT, $this->charset);
- break;
- }
- }
-
- $data .= implode(' ', $renderedElements);
-
- // Output line data
- $this->_outputData($data);
- }
-
- /**
- * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
- *
- * @return void
- */
- public function finish()
- {
- switch ($this->finishAction) {
- case self::FINISH_ACTION_EOL:
- $this->_outputData(PHP_EOL);
- break;
-
- case self::FINISH_ACTION_CLEAR_LINE:
- if ($this->outputStarted) {
- $data = str_repeat("\x08", $this->width)
- . str_repeat(' ', $this->width)
- . str_repeat("\x08", $this->width);
-
- $this->_outputData($data);
- }
- break;
-
- case self::FINISH_ACTION_NONE:
- break;
- }
- }
-
- /**
- * Calculate the bar width when other elements changed
- *
- * @return void
- */
- protected function _calculateBarWidth()
- {
- if (in_array(self::ELEMENT_BAR, $this->elements)) {
- $barWidth = $this->width;
-
- if (in_array(self::ELEMENT_PERCENT, $this->elements)) {
- $barWidth -= 4;
- }
-
- if (in_array(self::ELEMENT_ETA, $this->elements)) {
- $barWidth -= 12;
- }
-
- if (in_array(self::ELEMENT_TEXT, $this->elements)) {
- $barWidth -= $this->textWidth;
- }
-
- $this->barWidth = $barWidth - (count($this->elements) - 1);
- }
- }
-
- /**
- * Outputs given data to STDOUT.
- *
- * This split-off is required for unit-testing.
- *
- * @param string $data
- * @return void
- */
- protected function _outputData($data)
- {
- fwrite($this->getOutputStream(), $data);
- }
-}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Adapter\Exception;
-
-use Zend\ProgressBar\Exception\ExceptionInterface as ProgressBarException;
-
-/**
- * Exception class for Zend_ProgressBar_Adapter
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-interface ExceptionInterface extends ProgressBarException
-{
-}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Adapter\Exception;
-
-use Zend\ProgressBar\Exception;
-
-/**
- * Exception for Zend_Progressbar component.
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-class InvalidArgumentException extends Exception\InvalidArgumentException implements
- ExceptionInterface
-{}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Adapter\Exception;
-
-use Zend\ProgressBar\Exception;
-
-/**
- * Exception for Zend_Progressbar component.
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-class RuntimeException extends Exception\RuntimeException implements
- ExceptionInterface
-{}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Adapter;
-
-use Zend\Json\Json;
-
-/**
- * Zend_ProgressBar_Adapter_JsPull offers a simple method for updating a
- * progressbar in a browser.
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-class JsPull extends AbstractAdapter
-{
- /**
- * Whether to exit after json data send or not
- *
- * @var boolean
- */
- protected $exitAfterSend = true;
-
- /**
- * Set whether to exit after json data send or not
- *
- * @param boolean $exitAfterSend
- * @return \Zend\ProgressBar\Adapter\JsPull
- */
- public function setExitAfterSend($exitAfterSend)
- {
- $this->exitAfterSend = $exitAfterSend;
- }
-
- /**
- * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
- *
- * @param float $current Current progress value
- * @param float $max Max progress value
- * @param float $percent Current percent value
- * @param integer $timeTaken Taken time in seconds
- * @param integer $timeRemaining Remaining time in seconds
- * @param string $text Status text
- * @return void
- */
- public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
- {
- $arguments = array(
- 'current' => $current,
- 'max' => $max,
- 'percent' => ($percent * 100),
- 'timeTaken' => $timeTaken,
- 'timeRemaining' => $timeRemaining,
- 'text' => $text,
- 'finished' => false
- );
-
- $data = Json::encode($arguments);
-
- // Output the data
- $this->_outputData($data);
- }
-
- /**
- * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
- *
- * @return void
- */
- public function finish()
- {
- $data = Json::encode(array('finished' => true));
-
- $this->_outputData($data);
- }
-
- /**
- * Outputs given data the user agent.
- *
- * This split-off is required for unit-testing.
- *
- * @param string $data
- * @return void
- */
- protected function _outputData($data)
- {
- echo $data;
-
- if ($this->exitAfterSend) {
- exit;
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Adapter;
-
-use Zend\Json\Json;
-
-/**
- * Zend_ProgressBar_Adapter_JsPush offers a simple method for updating a
- * progressbar in a browser.
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-class JsPush extends AbstractAdapter
-{
- /**
- * Name of the JavaScript method to call on update
- *
- * @var string
- */
- protected $updateMethodName = 'Zend\ProgressBar\ProgressBar\Update';
-
- /**
- * Name of the JavaScript method to call on finish
- *
- * @var string
- */
- protected $finishMethodName;
-
- /**
- * Set the update method name
- *
- * @param string $methodName
- * @return \Zend\ProgressBar\Adapter\JsPush
- */
- public function setUpdateMethodName($methodName)
- {
- $this->updateMethodName = $methodName;
-
- return $this;
- }
-
- /**
- * Set the finish method name
- *
- * @param string $methodName
- * @return \Zend\ProgressBar\Adapter\JsPush
- */
- public function setFinishMethodName($methodName)
- {
- $this->finishMethodName = $methodName;
-
- return $this;
- }
-
- /**
- * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
- *
- * @param float $current Current progress value
- * @param float $max Max progress value
- * @param float $percent Current percent value
- * @param integer $timeTaken Taken time in seconds
- * @param integer $timeRemaining Remaining time in seconds
- * @param string $text Status text
- * @return void
- */
- public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
- {
- $arguments = array(
- 'current' => $current,
- 'max' => $max,
- 'percent' => ($percent * 100),
- 'timeTaken' => $timeTaken,
- 'timeRemaining' => $timeRemaining,
- 'text' => $text
- );
-
- $data = '<script type="text/javascript">'
- . 'parent.' . $this->updateMethodName . '(' . Json::encode($arguments) . ');'
- . '</script>';
-
- // Output the data
- $this->_outputData($data);
- }
-
- /**
- * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
- *
- * @return void
- */
- public function finish()
- {
- if ($this->finishMethodName === null) {
- return;
- }
-
- $data = '<script type="text/javascript">'
- . 'parent.' . $this->finishMethodName . '();'
- . '</script>';
-
- $this->_outputData($data);
- }
-
- /**
- * Outputs given data the user agent.
- *
- * This split-off is required for unit-testing.
- *
- * @param string $data
- * @return void
- */
- protected function _outputData($data)
- {
- // 1024 padding is required for Safari, while 256 padding is required
- // for Internet Explorer. The <br /> is required so Safari actually
- // executes the <script />
- echo str_pad($data . '<br />', 1024, ' ', STR_PAD_RIGHT) . "\n";
-
- flush();
- ob_flush();
- }
-}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Exception;
-
-/**
- * Exception class for Zend_ProgressBar
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-interface ExceptionInterface
-{
-}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Exception;
-
-/**
- * Exception for Zend_Progressbar component.
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-class InvalidArgumentException extends \InvalidArgumentException implements
- ExceptionInterface
-{}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Exception;
-
-/**
- * Exception for Zend_Progressbar component.
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-class OutOfRangeException extends \OutOfRangeException implements ExceptionInterface
-{
-}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar\Exception;
-
-/**
- * Exception for Zend_Progressbar component.
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-class RuntimeException extends \RuntimeException implements ExceptionInterface
-{}
+++ /dev/null
-<?php
-/**
- * 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)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @package Zend_ProgressBar
- */
-
-namespace Zend\ProgressBar;
-
-use Zend\ProgressBar\Exception;
-use Zend\Session;
-
-/**
- * Zend_ProgressBar offers an interface for multiple environments.
- *
- * @category Zend
- * @package Zend_ProgressBar
- */
-class ProgressBar
-{
- /**
- * Min value
- *
- * @var float
- */
- protected $min;
-
- /**
- * Max value
- *
- * @var float
- */
- protected $max;
-
- /**
- * Current value
- *
- * @var float
- */
- protected $current;
-
- /**
- * Start time of the progressbar, required for ETA
- *
- * @var integer
- */
- protected $startTime;
-
- /**
- * Current status text
- *
- * @var string
- */
- protected $statusText = null;
-
- /**
- * Adapter for the output
- *
- * @var \Zend\ProgressBar\Adapter\AbstractAdapter
- */
- protected $adapter;
-
- /**
- * Namespace for keeping the progressbar persistent
- *
- * @var string
- */
- protected $persistenceNamespace = null;
-
- /**
- * Create a new progressbar backend.
- *
- * @param \Adapter\AbstractAdapter $adapter
- * @param float|int $min
- * @param float|int $max
- * @param string|null $persistenceNamespace
- * @throws Exception\OutOfRangeException When $min is greater than $max
- */
- public function __construct(Adapter\AbstractAdapter $adapter, $min = 0, $max = 100, $persistenceNamespace = null)
- {
- // Check min/max values and set them
- if ($min > $max) {
- throw new Exception\OutOfRangeException('$max must be greater than $min');
- }
-
- $this->min = (float) $min;
- $this->max = (float) $max;
- $this->current = (float) $min;
-
- // See if we have to open a session namespace
- if ($persistenceNamespace !== null) {
- $this->persistenceNamespace = new Session\Container($persistenceNamespace);
- }
-
- // Set adapter
- $this->adapter = $adapter;
-
- // Track the start time
- $this->startTime = time();
-
- // See If a persistenceNamespace exists and handle accordingly
- if ($this->persistenceNamespace !== null) {
- if (isset($this->persistenceNamespace->isSet)) {
- $this->startTime = $this->persistenceNamespace->startTime;
- $this->current = $this->persistenceNamespace->current;
- $this->statusText = $this->persistenceNamespace->statusText;
- } else {
- $this->persistenceNamespace->isSet = true;
- $this->persistenceNamespace->startTime = $this->startTime;
- $this->persistenceNamespace->current = $this->current;
- $this->persistenceNamespace->statusText = $this->statusText;
- }
- } else {
- $this->update();
- }
- }
-
- /**
- * Get the current adapter
- *
- * @return \Adapter\AbstractAdapter
- */
- public function getAdapter()
- {
- return $this->adapter;
- }
-
- /**
- * Update the progressbar
- *
- * @param float $value
- * @param string $text
- * @return void
- */
- public function update($value = null, $text = null)
- {
- // Update value if given
- if ($value !== null) {
- $this->current = min($this->max, max($this->min, $value));
- }
-
- // Update text if given
- if ($text !== null) {
- $this->statusText = $text;
- }
-
- // See if we have to update a namespace
- if ($this->persistenceNamespace !== null) {
- $this->persistenceNamespace->current = $this->current;
- $this->persistenceNamespace->statusText = $this->statusText;
- }
-
- // Calculate percent
- if ($this->min === $this->max) {
- $percent = false;
- } else {
- $percent = (float) ($this->current - $this->min) / ($this->max - $this->min);
- }
-
- // Calculate ETA
- $timeTaken = time() - $this->startTime;
-
- if ($percent === .0 || $percent === false) {
- $timeRemaining = null;
- } else {
- $timeRemaining = round(((1 / $percent) * $timeTaken) - $timeTaken);
- }
-
- // Poll the adapter
- $this->adapter->notify($this->current, $this->max, $percent, $timeTaken, $timeRemaining, $this->statusText);
- }
-
- /**
- * Update the progressbar to the next value
- *
- * @param int $diff
- * @param string $text
- * @return void
- */
- public function next($diff = 1, $text = null)
- {
- $this->update(max($this->min, min($this->max, $this->current + $diff)), $text);
- }
-
- /**
- * Call the adapters finish() behaviour
- *
- * @return void
- */
- public function finish()
- {
- if ($this->persistenceNamespace !== null) {
- unset($this->persistenceNamespace->isSet);
- }
-
- $this->adapter->finish();
- }
-}
+++ /dev/null
-{
- "name": "zendframework/zend-progressbar",
- "description": "component to create and update progressbars in different environments",
- "license": "BSD-3-Clause",
- "keywords": [
- "zf2",
- "progressbar"
- ],
- "autoload": {
- "psr-0": {
- "Zend\\ProgressBar\\": ""
- }
- },
- "target-dir": "Zend/ProgressBar",
- "require": {
- "php": ">=5.3.3",
- "zendframework/zend-stdlib": "self.version"
- }
-}