Merge remote-tracking branch 'origin/1.7.x' into address-move-away-from-master

This commit is contained in:
Grégoire Paris
2021-01-19 08:35:58 +01:00
39 changed files with 672 additions and 4819 deletions

3
.gitattributes vendored
View File

@@ -1,8 +1,7 @@
/tests export-ignore
/.github export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.scrutinizer.yml export-ignore
.travis.yml export-ignore
phpunit.xml.dist export-ignore
/phpcs.xml.dist export-ignore
composer.lock export-ignore

40
.github/workflows/coding-standards.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: "Coding Standards"
on:
pull_request:
branches:
- "*.x"
- "master"
push:
branches:
- "*.x"
- "master"
jobs:
coding-standards:
name: "Coding Standards"
runs-on: "ubuntu-20.04"
strategy:
matrix:
php-version:
- "7.4"
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
tools: "cs2pr"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v1"
# https://github.com/doctrine/.github/issues/3
- name: "Run PHP_CodeSniffer"
run: "vendor/bin/phpcs -q --no-colors --report=checkstyle | cs2pr"

View File

@@ -0,0 +1,83 @@
name: "Continuous Integration"
on:
pull_request:
branches:
- "*.x"
- "master"
push:
branches:
- "*.x"
- "master"
env:
fail-fast: true
jobs:
phpunit:
name: "PHPUnit"
runs-on: "ubuntu-20.04"
strategy:
matrix:
php-version:
- "7.2"
- "7.3"
- "7.4"
- "8.0"
deps:
- "highest"
include:
- php-version: "7.2"
deps: "lowest"
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
with:
fetch-depth: 2
- name: "Install PHP with PCOV"
uses: "shivammathur/setup-php@v2"
with:
php-version: "${{ matrix.php-version }}"
coverage: "pcov"
ini-values: "zend.assertions=1"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v1"
with:
dependency-versions: "${{ matrix.deps }}"
- name: "Run PHPUnit"
run: "vendor/bin/phpunit --coverage-clover=coverage.xml"
- name: "Upload coverage file"
uses: "actions/upload-artifact@v2"
with:
name: "phpunit-${{ matrix.php-version }}.coverage"
path: "coverage.xml"
upload_coverage:
name: "Upload coverage to Codecov"
runs-on: "ubuntu-20.04"
needs:
- "phpunit"
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
with:
fetch-depth: 2
- name: "Download coverage files"
uses: "actions/download-artifact@v2"
with:
path: "reports"
- name: "Upload to Codecov"
uses: "codecov/codecov-action@v1"
with:
directory: "reports"

View File

@@ -0,0 +1,45 @@
name: "Automatic Releases"
on:
milestone:
types:
- "closed"
jobs:
release:
name: "Git tag, release & create merge-up PR"
runs-on: "ubuntu-20.04"
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
- name: "Release"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:release"
env:
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
- name: "Create Merge-Up Pull Request"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:create-merge-up-pull-request"
env:
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}
- name: "Create new milestones"
uses: "laminas/automatic-releases@v1"
with:
command-name: "laminas:automatic-releases:create-milestones"
env:
"GITHUB_TOKEN": ${{ secrets.GITHUB_TOKEN }}
"SIGNING_SECRET_KEY": ${{ secrets.SIGNING_SECRET_KEY }}
"GIT_AUTHOR_NAME": ${{ secrets.GIT_AUTHOR_NAME }}
"GIT_AUTHOR_EMAIL": ${{ secrets.GIT_AUTHOR_EMAIL }}

63
.github/workflows/static-analysis.yml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: "Static Analysis"
on:
pull_request:
branches:
- "*.x"
- "master"
push:
branches:
- "*.x"
- "master"
jobs:
static-analysis-phpstan:
name: "Static Analysis with PHPStan"
runs-on: "ubuntu-20.04"
strategy:
matrix:
php-version:
- "7.4"
steps:
- name: "Checkout code"
uses: "actions/checkout@v2"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v1"
- name: "Run a static analysis with phpstan/phpstan"
run: "vendor/bin/phpstan analyse"
static-analysis-psalm:
name: "Static Analysis with Psalm"
runs-on: "ubuntu-20.04"
strategy:
matrix:
php-version:
- "7.4"
steps:
- name: "Checkout code"
uses: "actions/checkout@v2"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v1"
- name: "Run a static analysis with vimeo/psalm"
run: "vendor/bin/psalm --show-info=false --stats --output-format=github --threads=$(nproc)"

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/composer.lock
/vendor
/build
/phpcs.xml

View File

