updated composer

This commit is contained in:
2021-05-18 13:47:03 +00:00
parent e248cd036c
commit ba92152daa
1187 changed files with 20804 additions and 22320 deletions

View File

@@ -1,120 +0,0 @@
# ramsey/collection Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
### Changed
### Deprecated
### Removed
### Fixed
### Security
## [1.1.1] - 2020-09-10
### Fixed
* Fixed broken `AbstractCollection::map()` implementation.
## [1.1.0] - 2020-08-10
### Fixed
* Fixed `AbstractCollection::diff()`, `AbstractCollection::intersect()` and
`AbstractCollection::merge()` when used with Generic collections.
* Fixed `AbstractCollection::diff()` and `AbstractCollection::intersect()`
returning inconsistent results when used on collections containing objects.
* Removed warning about deprecated dependency when running `composer install`
## [1.0.1] - 2020-01-04
### Fixed
* Fixed `AbstractCollection::offsetSet()` so that it uses the provided `$offset`
when setting `$value` in the array.
## [1.0.0] - 2018-12-31
### Added
* Added support for *queue* data structures to represent collections of ordered
entities. Together with *double-ended queues* (a.k.a. *deques*),
first-in-first-out (FIFO), last-in-first-out (LIFO), and other queue and stack
behaviors may be implemented. This functionality includes interfaces
`QueueInterface` and `DoubleEndedQueueInterface` and classes `Queue` and
`DoubleEndedQueue`.
* Added support for *set* data structures, representing collections that cannot
contain any duplicated elements; includes classes `AbstractSet` and `Set`.
* Added support for *typed map* data structures to represent maps of elements
where both keys and values have specified data types; includes
`TypedMapInterface` and the classes `AbstractTypedMap` and `TypedMap`.
* Added new manipulation and analyze methods for collections: `column()`,
`first()`, `last()`, `sort()`, `filter()`, `where()`, `map()`, `diff()`,
`intersect()`, and `merge()`. See [CollectionInterface](https://github.com/ramsey/collection/blob/master/src/CollectionInterface.php)
for more information.
* Added the following new exceptions specific to the ramsey/collection library:
`CollectionMismatchException`, `InvalidArgumentException`,
`InvalidSortOrderException`, `NoSuchElementException`, `OutOfBoundsException`,
`UnsupportedOperationException`, and `ValueExtractionException`.
### Changed
* Minimum PHP version supported is 7.2.
* Strict types are enforced throughout.
### Removed
* Removed support for HHVM.
### Security
* Fixed possible exploit using `AbstractArray::unserialize()`
(see [#47](https://github.com/ramsey/collection/issues/47)).
## [0.3.0] - 2016-05-23
### Added
* Added `MapInterface::keys()` method to return the keys from a `MapInterface`
object. This was added to the `AbstractMap` class.
### Removed
* Removed `getType()` and constructor methods from `AbstractCollection`. Children
of `AbstractCollection` must now implement `getType()`, which should return a
string value that defines the data type of items for the collection.
### Fixed
* Improve error messages in exceptions when `Collection` and `NamedParameterMap`
items fail type checks.
## [0.2.1] - 2016-02-22
### Fixed
* Allow non-strict checking of values in typed collections.
## [0.2.0] - 2016-02-05
### Added
* Support typed collections.
## [0.1.0] - 2015-10-27
### Added
* Support generic arrays and maps.
[Unreleased]: https://github.com/ramsey/collection/compare/1.1.0...HEAD
[1.1.0]: https://github.com/ramsey/collection/compare/1.0.1...1.1.0
[1.0.1]: https://github.com/ramsey/collection/compare/1.0.0...1.0.1
[1.0.0]: https://github.com/ramsey/collection/compare/0.3.0...1.0.0
[0.3.0]: https://github.com/ramsey/collection/compare/0.2.1...0.3.0
[0.2.1]: https://github.com/ramsey/collection/compare/0.2.0...0.2.1
[0.2.0]: https://github.com/ramsey/collection/compare/0.1.0...0.2.0
[0.1.0]: https://github.com/ramsey/collection/commits/0.1.0

View File

@@ -1,12 +1,22 @@
# ramsey/collection
<h1 align="center">ramsey/collection</h1>
[![Source Code][badge-source]][source]
[![Latest Version][badge-release]][packagist]
[![Software License][badge-license]][license]
[![PHP Version][badge-php]][php]
[![Build Status][badge-build]][build]
[![Coverage Status][badge-coverage]][coverage]
[![Total Downloads][badge-downloads]][downloads]
<p align="center">
<strong>A PHP library for representing and manipulating collections.</strong>
</p>
<p align="center">
<a href="https://github.com/ramsey/collection"><img src="http://img.shields.io/badge/source-ramsey/collection-blue.svg?style=flat-square" alt="Source Code"></a>
<a href="https://packagist.org/packages/ramsey/collection"><img src="https://img.shields.io/packagist/v/ramsey/collection.svg?style=flat-square&label=release" alt="Download Package"></a>
<a href="https://php.net"><img src="https://img.shields.io/packagist/php-v/ramsey/collection.svg?style=flat-square&colorB=%238892BF" alt="PHP Programming Language"></a>
<a href="https://github.com/ramsey/collection/actions?query=workflow%3ACI"><img src="https://img.shields.io/github/workflow/status/ramsey/collection/CI?label=CI&logo=github&style=flat-square" alt="Build Status"></a>
<a href="https://codecov.io/gh/ramsey/collection"><img src="https://img.shields.io/codecov/c/gh/ramsey/collection?label=codecov&logo=codecov&style=flat-square" alt="Codecov Code Coverage"></a>
<a href="https://shepherd.dev/github/ramsey/collection"><img src="https://img.shields.io/endpoint?style=flat-square&url=https%3A%2F%2Fshepherd.dev%2Fgithub%2Framsey%2Fcollection%2Fcoverage" alt="Psalm Type Coverage"></a>
<a href="https://github.com/ramsey/collection/blob/master/LICENSE"><img src="https://img.shields.io/packagist/l/ramsey/collection.svg?style=flat-square&colorB=darkcyan" alt="Read License"></a>
<a href="https://packagist.org/packages/ramsey/collection/stats"><img src="https://img.shields.io/packagist/dt/ramsey/collection.svg?style=flat-square&colorB=darkmagenta" alt="Package downloads on Packagist"></a>
<a href="https://phpc.chat/channel/ramsey"><img src="https://img.shields.io/badge/phpc.chat-%23ramsey-darkslateblue?style=flat-square" alt="Chat with the maintainers"></a>
</p>
## About
ramsey/collection is a PHP 7.2+ library for representing and manipulating collections.
@@ -16,7 +26,6 @@ This project adheres to a [code of conduct](CODE_OF_CONDUCT.md).
By participating in this project and its community, you are expected to
uphold this code.
## Installation
Install this package as a dependency using [Composer](https://getcomposer.org).
@@ -27,8 +36,6 @@ composer require ramsey/collection
## Usage
The [latest class API documentation][apidocs] is available online.
Examples of how to use this framework can be found in the
[Wiki pages](https://github.com/ramsey/collection/wiki/Examples).
@@ -49,99 +56,22 @@ composer install
Now, you are ready to develop!
### Tooling
## Coordinated Disclosure
This project uses [CaptainHook](https://github.com/CaptainHookPhp/captainhook)
to validate all staged changes prior to commit.
Keeping user information safe and secure is a top priority, and we welcome the
contribution of external security researchers. If you believe you've found a
security issue in software that is maintained in this repository, please read
[SECURITY.md][] for instructions on submitting a vulnerability report.
#### Composer Commands
## ramsey/collection for Enterprise
To see all the commands available in the project `br` namespace for
Composer, type:
Available as part of the Tidelift Subscription.
``` bash
composer list br
```
##### Composer Command Autocompletion
If you'd like to have Composer command auto-completion, you may use
[bamarni/symfony-console-autocomplete](https://github.com/bamarni/symfony-console-autocomplete).
Install it globally with Composer:
``` bash
composer global require bamarni/symfony-console-autocomplete
```
Then, in your shell configuration file — usually `~/.bash_profile` or `~/.zshrc`,
but it could be different depending on your settings — ensure that your global
Composer `bin` directory is in your `PATH`, and evaluate the
`symfony-autocomplete` command. This will look like this:
``` bash
export PATH="$(composer config home)/vendor/bin:$PATH"
eval "$(symfony-autocomplete)"
```
Now, you can use the `tab` key to auto-complete Composer commands:
``` bash
composer br:[TAB][TAB]
```
#### Coding Standards
This project follows a superset of [PSR-12](https://www.php-fig.org/psr/psr-12/)
coding standards, enforced by [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer).
The project PHP_CodeSniffer configuration may be found in `phpcs.xml.dist`.
CaptainHook will run PHP_CodeSniffer before committing. It will attempt to fix
any errors it can, and it will reject the commit if there are any un-fixable
issues. Many issues can be fixed automatically and will be done so pre-commit.
You may lint the entire codebase using PHP_CodeSniffer with the following
commands:
``` bash
# Lint
composer br:lint
# Lint and autofix
composer br:lint:fix
```
#### Static Analysis
This project uses a combination of [PHPStan](https://github.com/phpstan/phpstan)
and [Psalm](https://github.com/vimeo/psalm) to provide static analysis of PHP
code. Configurations for these are in `phpstan.neon.dist` and `psalm.xml`,
respectively.
CaptainHook will run PHPStan and Psalm before committing. The pre-commit hook
does not attempt to fix any static analysis errors. Instead, the commit will
fail, and you must fix the errors manually.
You may run static analysis manually across the whole codebase with the
following command:
``` bash
# Static analysis
composer br:analyze
```
### Project Structure
This project uses [pds/skeleton](https://github.com/php-pds/skeleton) as its
base folder structure and layout.
| Name | Description |
| ------------------| ---------------------------------------------- |
| **bin/** | Commands and scripts for this project |
| **build/** | Cache, logs, reports, etc. for project builds |
| **docs/** | Project-specific documentation |
| **resources/** | Additional resources for this project |
| **src/** | Project library and application source code |
| **tests/** | Tests for this project |
The maintainers of ramsey/collection and thousands of other packages are working
with Tidelift to deliver commercial support and maintenance for the open source
packages you use to build your applications. Save time, reduce risk, and improve
code health, while paying the maintainers of the exact packages you use.
[Learn more.](https://tidelift.com/subscription/pkg/packagist-ramsey-collection?utm_source=undefined&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
## Copyright and License
@@ -151,20 +81,4 @@ MIT License (MIT). Please see [LICENSE](LICENSE) for more information.
[java]: http://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html
[apidocs]: https://docs.benramsey.com/ramsey-collection/latest/
[badge-source]: http://img.shields.io/badge/source-ramsey/collection-blue.svg?style=flat-square
[badge-release]: https://img.shields.io/packagist/v/ramsey/collection.svg?style=flat-square&label=release
[badge-license]: https://img.shields.io/packagist/l/ramsey/collection.svg?style=flat-square
[badge-php]: https://img.shields.io/packagist/php-v/ramsey/collection.svg?style=flat-square
[badge-build]: https://img.shields.io/travis/ramsey/collection/master.svg?style=flat-square
[badge-coverage]: https://img.shields.io/coveralls/github/ramsey/collection/master.svg?style=flat-square
[badge-downloads]: https://img.shields.io/packagist/dt/ramsey/collection.svg?style=flat-square&colorB=mediumvioletred
[source]: https://github.com/ramsey/collection
[packagist]: https://packagist.org/packages/ramsey/collection
[license]: https://github.com/ramsey/collection/blob/master/LICENSE
[php]: https://php.net
[build]: https://travis-ci.org/ramsey/collection
[coverage]: https://coveralls.io/r/ramsey/collection?branch=master
[downloads]: https://packagist.org/packages/ramsey/collection
[security.md]: https://github.com/ramsey/collection/blob/master/SECURITY.md

113
vendor/ramsey/collection/SECURITY.md vendored Normal file
View File

@@ -0,0 +1,113 @@
<!--
This policy was created using the HackerOne Policy Builder:
https://hackerone.com/policy-builder/
-->
# Vulnerability Disclosure Policy
Keeping user information safe and secure is a top priority, and we welcome the
contribution of external security researchers.
## Scope
If you believe you've found a security issue in software that is maintained in
this repository, we encourage you to notify us.
| Version | In scope | Source code |
| :-----: | :------: | :---------- |
| latest | ✅ | https://github.com/ramsey/collection |
## How to Submit a Report
To submit a vulnerability report, please contact us at <security@ramsey.dev>.
Your submission will be reviewed and validated by a member of our team.
## Safe Harbor
We support safe harbor for security researchers who:
* Make a good faith effort to avoid privacy violations, destruction of data, and
interruption or degradation of our services.
* Only interact with accounts you own or with explicit permission of the account
holder. If you do encounter Personally Identifiable Information (PII) contact
us immediately, do not proceed with access, and immediately purge any local
information.
* Provide us with a reasonable amount of time to resolve vulnerabilities prior
to any disclosure to the public or a third-party.
We will consider activities conducted consistent with this policy to constitute
"authorized" conduct and will not pursue civil action or initiate a complaint to
law enforcement. We will help to the extent we can if legal action is initiated
by a third party against you.
Please submit a report to us before engaging in conduct that may be inconsistent
with or unaddressed by this policy.
## Preferences
* Please provide detailed reports with reproducible steps and a clearly defined
impact.
* Include the version number of the vulnerable package in your report
* Social engineering (e.g. phishing, vishing, smishing) is prohibited.
## Encryption Key for security@ramsey.dev
For increased privacy when reporting sensitive issues, you may encrypt your
messages using the following key:
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBF+Z9gEBEACbT/pIx8RR0K18t8Z2rDnmEV44YdT7HNsMdq+D6SAlx8UUb6AU
jGIbV9dgBgGNtOLU1pxloaJwL9bWIRbj+X/Qb2WNIP//Vz1Y40ox1dSpfCUrizXx
kb4p58Xml0PsB8dg3b4RDUgKwGC37ne5xmDnigyJPbiB2XJ6Xc46oPCjh86XROTK
wEBB2lY67ClBlSlvC2V9KmbTboRQkLdQDhOaUosMb99zRb0EWqDLaFkZVjY5HI7i
0pTveE6dI12NfHhTwKjZ5pUiAZQGlKA6J1dMjY2unxHZkQj5MlMfrLSyJHZxccdJ
xD94T6OTcTHt/XmMpI2AObpewZDdChDQmcYDZXGfAhFoJmbvXsmLMGXKgzKoZ/ls
RmLsQhh7+/r8E+Pn5r+A6Hh4uAc14ApyEP0ckKeIXw1C6pepHM4E8TEXVr/IA6K/
z6jlHORixIFX7iNOnfHh+qwOgZw40D6JnBfEzjFi+T2Cy+JzN2uy7I8UnecTMGo3
5t6astPy6xcH6kZYzFTV7XERR6LIIVyLAiMFd8kF5MbJ8N5ElRFsFHPW+82N2HDX
c60iSaTB85k6R6xd8JIKDiaKE4sSuw2wHFCKq33d/GamYezp1wO+bVUQg88efljC
2JNFyD+vl30josqhw1HcmbE1TP3DlYeIL5jQOlxCMsgai6JtTfHFM/5MYwARAQAB
tBNzZWN1cml0eUByYW1zZXkuZGV2iQJUBBMBCAA+FiEE4drPD+/ofZ570fAYq0bv
vXQCywIFAl+Z9gECGwMFCQeGH4AFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ
q0bvvXQCywIkEA//Qcwv8MtTCy01LHZd9c7VslwhNdXQDYymcTyjcYw8x7O22m4B
3hXE6vqAplFhVxxkqXB2ef0tQuzxhPHNJgkCE4Wq4i+V6qGpaSVHQT2W6DN/NIhL
vS8OdScc6zddmIbIkSrzVVAtjwehFNEIrX3DnbbbK+Iku7vsKT5EclOluIsjlYoX
goW8IeReyDBqOe2H3hoCGw6EA0D/NYV2bJnfy53rXVIyarsXXeOLp7eNEH6Td7aW
PVSrMZJe1t+knrEGnEdrXWzlg4lCJJCtemGv+pKBUomnyISXSdqyoRCCzvQjqyig
2kRebUX8BXPW33p4OXPj9sIboUOjZwormWwqqbFMO+J4TiVCUoEoheI7emPFRcNN
QtPJrjbY1++OznBc0GRpfeUkGoU1cbRl1bnepnFIZMTDLkrVW6I1Y4q8ZVwX3BkE
N81ctFrRpHBlU36EdHvjPQmGtuiL77Qq3fWmMv7yTvK1wHJAXfEb0ZJWHZCbck3w
l0CVq0Z+UUAOM8Rp1N0N8m92xtapav0qCFU9qzf2J5qX6GRmWv+d29wPgFHzDWBm
nnrYYIA4wJLx00U6SMcVBSnNe91B+RfGY5XQhbWPjQQecOGCSDsxaFAq2MeOVJyZ
bIjLYfG9GxoLKr5R7oLRJvZI4nKKBc1Kci/crZbdiSdQhSQGlDz88F1OHeCIdQQQ
EQgAHRYhBOhdAxHd+lus86YQ57Atl5icjAcbBQJfmfdIAAoJELAtl5icjAcbFVcA
/1LqB3ZjsnXDAvvAXZVjSPqofSlpMLeRQP6IM/A9Odq0AQCZrtZc1knOMGEcjppK
Rk+sy/R0Mshy8TDuaZIRgh2Ux7kCDQRfmfYBARAAmchKzzVz7IaEq7PnZDb3szQs
T/+E9F3m39yOpV4fEB1YzObonFakXNT7Gw2tZEx0eitUMqQ/13jjfu3UdzlKl2bR
qA8LrSQRhB+PTC9A1XvwxCUYhhjGiLzJ9CZL6hBQB43qHOmE9XJPme90geLsF+gK
u39Waj1SNWzwGg+Gy1Gl5f2AJoDTxznreCuFGj+Vfaczt/hlfgqpOdb9jsmdoE7t
3DSWppA9dRHWwQSgE6J28rR4QySBcqyXS6IMykqaJn7Z26yNIaITLnHCZOSY8zhP
ha7GFsN549EOCgECbrnPt9dmI2+hQE0RO0e7SOBNsIf5sz/i7urhwuj0CbOqhjc2
X1AEVNFCVcb6HPi/AWefdFCRu0gaWQxn5g+9nkq5slEgvzCCiKYzaBIcr8qR6Hb4
FaOPVPxO8vndRouq57Ws8XpAwbPttioFuCqF4u9K+tK/8e2/R8QgRYJsE3Cz/Fu8
+pZFpMnqbDEbK3DL3ss+1ed1sky+mDV8qXXeI33XW5hMFnk1JWshUjHNlQmE6ftC
U0xSTMVUtwJhzH2zDp8lEdu7qi3EsNULOl68ozDr6soWAvCbHPeTdTOnFySGCleG
/3TonsoZJs/sSPPJnxFQ1DtgQL6EbhIwa0ZwU4eKYVHZ9tjxuMX3teFzRvOrJjgs
+ywGlsIURtEckT5Y6nMAEQEAAYkCPAQYAQgAJhYhBOHazw/v6H2ee9HwGKtG7710
AssCBQJfmfYBAhsMBQkHhh+AAAoJEKtG7710AssC8NcP/iDAcy1aZFvkA0EbZ85p
i7/+ywtE/1wF4U4/9OuLcoskqGGnl1pJNPooMOSBCfreoTB8HimT0Fln0CoaOm4Q
pScNq39JXmf4VxauqUJVARByP6zUfgYarqoaZNeuFF0S4AZJ2HhGzaQPjDz1uKVM
PE6tQSgQkFzdZ9AtRA4vElTH6yRAgmepUsOihk0b0gUtVnwtRYZ8e0Qt3ie97a73
DxLgAgedFRUbLRYiT0vNaYbainBsLWKpN/T8odwIg/smP0Khjp/ckV60cZTdBiPR
szBTPJESMUTu0VPntc4gWwGsmhZJg/Tt/qP08XYo3VxNYBegyuWwNR66zDWvwvGH
muMv5UchuDxp6Rt3JkIO4voMT1JSjWy9p8krkPEE4V6PxAagLjdZSkt92wVLiK5x
y5gNrtPhU45YdRAKHr36OvJBJQ42CDaZ6nzrzghcIp9CZ7ANHrI+QLRM/csz+AGA
szSp6S4mc1lnxxfbOhPPpebZPn0nIAXoZnnoVKdrxBVedPQHT59ZFvKTQ9Fs7gd3
sYNuc7tJGFGC2CxBH4ANDpOQkc5q9JJ1HSGrXU3juxIiRgfA26Q22S9c71dXjElw
Ri584QH+bL6kkYmm8xpKF6TVwhwu5xx/jBPrbWqFrtbvLNrnfPoapTihBfdIhkT6
nmgawbBHA02D5xEqB5SU3WJu
=eJNx
-----END PGP PUBLIC KEY BLOCK-----
```

View File

@@ -25,19 +25,19 @@
"captainhook/captainhook": "^5.3",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"ergebnis/composer-normalize": "^2.6",
"fzaninotto/faker": "^1.5",
"fakerphp/faker": "^1.5",
"hamcrest/hamcrest-php": "^2",
"jangregor/phpstan-prophecy": "^0.6",
"jangregor/phpstan-prophecy": "^0.8",
"mockery/mockery": "^1.3",
"phpstan/extension-installer": "^1",
"phpstan/phpstan": "^0.12.32",
"phpstan/phpstan-mockery": "^0.12.5",
"phpstan/phpstan-phpunit": "^0.12.11",
"phpunit/phpunit": "^8.5",
"phpunit/phpunit": "^8.5 || ^9",
"psy/psysh": "^0.10.4",
"slevomat/coding-standard": "^6.3",
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^3.12.2"
"vimeo/psalm": "^4.4"
},
"config": {
"sort-packages": true
@@ -63,7 +63,7 @@
"@br:analyze:psalm"
],
"br:analyze:phpstan": "phpstan --memory-limit=1G analyse",
"br:analyze:psalm": "psalm --diff --diff-methods --config=psalm.xml",
"br:analyze:psalm": "psalm --diff --config=psalm.xml",
"br:build:clean": "git clean -fX build/.",
"br:build:clear-cache": "git clean -fX build/cache/.",
"br:lint": "phpcs --cache=build/cache/phpcs.cache",

View File

@@ -23,20 +23,23 @@ use function unserialize;
/**
* This class provides a basic implementation of `ArrayInterface`, to minimize
* the effort required to implement this interface.
*
* @template T
* @template-implements ArrayInterface<T>
*/
abstract class AbstractArray implements ArrayInterface
{
/**
* The items of this array.
*
* @var mixed[]
* @var array<array-key, T>
*/
protected $data = [];
/**
* Constructs a new array object.
*
* @param mixed[] $data The initial items to add to this array.
* @param array<array-key, T> $data The initial items to add to this array.
*/
public function __construct(array $data = [])
{
@@ -51,8 +54,6 @@ abstract class AbstractArray implements ArrayInterface
* Returns an iterator for this array.
*
* @link http://php.net/manual/en/iteratoraggregate.getiterator.php IteratorAggregate::getIterator()
*
* @return ArrayIterator<mixed, mixed>
*/
public function getIterator(): Traversable
{
@@ -64,7 +65,7 @@ abstract class AbstractArray implements ArrayInterface
*
* @link http://php.net/manual/en/arrayaccess.offsetexists.php ArrayAccess::offsetExists()
*
* @param mixed $offset The offset to check.
* @param array-key $offset The offset to check.
*/
public function offsetExists($offset): bool
{
@@ -76,9 +77,9 @@ abstract class AbstractArray implements ArrayInterface
*
* @link http://php.net/manual/en/arrayaccess.offsetget.php ArrayAccess::offsetGet()
*
* @param mixed $offset The offset for which a value should be returned.
* @param array-key $offset The offset for which a value should be returned.
*
* @return mixed|null the value stored at the offset, or null if the offset
* @return T|null the value stored at the offset, or null if the offset
* does not exist.
*/
public function offsetGet($offset)
@@ -91,10 +92,11 @@ abstract class AbstractArray implements ArrayInterface
*
* @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
*
* @param mixed|null $offset The offset to set. If `null`, the value may be
* @param array-key|null $offset The offset to set. If `null`, the value may be
* set at a numerically-indexed offset.
* @param mixed $value The value to set at the given offset.
* @param T $value The value to set at the given offset.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function offsetSet($offset, $value): void
{
if ($offset === null) {
@@ -109,7 +111,7 @@ abstract class AbstractArray implements ArrayInterface
*
* @link http://php.net/manual/en/arrayaccess.offsetunset.php ArrayAccess::offsetUnset()
*
* @param mixed $offset The offset to remove from the array.
* @param array-key $offset The offset to remove from the array.
*/
public function offsetUnset($offset): void
{
@@ -139,7 +141,10 @@ abstract class AbstractArray implements ArrayInterface
*/
public function unserialize($serialized): void
{
$this->data = unserialize($serialized, ['allowed_classes' => false]);
/** @var array<array-key, T> $data */
$data = unserialize($serialized, ['allowed_classes' => false]);
$this->data = $data;
}
/**
@@ -152,27 +157,19 @@ abstract class AbstractArray implements ArrayInterface
return count($this->data);
}
/**
* Removes all items from this array.
*/
public function clear(): void
{
$this->data = [];
}
/**
* Returns a native PHP array representation of this array object.
*
* @return mixed[]
* @inheritDoc
*/
public function toArray(): array
{
return $this->data;
}
/**
* Returns `true` if this array is empty.
*/
public function isEmpty(): bool
{
return count($this->data) === 0;

View File

@@ -14,11 +14,11 @@ declare(strict_types=1);
namespace Ramsey\Collection;
use Closure;
use Ramsey\Collection\Exception\CollectionMismatchException;
use Ramsey\Collection\Exception\InvalidArgumentException;
use Ramsey\Collection\Exception\InvalidSortOrderException;
use Ramsey\Collection\Exception\OutOfBoundsException;
use Ramsey\Collection\Exception\ValueExtractionException;
use Ramsey\Collection\Tool\TypeTrait;
use Ramsey\Collection\Tool\ValueExtractorTrait;
use Ramsey\Collection\Tool\ValueToStringTrait;
@@ -40,6 +40,10 @@ use function usort;
/**
* This class provides a basic implementation of `CollectionInterface`, to
* minimize the effort required to implement this interface
*
* @template T
* @template-extends AbstractArray<T>
* @template-implements CollectionInterface<T>
*/
abstract class AbstractCollection extends AbstractArray implements CollectionInterface
{
@@ -48,14 +52,7 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
use ValueExtractorTrait;
/**
* Ensures that this collection contains the specified element.
*
* @param mixed $element The element to add to the collection.
*
* @return bool `true` if this collection changed as a result of the call.
*
* @throws InvalidArgumentException when the element does not match the
* specified type for this collection.
* @inheritDoc
*/
public function add($element): bool
{
@@ -65,10 +62,7 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
/**
* Returns `true` if this collection contains the specified element.
*
* @param mixed $element The element to check whether the collection contains.
* @param bool $strict Whether to perform a strict type check on the value.
* @inheritDoc
*/
public function contains($element, bool $strict = true): bool
{
@@ -76,14 +70,7 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
/**
* Sets the given value to the given offset in the array.
*
* @param mixed|null $offset The position to set the value in the array, or
* `null` to append the value to the array.
* @param mixed $value The value to set at the given offset.
*
* @throws InvalidArgumentException when the value does not match the
* specified type for this collection.
* @inheritDoc
*/
public function offsetSet($offset, $value): void
{
@@ -102,12 +89,7 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
/**
* Removes a single instance of the specified element from this collection,
* if it is present.
*
* @param mixed $element The element to remove from the collection.
*
* @return bool `true` if an element was removed as a result of this call.
* @inheritDoc
*/
public function remove($element): bool
{
@@ -121,31 +103,25 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
/**
* Returns the values from given property or method.
*
* @param string $propertyOrMethod The property or method name to filter by.
*
* @return mixed[]
*
* @throws ValueExtractionException if property or method is not defined.
* @inheritDoc
*/
public function column(string $propertyOrMethod): array
{
$temp = [];
foreach ($this->data as $item) {
$temp[] = $this->extractValue($item, $propertyOrMethod);
/** @var mixed $value */
$value = $this->extractValue($item, $propertyOrMethod);
/** @psalm-suppress MixedAssignment */
$temp[] = $value;
}
return $temp;
}
/**
* Returns the first item of the collection.
*
* @return mixed
*
* @throws OutOfBoundsException when the collection is empty.
* @inheritDoc
*/
public function first()
{
@@ -155,15 +131,14 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
reset($this->data);
return current($this->data);
/** @var T $first */
$first = current($this->data);
return $first;
}
/**
* Returns the last item of the collection.
*
* @return mixed
*
* @throws OutOfBoundsException when the collection is empty.
* @inheritDoc
*/
public function last()
{
@@ -171,27 +146,13 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
throw new OutOfBoundsException('Can\'t determine last item. Collection is empty');
}
/** @var T $item */
$item = end($this->data);
reset($this->data);
return $item;
}
/**
* Returns a sorted collection.
*
* {@inheritdoc}
*
* @param string $propertyOrMethod The property or method to sort by.
* @param string $order The sort order for the resulting collection (one of
* this interface's `SORT_*` constants).
*
* @return CollectionInterface<mixed, mixed>
*
* @throws InvalidSortOrderException if neither "asc" nor "desc" was given
* as the order.
* @throws ValueExtractionException if property or method is not defined.
*/
public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): CollectionInterface
{
if (!in_array($order, [self::SORT_ASC, self::SORT_DESC], true)) {
@@ -200,25 +161,26 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
$collection = clone $this;
usort($collection->data, function ($a, $b) use ($propertyOrMethod, $order) {
$aValue = $this->extractValue($a, $propertyOrMethod);
$bValue = $this->extractValue($b, $propertyOrMethod);
usort(
$collection->data,
/**
* @param T $a
* @param T $b
*/
function ($a, $b) use ($propertyOrMethod, $order): int {
/** @var mixed $aValue */
$aValue = $this->extractValue($a, $propertyOrMethod);
return ($aValue <=> $bValue) * ($order === self::SORT_DESC ? -1 : 1);
});
/** @var mixed $bValue */
$bValue = $this->extractValue($b, $propertyOrMethod);
return ($aValue <=> $bValue) * ($order === self::SORT_DESC ? -1 : 1);
}
);
return $collection;
}
/**
* Returns a filtered collection.
*
* {@inheritdoc}
*
* @param callable $callback A callable to use for filtering elements.
*
* @return CollectionInterface<mixed, mixed>
*/
public function filter(callable $callback): CollectionInterface
{
$collection = clone $this;
@@ -228,84 +190,31 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
}
/**
* Returns a collection of matching items.
*
* {@inheritdoc}
*
* @param string $propertyOrMethod The property or method to evaluate.
* @param mixed $value The value to match.
*
* @return CollectionInterface<mixed, mixed>
*
* @throws ValueExtractionException if property or method is not defined.
*/
public function where(string $propertyOrMethod, $value): CollectionInterface
{
return $this->filter(function ($item) use ($propertyOrMethod, $value) {
/** @var mixed $accessorValue */
$accessorValue = $this->extractValue($item, $propertyOrMethod);
return $accessorValue === $value;
});
}
/**
* Applies a callback to each item of the collection.
*
* {@inheritdoc}
*
* @param callable $callback A callable to apply to each item of the
* collection.
*
* @return CollectionInterface<mixed, mixed>
*/
public function map(callable $callback): CollectionInterface
{
$collection = clone $this;
$collection->data = array_map($callback, $collection->data);
return $collection;
return new Collection('mixed', array_map($callback, $this->data));
}
/**
* Create a new collection with divergent items between current and given
* collection.
*
* @param CollectionInterface<mixed, mixed> $other The collection to check for divergent
* items.
*
* @return CollectionInterface<mixed, mixed>
*
* @throws CollectionMismatchException if the given collection is not of the
* same type.
*/
public function diff(CollectionInterface $other): CollectionInterface
{
if (!$other instanceof static) {
throw new CollectionMismatchException('Collection must be of type ' . static::class);
}
$this->compareCollectionTypes($other);
// When using generics (Collection.php, Set.php, etc),
// we also need to make sure that the internal types match each other
if ($other->getType() !== $this->getType()) {
throw new CollectionMismatchException('Collection items must be of type ' . $this->getType());
}
$diffAtoB = array_udiff($this->data, $other->toArray(), $this->getComparator());
$diffBtoA = array_udiff($other->toArray(), $this->data, $this->getComparator());
$comparator = function ($a, $b): int {
// If the two values are object, we convert them to unique scalars.
// If the collection contains mixed values (unlikely) where some are objects
// and some are not, we leave them as they are.
// The comparator should still work and the result of $a < $b should
// be consistent but unpredictable since not documented.
if (is_object($a) && is_object($b)) {
$a = spl_object_id($a);
$b = spl_object_id($b);
}
return $a === $b ? 0 : ($a < $b ? 1 : -1);
};
$diffAtoB = array_udiff($this->data, $other->data, $comparator);
$diffBtoA = array_udiff($other->data, $this->data, $comparator);
/** @var array<array-key, T> $diff */
$diff = array_merge($diffAtoB, $diffBtoA);
$collection = clone $this;
@@ -314,45 +223,12 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
return $collection;
}
/**
* Create a new collection with intersecting item between current and given
* collection.
*
* @param CollectionInterface<mixed, mixed> $other The collection to check for
* intersecting items.
*
* @return CollectionInterface<mixed, mixed>
*
* @throws CollectionMismatchException if the given collection is not of the
* same type.
*/
public function intersect(CollectionInterface $other): CollectionInterface
{
if (!$other instanceof static) {
throw new CollectionMismatchException('Collection must be of type ' . static::class);
}
$this->compareCollectionTypes($other);
// When using generics (Collection.php, Set.php, etc),
// we also need to make sure that the internal types match each other
if ($other->getType() !== $this->getType()) {
throw new CollectionMismatchException('Collection items must be of type ' . $this->getType());
}
$comparator = function ($a, $b): int {
// If the two values are object, we convert them to unique scalars.
// If the collection contains mixed values (unlikely) where some are objects
// and some are not, we leave them as they are.
// The comparator should still work and the result of $a < $b should
// be consistent but unpredictable since not documented.
if (is_object($a) && is_object($b)) {
$a = spl_object_id($a);
$b = spl_object_id($b);
}
return $a === $b ? 0 : ($a < $b ? 1 : -1);
};
$intersect = array_uintersect($this->data, $other->data, $comparator);
/** @var array<array-key, T> $intersect */
$intersect = array_uintersect($this->data, $other->toArray(), $this->getComparator());
$collection = clone $this;
$collection->data = $intersect;
@@ -360,15 +236,6 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
return $collection;
}
/**
* Merge current items and items of given collections into a new one.
*
* @param CollectionInterface<mixed, mixed> ...$collections The collections to merge.
*
* @return CollectionInterface<mixed, mixed>
*
* @throws CollectionMismatchException if any of the given collections are not of the same type.
*/
public function merge(CollectionInterface ...$collections): CollectionInterface
{
$temp = [$this->data];
@@ -391,6 +258,7 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
$temp[] = $collection->toArray();
}
/** @var array<array-key, T> $merge */
$merge = array_merge(...$temp);
$collection = clone $this;
@@ -404,6 +272,46 @@ abstract class AbstractCollection extends AbstractArray implements CollectionInt
*/
public function unserialize($serialized): void
{
$this->data = unserialize($serialized, ['allowed_classes' => [$this->getType()]]);
/** @var array<array-key, T> $data */
$data = unserialize($serialized, ['allowed_classes' => [$this->getType()]]);
$this->data = $data;
}
/**
* @param CollectionInterface<T> $other
*/
private function compareCollectionTypes(CollectionInterface $other): void
{
if (!$other instanceof static) {
throw new CollectionMismatchException('Collection must be of type ' . static::class);
}
// When using generics (Collection.php, Set.php, etc),
// we also need to make sure that the internal types match each other
if ($other->getType() !== $this->getType()) {
throw new CollectionMismatchException('Collection items must be of type ' . $this->getType());
}
}
private function getComparator(): Closure
{
return /**
* @param T $a
* @param T $b
*/
function ($a, $b): int {
// If the two values are object, we convert them to unique scalars.
// If the collection contains mixed values (unlikely) where some are objects
// and some are not, we leave them as they are.
// The comparator should still work and the result of $a < $b should
// be consistent but unpredictable since not documented.
if (is_object($a) && is_object($b)) {
$a = spl_object_id($a);
$b = spl_object_id($b);
}
return $a === $b ? 0 : ($a < $b ? 1 : -1);
};
}
}

View File

@@ -14,25 +14,18 @@ declare(strict_types=1);
namespace Ramsey\Collection;
use Ramsey\Collection\Exception\InvalidArgumentException;
/**
* This class contains the basic implementation of a collection that does not
* allow duplicated values (a set), to minimize the effort required to implement
* this specific type of collection.
*
* @template T
* @template-extends AbstractCollection<T>
*/
abstract class AbstractSet extends AbstractCollection
{
/**
* Adds the specified element to this set, if it is not already present.
*
* @param mixed $element The element to add to the set.
*
* @return bool `true` if this set did not already contain the specified
* element.
*
* @throws InvalidArgumentException when the element does not match the
* specified type for this set.
* @inheritDoc
*/
public function add($element): bool
{
@@ -44,14 +37,7 @@ abstract class AbstractSet extends AbstractCollection
}
/**
* Sets the given value to the given offset in this set, if it is not
* already present.
*
* @param mixed|null $offset The offset is ignored and is treated as `null`.
* @param mixed $value The value to set at the given offset.
*
* @throws InvalidArgumentException when the value does not match the
* specified type for this set.
* @inheritDoc
*/
public function offsetSet($offset, $value): void
{

View File

@@ -21,6 +21,8 @@ use Serializable;
/**
* `ArrayInterface` provides traversable array functionality to data types.
*
* @template T
*/
interface ArrayInterface extends
ArrayAccess,
@@ -36,7 +38,7 @@ interface ArrayInterface extends
/**
* Returns a native PHP array representation of this array object.
*
* @return mixed[]
* @return array<array-key, T>
*/
public function toArray(): array;

View File

@@ -69,6 +69,9 @@ namespace Ramsey\Collection;
* // the collection is a collection of My\Foo objects
* }
* ```
*
* @template T
* @template-extends AbstractCollection<T>
*/
class Collection extends AbstractCollection
{
@@ -88,7 +91,7 @@ class Collection extends AbstractCollection
*
* @param string $collectionType The type (FQCN) associated with this
* collection.
* @param mixed[] $data The initial items to store in the collection.
* @param array<array-key, T> $data The initial items to store in the collection.
*/
public function __construct(string $collectionType, array $data = [])
{
@@ -96,9 +99,6 @@ class Collection extends AbstractCollection
parent::__construct($data);
}
/**
* Returns the type associated with this collection.
*/
public function getType(): string
{
return $this->collectionType;

View File

@@ -19,6 +19,9 @@ namespace Ramsey\Collection;
*
* Some collections allow duplicate elements and others do not. Some are ordered
* and others unordered.
*
* @template T
* @template-extends ArrayInterface<T>
*/
interface CollectionInterface extends ArrayInterface
{
@@ -52,18 +55,20 @@ interface CollectionInterface extends ArrayInterface
* (rather than returning `false`). This preserves the invariant that a
* collection always contains the specified element after this call returns.
*
* @param mixed $element The element to add to the collection.
* @param T $element The element to add to the collection.
*
* @return bool `true` if this collection changed as a result of the call.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function add($element): bool;
/**
* Returns `true` if this collection contains the specified element.
*
* @param mixed $element The element to check whether the collection contains.
* @param T $element The element to check whether the collection contains.
* @param bool $strict Whether to perform a strict type check on the value.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function contains($element, bool $strict = true): bool;
/**
@@ -75,10 +80,11 @@ interface CollectionInterface extends ArrayInterface
* Removes a single instance of the specified element from this collection,
* if it is present.
*
* @param mixed $element The element to remove from the collection.
* @param T $element The element to remove from the collection.
*
* @return bool `true` if an element was removed as a result of this call.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function remove($element): bool;
/**
@@ -86,21 +92,21 @@ interface CollectionInterface extends ArrayInterface
*
* @param string $propertyOrMethod The property or method name to filter by.
*
* @return mixed[]
* @return list<mixed>
*/
public function column(string $propertyOrMethod): array;
/**
* Returns the first item of the collection.
*
* @return mixed
* @return T
*/
public function first();
/**
* Returns the last item of the collection.
*
* @return mixed
* @return T
*/
public function last();
@@ -114,7 +120,7 @@ interface CollectionInterface extends ArrayInterface
* @param string $order The sort order for the resulting collection (one of
* this interface's `SORT_*` constants).
*
* @return CollectionInterface<mixed, mixed>
* @return CollectionInterface<T>
*/
public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): self;
@@ -128,9 +134,9 @@ interface CollectionInterface extends ArrayInterface
* See the {@link http://php.net/manual/en/function.array-filter.php PHP array_filter() documentation}
* for examples of how the `$callback` parameter works.
*
* @param callable $callback A callable to use for filtering elements.
* @param callable(T):bool $callback A callable to use for filtering elements.
*
* @return CollectionInterface<mixed, mixed>
* @return CollectionInterface<T>
*/
public function filter(callable $callback): self;
@@ -141,25 +147,28 @@ interface CollectionInterface extends ArrayInterface
* a new one.
*
* @param string $propertyOrMethod The property or method to evaluate.
* @param mixed $value The value to match.
* @param mixed $value The value to match.
*
* @return CollectionInterface<mixed, mixed>
* @return CollectionInterface<T>
*/
public function where(string $propertyOrMethod, $value): self;
/**
* Apply a given callback method on each item of the collection.
*
* This will always leave the original collection untouched and will return
* a new one.
* This will always leave the original collection untouched. The new
* collection is created by mapping the callback to each item of the
* original collection.
*
* See the {@link http://php.net/manual/en/function.array-map.php PHP array_map() documentation}
* for examples of how the `$callback` parameter works.
*
* @param callable $callback A callable to apply to each item of the
* collection.
* @param callable(T):TCallbackReturn $callback A callable to apply to each
* item of the collection.
*
* @return CollectionInterface<mixed, mixed>
* @return CollectionInterface<TCallbackReturn>
*
* @template TCallbackReturn
*/
public function map(callable $callback): self;
@@ -167,10 +176,10 @@ interface CollectionInterface extends ArrayInterface
* Create a new collection with divergent items between current and given
* collection.
*
* @param CollectionInterface<mixed, mixed> $other The collection to check for divergent
* @param CollectionInterface<T> $other The collection to check for divergent
* items.
*
* @return CollectionInterface<mixed, mixed>
* @return CollectionInterface<T>
*/
public function diff(CollectionInterface $other): self;
@@ -178,19 +187,19 @@ interface CollectionInterface extends ArrayInterface
* Create a new collection with intersecting item between current and given
* collection.
*
* @param CollectionInterface<mixed, mixed> $other The collection to check for
* @param CollectionInterface<T> $other The collection to check for
* intersecting items.
*
* @return CollectionInterface<mixed, mixed>
* @return CollectionInterface<T>
*/
public function intersect(CollectionInterface $other): self;
/**
* Merge current items and items of given collections into a new one.
*
* @param CollectionInterface<mixed, mixed> ...$collections The collections to merge.
* @param CollectionInterface<T> ...$collections The collections to merge.
*
* @return CollectionInterface<mixed, mixed>
* @return CollectionInterface<T>
*/
public function merge(CollectionInterface ...$collections): self;
}

View File

@@ -20,6 +20,10 @@ use Ramsey\Collection\Exception\NoSuchElementException;
/**
* This class provides a basic implementation of `DoubleEndedQueueInterface`, to
* minimize the effort required to implement this interface.
*
* @template T
* @template-extends Queue<T>
* @template-implements DoubleEndedQueueInterface<T>
*/
class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
{
@@ -31,19 +35,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
private $tail = -1;
/**
* Sets the given value to the given offset in the queue.
*
* Since arbitrary offsets may not be manipulated in a queue, this method
* serves only to fulfill the `ArrayAccess` interface requirements. It is
* invoked by other operations when adding values to the queue.
*
* @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
*
* @param mixed|null $offset The offset is ignored and is treated as `null`.
* @param mixed $value The value to set at the given offset.
*
* @throws InvalidArgumentException when the value does not match the
* specified type for this queue.
* @inheritDoc
*/
public function offsetSet($offset, $value): void
{
@@ -60,16 +52,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Ensures that the specified element is inserted at the front of this queue.
*
* @see self::offerFirst()
*
* @param mixed $element The element to add to this queue.
*
* @return bool `true` if this queue changed as a result of the call.
*
* @throws InvalidArgumentException when the value does not match the
* specified type for this queue.
* @inheritDoc
*/
public function addFirst($element): bool
{
@@ -88,16 +71,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Ensures that the specified element in inserted at the end of this queue.
*
* @see Queue::add()
*
* @param mixed $element The element to add to this queue.
*
* @return bool `true` if this queue changed as a result of the call.
*
* @throws InvalidArgumentException when the value does not match the
* specified type for this queue.
* @inheritDoc
*/
public function addLast($element): bool
{
@@ -105,13 +79,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Inserts the specified element at the front this queue.
*
* @see self::addFirst()
*
* @param mixed $element The element to add to this queue.
*
* @return bool `true` if the element was added to this queue, else `false`.
* @inheritDoc
*/
public function offerFirst($element): bool
{
@@ -123,14 +91,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Inserts the specified element at the end this queue.
*
* @see self::addLast()
* @see Queue::offer()
*
* @param mixed $element The element to add to this queue.
*
* @return bool `true` if the element was added to this queue, else `false`.
* @inheritDoc
*/
public function offerLast($element): bool
{
@@ -138,17 +99,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Retrieves and removes the head of this queue.
*
* This method differs from `pollFirst()` only in that it throws an
* exception if this queue is empty.
*
* @see self::pollFirst()
* @see Queue::remove()
*
* @return mixed the head of this queue.
*
* @throws NoSuchElementException if this queue is empty.
* @inheritDoc
*/
public function removeFirst()
{
@@ -156,38 +107,21 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Retrieves and removes the tail of this queue.
*
* This method differs from `pollLast()` only in that it throws an exception
* if this queue is empty.
*
* @see self::pollLast()
*
* @return mixed the tail of this queue.
*
* @throws NoSuchElementException if this queue is empty.
* @inheritDoc
*/
public function removeLast()
{
if ($this->count() === 0) {
$tail = $this->pollLast();
if ($tail === null) {
throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
}
$tail = $this[$this->tail];
unset($this[$this->tail]);
$this->tail--;
return $tail;
}
/**
* Retrieves and removes the head of this queue, or returns `null` if this
* queue is empty.
*
* @see self::removeFirst()
*
* @return mixed|null the head of this queue, or `null` if this queue is empty.
* @inheritDoc
*/
public function pollFirst()
{
@@ -195,12 +129,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Retrieves and removes the tail of this queue, or returns `null` if this
* queue is empty.
*
* @see self::removeLast()
*
* @return mixed|null the tail of this queue, or `null` if this queue is empty.
* @inheritDoc
*/
public function pollLast()
{
@@ -217,17 +146,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Retrieves, but does not remove, the head of this queue.
*
* This method differs from `peekFirst()` only in that it throws an
* exception if this queue is empty.
*
* @see self::peekFirst()
* @see Queue::element()
*
* @return mixed the head of this queue.
*
* @throws NoSuchElementException if this queue is empty.
* @inheritDoc
*/
public function firstElement()
{
@@ -235,16 +154,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Retrieves, but does not remove, the tail of this queue.
*
* This method differs from `peekLast()` only in that it throws an exception
* if this queue is empty.
*
* @see self::peekLast()
*
* @return mixed the tail of this queue.
*
* @throws NoSuchElementException if this queue is empty.
* @inheritDoc
*/
public function lastElement()
{
@@ -256,13 +166,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Retrieves, but does not remove, the head of this queue, or returns `null`
* if this queue is empty.
*
* @see self::firstElement()
* @see Queue::peek()
*
* @return mixed|null the head of this queue, or `null` if this queue is empty.
* @inheritDoc
*/
public function peekFirst()
{
@@ -270,12 +174,7 @@ class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
}
/**
* Retrieves, but does not remove, the tail of this queue, or returns `null`
* if this queue is empty.
*
* @see self::lastElement()
*
* @return mixed|null the tail of this queue, or `null` if this queue is empty
* @inheritDoc
*/
public function peekLast()
{

View File

@@ -158,6 +158,9 @@ use Ramsey\Collection\Exception\NoSuchElementException;
* ability to insert nulls. This is so because `null` is used as a special
* return value by various methods to indicated that the double-ended queue is
* empty.
*
* @template T
* @template-extends QueueInterface<T>
*/
interface DoubleEndedQueueInterface extends QueueInterface
{
@@ -168,7 +171,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* When using a capacity-restricted double-ended queue, it is generally
* preferable to use the `offerFirst()` method.
*
* @param mixed $element The element to add to the front of this queue.
* @param T $element The element to add to the front of this queue.
*
* @return bool `true` if this queue changed as a result of the call.
*
@@ -177,6 +180,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* Implementations should use a more-specific exception that extends
* `\RuntimeException`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function addFirst($element): bool;
/**
@@ -188,7 +192,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
*
* This method is equivalent to `add()`.
*
* @param mixed $element The element to add to the end of this queue.
* @param T $element The element to add to the end of this queue.
*
* @return bool `true` if this queue changed as a result of the call.
*
@@ -197,6 +201,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* Implementations should use a more-specific exception that extends
* `\RuntimeException`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function addLast($element): bool;
/**
@@ -207,10 +212,11 @@ interface DoubleEndedQueueInterface extends QueueInterface
* preferable to `addFirst()`, which can fail to insert an element only by
* throwing an exception.
*
* @param mixed $element The element to add to the front of this queue.
* @param T $element The element to add to the front of this queue.
*
* @return bool `true` if the element was added to this queue, else `false`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function offerFirst($element): bool;
/**
@@ -221,10 +227,11 @@ interface DoubleEndedQueueInterface extends QueueInterface
* preferable to `addLast()` which can fail to insert an element only by
* throwing an exception.
*
* @param mixed $element The element to add to the end of this queue.
* @param T $element The element to add to the end of this queue.
*
* @return bool `true` if the element was added to this queue, else `false`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function offerLast($element): bool;
/**
@@ -233,7 +240,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* This method differs from `pollFirst()` only in that it throws an
* exception if this queue is empty.
*
* @return mixed the first element in this queue.
* @return T the first element in this queue.
*
* @throws NoSuchElementException if this queue is empty.
*/
@@ -245,7 +252,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* This method differs from `pollLast()` only in that it throws an exception
* if this queue is empty.
*
* @return mixed the last element in this queue.
* @return T the last element in this queue.
*
* @throws NoSuchElementException if this queue is empty.
*/
@@ -255,7 +262,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* Retrieves and removes the head of this queue, or returns `null` if this
* queue is empty.
*
* @return mixed|null the head of this queue, or `null` if this queue is empty.
* @return T|null the head of this queue, or `null` if this queue is empty.
*/
public function pollFirst();
@@ -263,7 +270,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* Retrieves and removes the tail of this queue, or returns `null` if this
* queue is empty.
*
* @return mixed|null the tail of this queue, or `null` if this queue is empty.
* @return T|null the tail of this queue, or `null` if this queue is empty.
*/
public function pollLast();
@@ -273,7 +280,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* This method differs from `peekFirst()` only in that it throws an
* exception if this queue is empty.
*
* @return mixed the head of this queue.
* @return T the head of this queue.
*
* @throws NoSuchElementException if this queue is empty.
*/
@@ -285,7 +292,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* This method differs from `peekLast()` only in that it throws an exception
* if this queue is empty.
*
* @return mixed the tail of this queue.
* @return T the tail of this queue.
*
* @throws NoSuchElementException if this queue is empty.
*/
@@ -295,7 +302,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* Retrieves, but does not remove, the head of this queue, or returns `null`
* if this queue is empty.
*
* @return mixed|null the head of this queue, or `null` if this queue is empty.
* @return T|null the head of this queue, or `null` if this queue is empty.
*/
public function peekFirst();
@@ -303,7 +310,7 @@ interface DoubleEndedQueueInterface extends QueueInterface
* Retrieves, but does not remove, the tail of this queue, or returns `null`
* if this queue is empty.
*
* @return mixed|null the tail of this queue, or `null` if this queue is empty.
* @return T|null the tail of this queue, or `null` if this queue is empty.
*/
public function peekLast();
}

View File

@@ -16,6 +16,8 @@ namespace Ramsey\Collection;
/**
* `GenericArray` represents a standard array object.
*
* @template-extends AbstractArray<mixed>
*/
class GenericArray extends AbstractArray
{

View File

@@ -24,23 +24,22 @@ use function in_array;
/**
* This class provides a basic implementation of `MapInterface`, to minimize the
* effort required to implement this interface.
*
* @template T
* @template-extends AbstractArray<T>
* @template-implements MapInterface<T>
*/
abstract class AbstractMap extends AbstractArray implements MapInterface
{
/**
* Sets the given value to the given offset in the map.
*
* @param mixed $offset The offset to set.
* @param mixed $value The value to set at the given offset.
*
* @throws InvalidArgumentException if the offset provided is `null`.
* @inheritDoc
*/
public function offsetSet($offset, $value): void
{
if ($offset === null) {
throw new InvalidArgumentException(
'Map elements are key/value pairs; a key must be provided for '
. 'value ' . $value
. 'value ' . var_export($value, true)
);
}
@@ -48,9 +47,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Returns `true` if this map contains a mapping for the specified key.
*
* @param mixed $key The key to check in the map.
* @inheritDoc
*/
public function containsKey($key): bool
{
@@ -58,11 +55,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Returns `true` if this map maps one or more keys to the specified value.
*
* This performs a strict type check on the value.
*
* @param mixed $value The value to check in the map.
* @inheritDoc
*/
public function containsValue($value): bool
{
@@ -70,9 +63,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Return an array of the keys contained in this map.
*
* @return mixed[]
* @inheritDoc
*/
public function keys(): array
{
@@ -80,14 +71,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Returns the value to which the specified key is mapped, `null` if this
* map contains no mapping for the key, or (optionally) `$defaultValue` if
* this map contains no mapping for the key.
*
* @param mixed $key The key to return from the map.
* @param mixed $defaultValue The default value to use if `$key` is not found.
*
* @return mixed|null the value or `null` if the key could not be found.
* @inheritDoc
*/
public function get($key, $defaultValue = null)
{
@@ -99,16 +83,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Associates the specified value with the specified key in this map.
*
* If the map previously contained a mapping for the key, the old value is
* replaced by the specified value.
*
* @param mixed $key The key to put or replace in the map.
* @param mixed $value The value to store at `$key`.
*
* @return mixed|null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
* @inheritDoc
*/
public function put($key, $value)
{
@@ -119,17 +94,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Associates the specified value with the specified key in this map only if
* it is not already set.
*
* If there is already a value associated with `$key`, this returns that
* value without replacing it.
*
* @param mixed $key The key to put in the map.
* @param mixed $value The value to store at `$key`.
*
* @return mixed|null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
* @inheritDoc
*/
public function putIfAbsent($key, $value)
{
@@ -143,12 +108,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Removes the mapping for a key from this map if it is present.
*
* @param mixed $key The key to remove from the map.
*
* @return mixed|null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
* @inheritDoc
*/
public function remove($key)
{
@@ -159,15 +119,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Removes the entry for the specified key only if it is currently mapped to
* the specified value.
*
* This performs a strict type check on the value.
*
* @param mixed $key The key to remove from the map.
* @param mixed $value The value to match.
*
* @return bool true if the value was removed.
* @inheritDoc
*/
public function removeIf($key, $value): bool
{
@@ -181,14 +133,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Replaces the entry for the specified key only if it is currently mapped
* to some value.
*
* @param mixed $key The key to replace.
* @param mixed $value The value to set at `$key`.
*
* @return mixed|null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
* @inheritDoc
*/
public function replace($key, $value)
{
@@ -202,16 +147,7 @@ abstract class AbstractMap extends AbstractArray implements MapInterface
}
/**
* Replaces the entry for the specified key only if currently mapped to the
* specified value.
*
* This performs a strict type check on the value.
*
* @param mixed $key The key to remove from the map.
* @param mixed $oldValue The value to match.
* @param mixed $newValue The value to use as a replacement.
*
* @return bool true if the value was replaced.
* @inheritDoc
*/
public function replaceIf($key, $oldValue, $newValue): bool
{

View File

@@ -21,6 +21,12 @@ use Ramsey\Collection\Tool\ValueToStringTrait;
/**
* This class provides a basic implementation of `TypedMapInterface`, to
* minimize the effort required to implement this interface.
*
* @phpstan-ignore-next-line
* @template K as array-key
* @template T
* @template-extends AbstractMap<T>
* @template-implements TypedMapInterface<T>
*/
abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
{
@@ -28,16 +34,22 @@ abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
use ValueToStringTrait;
/**
* Sets the given value to the given offset in the map.
* @param K|null $offset
* @param T $value
*
* @param mixed $offset The offset to set.
* @param mixed $value The value to set at the given offset.
* @inheritDoc
*
* @throws InvalidArgumentException if the offset or value do not match the
* expected types.
* @psalm-suppress MoreSpecificImplementedParamType
*/
public function offsetSet($offset, $value): void
{
if ($offset === null) {
throw new InvalidArgumentException(
'Map elements are key/value pairs; a key must be provided for '
. 'value ' . var_export($value, true)
);
}
if ($this->checkType($this->getKeyType(), $offset) === false) {
throw new InvalidArgumentException(
'Key must be of type ' . $this->getKeyType() . '; key is '

View File

@@ -16,6 +16,9 @@ namespace Ramsey\Collection\Map;
/**
* `AssociativeArrayMap` represents a standard associative array object.
*
* @template T
* @template-extends AbstractMap<T>
*/
class AssociativeArrayMap extends AbstractMap
{

View File

@@ -20,13 +20,16 @@ use Ramsey\Collection\ArrayInterface;
* An object that maps keys to values.
*
* A map cannot contain duplicate keys; each key can map to at most one value.
*
* @template T
* @template-extends ArrayInterface<T>
*/
interface MapInterface extends ArrayInterface
{
/**
* Returns `true` if this map contains a mapping for the specified key.
*
* @param mixed $key The key to check in the map.
* @param array-key $key The key to check in the map.
*/
public function containsKey($key): bool;
@@ -35,14 +38,15 @@ interface MapInterface extends ArrayInterface
*
* This performs a strict type check on the value.
*
* @param mixed $value The value to check in the map.
* @param T $value The value to check in the map.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function containsValue($value): bool;
/**
* Return an array of the keys contained in this map.
*
* @return mixed[]
* @return list<array-key>
*/
public function keys(): array;
@@ -51,11 +55,12 @@ interface MapInterface extends ArrayInterface
* map contains no mapping for the key, or (optionally) `$defaultValue` if
* this map contains no mapping for the key.
*
* @param mixed $key The key to return from the map.
* @param mixed $defaultValue The default value to use if `$key` is not found.
* @param array-key $key The key to return from the map.
* @param T|null $defaultValue The default value to use if `$key` is not found.
*
* @return mixed|null the value or `null` if the key could not be found.
* @return T|null the value or `null` if the key could not be found.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function get($key, $defaultValue = null);
/**
@@ -64,12 +69,13 @@ interface MapInterface extends ArrayInterface
* If the map previously contained a mapping for the key, the old value is
* replaced by the specified value.
*
* @param mixed $key The key to put or replace in the map.
* @param mixed $value The value to store at `$key`.
* @param array-key $key The key to put or replace in the map.
* @param T $value The value to store at `$key`.
*
* @return mixed|null the previous value associated with key, or `null` if
* @return T|null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function put($key, $value);
/**
@@ -79,22 +85,24 @@ interface MapInterface extends ArrayInterface
* If there is already a value associated with `$key`, this returns that
* value without replacing it.
*
* @param mixed $key The key to put in the map.
* @param mixed $value The value to store at `$key`.
* @param array-key $key The key to put in the map.
* @param T $value The value to store at `$key`.
*
* @return mixed|null the previous value associated with key, or `null` if
* @return T|null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function putIfAbsent($key, $value);
/**
* Removes the mapping for a key from this map if it is present.
*
* @param mixed $key The key to remove from the map.
* @param array-key $key The key to remove from the map.
*
* @return mixed|null the previous value associated with key, or `null` if
* @return T|null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function remove($key);
/**
@@ -103,23 +111,25 @@ interface MapInterface extends ArrayInterface
*
* This performs a strict type check on the value.
*
* @param mixed $key The key to remove from the map.
* @param mixed $value The value to match.
* @param array-key $key The key to remove from the map.
* @param T $value The value to match.
*
* @return bool true if the value was removed.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function removeIf($key, $value): bool;
/**
* Replaces the entry for the specified key only if it is currently mapped
* to some value.
*
* @param mixed $key The key to replace.
* @param mixed $value The value to set at `$key`.
* @param array-key $key The key to replace.
* @param T $value The value to set at `$key`.
*
* @return mixed|null the previous value associated with key, or `null` if
* @return T|null the previous value associated with key, or `null` if
* there was no mapping for `$key`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function replace($key, $value);
/**
@@ -128,11 +138,12 @@ interface MapInterface extends ArrayInterface
*
* This performs a strict type check on the value.
*
* @param mixed $key The key to remove from the map.
* @param mixed $oldValue The value to match.
* @param mixed $newValue The value to use as a replacement.
* @param array-key $key The key to remove from the map.
* @param T $oldValue The value to match.
* @param T $newValue The value to use as a replacement.
*
* @return bool true if the value was replaced.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function replaceIf($key, $oldValue, $newValue): bool;
}

View File

@@ -25,6 +25,8 @@ use function is_int;
/**
* `NamedParameterMap` represents a mapping of values to a set of named keys
* that may optionally be typed
*
* @template-extends AbstractMap<mixed>
*/
class NamedParameterMap extends AbstractMap
{
@@ -34,15 +36,15 @@ class NamedParameterMap extends AbstractMap
/**
* Named parameters defined for this map.
*
* @var array<mixed, string>
* @var array<string, string>
*/
protected $namedParameters;
/**
* Constructs a new `NamedParameterMap`.
*
* @param array<mixed, string> $namedParameters The named parameters defined for this map.
* @param mixed[] $data An initial set of data to set on this map.
* @param array<array-key, string> $namedParameters The named parameters defined for this map.
* @param array<array-key, mixed> $data An initial set of data to set on this map.
*/
public function __construct(array $namedParameters, array $data = [])
{
@@ -53,7 +55,7 @@ class NamedParameterMap extends AbstractMap
/**
* Returns named parameters set for this `NamedParameterMap`.
*
* @return array<mixed, string>
* @return array<string, string>
*/
public function getNamedParameters(): array
{
@@ -61,17 +63,17 @@ class NamedParameterMap extends AbstractMap
}
/**
* Sets the given value to the given offset in the map.
*
* @param mixed $offset The offset to set.
* @param mixed $value The value to set at the given offset.
*
* @throws InvalidArgumentException if the offset provided is not a
* defined named parameter, or if the value is not of the type defined
* for the given named parameter.
* @inheritDoc
*/
public function offsetSet($offset, $value): void
{
if ($offset === null) {
throw new InvalidArgumentException(
'Map elements are key/value pairs; a key must be provided for '
. 'value ' . var_export($value, true)
);
}
if (!array_key_exists($offset, $this->namedParameters)) {
throw new InvalidArgumentException(
'Attempting to set value for unconfigured parameter \''
@@ -94,9 +96,9 @@ class NamedParameterMap extends AbstractMap
* Given an array of named parameters, constructs a proper mapping of
* named parameters to types.
*
* @param array<mixed, string> $namedParameters The named parameters to filter.
* @param array<array-key, string> $namedParameters The named parameters to filter.
*
* @return array<mixed, string>
* @return array<string, string>
*/
protected function filterNamedParameters(array $namedParameters): array
{
@@ -105,11 +107,11 @@ class NamedParameterMap extends AbstractMap
foreach ($namedParameters as $key => $value) {
if (is_int($key)) {
$names[] = (string) $value;
$names[] = $value;
$types[] = 'mixed';
} else {
$names[] = $key;
$types[] = (string) $value;
$types[] = $value;
}
}

View File

@@ -79,6 +79,11 @@ use Ramsey\Collection\Tool\TypeTrait;
* }
* }
* ```
*
* @phpstan-ignore-next-line
* @template K as array-key
* @template T
* @template-extends AbstractTypedMap<K, T>
*/
class TypedMap extends AbstractTypedMap
{
@@ -97,7 +102,7 @@ class TypedMap extends AbstractTypedMap
/**
* The data type of values stored in this collection.
*
* A map values's type is immutable once it is set. For this reason, this
* A map value's type is immutable once it is set. For this reason, this
* property is set private.
*
* @var string data type of the map value.
@@ -110,7 +115,7 @@ class TypedMap extends AbstractTypedMap
*
* @param string $keyType The data type of the map's keys.
* @param string $valueType The data type of the map's values.
* @param mixed[] $data The initial data to set for this map.
* @param array<K, T> $data The initial data to set for this map.
*/
public function __construct(string $keyType, string $valueType, array $data = [])
{
@@ -119,17 +124,11 @@ class TypedMap extends AbstractTypedMap
parent::__construct($data);
}
/**
* Return the type used on the key.
*/
public function getKeyType(): string
{
return $this->keyType;
}
/**
* Return the type forced on the values.
*/
public function getValueType(): string
{
return $this->valueType;

View File

@@ -17,6 +17,9 @@ namespace Ramsey\Collection\Map;
/**
* A `TypedMapInterface` represents a map of elements where key and value are
* typed.
*
* @template T
* @template-extends MapInterface<T>
*/
interface TypedMapInterface extends MapInterface
{

View File

@@ -22,6 +22,10 @@ use Ramsey\Collection\Tool\ValueToStringTrait;
/**
* This class provides a basic implementation of `QueueInterface`, to minimize
* the effort required to implement this interface.
*
* @template T
* @template-extends AbstractArray<T>
* @template-implements QueueInterface<T>
*/
class Queue extends AbstractArray implements QueueInterface
{
@@ -50,7 +54,7 @@ class Queue extends AbstractArray implements QueueInterface
* specified data.
*
* @param string $queueType The type (FQCN) associated with this queue.
* @param mixed[] $data The initial items to store in the collection.
* @param array<array-key, T> $data The initial items to store in the collection.
*/
public function __construct(string $queueType, array $data = [])
{
@@ -59,19 +63,11 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
* Sets the given value to the given offset in the queue.
* {@inheritDoc}
*
* Since arbitrary offsets may not be manipulated in a queue, this method
* serves only to fulfill the `ArrayAccess` interface requirements. It is
* invoked by other operations when adding values to the queue.
*
* @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
*
* @param mixed|null $offset The offset is ignored and is treated as `null`.
* @param mixed $value The value to set at the given offset.
*
* @throws InvalidArgumentException when the value does not match the
* specified type for this queue.
*/
public function offsetSet($offset, $value): void
{
@@ -86,19 +82,7 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
* Ensures that this queue contains the specified element.
*
* This method differs from `offer()` only in that it throws an exception if
* it cannot add the element to the queue.
*
* @see self::offer()
*
* @param mixed $element The element to add to this queue.
*
* @return bool `true` if this queue changed as a result of the call.
*
* @throws InvalidArgumentException when the element does not match the
* specified type for this queue.
* @inheritDoc
*/
public function add($element): bool
{
@@ -108,39 +92,23 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
* Retrieves, but does not remove, the head of this queue.
*
* This method differs from `peek()` only in that it throws an exception if
* this queue is empty.
*
* @see self::peek()
*
* @return mixed the head of this queue.
*
* @throws NoSuchElementException if this queue is empty.
* @inheritDoc
*/
public function element()
{
if ($this->count() === 0) {
$element = $this->peek();
if ($element === null) {
throw new NoSuchElementException(
'Can\'t return element from Queue. Queue is empty.'
);
}
return $this[$this->index];
return $element;
}
/**
* Inserts the specified element into this queue.
*
* This method differs from `add()` only in that it does not throw an
* exception if it cannot add the element to the queue.
*
* @see self::add()
*
* @param mixed $element The element to add to this queue.
*
* @return bool `true` if the element was added to this queue, else `false`.
* @inheritDoc
*/
public function offer($element): bool
{
@@ -152,12 +120,7 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
* Retrieves, but does not remove, the head of this queue, or returns `null`
* if this queue is empty.
*
* @see self::element()
*
* @return mixed|null the head of this queue, or `null` if this queue is empty.
* @inheritDoc
*/
public function peek()
{
@@ -169,12 +132,7 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
* Retrieves and removes the head of this queue, or returns `null`
* if this queue is empty.
*
* @see self::remove()
*
* @return mixed|null the head of this queue, or `null` if this queue is empty.
* @inheritDoc
*/
public function poll()
{
@@ -191,34 +149,19 @@ class Queue extends AbstractArray implements QueueInterface
}
/**
* Retrieves and removes the head of this queue.
*
* This method differs from `poll()` only in that it throws an exception if
* this queue is empty.
*
* @see self::poll()
*
* @return mixed the head of this queue.
*
* @throws NoSuchElementException if this queue is empty.
* @inheritDoc
*/
public function remove()
{
if ($this->count() === 0) {
$head = $this->poll();
if ($head === null) {
throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
}
$head = $this[$this->index];
unset($this[$this->index]);
$this->index++;
return $head;
}
/**
* Returns the type associated with this queue.
*/
public function getType(): string
{
return $this->queueType;

View File

@@ -92,6 +92,9 @@ use Ramsey\Collection\Exception\NoSuchElementException;
* Even in the implementations that permit it, `null` should not be inserted
* into a queue, as `null` is also used as a special return value by the
* `poll()` method to indicate that the queue contains no elements.
*
* @template T
* @template-extends ArrayInterface<T>
*/
interface QueueInterface extends ArrayInterface
{
@@ -116,7 +119,7 @@ interface QueueInterface extends ArrayInterface
*
* @see self::offer()
*
* @param mixed $element The element to add to this queue.
* @param T $element The element to add to this queue.
*
* @return bool `true` if this queue changed as a result of the call.
*
@@ -125,6 +128,7 @@ interface QueueInterface extends ArrayInterface
* Implementations should use a more-specific exception that extends
* `\RuntimeException`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function add($element): bool;
/**
@@ -135,7 +139,7 @@ interface QueueInterface extends ArrayInterface
*
* @see self::peek()
*
* @return mixed the head of this queue.
* @return T the head of this queue.
*
* @throws NoSuchElementException if this queue is empty.
*/
@@ -151,10 +155,11 @@ interface QueueInterface extends ArrayInterface
*
* @see self::add()
*
* @param mixed $element The element to add to this queue.
* @param T $element The element to add to this queue.
*
* @return bool `true` if the element was added to this queue, else `false`.
*/
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function offer($element): bool;
/**
@@ -163,7 +168,7 @@ interface QueueInterface extends ArrayInterface
*
* @see self::element()
*
* @return mixed|null the head of this queue, or `null` if this queue is empty.
* @return T|null the head of this queue, or `null` if this queue is empty.
*/
public function peek();
@@ -173,7 +178,7 @@ interface QueueInterface extends ArrayInterface
*
* @see self::remove()
*
* @return mixed|null the head of this queue, or `null` if this queue is empty.
* @return T|null the head of this queue, or `null` if this queue is empty.
*/
public function poll();
@@ -185,7 +190,7 @@ interface QueueInterface extends ArrayInterface
*
* @see self::poll()
*
* @return mixed the head of this queue.
* @return T the head of this queue.
*
* @throws NoSuchElementException if this queue is empty.
*/

View File

@@ -34,6 +34,9 @@ namespace Ramsey\Collection;
* $bar = new \My\Foo();
* $set->add($bar); // returns TRUE, $bar !== $foo
* ```
*
* @template T
* @template-extends AbstractSet<T>
*/
class Set extends AbstractSet
{
@@ -51,7 +54,7 @@ class Set extends AbstractSet
* specified data.
*
* @param string $setType The type (FQCN) associated with this set.
* @param mixed[] $data The initial items to store in the set.
* @param array<array-key, T> $data The initial items to store in the set.
*/
public function __construct(string $setType, array $data = [])
{
@@ -59,9 +62,6 @@ class Set extends AbstractSet
parent::__construct($data);
}
/**
* Returns the type associated with this set.
*/
public function getType(): string
{
return $this->setType;

View File

@@ -29,7 +29,7 @@ trait ValueExtractorTrait
/**
* Extracts the value of the given property or method from the object.
*
* @param object $object The object to extract the value from.
* @param mixed $object The object to extract the value from.
* @param string $propertyOrMethod The property or method for which the
* value should be extracted.
*
@@ -37,8 +37,12 @@ trait ValueExtractorTrait
*
* @throws ValueExtractionException if the method or property is not defined.
*/
protected function extractValue(object $object, string $propertyOrMethod)
protected function extractValue($object, string $propertyOrMethod)
{
if (!is_object($object)) {
throw new ValueExtractionException('Unable to extract a value from a non-object');
}
if (property_exists($object, $propertyOrMethod)) {
return $object->$propertyOrMethod;
}

View File

@@ -71,7 +71,12 @@ trait ValueToStringTrait
return '(' . get_resource_type($value) . ' resource #' . (int) $value . ')';
}
// after this line $value is an object since is not null, scalar, array or resource
// If we don't know what it is, use var_export().
if (!is_object($value)) {
return '(' . var_export($value, true) . ')';
}
// From here, $value should be an object.
// __toString() is implemented
if (is_callable([$value, '__toString'])) {