update v1.0.7.9 R.C.

This is a Release Candidate. We are still testing.
This commit is contained in:
Sujit Prasad
2016-08-03 20:04:36 +05:30
parent 8b6b924d09
commit ffa56a43cb
3830 changed files with 181529 additions and 495353 deletions

View File

@@ -0,0 +1,286 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 3.0.1 - 2016-04-12
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#59](https://github.com/zendframework/zend-stdlib/pull/59) fixes a notice
when defining the `Zend\Json\Json::GLOB_BRACE` constant on systems using
non-gcc glob implementations.
## 3.0.0 - 2016-02-03
### Added
- [#51](https://github.com/zendframework/zend-stdlib/pull/51) adds PHP 7 as a
supported PHP version.
- [#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
zend-hydrator instead!
- [#51](https://github.com/zendframework/zend-stdlib/pull/51) adds automated
documentation builds to gh-pages.
### Deprecated
- Nothing.
### Removed
- [#33](https://github.com/zendframework/zend-stdlib/pull/33) - removed
deprecated classes
- *All Hydrator classes* see #22.
- `Zend\Stdlib\CallbackHandler` see #35
- [#37](https://github.com/zendframework/zend-stdlib/pull/37) - removed
deprecated classes and polyfills:
- `Zend\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.
- `Zend\Stdlib\Exception\InvalidCallbackException`, which was unused since #33.
- `Zend\Stdlib\Guard\GuardUtils`, which duplicated `Zend\Stdlib\Guard\AllGuardsTrait`
to allow usage with pre-PHP 5.4 versions.
- `src/compatibility/autoload.php`, which has been dprecated since 2.5.
- [#37](https://github.com/zendframework/zend-stdlib/pull/37) - removed
unneeded dependencies:
- zend-config (used only in testing ArrayUtils, and the test was redundant)
- zend-serializer (no longer used)
- [#51](https://github.com/zendframework/zend-stdlib/pull/51) removes the
documentation for hydrators, as those are part of the zend-hydrator
component.
### Fixed
- Nothing.
## 2.7.4 - 2015-10-15
### Added
- Nothing.
### Deprecated
- [#35](https://github.com/zendframework/zend-stdlib/pull/35) deprecates
`Zend\Stdlib\CallbackHandler`, as the one component that used it,
zend-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
- [#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
- [#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 zend-hydrator `HydratorInterface` to
ensure LSP is preserved.
## 2.7.1 - 2015-09-22
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#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
- [#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
`Zend\Stdlib\PriorityQueue` implementation.
- extracts are 4x faster than `SplPriorityQueue` and 4-5x faster than the
`Zend\Stdlib\PriorityQueue` implementation.
The intention is to use this as a drop-in replacement in the
`zend-eventmanager` component to provide performance benefits.
### Deprecated
- [#20](https://github.com/zendframework/zend-stdlib/pull/20) deprecates *all
hydrator* classes, in favor of the new [zend-hydrator](https://github.com/zendframework/zend-hydrator)
component. All classes were updated to extend their zend-hydrator equivalents,
and marked as `@deprecated`, indicating the equivalent class from the other
repository.
Users *should* immediately start changing their code to use the zend-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 zend-stdlib in v3.0, and all future updates to hydrators
will occur in the zend-hydrator library.
Changes with backwards compatibility implications:
- Users implementing `Zend\Stdlib\Hydrator\HydratorAwareInterface` will need to
update their `setHydrator()` implementation to typehint on
`Zend\Hydrator\HydratorInterface`. This can be done by changing the import
statement for that interface as follows:
```php
// Replace this:
use Zend\Stdlib\Hydrator\HydratorInterface;
// with this:
use Zend\Hydrator\HydratorInterface;
```
If you are not using imports, change the typehint within the signature itself:
```php
// Replace this:
public function setHydrator(\Zend\Stdlib\Hydrator\HydratorInterface $hydrator)
// with this:
public function setHydrator(\Zend\Hydrator\HydratorInterface $hydrator)
```
If you are using `Zend\Stdlib\Hydrator\HydratorAwareTrait`, no changes are
necessary, unless you override that method.
- If you were catching hydrator-generated exceptions, these were previously in
the `Zend\Stdlib\Exception` namespace. You will need to update your code to
catch exceptions in the `Zend\Hydrator\Exception` namespace.
- Users who *do* migrate to zend-hydrator may end up in a situation where
their code will not work with existing libraries that are still type-hinting
on the zend-stdlib interfaces. We will be attempting to address that ASAP,
but the deprecation within zend-stdlib is necessary as a first step.
In the meantime, you can write hydrators targeting zend-stdlib still in
order to guarantee compatibility.
### Removed
- Nothing.
### Fixed
- Nothing.
## 2.6.0 - 2015-07-21
### Added
- [#13](https://github.com/zendframework/zend-stdlib/pull/13) adds
`Zend\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
- [#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
- [#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.

View File

@@ -0,0 +1,43 @@
# Contributor Code of Conduct
The Zend Framework project adheres to [The Code Manifesto](http://codemanifesto.com)
as its guidelines for contributor interactions.
## The Code Manifesto
We want to work in an ecosystem that empowers developers to reach their
potential — one that encourages growth and effective collaboration. A space that
is safe for all.
A space such as this benefits everyone that participates in it. It encourages
new developers to enter our field. It is through discussion and collaboration
that we grow, and through growth that we improve.
In the effort to create such a place, we hold to these values:
1. **Discrimination limits us.** This includes discrimination on the basis of
race, gender, sexual orientation, gender identity, age, nationality, technology
and any other arbitrary exclusion of a group of people.
2. **Boundaries honor us.** Your comfort levels are not everyones comfort
levels. Remember that, and if brought to your attention, heed it.
3. **We are our biggest assets.** None of us were born masters of our trade.
Each of us has been helped along the way. Return that favor, when and where
you can.
4. **We are resources for the future.** As an extension of #3, share what you
know. Make yourself a resource to help those that come after you.
5. **Respect defines us.** Treat others as you wish to be treated. Make your
discussions, criticisms and debates from a position of respectfulness. Ask
yourself, is it true? Is it necessary? Is it constructive? Anything less is
unacceptable.
6. **Reactions require grace.** Angry responses are valid, but abusive language
and vindictive actions are toxic. When something happens that offends you,
handle it assertively, but be respectful. Escalate reasonably, and try to
allow the offender an opportunity to explain themselves, and possibly correct
the issue.
7. **Opinions are just that: opinions.** Each and every one of us, due to our
background and upbringing, have varying opinions. The fact of the matter, is
that is perfectly acceptable. Remember this: if you respect your own
opinions, you should respect the opinions of others.
8. **To err is human.** You might not intend it, but mistakes do happen and
contribute to build experience. Tolerate honest mistakes, and don't hesitate
to apologize if you make one yourself.

View File

@@ -0,0 +1,244 @@
# CONTRIBUTING
## RESOURCES
If you wish to contribute to Zend Framework, please be sure to
read/subscribe to the following resources:
- [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards)
- [Contributor's Guide](http://framework.zend.com/participate/contributor-guide)
- ZF Contributor's mailing list:
Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html
Subscribe: zf-contributors-subscribe@lists.zend.com
- ZF Contributor's IRC channel:
#zftalk.dev on Freenode.net
If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-stdlib/issues/new).
## Reporting Potential Security Issues
If you have encountered a potential security vulnerability, please **DO NOT** report it on the public
issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead.
We will work with you to verify the vulnerability and patch it as soon as possible.
When reporting issues, please provide the following information:
- Component(s) affected
- A description indicating how to reproduce the issue
- A summary of the security vulnerability and impact
We request that you contact us via the email address above and give the project
contributors a chance to resolve the vulnerability and issue a new release prior
to any public exposure; this helps protect users and provides them with a chance
to upgrade and/or update in order to protect their applications.
For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc).
## RUNNING TESTS
> ### Note: testing versions prior to 2.4
>
> This component originates with Zend Framework 2. During the lifetime of ZF2,
> testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no
> changes were necessary. However, due to the migration, tests may not run on
> versions < 2.4. As such, you may need to change the PHPUnit dependency if
> attempting a fix on such a version.
To run tests:
- Clone the repository:
```console
$ git clone git@github.com:zendframework/zend-stdlib.git
$ cd
```
- Install dependencies via composer:
```console
$ curl -sS https://getcomposer.org/installer | php --
$ ./composer.phar install
```
If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/
- Run the tests via `phpunit` and the provided PHPUnit config, like in this example:
```console
$ ./vendor/bin/phpunit
```
You can turn on conditional tests with the phpunit.xml file.
To do so:
- Copy `phpunit.xml.dist` file to `phpunit.xml`
- Edit `phpunit.xml` to enable any specific functionality you
want to test, as well as to provide test values to utilize.
## Running Coding Standards Checks
This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding
standards checks, and provides configuration for our selected checks.
`php-cs-fixer` is installed by default via Composer.
To run checks only:
```console
$ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs
```
To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run`
flag:
```console
$ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs
```
If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure
they pass, and make sure you add and commit the changes after verification.
## Benchmarks
We provide benchmark tests for zend-stdlib under the directory [benchmark/](benchmark/),
using. [athletic](https://github.com/polyfractal/athletic). You can execute
the benchmarks running the following command:
```bash
$ ./vendor/bin/athletic -p benchmark
```
## Recommended Workflow for Contributions
Your first step is to establish a public repository from which we can
pull your work into the master repository. We recommend using
[GitHub](https://github.com), as that is where the component is already hosted.
1. Setup a [GitHub account](http://github.com/), if you haven't yet
2. Fork the repository (http://github.com/zendframework/zend-stdlib)
3. Clone the canonical repository locally and enter it.
```console
$ git clone git://github.com:zendframework/zend-stdlib.git
$ cd zend-stdlib
```
4. Add a remote to your fork; substitute your GitHub username in the command
below.
```console
$ git remote add {username} git@github.com:{username}/zend-stdlib.git
$ git fetch {username}
```
### Keeping Up-to-Date
Periodically, you should update your fork or personal repository to
match the canonical ZF repository. Assuming you have setup your local repository
per the instructions above, you can do the following:
```console
$ git checkout master
$ git fetch origin
$ git rebase origin/master
# OPTIONALLY, to keep your remote up-to-date -
$ git push {username} master:master
```
If you're tracking other branches -- for example, the "develop" branch, where
new feature development occurs -- you'll want to do the same operations for that
branch; simply substitute "develop" for "master".
### Working on a patch
We recommend you do each new feature or bugfix in a new branch. This simplifies
the task of code review as well as the task of merging your changes into the
canonical repository.
A typical workflow will then consist of the following:
1. Create a new local branch based off either your master or develop branch.
2. Switch to your new local branch. (This step can be combined with the
previous step with the use of `git checkout -b`.)
3. Do some work, commit, repeat as necessary.
4. Push the local branch to your remote repository.
5. Send a pull request.
The mechanics of this process are actually quite trivial. Below, we will
create a branch for fixing an issue in the tracker.
```console
$ git checkout -b hotfix/9295
Switched to a new branch 'hotfix/9295'
```
... do some work ...
```console
$ git commit
```
... write your log message ...
```console
$ git push {username} hotfix/9295:hotfix/9295
Counting objects: 38, done.
Delta compression using up to 2 threads.
Compression objects: 100% (18/18), done.
Writing objects: 100% (20/20), 8.19KiB, done.
Total 20 (delta 12), reused 0 (delta 0)
To ssh://git@github.com/{username}/zend-stdlib.git
b5583aa..4f51698 HEAD -> master
```
To send a pull request, you have two options.
If using GitHub, you can do the pull request from there. Navigate to
your repository, select the branch you just created, and then select the
"Pull Request" button in the upper right. Select the user/organization
"zendframework" as the recipient.
If using your own repository - or even if using GitHub - you can use `git
format-patch` to create a patchset for us to apply; in fact, this is
**recommended** for security-related patches. If you use `format-patch`, please
send the patches as attachments to:
- zf-devteam@zend.com for patches without security implications
- zf-security@zend.com for security patches
#### What branch to issue the pull request against?
Which branch should you issue a pull request against?
- For fixes against the stable release, issue the pull request against the
"master" branch.
- For new features, or fixes that introduce new elements to the public API (such
as new public methods or properties), issue the pull request against the
"develop" branch.
### Branch Cleanup
As you might imagine, if you are a frequent contributor, you'll start to
get a ton of branches both locally and on your remote.
Once you know that your changes have been accepted to the master
repository, we suggest doing some cleanup of these branches.
- Local branch cleanup
```console
$ git branch -d <branchname>
```
- Remote branch removal
```console
$ git push {username} :<branchname>
```
## Conduct
Please see our [CONDUCT.md](CONDUCT.md) to understand expected behavior when interacting with others in the project.

View File

@@ -0,0 +1,28 @@
Copyright (c) 2005-2015, Zend Technologies USA, Inc.
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 Zend Technologies USA, Inc. 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.

View File

@@ -0,0 +1,18 @@
# zend-stdlib
[![Build Status](https://secure.travis-ci.org/zendframework/zend-stdlib.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-stdlib)
[![Coverage Status](https://coveralls.io/repos/zendframework/zend-stdlib/badge.svg?branch=master)](https://coveralls.io/r/zendframework/zend-stdlib?branch=master)
`Zend\Stdlib` is a set of components that implements general purpose utility
class for different scopes like:
- array utilities functions;
- json serializable interfaces;
- general messaging systems;
- string wrappers;
- etc.
---
- File issues at https://github.com/zendframework/zend-stdlib/issues
- Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-stdlib

View File

@@ -0,0 +1,56 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace ZendBench\Stdlib;
use Athletic\AthleticEvent;
use Zend\Stdlib\FastPriorityQueue;
use Zend\Stdlib\PriorityQueue;
use Zend\Stdlib\SplPriorityQueue;
class ExtractPriorityQueue extends AthleticEvent
{
public function classSetUp()
{
$this->splPriorityQueue = new SplPriorityQueue();
$this->fastPriorityQueue = new FastPriorityQueue();
$this->priorityQueue = new PriorityQueue();
for ($i = 0; $i < 5000; $i += 1) {
$priority = rand(1, 100);
$this->splPriorityQueue->insert('foo', $priority);
$this->fastPriorityQueue->insert('foo', $priority);
$this->priorityQueue->insert('foo', $priority);
}
}
/**
* @iterations 5000
*/
public function extractSplPriorityQueue()
{
$this->splPriorityQueue->extract();
}
/**
* @iterations 5000
*/
public function extractPriorityQueue()
{
$this->priorityQueue->extract();
}
/**
* @iterations 5000
*/
public function extractFastPriorityQueue()
{
$this->fastPriorityQueue->extract();
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace ZendBench\Stdlib;
use Athletic\AthleticEvent;
use Zend\Stdlib\FastPriorityQueue;
use Zend\Stdlib\PriorityQueue;
use Zend\Stdlib\SplPriorityQueue;
class InsertPriorityQueue extends AthleticEvent
{
public function classSetUp()
{
$this->splPriorityQueue = new SplPriorityQueue();
$this->fastPriorityQueue = new FastPriorityQueue();
$this->priorityQueue = new PriorityQueue();
}
/**
* @iterations 5000
*/
public function insertSplPriorityQueue()
{
$this->splPriorityQueue->insert('foo', rand(1, 100));
}
/**
* @iterations 5000
*/
public function insertPriorityQueue()
{
$this->priorityQueue->insert('foo', rand(1, 100));
}
/**
* @iterations 5000
*/
public function insertFastPriorityQueue()
{
$this->fastPriorityQueue->insert('foo', rand(1, 100));
}
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace ZendBench\Stdlib;
use Athletic\AthleticEvent;
use Zend\Stdlib\FastPriorityQueue;
use Zend\Stdlib\PriorityQueue;
class RemovePriorityQueue extends AthleticEvent
{
public function classSetUp()
{
$this->fastPriorityQueue = new FastPriorityQueue();
$this->priorityQueue = new PriorityQueue();
for ($i = 0; $i < 1000; $i += 1) {
$priority = rand(1, 100);
$this->fastPriorityQueue->insert('foo', $priority);
$this->priorityQueue->insert('foo', $priority);
}
}
/**
* @iterations 1000
*/
public function removePriorityQueue()
{
$this->priorityQueue->remove('foo');
}
/**
* @iterations 1000
*/
public function removeFastPriorityQueue()
{
$this->fastPriorityQueue->remove('foo');
}
}

View File

@@ -0,0 +1,35 @@
{
"name": "zendframework/zend-stdlib",
"description": " ",
"license": "BSD-3-Clause",
"keywords": [
"zf2",
"stdlib"
],
"homepage": "https://github.com/zendframework/zend-stdlib",
"autoload": {
"psr-4": {
"Zend\\Stdlib\\": "src/"
}
},
"require": {
"php": "^5.5 || ^7.0"
},
"require-dev": {
"fabpot/php-cs-fixer": "1.7.*",
"phpunit/PHPUnit": "~4.0",
"athletic/athletic": "~0.1"
},
"extra": {
"branch-alias": {
"dev-master": "3.0-dev",
"dev-develop": "3.1-dev"
}
},
"autoload-dev": {
"psr-4": {
"ZendTest\\Stdlib\\": "test/",
"ZendBench\\Stdlib\\": "benchmark/"
}
}
}

View File

@@ -0,0 +1,10 @@
<div class="container">
<div class="jumbotron">
<h1>zend-stdlib</h1>
<p>SPL extensions, array utilities, error handlers, and more.</p>
<pre><code class="language-bash">$ composer require zendframework/zend-stdlib</code></pre>
</div>
</div>

View File

@@ -0,0 +1 @@
../../README.md

View File

@@ -0,0 +1,60 @@
# Migration Guide
## From v2 to v3
The changes made going from v2 to v3 were:
- Removal of the Hydrator subcomponent.
- Removal of the `CallbackHandler` class.
- Removal of `Zend\Stdlib\Guard\GuardUtils`.
### Hydrators
The biggest single change from version 2 to version 3 is that the hydrator
subcomponent, which was deprecated in v2.7.0, is now removed. This means that if
you were using zend-stdlib principally for the hydrators, you need to convert
your code to use [zend-hydrator](https://github.com/zendframework/zend-hydrator).
This will also mean a multi-step migration. zend-stdlib v3 pre-dates
zend-hydrator v2.1, which will be the first version that supports zend-stdlib v3
and zend-servicemanager v3. If you are using Composer, the migration should be
seamless:
- Remove your zend-stdlib dependency:
```bash
$ composer remove zendframework/zend-stdlib
```
- Update to use zend-hydrator:
```bash
$ composer require zendframework/zend-hydrator
```
When zend-hydrator updates to newer versions of zend-stdlib and
zend-servicemanager, you will either automatically get those versions, or you
can tell composer to use those specific versions:
```bash
$ composer require "zendframework/zend-stdlib:^3.0"
```
### CallbackHandler
`Zend\Stdlib\CallbackHandler` primarily existed for legacy purposes; it was
created before the `callable` typehint existed, so that we could typehint PHP
callables. It also provided some minimal features around lazy-loading callables
from instantiable classes, but these features were rarely used, and better
approaches already exist for handling such functinality in zend-servicemanager
and zend-expressive.
As such, the class was marked deprecated in v2.7.0, and removed for v3.0.0.
### GuardUtils
Version 3 removes `Zend\Stdlib\Guard\GuardUtils`. This abstract class existed to
provide the functionality of the various traits also present in that
subcomponent, for consumers on versions of PHP earlier than 5.4. Since the
minimum required version is now PHP 5.5, the class is unnecessary. If you were
using it previously, compose the related traits instead.

View File

@@ -0,0 +1,14 @@
{
"title": "Zend\\Stdlib",
"target": "html/",
"content": [
"book/zend.stdlib.hydrator.md",
"book/zend.stdlib.hydrator.filter.md",
"book/zend.stdlib.hydrator.strategy.md",
"book/zend.stdlib.hydrator.aggregate.md",
"book/zend.stdlib.hydrator.namingstrategy.compositenamingstrategy.md",
"book/zend.stdlib.hydrator.namingstrategy.identitynamingstrategy.md",
"book/zend.stdlib.hydrator.namingstrategy.mapnamingstrategy.md",
"book/zend.stdlib.hydrator.namingstrategy.underscorenamingstrategy.md"
]
}

View File

@@ -0,0 +1,9 @@
docs_dir: doc/book
site_dir: doc/html
pages:
- index.md
- Migration: migration.md
site_name: zend-stdlib
site_description: Zend\Stdlib
repo_url: 'https://github.com/zendframework/zend-stdlib'
copyright: 'Copyright (c) 2016 <a href="http://www.zend.com/">Zend Technologies USA Inc.</a>'

View File

@@ -0,0 +1,176 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
use Traversable;
abstract class AbstractOptions implements ParameterObjectInterface
{
/**
* We use the __ prefix to avoid collisions with properties in
* user-implementations.
*
* @var bool
*/
protected $__strictMode__ = true;
/**
* 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',
'Zend\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
);
}
}
}

View File

@@ -0,0 +1,432 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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':
continue;
default:
$this->__set($k, $v);
}
}
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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();
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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));
}
}

View File

@@ -0,0 +1,335 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
use Traversable;
use Zend\Stdlib\ArrayUtils\MergeRemoveKey;
use Zend\Stdlib\ArrayUtils\MergeReplaceKeyInterface;
/**
* 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;
}
/**
* Compatibility Method for array_filter on <5.6 systems
*
* @param array $data
* @param callable $callback
* @param null|int $flag
* @return array
*/
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__
));
}
if (version_compare(PHP_VERSION, '5.6.0') >= 0) {
return array_filter($data, $callback, $flag);
}
$output = [];
foreach ($data as $key => $value) {
$params = [$value];
if ($flag === static::ARRAY_FILTER_USE_BOTH) {
$params[] = $key;
}
if ($flag === static::ARRAY_FILTER_USE_KEY) {
$params = [$key];
}
$response = call_user_func_array($callback, $params);
if ($response) {
$output[$key] = $value;
}
}
return $output;
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\ArrayUtils;
final class MergeRemoveKey
{
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\ArrayUtils;
/**
* Marker interface: can be used to replace keys completely in {@see ArrayUtils::merge()} operations
*/
interface MergeReplaceKeyInterface
{
/**
* @return mixed
*/
public function getData();
}

View File

@@ -0,0 +1,22 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
interface DispatchableInterface
{
/**
* Dispatch a request
*
* @param RequestInterface $request
* @param null|ResponseInterface $response
* @return Response|mixed
*/
public function dispatch(RequestInterface $request, ResponseInterface $response = null);
}

View File

@@ -0,0 +1,115 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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 catched 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);
}
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\Exception;
/**
* Bad method call exception
*/
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\Exception;
/**
* Domain exception
*/
class DomainException extends \DomainException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\Exception;
/**
* Exception marker interface
*/
interface ExceptionInterface
{
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\Exception;
/**
* Extension not loaded exception
*/
class ExtensionNotLoadedException extends RuntimeException
{
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\Exception;
/**
* Invalid Argument Exception
*/
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\Exception;
/**
* Logic exception
*/
class LogicException extends \LogicException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\Exception;
/**
* Runtime exception
*/
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,343 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
use Iterator;
use Countable;
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
*/
protected $maxPriority = 0;
/**
* 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 a positive integer
*/
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 = 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)
{
$this->rewind();
while ($this->valid()) {
if (current($this->values[$this->maxPriority]) === $datum) {
$index = key($this->values[$this->maxPriority]);
unset($this->values[$this->maxPriority][$index]);
--$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()
{
if (false === next($this->values[$this->maxPriority])) {
unset($this->priorities[$this->maxPriority]);
unset($this->values[$this->maxPriority]);
$this->maxPriority = empty($this->priorities) ? 0 : max($this->priorities);
$this->subIndex = -1;
}
++$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) ? 0 : 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]);
}
}

View File

@@ -0,0 +1,202 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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);
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\Guard;
/**
* An aggregate for all guard traits
*/
trait AllGuardsTrait
{
use ArrayOrTraversableGuardTrait;
use EmptyGuardTrait;
use NullGuardTrait;
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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 = 'Zend\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);
}
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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 = 'Zend\Stdlib\Exception\InvalidArgumentException'
) {
if (empty($data)) {
$message = sprintf('%s cannot be empty', $dataName);
throw new $exceptionClass($message);
}
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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 = 'Zend\Stdlib\Exception\InvalidArgumentException'
) {
if (null === $data) {
$message = sprintf('%s cannot be null', $dataName);
throw new $exceptionClass($message);
}
}
}

View File

@@ -0,0 +1,23 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
/**
* Interface to allow objects to have initialization logic
*/
interface InitializableInterface
{
/**
* Init an object
*
* @return void
*/
public function init();
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
interface JsonSerializable extends \JsonSerializable
{
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
use Traversable;
class Message implements MessageInterface
{
/**
* @var array
*/
protected $metadata = [];
/**
* @var string
*/
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;
}
}

View File

@@ -0,0 +1,44 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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();
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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);
}

View File

@@ -0,0 +1,115 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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);
}
/**
* 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;
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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);
}

View File

@@ -0,0 +1,274 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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
);
}
}

View File

@@ -0,0 +1,301 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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 = 'Zend\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 Zend\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;
}
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
class Request extends Message implements RequestInterface
{
// generic request implementation
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
interface RequestInterface extends MessageInterface
{
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
class Response extends Message implements ResponseInterface
{
// generic response implementation
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
interface ResponseInterface extends MessageInterface
{
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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)
{
foreach (unserialize($data) as $item) {
$this->insert($item['data'], $item['priority']);
}
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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);
}
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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);
}
}
}

View File

@@ -0,0 +1,187 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib;
use Zend\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[] = 'Zend\Stdlib\StringWrapper\Intl';
}
if (extension_loaded('mbstring')) {
static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\MbString';
}
if (extension_loaded('iconv')) {
static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Iconv';
}
static::$wrapperRegistry[] = 'Zend\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;
}
}

View File

@@ -0,0 +1,269 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\StringWrapper;
use Zend\Stdlib\Exception;
use Zend\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;
}
}

View File

@@ -0,0 +1,289 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\StringWrapper;
use Zend\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);
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\StringWrapper;
use Zend\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);
}
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\StringWrapper;
use Zend\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);
}
}

View File

@@ -0,0 +1,134 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Stdlib\StringWrapper;
use Zend\Stdlib\Exception;
use Zend\Stdlib\StringUtils;
class Native extends AbstractStringWrapper
{
/**
* The character encoding working on
* (overwritten to change defaut encoding)
*
* @var string
*/
protected $encoding = 'ASCII';
/**
* Check if the given character encoding is supported by this wrapper
* and the character encoding to convert to is also supported.
*
* @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);
}
}

View File

@@ -0,0 +1,111 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\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);
}