@@ -1,60 +0,0 @@
dist: trusty
sudo: false
language: php
cache:
directories:
- $HOME/.composer/cache
php:
- 7.2
- 7.3
- 7.4
before_install:
- mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{,.disabled} || echo "xdebug not available"
- travis_retry composer self-update
install:
- rm composer.lock
- travis_retry composer -n --prefer-source install
script: ./vendor/bin/phpunit
jobs:
allow_failures:
- php: nightly
include:
- stage: Test
php: nightly
before_install:
- composer config platform.php 7.4.99
install:
- travis_retry composer update --prefer-dist
- stage: Test
env: COVERAGE
before_script:
- mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{.disabled,}
- if [[ ! $(php -m | grep -si xdebug) ]]; then echo "xdebug required for coverage"; exit 1; fi
script:
- ./vendor/bin/phpunit --coverage-clover clover.xml --coverage-xml=build/coverage/coverage-xml --log-junit=build/coverage/phpunit.junit.xml
- ./vendor/bin/infection --coverage=build/coverage --threads=4 --min-msi=82 --min-covered-msi=84
after_script:
- bash <(curl -s https://codecov.io/bash)
- stage: Code Quality
env: CODING_STANDARDS
install: travis_retry composer install --prefer-dist
script: ./vendor/bin/phpcs
- stage: Code Quality
env: STATIC_ANALYSIS
install: travis_retry composer install --prefer-dist
script: vendor/bin/phpstan analyse
- stage: Code Quality
env: STATIC_ANALYSIS
install: travis_retry composer install --prefer-dist
script: vendor/bin/psalm

View File

@@ -30,11 +30,11 @@ curl -sS https://getcomposer.org/installer | php --
./composer.phar install
```
## Travis
## Github Actions
We automatically run your pull request through [Travis CI](https://www.travis-ci.org)
against supported PHP versions. If you break the tests, we cannot merge your code,
so please make sure that your code is working before opening up a Pull-Request.
We automatically run your pull request through Github Actions against supported
PHP versions. If you break the tests, we cannot merge your code, so please make
sure that your code is working before opening up a Pull-Request.
## Getting merged

View File

@@ -1,7 +1,7 @@
# Doctrine Collections
[![Build Status](https://travis-ci.org/doctrine/collections.svg?branch=2.0.x)](https://travis-ci.org/doctrine/collections)
[![Code Coverage](https://codecov.io/gh/doctrine/collections/branch/cache/graph/badge.svg)](https://codecov.io/gh/doctrine/collections/branch/2.0.x)
[![Build Status](https://github.com/doctrine/collections/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/collections/actions)
[![Code Coverage](https://codecov.io/gh/doctrine/collections/branch/2.0.x/graph/badge.svg)](https://codecov.io/gh/doctrine/collections/branch/2.0.x)
Collections Abstraction library

View File

@@ -21,12 +21,12 @@
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^6.0",
"infection/infection": "^0.14.2",
"phpstan/phpstan": "^0.11",
"phpstan/phpstan-phpunit": "^0.11",
"phpunit/phpunit": "^8.0",
"vimeo/psalm": "^3.8.1",
"doctrine/coding-standard": "^6.0 || ^8.0",
"infection/infection": "^0.14.2 || ^0.20.2",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5",
"vimeo/psalm": "^4.2.1",
"ext-json": "*"
},
"config": {

4425
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -12,8 +12,8 @@ arrays of data. Here is an example using the simple
$collection = new ArrayCollection([1, 2, 3]);
$filteredCollection = $collection->filter(function($count) {
return $count > 1;
$filteredCollection = $collection->filter(function($element) {
return $element > 1;
}); // [2, 3]
Collection Methods
@@ -151,13 +151,14 @@ Tests for the existence of an element that satisfies the given predicate.
filter
------
Returns all the elements of this collection that satisfy the predicate. The order of the elements is preserved.
Returns all the elements of this collection for which your callback function returns `true`.
The order and keys of the elements are preserved.
.. code-block:: php
$collection = new ArrayCollection([1, 2, 3]);
$filteredCollection = $collection->filter(function($count) {
return $count > 1;
$filteredCollection = $collection->filter(function($element) {
return $element > 1;
}); // [2, 3]
forAll

View File

@@ -21,17 +21,14 @@ abstract class AbstractLazyCollection implements Collection
* The backed collection to use
*
* @psalm-var Collection<TKey,T>
* @var Collection
* @var Collection<mixed>
*/
protected $collection;
/** @var bool */
protected $initialized = false;
/**
* {@inheritDoc}
*/
public function count() : int
public function count(): int
{
$this->initialize();
@@ -41,17 +38,14 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function add($element) : bool
public function add($element): bool
{
$this->initialize();
return $this->collection->add($element);
}
/**
* {@inheritDoc}
*/
public function clear() : void
public function clear(): void
{
$this->initialize();
$this->collection->clear();
@@ -60,17 +54,14 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function contains($element) : bool
public function contains($element): bool
{
$this->initialize();
return $this->collection->contains($element);
}
/**
* {@inheritDoc}
*/
public function isEmpty() : bool
public function isEmpty(): bool
{
$this->initialize();
@@ -90,7 +81,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function removeElement($element) : bool
public function removeElement($element): bool
{
$this->initialize();
@@ -100,7 +91,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function containsKey($key) : bool
public function containsKey($key): bool
{
$this->initialize();
@@ -120,7 +111,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function getKeys() : array
public function getKeys(): array
{
$this->initialize();
@@ -130,7 +121,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function getValues() : array
public function getValues(): array
{
$this->initialize();
@@ -140,7 +131,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function set($key, $value) : void
public function set($key, $value): void
{
$this->initialize();
$this->collection->set($key, $value);
@@ -149,7 +140,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function toArray() : array
public function toArray(): array
{
$this->initialize();
@@ -206,10 +197,7 @@ abstract class AbstractLazyCollection implements Collection
return $this->collection->next();
}
/**
* {@inheritDoc}
*/
public function exists(Closure $p) : bool
public function exists(Closure $p): bool
{
$this->initialize();
@@ -217,19 +205,18 @@ abstract class AbstractLazyCollection implements Collection
}
/**
* {@inheritDoc}
* @return Collection<mixed>
*
* @psalm-return Collection<TKey, T>
*/
public function filter(Closure $p) : Collection
public function filter(Closure $p): Collection
{
$this->initialize();
return $this->collection->filter($p);
}
/**
* {@inheritDoc}
*/
public function forAll(Closure $p) : bool
public function forAll(Closure $p): bool
{
$this->initialize();
@@ -237,9 +224,13 @@ abstract class AbstractLazyCollection implements Collection
}
/**
* {@inheritDoc}
* @return Collection<mixed>
*
* @psalm-template U
* @psalm-param Closure(T=):U $func
* @psalm-return Collection<TKey, U>
*/
public function map(Closure $func) : Collection
public function map(Closure $func): Collection
{
$this->initialize();
@@ -249,7 +240,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function partition(Closure $p) : array
public function partition(Closure $p): array
{
$this->initialize();
@@ -269,7 +260,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* {@inheritDoc}
*/
public function slice(int $offset, ?int $length = null) : array
public function slice(int $offset, ?int $length = null): array
{
$this->initialize();
@@ -277,9 +268,11 @@ abstract class AbstractLazyCollection implements Collection
}
/**
* {@inheritDoc}
* @return Traversable<mixed>
*
* @psalm-return Traversable<TKey, T>
*/
public function getIterator() : Traversable
public function getIterator(): Traversable
{
$this->initialize();
@@ -293,7 +286,7 @@ abstract class AbstractLazyCollection implements Collection
*
* @psalm-param TKey $offset
*/
public function offsetExists($offset) : bool
public function offsetExists($offset): bool
{
$this->initialize();
@@ -324,7 +317,7 @@ abstract class AbstractLazyCollection implements Collection
*
* @psalm-param TKey $offset
*/
public function offsetSet($offset, $value) : void
public function offsetSet($offset, $value): void
{
$this->initialize();
$this->collection->offsetSet($offset, $value);
@@ -337,7 +330,7 @@ abstract class AbstractLazyCollection implements Collection
*
* @psalm-param TKey $offset
*/
public function offsetUnset($offset) : void
public function offsetUnset($offset): void
{
$this->initialize();
$this->collection->offsetUnset($offset);
@@ -346,7 +339,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* Is the lazy collection already initialized?
*/
public function isInitialized() : bool
public function isInitialized(): bool
{
return $this->initialized;
}
@@ -354,7 +347,7 @@ abstract class AbstractLazyCollection implements Collection
/**
* Initialize the collection
*/
protected function initialize() : void
protected function initialize(): void
{
if ($this->initialized) {
return;
@@ -367,5 +360,5 @@ abstract class AbstractLazyCollection implements Collection
/**
* Do the initialization logic
*/
abstract protected function doInitialize() : void;
abstract protected function doInitialize(): void;
}

View File

@@ -8,7 +8,7 @@ use ArrayIterator;
use Closure;
use Doctrine\Common\Collections\Expr\ClosureExpressionVisitor;
use Traversable;
use const ARRAY_FILTER_USE_BOTH;
use function array_filter;
use function array_key_exists;
use function array_keys;
@@ -28,6 +28,8 @@ use function reset;
use function spl_object_hash;
use function uasort;
use const ARRAY_FILTER_USE_BOTH;
/**
* An ArrayCollection is a Collection implementation that wraps a regular PHP array.
*
@@ -41,6 +43,7 @@ use function uasort;
* @psalm-template T
* @template-implements Collection<TKey,T>
* @template-implements Selectable<TKey,T>
* @psalm-consistent-constructor
*/
class ArrayCollection implements Collection, Selectable
{
@@ -48,7 +51,7 @@ class ArrayCollection implements Collection, Selectable
* An array containing the entries of this collection.
*
* @psalm-var array<TKey,T>
* @var array
* @var mixed[]
*/
private $elements = [];
@@ -67,7 +70,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
public function toArray() : array
public function toArray(): array
{
return $this->elements;
}
@@ -90,8 +93,12 @@ class ArrayCollection implements Collection, Selectable
*
* @return static
*
* @psalm-param array<TKey,T> $elements
* @psalm-return static<TKey,T>
* @psalm-template K of array-key
* @psalm-template V
* @phpstan-template K
*
* @psalm-param array<K,V> $elements
* @psalm-return static<K,V>
*/
protected function createFrom(array $elements)
{
@@ -148,7 +155,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
public function removeElement($element) : bool
public function removeElement($element): bool
{
$key = array_search($element, $this->elements, true);
@@ -170,7 +177,7 @@ class ArrayCollection implements Collection, Selectable
*
* @psalm-param TKey $offset
*/
public function offsetExists($offset) : bool
public function offsetExists($offset): bool
{
return $this->containsKey($offset);
}
@@ -196,8 +203,10 @@ class ArrayCollection implements Collection, Selectable
*
* @param int|string|null $offset
* @param mixed $value
*
* @psalm-param TKey|null $offset
*/
public function offsetSet($offset, $value) : void
public function offsetSet($offset, $value): void
{
if ($offset === null) {
$this->add($value);
@@ -217,7 +226,7 @@ class ArrayCollection implements Collection, Selectable
*
* @psalm-param TKey $offset
*/
public function offsetUnset($offset) : void
public function offsetUnset($offset): void
{
$this->remove($offset);
}
@@ -225,7 +234,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
public function containsKey($key) : bool
public function containsKey($key): bool
{
return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
}
@@ -233,15 +242,12 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
public function contains($element) : bool
public function contains($element): bool
{
return in_array($element, $this->elements, true);
}
/**
* {@inheritDoc}
*/
public function exists(Closure $p) : bool
public function exists(Closure $p): bool
{
foreach ($this->elements as $key => $element) {
if ($p($key, $element)) {
@@ -271,7 +277,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
public function getKeys() : array
public function getKeys(): array
{
return array_keys($this->elements);
}
@@ -279,15 +285,12 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
public function getValues() : array
public function getValues(): array
{
return array_values($this->elements);
}
/**
* {@inheritDoc}
*/
public function count() : int
public function count(): int
{
return count($this->elements);
}
@@ -295,7 +298,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
public function set($key, $value) : void
public function set($key, $value): void
{
$this->elements[$key] = $value;
}
@@ -308,17 +311,14 @@ class ArrayCollection implements Collection, Selectable
* This breaks assumptions about the template type, but it would
* be a backwards-incompatible change to remove this method
*/
public function add($element) : bool
public function add($element): bool
{
$this->elements[] = $element;
return true;
}
/**
* {@inheritDoc}
*/
public function isEmpty() : bool
public function isEmpty(): bool
{
return empty($this->elements);
}
@@ -330,7 +330,7 @@ class ArrayCollection implements Collection, Selectable
*
* @psalm-return Traversable<TKey, T>
*/
public function getIterator() : Traversable
public function getIterator(): Traversable
{
return new ArrayIterator($this->elements);
}
@@ -344,7 +344,7 @@ class ArrayCollection implements Collection, Selectable
* @psalm-param Closure(T=):U $func
* @psalm-return static<TKey, U>
*/
public function map(Closure $func) : Collection
public function map(Closure $func): Collection
{
return $this->createFrom(array_map($func, $this->elements));
}
@@ -356,15 +356,12 @@ class ArrayCollection implements Collection, Selectable
*
* @psalm-return static<TKey,T>
*/
public function filter(Closure $p) : Collection
public function filter(Closure $p): Collection
{
return $this->createFrom(array_filter($this->elements, $p, ARRAY_FILTER_USE_BOTH));
}
/**
* {@inheritDoc}
*/
public function forAll(Closure $p) : bool
public function forAll(Closure $p): bool
{
foreach ($this->elements as $key => $element) {
if (! $p($key, $element)) {
@@ -378,7 +375,7 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
public function partition(Closure $p) : array
public function partition(Closure $p): array
{
$matches = $noMatches = [];
@@ -396,15 +393,12 @@ class ArrayCollection implements Collection, Selectable
/**
* Returns a string representation of this object.
*/
public function __toString() : string
public function __toString(): string
{
return self::class . '@' . spl_object_hash($this);
}
/**
* {@inheritDoc}
*/
public function clear() : void
public function clear(): void
{
$this->elements = [];
}
@@ -412,15 +406,15 @@ class ArrayCollection implements Collection, Selectable
/**
* {@inheritDoc}
*/
public function slice(int $offset, ?int $length = null) : array
public function slice(int $offset, ?int $length = null): array
{
return array_slice($this->elements, $offset, $length, true);
}
/**
* {@inheritDoc}
* @psalm-return Collection<TKey, T>
*/
public function matching(Criteria $criteria) : Collection
public function matching(Criteria $criteria): Collection
{
$expr = $criteria->getWhereExpression();
$filtered = $this->elements;

View File

@@ -43,12 +43,12 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*
* @psalm-param T $element
*/
public function add($element) : bool;
public function add($element): bool;
/**
* Clears the collection, removing all elements.
*/
public function clear() : void;
public function clear(): void;
/**
* Checks whether an element is contained in the collection.
@@ -60,14 +60,14 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*
* @psalm-param T $element
*/
public function contains($element) : bool;
public function contains($element): bool;
/**
* Checks whether the collection is empty (contains no elements).
*
* @return bool TRUE if the collection is empty, FALSE otherwise.
*/
public function isEmpty() : bool;
public function isEmpty(): bool;
/**
* Removes the element at the specified index from the collection.
@@ -90,7 +90,7 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*
* @psalm-param T $element
*/
public function removeElement($element) : bool;
public function removeElement($element): bool;
/**
* Checks whether the collection contains an element with the specified key/index.
@@ -102,7 +102,7 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*
* @psalm-param TKey $key
*/
public function containsKey($key) : bool;
public function containsKey($key): bool;
/**
* Gets the element at the specified key/index.
@@ -124,17 +124,17 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*
* @psalm-return TKey[]
*/
public function getKeys() : array;
public function getKeys(): array;
/**
* Gets all values of the collection.
*
* @return array The values of all elements in the collection, in the order they
* appear in the collection.
* @return mixed[] The values of all elements in the collection, in the
* order they appear in the collection.
*
* @psalm-return T[]
*/
public function getValues() : array;
public function getValues(): array;
/**
* Sets an element in the collection at the specified key/index.
@@ -145,16 +145,16 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
* @psalm-param TKey $key
* @psalm-param T $value
*/
public function set($key, $value) : void;
public function set($key, $value): void;
/**
* Gets a native PHP array representation of the collection.
*
* @return array
* @return mixed[]
*
* @psalm-return array<TKey,T>
*/
public function toArray() : array;
public function toArray(): array;
/**
* Sets the internal iterator to the first element in the collection and returns this element.
@@ -210,7 +210,7 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*
* @psalm-param Closure(TKey=, T=):bool $p
*/
public function exists(Closure $p) : bool;
public function exists(Closure $p): bool;
/**
* Returns all the elements of this collection that satisfy the predicate p.
@@ -218,12 +218,12 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*
* @param Closure $p The predicate used for filtering.
*
* @return Collection A collection with the results of the filter operation.
* @return Collection<mixed> A collection with the results of the filter operation.
*
* @psalm-param Closure(T=, TKey=):bool $p
* @psalm-return Collection<TKey, T>
*/
public function filter(Closure $p) : self;
public function filter(Closure $p): self;
/**
* Tests whether the given predicate p holds for all elements of this collection.
@@ -234,19 +234,19 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*
* @psalm-param Closure(TKey=, T=):bool $p
*/
public function forAll(Closure $p) : bool;
public function forAll(Closure $p): bool;
/**
* Applies the given function to each element in the collection and returns
* a new collection with the elements returned by the function.
*
* @return Collection
* @return Collection<mixed>
*
* @psalm-template U
* @psalm-param Closure(T=):U $func
* @psalm-return Collection<TKey, U>
*/
public function map(Closure $func) : self;
public function map(Closure $func): self;
/**
* Partitions this collection in two collections according to a predicate.
@@ -254,14 +254,14 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*
* @param Closure $p The predicate on which to partition.
*
* @return array<int, Collection> An array with two elements. The first element contains the collection
* @return Collection<mixed> An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
*
* @psalm-param Closure(TKey=, T=):bool $p
* @psalm-return array{0: Collection<TKey, T>, 1: Collection<TKey, T>}
*/
public function partition(Closure $p) : array;
public function partition(Closure $p): array;
/**
* Gets the index/key of a given element. The comparison of two elements is strict,
@@ -287,9 +287,9 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
* @param int $offset The offset to start from.
* @param int|null $length The maximum number of elements to return, or null for no limit.
*
* @return array
* @return mixed[]
*
* @psalm-return array<TKey,T>
*/
public function slice(int $offset, ?int $length = null) : array;
public function slice(int $offset, ?int $length = null): array;
}

View File

@@ -6,11 +6,14 @@ namespace Doctrine\Common\Collections;
use Doctrine\Common\Collections\Expr\CompositeExpression;
use Doctrine\Common\Collections\Expr\Expression;
use function array_map;
use function strtoupper;
/**
* Criteria for filtering Selectable collections.
*
* @psalm-consistent-constructor
*/
class Criteria
{
@@ -37,7 +40,7 @@ class Criteria
*
* @return Criteria
*/
public static function create() : self
public static function create(): self
{
return new static();
}
@@ -45,7 +48,7 @@ class Criteria
/**
* Returns the expression builder.
*/
public static function expr() : ExpressionBuilder
public static function expr(): ExpressionBuilder
{
if (self::$expressionBuilder === null) {
self::$expressionBuilder = new ExpressionBuilder();
@@ -78,7 +81,7 @@ class Criteria
*
* @return Criteria
*/
public function where(Expression $expression) : self
public function where(Expression $expression): self
{
$this->expression = $expression;
@@ -91,7 +94,7 @@ class Criteria
*
* @return Criteria
*/
public function andWhere(Expression $expression) : self
public function andWhere(Expression $expression): self
{
if ($this->expression === null) {
return $this->where($expression);
@@ -111,7 +114,7 @@ class Criteria
*
* @return Criteria
*/
public function orWhere(Expression $expression) : self
public function orWhere(Expression $expression): self
{
if ($this->expression === null) {
return $this->where($expression);
@@ -128,7 +131,7 @@ class Criteria
/**
* Gets the expression attached to this Criteria.
*/
public function getWhereExpression() : ?Expression
public function getWhereExpression(): ?Expression
{
return $this->expression;
}
@@ -138,7 +141,7 @@ class Criteria
*
* @return array<string, string>
*/
public function getOrderings() : array
public function getOrderings(): array
{
return $this->orderings;
}
@@ -155,10 +158,10 @@ class Criteria
*
* @return Criteria
*/
public function orderBy(array $orderings) : self
public function orderBy(array $orderings): self
{
$this->orderings = array_map(
static function (string $ordering) : string {
static function (string $ordering): string {
return strtoupper($ordering) === Criteria::ASC ? Criteria::ASC : Criteria::DESC;
},
$orderings
@@ -170,7 +173,7 @@ class Criteria
/**
* Gets the current first result option of this Criteria.
*/
public function getFirstResult() : ?int
public function getFirstResult(): ?int
{
return $this->firstResult;
}
@@ -182,7 +185,7 @@ class Criteria
*
* @return Criteria
*/
public function setFirstResult(?int $firstResult) : self
public function setFirstResult(?int $firstResult): self
{
$this->firstResult = $firstResult;
@@ -192,7 +195,7 @@ class Criteria
/**
* Gets maxResults.
*/
public function getMaxResults() : ?int
public function getMaxResults(): ?int
{
return $this->maxResults;
}
@@ -204,7 +207,7 @@ class Criteria
*
* @return Criteria
*/
public function setMaxResults(?int $maxResults) : self
public function setMaxResults(?int $maxResults): self
{
$this->maxResults = $maxResults;

View File

@@ -7,8 +7,10 @@ namespace Doctrine\Common\Collections\Expr;
use ArrayAccess;
use Closure;
use RuntimeException;
use function in_array;
use function is_array;
use function is_scalar;
use function iterator_to_array;
use function method_exists;
use function preg_match;
@@ -31,7 +33,7 @@ class ClosureExpressionVisitor extends ExpressionVisitor
* directly or indirectly (through an accessor get*, is*, or a magic
* method, __get, __call).
*
* @param object|array $object
* @param object|mixed[] $object
*
* @return mixed
*/
@@ -89,15 +91,15 @@ class ClosureExpressionVisitor extends ExpressionVisitor
/**
* Helper for sorting arrays of objects based on multiple fields + orientations.
*/
public static function sortByField(string $name, int $orientation = 1, ?Closure $next = null) : Closure
public static function sortByField(string $name, int $orientation = 1, ?Closure $next = null): Closure
{
if (! $next) {
$next = static function () : int {
$next = static function (): int {
return 0;
};
}
return static function ($a, $b) use ($name, $next, $orientation) : int {
return static function ($a, $b) use ($name, $next, $orientation): int {
$aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
$bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);
@@ -120,43 +122,56 @@ class ClosureExpressionVisitor extends ExpressionVisitor
switch ($comparison->getOperator()) {
case Comparison::EQ:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value;
};
case Comparison::NEQ:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value;
};
case Comparison::LT:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value;
};
case Comparison::LTE:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value;
};
case Comparison::GT:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value;
};
case Comparison::GTE:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value;
};
case Comparison::IN:
return static function ($object) use ($field, $value) : bool {
return in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value, true);
return static function ($object) use ($field, $value): bool {
$fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
return in_array($fieldValue, $value, is_scalar($fieldValue));
};
case Comparison::NIN:
return static function ($object) use ($field, $value) : bool {
return ! in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value, true);
return static function ($object) use ($field, $value): bool {
$fieldValue = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
return ! in_array($fieldValue, $value, is_scalar($fieldValue));
};
case Comparison::CONTAINS:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) !== false;
};
case Comparison::MEMBER_OF:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
$fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field);
if (! is_array($fieldValues)) {
@@ -165,14 +180,17 @@ class ClosureExpressionVisitor extends ExpressionVisitor
return in_array($value, $fieldValues, true);
};
case Comparison::STARTS_WITH:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) === 0;
};
case Comparison::ENDS_WITH:
return static function ($object) use ($field, $value) : bool {
return static function ($object) use ($field, $value): bool {
return $value === substr(ClosureExpressionVisitor::getObjectFieldValue($object, $field), -strlen($value));
};
default:
throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator());
}
@@ -200,19 +218,21 @@ class ClosureExpressionVisitor extends ExpressionVisitor
switch ($expr->getType()) {
case CompositeExpression::TYPE_AND:
return $this->andExpressions($expressionList);
case CompositeExpression::TYPE_OR:
return $this->orExpressions($expressionList);
default:
throw new RuntimeException('Unknown composite ' . $expr->getType());
}
}
/**
* @param array $expressions
* @param callable[] $expressions
*/
private function andExpressions(array $expressions) : callable
private function andExpressions(array $expressions): callable
{
return static function ($object) use ($expressions) : bool {
return static function ($object) use ($expressions): bool {
foreach ($expressions as $expression) {
if (! $expression($object)) {
return false;
@@ -224,11 +244,11 @@ class ClosureExpressionVisitor extends ExpressionVisitor
}
/**
* @param array $expressions
* @param callable[] $expressions
*/
private function orExpressions(array $expressions) : callable
private function orExpressions(array $expressions): callable
{
return static function ($object) use ($expressions) : bool {
return static function ($object) use ($expressions): bool {
foreach ($expressions as $expression) {
if ($expression($object)) {
return true;

View File

@@ -46,17 +46,17 @@ class Comparison implements Expression
$this->value = $value;
}
public function getField() : string
public function getField(): string
{
return $this->field;
}
public function getValue() : Value
public function getValue(): Value
{
return $this->value;
}
public function getOperator() : string
public function getOperator(): string
{
return $this->op;
}

View File

@@ -33,6 +33,7 @@ class CompositeExpression implements Expression
if ($expr instanceof Value) {
throw new RuntimeException('Values are not supported expressions as children of and/or expressions.');
}
if (! ($expr instanceof Expression)) {
throw new RuntimeException('No expression given to CompositeExpression.');
}
@@ -46,12 +47,12 @@ class CompositeExpression implements Expression
*
* @return array<int, Expression>
*/
public function getExpressionList() : array
public function getExpressionList(): array
{
return $this->expressions;
}
public function getType() : string
public function getType(): string
{
return $this->type;
}

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Doctrine\Common\Collections\Expr;
use RuntimeException;
use function get_class;
/**
@@ -46,10 +47,13 @@ abstract class ExpressionVisitor
switch (true) {
case $expr instanceof Comparison:
return $this->walkComparison($expr);
case $expr instanceof Value:
return $this->walkValue($expr);
case $expr instanceof CompositeExpression:
return $this->walkCompositeExpression($expr);
default:
throw new RuntimeException('Unknown Expression ' . get_class($expr));
}

View File

@@ -18,12 +18,12 @@ use Doctrine\Common\Collections\Expr\Value;
*/
class ExpressionBuilder
{
public function andX(Expression ...$expressions) : CompositeExpression
public function andX(Expression ...$expressions): CompositeExpression
{
return new CompositeExpression(CompositeExpression::TYPE_AND, $expressions);
}
public function orX(Expression ...$expressions) : CompositeExpression
public function orX(Expression ...$expressions): CompositeExpression
{
return new CompositeExpression(CompositeExpression::TYPE_OR, $expressions);
}
@@ -31,7 +31,7 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function eq(string $field, $value) : Comparison
public function eq(string $field, $value): Comparison
{
return new Comparison($field, Comparison::EQ, new Value($value));
}
@@ -39,7 +39,7 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function gt(string $field, $value) : Comparison
public function gt(string $field, $value): Comparison
{
return new Comparison($field, Comparison::GT, new Value($value));
}
@@ -47,7 +47,7 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function lt(string $field, $value) : Comparison
public function lt(string $field, $value): Comparison
{
return new Comparison($field, Comparison::LT, new Value($value));
}
@@ -55,7 +55,7 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function gte(string $field, $value) : Comparison
public function gte(string $field, $value): Comparison
{
return new Comparison($field, Comparison::GTE, new Value($value));
}
@@ -63,7 +63,7 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function lte(string $field, $value) : Comparison
public function lte(string $field, $value): Comparison
{
return new Comparison($field, Comparison::LTE, new Value($value));
}
@@ -71,28 +71,28 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function neq(string $field, $value) : Comparison
public function neq(string $field, $value): Comparison
{
return new Comparison($field, Comparison::NEQ, new Value($value));
}
public function isNull(string $field) : Comparison
public function isNull(string $field): Comparison
{
return new Comparison($field, Comparison::EQ, new Value(null));
}
/**
* @param array $values
* @param mixed[] $values
*/
public function in(string $field, array $values) : Comparison
public function in(string $field, array $values): Comparison
{
return new Comparison($field, Comparison::IN, new Value($values));
}
/**
* @param array $values
* @param mixed[] $values
*/
public function notIn(string $field, array $values) : Comparison
public function notIn(string $field, array $values): Comparison
{
return new Comparison($field, Comparison::NIN, new Value($values));
}
@@ -100,7 +100,7 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function contains(string $field, $value) : Comparison
public function contains(string $field, $value): Comparison
{
return new Comparison($field, Comparison::CONTAINS, new Value($value));
}
@@ -108,7 +108,7 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function memberOf(string $field, $value) : Comparison
public function memberOf(string $field, $value): Comparison
{
return new Comparison($field, Comparison::MEMBER_OF, new Value($value));
}
@@ -116,7 +116,7 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function startsWith(string $field, $value) : Comparison
public function startsWith(string $field, $value): Comparison
{
return new Comparison($field, Comparison::STARTS_WITH, new Value($value));
}
@@ -124,7 +124,7 @@ class ExpressionBuilder
/**
* @param mixed $value
*/
public function endsWith(string $field, $value) : Comparison
public function endsWith(string $field, $value): Comparison
{
return new Comparison($field, Comparison::ENDS_WITH, new Value($value));
}

View File

@@ -26,9 +26,9 @@ interface Selectable
* Selects all elements from a selectable that match the expression and
* returns a new collection containing these elements and preserved keys.
*
* @return Collection
* @return Collection<mixed>
*
* @psalm-return Collection<TKey,T>
*/
public function matching(Criteria $criteria) : Collection;
public function matching(Criteria $criteria): Collection;
}

View File

@@ -6,6 +6,8 @@
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors"/>
<config name="php_version" value="70100"/>
<!-- Ignore warnings, show progress of the run and show sniff names -->
<arg value="nps"/>
@@ -13,6 +15,10 @@
<file>tests</file>
<rule ref="Doctrine">
<exclude name="SlevomatCodingStandard.TypeHints.DeclareStrictTypes"/>
<exclude name="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint"/>
<exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint"/>
<!-- Since Collections are built around mixed content, this has no value here -->
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingTraversablePropertyTypeHintSpecification"/>
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingTraversableParameterTypeHintSpecification"/>
@@ -34,4 +40,11 @@
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming">
<exclude-pattern>lib/Doctrine/Common/Collections/AbstractLazyCollection.php</exclude-pattern>
</rule>
<rule ref="Squiz.NamingConventions.ValidVariableName.NotCamelCaps">
<exclude-pattern>tests/Doctrine/Tests/Common/Collections/ClosureExpressionVisitorTest.php</exclude-pattern>
</rule>
<rule ref="Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps">
<exclude-pattern>tests/Doctrine/Tests/Common/Collections/ClosureExpressionVisitorTest.php</exclude-pattern>
</rule>
</ruleset>

View File

@@ -4,6 +4,17 @@ parameters:
paths:
- lib
ignoreErrors:
# Making classes final as suggested would be a BC-break
-
message: '~Unsafe usage of new static\(\)\.~'
paths:
- 'lib/Doctrine/Common/Collections/ArrayCollection.php'
- 'lib/Doctrine/Common/Collections/Criteria.php'
-
message: '~Array \(array\<TKey, T\>\) does not accept key int\.~'
path: 'lib/Doctrine/Common/Collections/ArrayCollection.php'
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon

View File

@@ -33,7 +33,6 @@
<MissingReturnType errorLevel="info" />
<MissingPropertyType errorLevel="info" />
<InvalidDocblock errorLevel="info" />
<MisplacedRequiredParam errorLevel="info" />
<PropertyNotSetInConstructor errorLevel="info" />
<MissingConstructor errorLevel="info" />

View File

@@ -8,6 +8,8 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Tests\LazyArrayCollection;
use function assert;
/**
* Tests for {@see \Doctrine\Common\Collections\AbstractLazyCollection}.
*
@@ -15,15 +17,20 @@ use Doctrine\Tests\LazyArrayCollection;
*/
class AbstractLazyArrayCollectionTest extends BaseArrayCollectionTest
{
protected function buildCollection(array $elements = []) : Collection
/**
* @param mixed[] $elements
*
* @return Collection<mixed>
*/
protected function buildCollection(array $elements = []): Collection
{
return new LazyArrayCollection(new ArrayCollection($elements));
}
public function testLazyCollection() : void
public function testLazyCollection(): void
{
/** @var LazyArrayCollection $collection */
$collection = $this->buildCollection(['a', 'b', 'c']);
assert($collection instanceof LazyArrayCollection);
self::assertFalse($collection->isInitialized());
self::assertCount(3, $collection);

View File

@@ -6,6 +6,8 @@ namespace Doctrine\Tests\Common\Collections;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Tests\LazyArrayCollection;
use function assert;
use function is_array;
use function is_numeric;
use function is_string;
@@ -17,20 +19,23 @@ use function is_string;
*/
class AbstractLazyCollectionTest extends BaseCollectionTest
{
protected function setUp() : void
protected function setUp(): void
{
$this->collection = new LazyArrayCollection(new ArrayCollection());
}
private function buildCollection(array $elements) : LazyArrayCollection
/**
* @psalm-param mixed[] $elements
*/
private function buildCollection(array $elements): LazyArrayCollection
{
return new LazyArrayCollection(new ArrayCollection($elements));
}
public function testClearInitializes() : void
public function testClearInitializes(): void
{
/** @var LazyArrayCollection $collection */
$collection = $this->buildCollection(['a', 'b', 'c']);
assert($collection instanceof LazyArrayCollection);
$collection->clear();
@@ -38,10 +43,10 @@ class AbstractLazyCollectionTest extends BaseCollectionTest
self::assertCount(0, $collection);
}
public function testFilterInitializes() : void
public function testFilterInitializes(): void
{
/** @var LazyArrayCollection $collection */
$collection = $this->buildCollection([1, 'foo', 3]);
assert($collection instanceof LazyArrayCollection);
$res = $collection->filter(static function ($value) {
return is_numeric($value);
@@ -50,7 +55,7 @@ class AbstractLazyCollectionTest extends BaseCollectionTest
self::assertEquals([0 => 1, 2 => 3], $res->toArray());
}
public function testForAllInitializes() : void
public function testForAllInitializes(): void
{
$collection = $this->buildCollection(['foo', 'bar']);
@@ -63,7 +68,7 @@ class AbstractLazyCollectionTest extends BaseCollectionTest
}), false);
}
public function testMapInitializes() : void
public function testMapInitializes(): void
{
$collection = $this->buildCollection([1, 2]);
@@ -73,7 +78,7 @@ class AbstractLazyCollectionTest extends BaseCollectionTest
self::assertEquals([2, 4], $res->toArray());
}
public function testPartitionInitializes() : void
public function testPartitionInitializes(): void
{
$collection = $this->buildCollection([true, false]);
$partition = $collection->partition(static function ($k, $e) {
@@ -83,7 +88,7 @@ class AbstractLazyCollectionTest extends BaseCollectionTest
self::assertEquals($partition[1][0], false);
}
public function testSliceInitializes() : void
public function testSliceInitializes(): void
{
$collection = $this->buildCollection(['one', 'two', 'three']);
@@ -98,14 +103,14 @@ class AbstractLazyCollectionTest extends BaseCollectionTest
self::assertEquals([1 => 'two'], $slice);
}
public function testGetInitializes() : void
public function testGetInitializes(): void
{
$value = 'foo';
$collection = $this->buildCollection([$value]);
$this->assertSame($value, $collection[0]);
}
public function testUnsetInitializes() : void
public function testUnsetInitializes(): void
{
$collection = $this->buildCollection(['foo', 'bar']);

View File

@@ -7,6 +7,7 @@ namespace Doctrine\Tests\Common\Collections;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Serializable;
use function json_decode;
use function json_encode;
use function serialize;
@@ -19,12 +20,17 @@ use function unserialize;
*/
class ArrayCollectionTest extends BaseArrayCollectionTest
{
protected function buildCollection(array $elements = []) : Collection
/**
* @param mixed[] $elements
*
* @return Collection<mixed>
*/
protected function buildCollection(array $elements = []): Collection
{
return new ArrayCollection($elements);
}
public function testUnserializeEmptyArrayCollection() : void
public function testUnserializeEmptyArrayCollection(): void
{
$collection = new SerializableArrayCollection();
$serializeCollection = serialize($collection);
@@ -40,13 +46,13 @@ class ArrayCollectionTest extends BaseArrayCollectionTest
*/
class SerializableArrayCollection extends ArrayCollection implements Serializable
{
public function serialize() : string
public function serialize(): string
{
return json_encode($this->getKeys());
}
// phpcs:ignore SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
public function unserialize($serialized) : void
// phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint
public function unserialize($serialized): void
{
foreach (json_decode($serialized) as $value) {
parent::add($value);

View File

@@ -9,6 +9,7 @@ use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Collections\Selectable;
use PHPUnit\Framework\TestCase;
use stdClass;
use function array_keys;
use function array_search;
use function array_values;
@@ -21,9 +22,14 @@ use function reset;
abstract class BaseArrayCollectionTest extends TestCase
{
abstract protected function buildCollection(array $elements = []) : Collection;
/**
* @param mixed[] $elements
*
* @return Collection<mixed>
*/
abstract protected function buildCollection(array $elements = []): Collection;
protected function isSelectable(object $obj) : bool
protected function isSelectable(object $obj): bool
{
return $obj instanceof Selectable;
}
@@ -33,7 +39,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testToArray(array $elements) : void
public function testToArray(array $elements): void
{
$collection = $this->buildCollection($elements);
@@ -45,7 +51,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testFirst(array $elements) : void
public function testFirst(array $elements): void
{
$collection = $this->buildCollection($elements);
self::assertSame(reset($elements), $collection->first());
@@ -56,7 +62,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testLast(array $elements) : void
public function testLast(array $elements): void
{
$collection = $this->buildCollection($elements);
self::assertSame(end($elements), $collection->last());
@@ -67,7 +73,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testKey(array $elements) : void
public function testKey(array $elements): void
{
$collection = $this->buildCollection($elements);
@@ -84,7 +90,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testNext(array $elements) : void
public function testNext(array $elements): void
{
$count = count($elements);
$collection = $this->buildCollection($elements);
@@ -110,7 +116,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testCurrent(array $elements) : void
public function testCurrent(array $elements): void
{
$collection = $this->buildCollection($elements);
@@ -127,7 +133,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testGetKeys(array $elements) : void
public function testGetKeys(array $elements): void
{
$collection = $this->buildCollection($elements);
@@ -139,7 +145,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testGetValues(array $elements) : void
public function testGetValues(array $elements): void
{
$collection = $this->buildCollection($elements);
@@ -151,7 +157,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testCount(array $elements) : void
public function testCount(array $elements): void
{
$collection = $this->buildCollection($elements);
@@ -163,7 +169,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideDifferentElements
*/
public function testIterator(array $elements) : void
public function testIterator(array $elements): void
{
$collection = $this->buildCollection($elements);
@@ -176,7 +182,10 @@ abstract class BaseArrayCollectionTest extends TestCase
self::assertEquals(count($elements), $iterations, 'Number of iterations not match');
}
public function provideDifferentElements() : array
/**
* @psalm-return array<string, array{mixed[]}>
*/
public function provideDifferentElements(): array
{
return [
'indexed' => [[1, 2, 3, 4, 5]],
@@ -185,7 +194,7 @@ abstract class BaseArrayCollectionTest extends TestCase
];
}
public function testRemove() : void
public function testRemove(): void
{
$elements = [1, 'A' => 'a', 2, 'B' => 'b', 3];
$collection = $this->buildCollection($elements);
@@ -205,7 +214,7 @@ abstract class BaseArrayCollectionTest extends TestCase
self::assertEquals($elements, $collection->toArray());
}
public function testRemoveElement() : void
public function testRemoveElement(): void
{
$elements = [1, 'A' => 'a', 2, 'B' => 'b', 3, 'A2' => 'a', 'B2' => 'b'];
$collection = $this->buildCollection($elements);
@@ -224,7 +233,7 @@ abstract class BaseArrayCollectionTest extends TestCase
self::assertEquals($elements, $collection->toArray());
}
public function testContainsKey() : void
public function testContainsKey(): void
{
$elements = [1, 'A' => 'a', 2, 'null' => null, 3, 'A2' => 'a', 'B2' => 'b'];
$collection = $this->buildCollection($elements);
@@ -235,7 +244,7 @@ abstract class BaseArrayCollectionTest extends TestCase
self::assertFalse($collection->containsKey('non-existent'), "Doesn't contain key");
}
public function testEmpty() : void
public function testEmpty(): void
{
$collection = $this->buildCollection();
self::assertTrue($collection->isEmpty(), 'Empty collection');
@@ -244,7 +253,7 @@ abstract class BaseArrayCollectionTest extends TestCase
self::assertFalse($collection->isEmpty(), 'Not empty collection');
}
public function testContains() : void
public function testContains(): void
{
$elements = [1, 'A' => 'a', 2, 'null' => null, 3, 'A2' => 'a', 'zero' => 0];
$collection = $this->buildCollection($elements);
@@ -255,7 +264,7 @@ abstract class BaseArrayCollectionTest extends TestCase
self::assertFalse($collection->contains('non-existent'), "Doesn't contain an element");
}
public function testExists() : void
public function testExists(): void
{
$elements = [1, 'A' => 'a', 2, 'null' => null, 3, 'A2' => 'a', 'zero' => 0];
$collection = $this->buildCollection($elements);
@@ -269,7 +278,7 @@ abstract class BaseArrayCollectionTest extends TestCase
}), 'Element not exists');
}
public function testIndexOf() : void
public function testIndexOf(): void
{
$elements = [1, 'A' => 'a', 2, 'null' => null, 3, 'A2' => 'a', 'zero' => 0];
$collection = $this->buildCollection($elements);
@@ -279,7 +288,7 @@ abstract class BaseArrayCollectionTest extends TestCase
self::assertSame(array_search('non-existent', $elements, true), $collection->indexOf('non-existent'), 'Index of non existent');
}
public function testGet() : void
public function testGet(): void
{
$elements = [1, 'A' => 'a', 2, 'null' => null, 3, 'A2' => 'a', 'zero' => 0];
$collection = $this->buildCollection($elements);
@@ -289,7 +298,7 @@ abstract class BaseArrayCollectionTest extends TestCase
self::assertSame(null, $collection->get('non-existent'), 'Get non existent element');
}
public function testMatchingWithSortingPreservesyKeys() : void
public function testMatchingWithSortingPreservesyKeys(): void
{
$object1 = new stdClass();
$object2 = new stdClass();
@@ -323,7 +332,7 @@ abstract class BaseArrayCollectionTest extends TestCase
*
* @dataProvider provideSlices
*/
public function testMatchingWithSlicingPreserveKeys(array $array, array $slicedArray, ?int $firstResult, ?int $maxResult) : void
public function testMatchingWithSlicingPreserveKeys(array $array, array $slicedArray, ?int $firstResult, ?int $maxResult): void
{
$collection = $this->buildCollection($array);
@@ -342,7 +351,7 @@ abstract class BaseArrayCollectionTest extends TestCase
/**
* @return mixed[][]
*/
public function provideSlices() : array
public function provideSlices(): array
{
return [
'preserve numeric keys' => [
@@ -405,7 +414,7 @@ abstract class BaseArrayCollectionTest extends TestCase
];
}
public function testMultiColumnSortAppliesAllSorts() : void
public function testMultiColumnSortAppliesAllSorts(): void
{
$collection = $this->buildCollection([
['foo' => 1, 'bar' => 2],

View File

@@ -7,6 +7,7 @@ namespace Doctrine\Tests\Common\Collections;
use Doctrine\Common\Collections\Collection;
use PHPUnit\Framework\TestCase;
use stdClass;
use function count;
use function is_array;
use function is_numeric;
@@ -14,10 +15,10 @@ use function is_string;
abstract class BaseCollectionTest extends TestCase
{
/** @var Collection */
/** @var Collection<mixed> */
protected $collection;
public function testIssetAndUnset() : void
public function testIssetAndUnset(): void
{
self::assertFalse(isset($this->collection[0]));
$this->collection->add('testing');
@@ -26,12 +27,12 @@ abstract class BaseCollectionTest extends TestCase
self::assertFalse(isset($this->collection[0]));
}
public function testRemovingNonExistentEntryReturnsNull() : void
public function testRemovingNonExistentEntryReturnsNull(): void
{
self::assertEquals(null, $this->collection->remove('testing_does_not_exist'));
}
public function testExists() : void
public function testExists(): void
{
$this->collection->add('one');
$this->collection->add('two');
@@ -45,7 +46,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertFalse($exists);
}
public function testMap() : void
public function testMap(): void
{
$this->collection->add(1);
$this->collection->add(2);
@@ -55,7 +56,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertEquals([2, 4], $res->toArray());
}
public function testFilter() : void
public function testFilter(): void
{
$this->collection->add(1);
$this->collection->add('foo');
@@ -66,7 +67,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertEquals([0 => 1, 2 => 3], $res->toArray());
}
public function testFilterByValueAndKey() : void
public function testFilterByValueAndKey(): void
{
$this->collection->add(1);
$this->collection->add('foo');
@@ -79,7 +80,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertSame([0 => 1, 2 => 3, 4 => 5], $res->toArray());
}
public function testFirstAndLast() : void
public function testFirstAndLast(): void
{
$this->collection->add('one');
$this->collection->add('two');
@@ -88,7 +89,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertEquals($this->collection->last(), 'two');
}
public function testArrayAccess() : void
public function testArrayAccess(): void
{
$this->collection[] = 'one';
$this->collection[] = 'two';
@@ -100,45 +101,45 @@ abstract class BaseCollectionTest extends TestCase
self::assertEquals($this->collection->count(), 1);
}
public function testContainsKey() : void
public function testContainsKey(): void
{
$this->collection[5] = 'five';
self::assertTrue($this->collection->containsKey(5));
}
public function testContains() : void
public function testContains(): void
{
$this->collection[0] = 'test';
self::assertTrue($this->collection->contains('test'));
}
public function testSearch() : void
public function testSearch(): void
{
$this->collection[0] = 'test';
self::assertEquals(0, $this->collection->indexOf('test'));
}
public function testGet() : void
public function testGet(): void
{
$this->collection[0] = 'test';
self::assertEquals('test', $this->collection->get(0));
}
public function testGetKeys() : void
public function testGetKeys(): void
{
$this->collection[] = 'one';
$this->collection[] = 'two';
self::assertEquals([0, 1], $this->collection->getKeys());
}
public function testGetValues() : void
public function testGetValues(): void
{
$this->collection[] = 'one';
$this->collection[] = 'two';
self::assertEquals(['one', 'two'], $this->collection->getValues());
}
public function testCount() : void
public function testCount(): void
{
$this->collection[] = 'one';
$this->collection[] = 'two';
@@ -146,7 +147,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertEquals(count($this->collection), 2);
}
public function testForAll() : void
public function testForAll(): void
{
$this->collection[] = 'one';
$this->collection[] = 'two';
@@ -158,7 +159,7 @@ abstract class BaseCollectionTest extends TestCase
}), false);
}
public function testPartition() : void
public function testPartition(): void
{
$this->collection[] = true;
$this->collection[] = false;
@@ -169,7 +170,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertEquals($partition[1][0], false);
}
public function testClear() : void
public function testClear(): void
{
$this->collection[] = 'one';
$this->collection[] = 'two';
@@ -177,7 +178,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertEquals($this->collection->isEmpty(), true);
}
public function testRemove() : void
public function testRemove(): void
{
$this->collection[] = 'one';
$this->collection[] = 'two';
@@ -188,7 +189,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertNull($this->collection->remove(0));
}
public function testRemoveElement() : void
public function testRemoveElement(): void
{
$this->collection[] = 'one';
$this->collection[] = 'two';
@@ -198,7 +199,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertFalse($this->collection->removeElement('two'));
}
public function testSlice() : void
public function testSlice(): void
{
$this->collection[] = 'one';
$this->collection[] = 'two';
@@ -215,7 +216,7 @@ abstract class BaseCollectionTest extends TestCase
self::assertEquals([1 => 'two'], $slice);
}
protected function fillMatchingFixture() : void
protected function fillMatchingFixture(): void
{
$std1 = new stdClass();
$std1->foo = 'bar';
@@ -226,14 +227,14 @@ abstract class BaseCollectionTest extends TestCase
$this->collection[] = $std2;
}
public function testCanRemoveNullValuesByKey() : void
public function testCanRemoveNullValuesByKey(): void
{
$this->collection->add(null);
$this->collection->remove(0);
self::assertTrue($this->collection->isEmpty());
}
public function testCanVerifyExistingKeysWithNullValues() : void
public function testCanVerifyExistingKeysWithNullValues(): void
{
$this->collection->set('key', null);
self::assertTrue($this->collection->containsKey('key'));

View File

@@ -7,6 +7,7 @@ namespace Doctrine\Tests\Common\Collections;
use Doctrine\Common\Collections\Expr\ClosureExpressionVisitor;
use Doctrine\Common\Collections\ExpressionBuilder;
use PHPUnit\Framework\TestCase;
use function usort;
/**
@@ -20,27 +21,27 @@ class ClosureExpressionVisitorTest extends TestCase
/** @var ExpressionBuilder */
private $builder;
protected function setUp() : void
protected function setUp(): void
{
$this->visitor = new ClosureExpressionVisitor();
$this->builder = new ExpressionBuilder();
}
public function testGetObjectFieldValueIsAccessor() : void
public function testGetObjectFieldValueIsAccessor(): void
{
$object = new TestObject(1, 2, true);
self::assertTrue($this->visitor->getObjectFieldValue($object, 'baz'));
}
public function testGetObjectFieldValueIsAccessorWithIsPrefix() : void
public function testGetObjectFieldValueIsAccessorWithIsPrefix(): void
{
$object = new TestObject(1, 2, true);
self::assertTrue($this->visitor->getObjectFieldValue($object, 'isBaz'));
}
public function testGetObjectFieldValueIsAccessorCamelCase() : void
public function testGetObjectFieldValueIsAccessorCamelCase(): void
{
$object = new TestObjectNotCamelCase(1);
@@ -49,7 +50,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertEquals(1, $this->visitor->getObjectFieldValue($object, 'fooBar'));
}
public function testGetObjectFieldValueIsAccessorBoth() : void
public function testGetObjectFieldValueIsAccessorBoth(): void
{
$object = new TestObjectBothCamelCaseAndUnderscore(1, 2);
@@ -58,7 +59,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertEquals(2, $this->visitor->getObjectFieldValue($object, 'fooBar'));
}
public function testGetObjectFieldValueIsAccessorOnePublic() : void
public function testGetObjectFieldValueIsAccessorOnePublic(): void
{
$object = new TestObjectPublicCamelCaseAndPrivateUnderscore(1, 2);
@@ -67,7 +68,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertEquals(2, $this->visitor->getObjectFieldValue($object, 'fooBar'));
}
public function testGetObjectFieldValueIsAccessorBothPublic() : void
public function testGetObjectFieldValueIsAccessorBothPublic(): void
{
$object = new TestObjectPublicCamelCaseAndPrivateUnderscore(1, 2);
@@ -76,14 +77,14 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertEquals(2, $this->visitor->getObjectFieldValue($object, 'fooBar'));
}
public function testGetObjectFieldValueMagicCallMethod() : void
public function testGetObjectFieldValueMagicCallMethod(): void
{
$object = new TestObject(1, 2, true, 3);
self::assertEquals(3, $this->visitor->getObjectFieldValue($object, 'qux'));
}
public function testWalkEqualsComparison() : void
public function testWalkEqualsComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->eq('foo', 1));
@@ -91,7 +92,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject(2)));
}
public function testWalkNotEqualsComparison() : void
public function testWalkNotEqualsComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->neq('foo', 1));
@@ -99,7 +100,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertTrue($closure(new TestObject(2)));
}
public function testWalkLessThanComparison() : void
public function testWalkLessThanComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->lt('foo', 1));
@@ -107,7 +108,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertTrue($closure(new TestObject(0)));
}
public function testWalkLessThanEqualsComparison() : void
public function testWalkLessThanEqualsComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->lte('foo', 1));
@@ -116,7 +117,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertTrue($closure(new TestObject(0)));
}
public function testWalkGreaterThanEqualsComparison() : void
public function testWalkGreaterThanEqualsComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->gte('foo', 1));
@@ -125,7 +126,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject(0)));
}
public function testWalkGreaterThanComparison() : void
public function testWalkGreaterThanComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->gt('foo', 1));
@@ -134,7 +135,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject(0)));
}
public function testWalkInComparison() : void
public function testWalkInComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->in('foo', [1, 2, 3, '04']));
@@ -145,7 +146,18 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertTrue($closure(new TestObject('04')));
}
public function testWalkNotInComparison() : void
public function testWalkInComparisonObjects(): void
{
$closure = $this->visitor->walkComparison($this->builder->in('foo', [new TestObject(1), new TestObject(2), new TestObject(4)]));
self::assertTrue($closure(new TestObject(new TestObject(2))));
self::assertTrue($closure(new TestObject(new TestObject(1))));
self::assertFalse($closure(new TestObject(new TestObject(0))));
self::assertTrue($closure(new TestObject(new TestObject(4))));
self::assertFalse($closure(new TestObject(new TestObject('baz'))));
}
public function testWalkNotInComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->notIn('foo', [1, 2, 3, '04']));
@@ -156,7 +168,18 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject('04')));
}
public function testWalkContainsComparison() : void
public function testWalkNotInComparisonObjects(): void
{
$closure = $this->visitor->walkComparison($this->builder->notIn('foo', [new TestObject(1), new TestObject(2), new TestObject(4)]));
self::assertFalse($closure(new TestObject(new TestObject(1))));
self::assertFalse($closure(new TestObject(new TestObject(2))));
self::assertTrue($closure(new TestObject(new TestObject(0))));
self::assertFalse($closure(new TestObject(new TestObject(4))));
self::assertTrue($closure(new TestObject(new TestObject('baz'))));
}
public function testWalkContainsComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->contains('foo', 'hello'));
@@ -164,7 +187,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject('world')));
}
public function testWalkMemberOfComparisonWithObject() : void
public function testWalkMemberOfComparisonWithObject(): void
{
$closure = $this->visitor->walkComparison($this->builder->memberof('foo', 2));
@@ -174,7 +197,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject([1, '02'])));
}
public function testWalkStartsWithComparison() : void
public function testWalkStartsWithComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->startsWith('foo', 'hello'));
@@ -182,7 +205,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject('world')));
}
public function testWalkEndsWithComparison() : void
public function testWalkEndsWithComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->endsWith('foo', 'world'));
@@ -190,7 +213,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject('hello')));
}
public function testWalkAndCompositeExpression() : void
public function testWalkAndCompositeExpression(): void
{
$closure = $this->visitor->walkCompositeExpression(
$this->builder->andX(
@@ -205,7 +228,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject(0, 0)));
}
public function testWalkOrCompositeExpression() : void
public function testWalkOrCompositeExpression(): void
{
$closure = $this->visitor->walkCompositeExpression(
$this->builder->orX(
@@ -220,7 +243,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertFalse($closure(new TestObject(0, 0)));
}
public function testSortByFieldAscending() : void
public function testSortByFieldAscending(): void
{
$objects = [new TestObject('b'), new TestObject('a'), new TestObject('c')];
$sort = ClosureExpressionVisitor::sortByField('foo');
@@ -232,7 +255,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertEquals('c', $objects[2]->getFoo());
}
public function testSortByFieldDescending() : void
public function testSortByFieldDescending(): void
{
$objects = [new TestObject('b'), new TestObject('a'), new TestObject('c')];
$sort = ClosureExpressionVisitor::sortByField('foo', -1);
@@ -244,7 +267,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertEquals('a', $objects[2]->getFoo());
}
public function testSortDelegate() : void
public function testSortDelegate(): void
{
$objects = [new TestObject('a', 'c'), new TestObject('a', 'b'), new TestObject('a', 'a')];
$sort = ClosureExpressionVisitor::sortByField('bar', 1);
@@ -257,7 +280,7 @@ class ClosureExpressionVisitorTest extends TestCase
self::assertEquals('c', $objects[2]->getBar());
}
public function testArrayComparison() : void
public function testArrayComparison(): void
{
$closure = $this->visitor->walkComparison($this->builder->eq('foo', 42));
@@ -340,7 +363,7 @@ class TestObjectNotCamelCase
$this->foo_bar = $foo_bar;
}
public function getFooBar() : ?int
public function getFooBar(): ?int
{
return $this->foo_bar;
}
@@ -360,7 +383,7 @@ class TestObjectBothCamelCaseAndUnderscore
$this->fooBar = $fooBar;
}
public function getFooBar() : ?int
public function getFooBar(): ?int
{
return $this->fooBar;
}
@@ -380,7 +403,7 @@ class TestObjectPublicCamelCaseAndPrivateUnderscore
$this->fooBar = $fooBar;
}
public function getFooBar() : ?int
public function getFooBar(): ?int
{
return $this->fooBar;
}

View File

@@ -7,17 +7,18 @@ namespace Doctrine\Tests\Common\Collections;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use function count;
use function is_string;
class CollectionTest extends BaseCollectionTest
{
protected function setUp() : void
protected function setUp(): void
{
$this->collection = new ArrayCollection();
}
public function testToString() : void
public function testToString(): void
{
$this->collection->add('testing');
self::assertTrue(is_string((string) $this->collection));
@@ -26,7 +27,7 @@ class CollectionTest extends BaseCollectionTest
/**
* @group DDC-1637
*/
public function testMatching() : void
public function testMatching(): void
{
$this->fillMatchingFixture();
@@ -39,7 +40,7 @@ class CollectionTest extends BaseCollectionTest
/**
* @group DDC-1637
*/
public function testMatchingOrdering() : void
public function testMatchingOrdering(): void
{
$this->fillMatchingFixture();
@@ -55,7 +56,7 @@ class CollectionTest extends BaseCollectionTest
/**
* @group DDC-1637
*/
public function testMatchingSlice() : void
public function testMatchingSlice(): void
{
$this->fillMatchingFixture();

View File

@@ -12,14 +12,14 @@ use PHPUnit\Framework\TestCase;
class CriteriaTest extends TestCase
{
public function testCreate() : void
public function testCreate(): void
{
$criteria = Criteria::create();
self::assertInstanceOf(Criteria::class, $criteria);
}
public function testConstructor() : void
public function testConstructor(): void
{
$expr = new Comparison('field', '=', 'value');
$criteria = new Criteria($expr, ['foo' => 'ASC'], 10, 20);
@@ -30,7 +30,7 @@ class CriteriaTest extends TestCase
self::assertEquals(20, $criteria->getMaxResults());
}
public function testWhere() : void
public function testWhere(): void
{
$expr = new Comparison('field', '=', 'value');
$criteria = new Criteria();
@@ -40,7 +40,7 @@ class CriteriaTest extends TestCase
self::assertSame($expr, $criteria->getWhereExpression());
}
public function testAndWhere() : void
public function testAndWhere(): void
{
$expr = new Comparison('field', '=', 'value');
$criteria = new Criteria();
@@ -56,7 +56,7 @@ class CriteriaTest extends TestCase
self::assertSame([$expr, $expr], $where->getExpressionList());
}
public function testAndWhereWithoutWhere() : void
public function testAndWhereWithoutWhere(): void
{
$expr = new Comparison('field', '=', 'value');
$criteria = new Criteria();
@@ -66,7 +66,7 @@ class CriteriaTest extends TestCase
self::assertSame($expr, $criteria->getWhereExpression());
}
public function testOrWhere() : void
public function testOrWhere(): void
{
$expr = new Comparison('field', '=', 'value');
$criteria = new Criteria();
@@ -82,7 +82,7 @@ class CriteriaTest extends TestCase
self::assertSame([$expr, $expr], $where->getExpressionList());
}
public function testOrWhereWithoutWhere() : void
public function testOrWhereWithoutWhere(): void
{
$expr = new Comparison('field', '=', 'value');
$criteria = new Criteria();
@@ -92,7 +92,7 @@ class CriteriaTest extends TestCase
self::assertSame($expr, $criteria->getWhereExpression());
}
public function testOrderings() : void
public function testOrderings(): void
{
$criteria = Criteria::create()
->orderBy(['foo' => 'ASC']);
@@ -100,7 +100,7 @@ class CriteriaTest extends TestCase
self::assertEquals(['foo' => 'ASC'], $criteria->getOrderings());
}
public function testExpr() : void
public function testExpr(): void
{
self::assertInstanceOf(ExpressionBuilder::class, Criteria::expr());
}

View File

@@ -15,7 +15,7 @@ class DerivedCollectionTest extends TestCase
* Tests that methods that create a new instance can be called in a derived
* class that implements different constructor semantics.
*/
public function testDerivedClassCreation() : void
public function testDerivedClassCreation(): void
{
$collection = new DerivedArrayCollection(new stdClass());
$closure = static function () {

View File

@@ -16,7 +16,10 @@ use RuntimeException;
*/
class CompositeExpressionTest extends TestCase
{
public function invalidDataProvider() : array
/**
* @return list<array{expression: mixed}>
*/
public function invalidDataProvider(): array
{
return [
['expression' => new Value('value')],
@@ -29,7 +32,7 @@ class CompositeExpressionTest extends TestCase
*
* @dataProvider invalidDataProvider
*/
public function testExceptions($expression) : void
public function testExceptions($expression): void
{
$type = CompositeExpression::TYPE_AND;
$expressions = [$expression];
@@ -38,7 +41,7 @@ class CompositeExpressionTest extends TestCase
new CompositeExpression($type, $expressions);
}
public function testGetType() : void
public function testGetType(): void
{
$compositeExpression = $this->createCompositeExpression();
@@ -48,7 +51,7 @@ class CompositeExpressionTest extends TestCase
self::assertSame($expectedType, $actualType);
}
protected function createCompositeExpression() : CompositeExpression
protected function createCompositeExpression(): CompositeExpression
{
$type = CompositeExpression::TYPE_AND;
$expressions = [$this->createMock(Expression::class)];
@@ -56,7 +59,7 @@ class CompositeExpressionTest extends TestCase
return new CompositeExpression($type, $expressions);
}
public function testGetExpressionList() : void
public function testGetExpressionList(): void
{
$compositeExpression = $this->createCompositeExpression();
$expectedExpressionList = [$this->createMock(Expression::class)];
@@ -65,7 +68,7 @@ class CompositeExpressionTest extends TestCase
self::assertEquals($expectedExpressionList, $actualExpressionList);
}
public function testVisitor() : void
public function testVisitor(): void
{
$compositeExpression = $this->createCompositeExpression();
@@ -74,7 +77,6 @@ class CompositeExpressionTest extends TestCase
->expects($this->once())
->method('walkCompositeExpression');
/** @var ExpressionVisitor $visitor */
$compositeExpression->visit($visitor);
}
}

View File

@@ -13,7 +13,7 @@ use PHPUnit\Framework\TestCase;
*/
class ValueTest extends TestCase
{
public function testGetter() : void
public function testGetter(): void
{
$value = 'foo';
$valueExpression = new Value($value);
@@ -23,14 +23,13 @@ class ValueTest extends TestCase
self::assertEquals($value, $actualValue);
}
public function testVisitor() : void
public function testVisitor(): void
{
$visitor = $this->getMockForAbstractClass(ExpressionVisitor::class);
$visitor
->expects($this->once())
->method('walkValue');
/** @var ExpressionVisitor $visitor */
$value = 'foo';
$valueExpression = new Value($value);
$valueExpression->visit($visitor);

View File

@@ -8,6 +8,7 @@ use Doctrine\Common\Collections\Expr\Comparison;
use Doctrine\Common\Collections\Expr\CompositeExpression;
use Doctrine\Common\Collections\ExpressionBuilder;
use PHPUnit\Framework\TestCase;
use TypeError;
/**
* @group DDC-1637
@@ -17,12 +18,12 @@ class ExpressionBuilderTest extends TestCase
/** @var ExpressionBuilder */
private $builder;
protected function setUp() : void
protected function setUp(): void
{
$this->builder = new ExpressionBuilder();
}
public function testAndX() : void
public function testAndX(): void
{
$expr = $this->builder->andX($this->builder->eq('a', 'b'));
@@ -30,7 +31,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(CompositeExpression::TYPE_AND, $expr->getType());
}
public function testOrX() : void
public function testOrX(): void
{
$expr = $this->builder->orX($this->builder->eq('a', 'b'));
@@ -38,7 +39,13 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(CompositeExpression::TYPE_OR, $expr->getType());
}
public function testEq() : void
public function testInvalidAndXArgument(): void
{
$this->expectException(TypeError::class);
$this->builder->andX('foo');
}
public function testEq(): void
{
$expr = $this->builder->eq('a', 'b');
@@ -46,7 +53,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::EQ, $expr->getOperator());
}
public function testNeq() : void
public function testNeq(): void
{
$expr = $this->builder->neq('a', 'b');
@@ -54,7 +61,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::NEQ, $expr->getOperator());
}
public function testLt() : void
public function testLt(): void
{
$expr = $this->builder->lt('a', 'b');
@@ -62,7 +69,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::LT, $expr->getOperator());
}
public function testGt() : void
public function testGt(): void
{
$expr = $this->builder->gt('a', 'b');
@@ -70,7 +77,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::GT, $expr->getOperator());
}
public function testGte() : void
public function testGte(): void
{
$expr = $this->builder->gte('a', 'b');
@@ -78,7 +85,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::GTE, $expr->getOperator());
}
public function testLte() : void
public function testLte(): void
{
$expr = $this->builder->lte('a', 'b');
@@ -86,7 +93,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::LTE, $expr->getOperator());
}
public function testIn() : void
public function testIn(): void
{
$expr = $this->builder->in('a', ['b']);
@@ -94,7 +101,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::IN, $expr->getOperator());
}
public function testNotIn() : void
public function testNotIn(): void
{
$expr = $this->builder->notIn('a', ['b']);
@@ -102,7 +109,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::NIN, $expr->getOperator());
}
public function testIsNull() : void
public function testIsNull(): void
{
$expr = $this->builder->isNull('a');
@@ -110,7 +117,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::EQ, $expr->getOperator());
}
public function testContains() : void
public function testContains(): void
{
$expr = $this->builder->contains('a', 'b');
@@ -118,7 +125,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::CONTAINS, $expr->getOperator());
}
public function testMemberOf() : void
public function testMemberOf(): void
{
$expr = $this->builder->memberOf('b', ['a']);
@@ -126,7 +133,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::MEMBER_OF, $expr->getOperator());
}
public function testStartsWith() : void
public function testStartsWith(): void
{
$expr = $this->builder->startsWith('a', 'b');
@@ -134,7 +141,7 @@ class ExpressionBuilderTest extends TestCase
self::assertEquals(Comparison::STARTS_WITH, $expr->getOperator());
}
public function testEndsWith() : void
public function testEndsWith(): void
{
$expr = $this->builder->endsWith('a', 'b');

View File

@@ -15,6 +15,9 @@ final class DerivedArrayCollection extends ArrayCollection
/** @var stdClass */
private $foo;
/**
* @param mixed[] $elements
*/
public function __construct(stdClass $foo, array $elements = [])
{
$this->foo = $foo;
@@ -22,7 +25,12 @@ final class DerivedArrayCollection extends ArrayCollection
parent::__construct($elements);
}
protected function createFrom(array $elements) : parent
/**
* @param mixed[] $elements
*
* @return self<mixed>
*/
protected function createFrom(array $elements): self
{
return new static($this->foo, $elements);
}

View File

@@ -15,12 +15,12 @@ class LazyArrayCollection extends AbstractLazyCollection
/**
* Apply the collection only in method doInitialize
*
* @var Collection
* @var Collection<mixed>
*/
private $collectionOnInitialization;
/**
* @param Collection $collection
* @param Collection<mixed> $collection
*/
public function __construct(Collection $collection)
{
@@ -30,7 +30,7 @@ class LazyArrayCollection extends AbstractLazyCollection
/**
* Do the initialization logic.
*/
protected function doInitialize() : void
protected function doInitialize(): void
{
$this->collection = $this->collectionOnInitialization;
}