From 6e8451e7812f6c1a9e7c7f050e553a0065129016 Mon Sep 17 00:00:00 2001 From: Sebastiaan Stok Date: Fri, 30 Jul 2021 16:39:42 +0200 Subject: [PATCH 1/8] Bump minimum PHP version to 7.4 --- UPGRADE-2.0.md | 6 ++-- composer.json | 2 +- lib/ApiPlatform/composer.json | 2 +- lib/Core/composer.json | 4 +-- lib/Doctrine/Dbal/composer.json | 2 +- lib/Doctrine/Orm/composer.json | 2 +- lib/Elasticsearch/composer.json | 2 +- lib/Symfony/SearchBundle/composer.json | 2 +- lib/Symfony/Validator/composer.json | 2 +- phpunit.xml.dist | 48 ++++++++++++++------------ phpunit/mysql.xml | 48 +++++++++++++++----------- phpunit/pgsql.xml | 48 +++++++++++++++----------- 12 files changed, 94 insertions(+), 74 deletions(-) diff --git a/UPGRADE-2.0.md b/UPGRADE-2.0.md index d6091670..5c4aa2fd 100644 --- a/UPGRADE-2.0.md +++ b/UPGRADE-2.0.md @@ -1,9 +1,11 @@ UPGRADE FROM 2.0-BETA1 to 2.0-BETA2 =================================== - * Support for PHP 7.1 was dropped, you need at least PHP 7.2 or greater. + * Support for PHP < 7.4 was dropped. - * Support for Symfony below 4.4 was dropped. + * Support for Symfony < 4.4 was dropped. + + * Support for PHPUnit < 9.5 was dropped. ### Doctrine ORM diff --git a/composer.json b/composer.json index 68313736..692a3d16 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,7 @@ "friendsofsymfony/elastica-bundle": "^5.0 || ^5.2@dev", "matthiasnoback/symfony-dependency-injection-test": "^3.0 || ^4.1.1", "moneyphp/money": "^3.2.0", - "phpunit/phpunit": "^7.5.20 || ^8.0 || ^9.5.7", + "phpunit/phpunit": "^9.5.7", "psr/simple-cache": "^1.0.0", "ruflin/elastica": "^3.2 || ^6.0.0", "symfony/asset": "^4.4 || ^5.0", diff --git a/lib/ApiPlatform/composer.json b/lib/ApiPlatform/composer.json index 3d5a56e3..744964d7 100644 --- a/lib/ApiPlatform/composer.json +++ b/lib/ApiPlatform/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": ">=7.2", + "php": ">=7.4", "api-platform/core": "^2.0.10", "rollerworks/search": "^2.0@dev,>=2.0.0-BETA2", "rollerworks/uri-encoder": "^1.1.0 || ^2.0", diff --git a/lib/Core/composer.json b/lib/Core/composer.json index 34e965d5..460e594f 100644 --- a/lib/Core/composer.json +++ b/lib/Core/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=7.2", + "php": ">=7.4", "nesbot/carbon": "^2.38", "psr/container": "^1.0.0", "symfony/intl": "^4.4 || ^5.0", @@ -33,7 +33,7 @@ }, "require-dev": { "moneyphp/money": "^3.2.0", - "phpunit/phpunit": "^6.5.4", + "phpunit/phpunit": "^9.5", "symfony/phpunit-bridge": "^4.4 || ^5.0", "symfony/var-dumper": "^4.4 || ^5.0" }, diff --git a/lib/Doctrine/Dbal/composer.json b/lib/Doctrine/Dbal/composer.json index 47709f45..a1db68fd 100644 --- a/lib/Doctrine/Dbal/composer.json +++ b/lib/Doctrine/Dbal/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=7.2", + "php": ">=7.4", "doctrine/dbal": "^2.8", "psr/simple-cache": "^1.0.0", "rollerworks/search": "^2.0@dev,>=2.0.0-BETA1" diff --git a/lib/Doctrine/Orm/composer.json b/lib/Doctrine/Orm/composer.json index 161c7bd4..45804512 100644 --- a/lib/Doctrine/Orm/composer.json +++ b/lib/Doctrine/Orm/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=7.2", + "php": ">=7.4", "doctrine/orm": "^2.6", "rollerworks/search": "^2.0@dev,>=2.0.0-BETA1", "rollerworks/search-doctrine-dbal": "^2.0@dev,>=2.0.0-BETA1" diff --git a/lib/Elasticsearch/composer.json b/lib/Elasticsearch/composer.json index 7bcf2c4d..dc209e2c 100644 --- a/lib/Elasticsearch/composer.json +++ b/lib/Elasticsearch/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=7.2", + "php": ">=7.4", "psr/simple-cache": "^1.0", "rollerworks/search": "^2.0@dev,>=2.0.0-BETA1", "ruflin/elastica": "^4.0 || ^5.0 || ^6.0" diff --git a/lib/Symfony/SearchBundle/composer.json b/lib/Symfony/SearchBundle/composer.json index a97d51f9..7a5ab4c2 100644 --- a/lib/Symfony/SearchBundle/composer.json +++ b/lib/Symfony/SearchBundle/composer.json @@ -17,7 +17,7 @@ } ], "require": { - "php": ">=7.2", + "php": ">=7.4", "psr/simple-cache": "^1.0.0", "rollerworks/search": "^2.0@dev,>=2.0.0-ALPHA23", "symfony/framework-bundle": "^4.4 || ^5.0", diff --git a/lib/Symfony/Validator/composer.json b/lib/Symfony/Validator/composer.json index cbe28ea2..812168ab 100644 --- a/lib/Symfony/Validator/composer.json +++ b/lib/Symfony/Validator/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=7.2", + "php": ">=7.4", "rollerworks/search": "^2.0@dev,>=2.0.0-BETA1", "symfony/validator": "^4.4 || ^5.0" }, diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7f99bf3a..01af4651 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,21 +1,24 @@ + - - - - - + + + + + @@ -27,19 +30,18 @@ - - + + ./lib - - ./vendor/ - ./lib/*/Tests/ - ./lib/*/*/Tests/ - - - + + + ./vendor/ + ./lib/*/Tests/ + ./lib/*/*/Tests/ + + - diff --git a/phpunit/mysql.xml b/phpunit/mysql.xml index 53e4d88a..b7c7a447 100644 --- a/phpunit/mysql.xml +++ b/phpunit/mysql.xml @@ -1,19 +1,24 @@ - - - - - + + + + + @@ -25,20 +30,23 @@ - ../lib/Doctrine/ + ../lib/*/Tests/ + ../lib/*/*/Tests/ + ../lib/Doctrine/Dbal/Tests/ + ../lib/Doctrine/Orm/Tests/ - - + + ../lib - - ../vendor/ - ../lib/*/Tests/ - ../lib/*/*/Tests/ - - - + + + ../vendor/ + ../lib/*/Tests/ + ../lib/*/*/Tests/ + + diff --git a/phpunit/pgsql.xml b/phpunit/pgsql.xml index bc8b1bce..229e3b52 100644 --- a/phpunit/pgsql.xml +++ b/phpunit/pgsql.xml @@ -1,19 +1,24 @@ - - - - - + + + + + @@ -25,20 +30,23 @@ - ../lib/Doctrine/ + ../lib/*/Tests/ + ../lib/*/*/Tests/ + ../lib/Doctrine/Dbal/Tests/ + ../lib/Doctrine/Orm/Tests/ - - + + ../lib - - ../vendor/ - ../lib/*/Tests/ - ../lib/*/*/Tests/ - - - + + + ../vendor/ + ../lib/*/Tests/ + ../lib/*/*/Tests/ + + From afae894e4c238d9a44c25d42bd845e06e2605902 Mon Sep 17 00:00:00 2001 From: Sebastiaan Stok Date: Thu, 5 Aug 2021 16:02:36 +0200 Subject: [PATCH 2/8] [Elasticsearch] Upgrade to Elastica 5 Note: Because Elasticsearch has changed the way how dates are stored it's now required to convert there internal value when using this has_child query-script for ordering (sorting). The FosElasticaBundle is no longer required --- .github/workflows/ci.yaml | 2 +- UPGRADE-2.0.md | 8 ++ composer.json | 3 +- docker-compose.yaml | 2 +- .../Extension/SearchExtension.php | 7 +- .../Extension/SearchExtensionTest.php | 3 +- .../SearchConditionListenerTest.php | 7 +- lib/Core/Field/OrderFieldType.php | 4 + lib/Core/GenericSearchFactory.php | 19 ++- lib/Elasticsearch/ChildOrderConversion.php | 33 ++++++ .../Conversion/DateChildOrderConversion.php | 24 ++++ .../Extension/ElasticsearchExtension.php | 1 + .../Extension/Type/BirthdayTypeExtension.php | 2 + .../Extension/Type/DateTimeTypeExtension.php | 2 + .../Extension/Type/DateTypeExtension.php | 2 + .../Extension/Type/FieldTypeExtension.php | 27 +++-- .../Extension/Type/OrderTypeExtension.php | 48 ++++++++ lib/Elasticsearch/FieldMapping.php | 24 +++- lib/Elasticsearch/QueryConditionGenerator.php | 5 +- .../ConditionGeneratorResultsTest.php | 6 +- .../FunctionalElasticsearchTestCase.php | 110 +++++++++--------- lib/Elasticsearch/composer.json | 2 +- .../Compiler/ElasticaBundlePass.php | 32 ----- .../Compiler/ElasticaClientPass.php | 41 +++++++ .../Resources/config/elasticsearch.xml | 6 + .../SearchBundle/RollerworksSearchBundle.php | 2 +- .../Application/config/api_platform.yml | 14 ++- .../Application/config/elasticsearch.yml | 7 ++ 28 files changed, 312 insertions(+), 131 deletions(-) create mode 100644 lib/Elasticsearch/ChildOrderConversion.php create mode 100644 lib/Elasticsearch/Extension/Conversion/DateChildOrderConversion.php create mode 100644 lib/Elasticsearch/Extension/Type/OrderTypeExtension.php delete mode 100644 lib/Symfony/SearchBundle/DependencyInjection/Compiler/ElasticaBundlePass.php create mode 100644 lib/Symfony/SearchBundle/DependencyInjection/Compiler/ElasticaClientPass.php diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 48dc9516..a7589cbc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -45,7 +45,7 @@ jobs: # https://hub.docker.com/_/elasticsearch/ elasticsearch: - image: elasticsearch:5.6.3 + image: elasticsearch:7.3.0 ports: - "59200:9200" options: -e="discovery.type=single-node" -e="xpack.security.enabled=false" --health-cmd="curl http://localhost:9200/_cluster/health" --health-interval=10s --health-timeout=5s --health-retries=10 diff --git a/UPGRADE-2.0.md b/UPGRADE-2.0.md index 5c4aa2fd..b760f782 100644 --- a/UPGRADE-2.0.md +++ b/UPGRADE-2.0.md @@ -7,6 +7,14 @@ UPGRADE FROM 2.0-BETA1 to 2.0-BETA2 * Support for PHPUnit < 9.5 was dropped. +### Elasticsearch + + * Support for Elastica 6 was dropped. + + * Support for Elasticsearch 6 was dropped. + + _See the upgrade instructions of Elasticsearch itself for more information._ + ### Doctrine ORM * Support for passing a `Doctrine\ORM\Query` object in the generators was removed, diff --git a/composer.json b/composer.json index 692a3d16..47f4e99a 100644 --- a/composer.json +++ b/composer.json @@ -40,12 +40,11 @@ "doctrine/dbal": "^2.10.3", "doctrine/doctrine-bundle": "^1.9.1 || ^2.0", "doctrine/orm": "^2.7.3", - "friendsofsymfony/elastica-bundle": "^5.0 || ^5.2@dev", "matthiasnoback/symfony-dependency-injection-test": "^3.0 || ^4.1.1", "moneyphp/money": "^3.2.0", "phpunit/phpunit": "^9.5.7", "psr/simple-cache": "^1.0.0", - "ruflin/elastica": "^3.2 || ^6.0.0", + "ruflin/elastica": "^7.0", "symfony/asset": "^4.4 || ^5.0", "symfony/browser-kit": "^4.4 || ^5.0", "symfony/dom-crawler": "^4.4 || ^5.0", diff --git a/docker-compose.yaml b/docker-compose.yaml index 4b305b36..7f50b985 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -33,7 +33,7 @@ services: - "53306:3306" elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:5.6.3 + image: docker.elastic.co/elasticsearch/elasticsearch:7.3.0 environment: - "discovery.type=single-node" - "xpack.security.enabled=false" diff --git a/lib/ApiPlatform/Elasticsearch/Extension/SearchExtension.php b/lib/ApiPlatform/Elasticsearch/Extension/SearchExtension.php index 622fce2b..f17c4c4a 100644 --- a/lib/ApiPlatform/Elasticsearch/Extension/SearchExtension.php +++ b/lib/ApiPlatform/Elasticsearch/Extension/SearchExtension.php @@ -19,7 +19,6 @@ use Doctrine\Persistence\ManagerRegistry; use Elastica\Client; use Elastica\Document; -use Elastica\Query; use Elastica\Search; use Rollerworks\Component\Search\ApiPlatform\ArrayKeysValidator; use Rollerworks\Component\Search\Elasticsearch\ElasticsearchFactory; @@ -121,11 +120,9 @@ public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGenerator foreach ($mappings as $mapping) { $index = $this->client->getIndex($mapping->indexName); - $type = $index->getType($mapping->typeName); - $search - ->addIndex($index) - ->addType($type); + $search->addIndex($index); } + $response = $search->search($query); // NOTE: written like this so we only check if we have a normalizer once diff --git a/lib/ApiPlatform/Tests/Elasticsearch/Extension/SearchExtensionTest.php b/lib/ApiPlatform/Tests/Elasticsearch/Extension/SearchExtensionTest.php index 4f4bebc9..ca74252f 100644 --- a/lib/ApiPlatform/Tests/Elasticsearch/Extension/SearchExtensionTest.php +++ b/lib/ApiPlatform/Tests/Elasticsearch/Extension/SearchExtensionTest.php @@ -23,6 +23,7 @@ use Elastica\Query; use Elastica\Response; use PHPUnit\Framework\TestCase; +use Prophecy\Argument; use Rollerworks\Component\Search\ApiPlatform\Elasticsearch\Extension\SearchExtension; use Rollerworks\Component\Search\ApiPlatform\Tests\Fixtures\Dummy; use Rollerworks\Component\Search\Elasticsearch\CachedConditionGenerator; @@ -80,7 +81,7 @@ public function apply_to_collection_with_valid_condition(): void $managerRegistry = $managerRegistryProphecy->reveal(); $elasticaClientProphecy = $this->prophesize(Client::class); - $elasticaClientProphecy->request('/_search', 'GET', $query->toArray(), [])->willReturn($elasticaResponse); + $elasticaClientProphecy->request('/_search', Argument::in(['POST', 'GET']), $query->toArray(), [])->willReturn($elasticaResponse)->shouldBeCalled(); $elasticaClient = $elasticaClientProphecy->reveal(); $conditionGeneratorProphecy = $this->prophesize(QueryConditionGenerator::class); diff --git a/lib/ApiPlatform/Tests/EventListener/SearchConditionListenerTest.php b/lib/ApiPlatform/Tests/EventListener/SearchConditionListenerTest.php index 5cf8aeed..55ea93e2 100644 --- a/lib/ApiPlatform/Tests/EventListener/SearchConditionListenerTest.php +++ b/lib/ApiPlatform/Tests/EventListener/SearchConditionListenerTest.php @@ -41,7 +41,7 @@ final class SearchConditionListenerTest extends SearchIntegrationTestCase { /** @test */ - public function it_sets_search_condition_and_config_for_empty_qeury(): void + public function it_sets_search_condition_and_config_for_empty_query(): void { $dummyMetadata = new ResourceMetadata( 'dummy', @@ -142,7 +142,10 @@ public function it_sets_search_condition_and_config_for_json_query(): void self::assertEquals(BookFieldSet::class, $config->getFieldSet()->getSetName()); } - /** @test */ + /** + * @test + * @group legacy + */ public function it_requires_a_string_search_condition(): void { $dummyMetadata = new ResourceMetadata( diff --git a/lib/Core/Field/OrderFieldType.php b/lib/Core/Field/OrderFieldType.php index eccd2420..4323216c 100644 --- a/lib/Core/Field/OrderFieldType.php +++ b/lib/Core/Field/OrderFieldType.php @@ -32,6 +32,8 @@ public function configureOptions(OptionsResolver $resolver): void 'default' => null, 'case' => OrderTransformer::CASE_UPPERCASE, 'alias' => ['ASC' => 'ASC', 'DESC' => 'DESC'], + 'type' => null, + 'type_options' => [], ]); $resolver->setAllowedValues('case', [ @@ -40,6 +42,8 @@ public function configureOptions(OptionsResolver $resolver): void ]); $resolver->setAllowedTypes('alias', 'array'); $resolver->setAllowedTypes('default', ['null', 'string']); + $resolver->setAllowedTypes('type', ['string', 'null']); + $resolver->setAllowedTypes('type_options', ['array']); } public function buildType(FieldConfig $config, array $options): void diff --git a/lib/Core/GenericSearchFactory.php b/lib/Core/GenericSearchFactory.php index 5f85ec44..308327a4 100644 --- a/lib/Core/GenericSearchFactory.php +++ b/lib/Core/GenericSearchFactory.php @@ -14,6 +14,7 @@ namespace Rollerworks\Component\Search; use Rollerworks\Component\Search\Field\FieldConfig; +use Rollerworks\Component\Search\Field\OrderField; use Rollerworks\Component\Search\Field\TypeRegistry; /** @@ -46,16 +47,28 @@ public function createFieldSet($configurator): FieldSet public function createField(string $name, string $type, array $options = []): FieldConfig { - $type = $this->registry->getType($type); - $field = $type->createField($name, $options); + if (OrderField::isOrder($name) && isset($options['type'])) { + $options = $this->createOptionsForOrderField($name, $options); + } + + $resolvedType = $this->registry->getType($type); + $field = $resolvedType->createField($name, $options); // Explicitly call buildType() in order to be able to override either // createField() or buildType() in the resolved field type - $type->buildType($field, $field->getOptions()); + $resolvedType->buildType($field, $field->getOptions()); return $field; } + private function createOptionsForOrderField(string $name, array $options): array + { + $type = $this->registry->getType($options['type']); + $options['type_options'] = $type->getOptionsResolver()->resolve($options['type_options'] ?? []); + + return $options; + } + public function createFieldSetBuilder(): FieldSetBuilder { return new GenericFieldSetBuilder($this); diff --git a/lib/Elasticsearch/ChildOrderConversion.php b/lib/Elasticsearch/ChildOrderConversion.php new file mode 100644 index 00000000..5a038a98 --- /dev/null +++ b/lib/Elasticsearch/ChildOrderConversion.php @@ -0,0 +1,33 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Rollerworks\Component\Search\Elasticsearch; + +/** + * The ChildOrderConversion converts a has_child QueryScript + * to an usable format, for example dates are not natively + * supported for sorting, and need to be converted milliseconds. + * + * Caution: This must not be combined with other Elasticsearch conversions. + */ +interface ChildOrderConversion +{ + /** + * Returns the query-script in transformed format. + * + * @param string $script either doc["field-name"].value + * + * @return string either doc["field-name"].value.millis + */ + public function convert(string $property, string $script): string; +} diff --git a/lib/Elasticsearch/Extension/Conversion/DateChildOrderConversion.php b/lib/Elasticsearch/Extension/Conversion/DateChildOrderConversion.php new file mode 100644 index 00000000..89182403 --- /dev/null +++ b/lib/Elasticsearch/Extension/Conversion/DateChildOrderConversion.php @@ -0,0 +1,24 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Rollerworks\Component\Search\Elasticsearch\Extension\Conversion; + +use Rollerworks\Component\Search\Elasticsearch\ChildOrderConversion; + +final class DateChildOrderConversion implements ChildOrderConversion +{ + public function convert(string $property, string $script): string + { + return \sprintf('%s.millis', $script); + } +} diff --git a/lib/Elasticsearch/Extension/ElasticsearchExtension.php b/lib/Elasticsearch/Extension/ElasticsearchExtension.php index 037ad152..7325dd8a 100644 --- a/lib/Elasticsearch/Extension/ElasticsearchExtension.php +++ b/lib/Elasticsearch/Extension/ElasticsearchExtension.php @@ -21,6 +21,7 @@ protected function loadTypesExtensions(): array { return [ new Type\FieldTypeExtension(), + new Type\OrderTypeExtension(), new Type\DateTypeExtension(new Conversion\DateConversion()), new Type\DateTimeTypeExtension(new Conversion\DateTimeConversion()), new Type\MoneyTypeExtension(new Conversion\CurrencyConversion()), diff --git a/lib/Elasticsearch/Extension/Type/BirthdayTypeExtension.php b/lib/Elasticsearch/Extension/Type/BirthdayTypeExtension.php index af08c077..d008599c 100644 --- a/lib/Elasticsearch/Extension/Type/BirthdayTypeExtension.php +++ b/lib/Elasticsearch/Extension/Type/BirthdayTypeExtension.php @@ -13,6 +13,7 @@ namespace Rollerworks\Component\Search\Elasticsearch\Extension\Type; +use Rollerworks\Component\Search\Elasticsearch\Extension\Conversion\DateChildOrderConversion; use Rollerworks\Component\Search\Elasticsearch\Extension\Conversion\DateConversion; use Rollerworks\Component\Search\Extension\Core\Type\BirthdayType; use Rollerworks\Component\Search\Field\AbstractFieldTypeExtension; @@ -35,6 +36,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setDefaults( [ 'elasticsearch_conversion' => $this->conversion, + 'elasticsearch_child_order_conversion' => new DateChildOrderConversion(), ] ); } diff --git a/lib/Elasticsearch/Extension/Type/DateTimeTypeExtension.php b/lib/Elasticsearch/Extension/Type/DateTimeTypeExtension.php index a3a08afb..81867354 100644 --- a/lib/Elasticsearch/Extension/Type/DateTimeTypeExtension.php +++ b/lib/Elasticsearch/Extension/Type/DateTimeTypeExtension.php @@ -13,6 +13,7 @@ namespace Rollerworks\Component\Search\Elasticsearch\Extension\Type; +use Rollerworks\Component\Search\Elasticsearch\Extension\Conversion\DateChildOrderConversion; use Rollerworks\Component\Search\Elasticsearch\Extension\Conversion\DateTimeConversion; use Rollerworks\Component\Search\Extension\Core\Type\DateTimeType; use Rollerworks\Component\Search\Field\AbstractFieldTypeExtension; @@ -35,6 +36,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setDefaults( [ 'elasticsearch_conversion' => $this->conversion, + 'elasticsearch_child_order_conversion' => new DateChildOrderConversion(), ] ); } diff --git a/lib/Elasticsearch/Extension/Type/DateTypeExtension.php b/lib/Elasticsearch/Extension/Type/DateTypeExtension.php index d409bf7b..6fd433b9 100644 --- a/lib/Elasticsearch/Extension/Type/DateTypeExtension.php +++ b/lib/Elasticsearch/Extension/Type/DateTypeExtension.php @@ -13,6 +13,7 @@ namespace Rollerworks\Component\Search\Elasticsearch\Extension\Type; +use Rollerworks\Component\Search\Elasticsearch\Extension\Conversion\DateChildOrderConversion; use Rollerworks\Component\Search\Elasticsearch\Extension\Conversion\DateConversion; use Rollerworks\Component\Search\Extension\Core\Type\DateType; use Rollerworks\Component\Search\Field\AbstractFieldTypeExtension; @@ -35,6 +36,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setDefaults( [ 'elasticsearch_conversion' => $this->conversion, + 'elasticsearch_child_order_conversion' => new DateChildOrderConversion(), ] ); } diff --git a/lib/Elasticsearch/Extension/Type/FieldTypeExtension.php b/lib/Elasticsearch/Extension/Type/FieldTypeExtension.php index d49f0f23..86d48349 100644 --- a/lib/Elasticsearch/Extension/Type/FieldTypeExtension.php +++ b/lib/Elasticsearch/Extension/Type/FieldTypeExtension.php @@ -13,28 +13,31 @@ namespace Rollerworks\Component\Search\Elasticsearch\Extension\Type; +use Rollerworks\Component\Search\Elasticsearch\ChildOrderConversion; use Rollerworks\Component\Search\Elasticsearch\QueryConversion; use Rollerworks\Component\Search\Elasticsearch\ValueConversion; use Rollerworks\Component\Search\Extension\Core\Type\SearchFieldType; use Rollerworks\Component\Search\Field\AbstractFieldTypeExtension; use Symfony\Component\OptionsResolver\OptionsResolver; -/** - * Class FieldTypeExtension. - */ class FieldTypeExtension extends AbstractFieldTypeExtension { public function configureOptions(OptionsResolver $resolver): void { - $resolver->setDefaults(['elasticsearch_conversion' => null]); - $resolver->setAllowedTypes( - 'elasticsearch_conversion', - [ - 'null', - ValueConversion::class, - QueryConversion::class, - ] - ); + $resolver + ->setDefaults([ + 'elasticsearch_child_order_conversion' => null, + 'elasticsearch_conversion' => null, + ]) + ->setAllowedTypes('elasticsearch_child_order_conversion', ['null', ChildOrderConversion::class]) + ->setAllowedTypes( + 'elasticsearch_conversion', + [ + 'null', + ValueConversion::class, + QueryConversion::class, + ] + ); } public function getExtendedType(): string diff --git a/lib/Elasticsearch/Extension/Type/OrderTypeExtension.php b/lib/Elasticsearch/Extension/Type/OrderTypeExtension.php new file mode 100644 index 00000000..f65d8811 --- /dev/null +++ b/lib/Elasticsearch/Extension/Type/OrderTypeExtension.php @@ -0,0 +1,48 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Rollerworks\Component\Search\Elasticsearch\Extension\Type; + +use Rollerworks\Component\Search\Elasticsearch\ChildOrderConversion; +use Rollerworks\Component\Search\Elasticsearch\QueryConversion; +use Rollerworks\Component\Search\Elasticsearch\ValueConversion; +use Rollerworks\Component\Search\Field\AbstractFieldTypeExtension; +use Rollerworks\Component\Search\Field\OrderFieldType; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class OrderTypeExtension extends AbstractFieldTypeExtension +{ + public function configureOptions(OptionsResolver $resolver): void + { + $resolver + ->setDefaults([ + 'elasticsearch_child_order_conversion' => static fn (Options $options) => $options['type_options']['elasticsearch_child_order_conversion'] ?? null, + 'elasticsearch_conversion' => null, + ]) + ->setAllowedTypes('elasticsearch_child_order_conversion', ['null', ChildOrderConversion::class]) + ->setAllowedTypes( + 'elasticsearch_conversion', + [ + 'null', + ValueConversion::class, + QueryConversion::class, + ] + ); + } + + public function getExtendedType(): string + { + return OrderFieldType::class; + } +} diff --git a/lib/Elasticsearch/FieldMapping.php b/lib/Elasticsearch/FieldMapping.php index f35548bd..1c12cb44 100644 --- a/lib/Elasticsearch/FieldMapping.php +++ b/lib/Elasticsearch/FieldMapping.php @@ -39,6 +39,8 @@ final class FieldMapping implements \Serializable */ public $queryConversion; + public ?ChildOrderConversion $childOrderConversion = null; + /** * @var self[] */ @@ -60,18 +62,23 @@ public function __construct(string $fieldName, string $property, FieldConfig $fi $this->nested = $mapping['nested']; $this->join = $mapping['join']; - $this->conditions = $this->expandConditions($conditions, $fieldConfig); - $this->options = $options; - $converter = $fieldConfig->getOption('elasticsearch_conversion'); + $childOrderConverter = $fieldConfig->getOption('elasticsearch_child_order_conversion'); if ($converter instanceof ValueConversion) { $this->valueConversion = $converter; } + if ($childOrderConverter instanceof ChildOrderConversion) { + $this->childOrderConversion = $childOrderConverter; + } + if ($converter instanceof QueryConversion) { $this->queryConversion = $converter; } + + $this->conditions = $this->expandConditions($conditions, $fieldConfig); + $this->options = $options; } /** @@ -138,16 +145,23 @@ private function parseProperty(string $property): array private function expandConditions(array $conditions, FieldConfig $fieldConfig): array { - if (OrderField::isOrder($this->fieldName) && $this->join) { + if ($this->join && OrderField::isOrder($this->fieldName)) { // sorting by has_child query is special // https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-has-child-query.html#_sorting $property = $this->indexName . ($this->typeName ? '/' . $this->typeName : '') . '#' . $this->join['type'] . '>'; + $queryScript = \sprintf('doc["%s"].value', $this->propertyName); + + if ($this->childOrderConversion !== null) { + $queryScript = $this->childOrderConversion->convert($property, $queryScript); + } + + $queryScript = \sprintf('%1$s * %2$s', QueryConditionGenerator::SORT_SCORE, $queryScript); $scoreQuery = new self('_', $property, $fieldConfig, [], ['score_mode' => 'max']); $scoreQuery->propertyQuery = [ QueryConditionGenerator::QUERY_FUNCTION_SCORE => [ QueryConditionGenerator::QUERY_SCRIPT_SCORE => [ - QueryConditionGenerator::QUERY_SCRIPT => \sprintf('%1$s * doc["%2$s"].value', QueryConditionGenerator::SORT_SCORE, $this->propertyName), + QueryConditionGenerator::QUERY_SCRIPT => $queryScript, ], ], ]; diff --git a/lib/Elasticsearch/QueryConditionGenerator.php b/lib/Elasticsearch/QueryConditionGenerator.php index e3ee7cca..1a62569d 100644 --- a/lib/Elasticsearch/QueryConditionGenerator.php +++ b/lib/Elasticsearch/QueryConditionGenerator.php @@ -336,11 +336,10 @@ private function processOrder(?SearchOrder $order, array &$clause, array &$condi return; } - $orderGroup = $order->getValuesGroup(); $hints = new QueryPreparationHints(); $hints->context = QueryPreparationHints::CONTEXT_ORDER; - foreach ($orderGroup->getFields() as $fieldName => $valuesBag) { + foreach ($order->getFields() as $fieldName => $direction) { $mapping = $this->mappings[$fieldName]; // apply conditions from order fields @@ -365,7 +364,7 @@ private function processOrder(?SearchOrder $order, array &$clause, array &$condi $mapping->options, [ $propertyName => [ - self::SORT_ORDER => \current($valuesBag->getSimpleValues()), + self::SORT_ORDER => $direction, ], ] ); diff --git a/lib/Elasticsearch/Tests/Functional/ConditionGeneratorResultsTest.php b/lib/Elasticsearch/Tests/Functional/ConditionGeneratorResultsTest.php index deae8bc2..833399fc 100644 --- a/lib/Elasticsearch/Tests/Functional/ConditionGeneratorResultsTest.php +++ b/lib/Elasticsearch/Tests/Functional/ConditionGeneratorResultsTest.php @@ -179,19 +179,19 @@ public function it_finds_by_excluding_equals_pattern(): void /** @test */ public function it_sorts_by_total(): void { - $this->makeTest('@total: ASC', [3, 6, 8, 9, 7, 2, 4, 1, 5]); + $this->makeTest('@total: ASC', [3, 6, 7, 8, 9, 2, 1, 4, 5]); } /** @test */ public function it_sorts_by_total_desc(): void { - $this->makeTest('@total: DESC', [5, 4, 1, 2, 8, 9, 7, 6, 3]); + $this->makeTest('@total: DESC', [5, 1, 4, 2, 7, 8, 9, 6, 3]); } /** @test */ public function it_sorts_by_customer_name(): void { - $this->makeTest('@customer-name: ASC', [5, 2, 4, 3, 8, 9, 1, 7, 6]); + $this->makeTest('@customer-name: ASC', [5, 2, 3, 4, 1, 7, 8, 9, 6]); } /** @test */ diff --git a/lib/Elasticsearch/Tests/Functional/FunctionalElasticsearchTestCase.php b/lib/Elasticsearch/Tests/Functional/FunctionalElasticsearchTestCase.php index 83b0e41a..59da81f5 100644 --- a/lib/Elasticsearch/Tests/Functional/FunctionalElasticsearchTestCase.php +++ b/lib/Elasticsearch/Tests/Functional/FunctionalElasticsearchTestCase.php @@ -17,7 +17,6 @@ use Elastica\Document; use Elastica\Exception\ResponseException; use Elastica\Search; -use Elastica\Type\Mapping; use Rollerworks\Component\Search\Elasticsearch\QueryConditionGenerator; use Rollerworks\Component\Search\Extension\Core\Type\BirthdayType; use Rollerworks\Component\Search\Extension\Core\Type\ChoiceType; @@ -31,22 +30,28 @@ use Rollerworks\Component\Search\SearchCondition; use Rollerworks\Component\Search\Tests\Elasticsearch\ElasticsearchTestCase; -/** - * Class FunctionalElasticsearchTestCase. - */ abstract class FunctionalElasticsearchTestCase extends ElasticsearchTestCase { protected function setUp(): void { - $mappings = $this->getMappings(); - $documents = $this->getDocuments(); + try { + $mappings = $this->getMappings(); + $documents = $this->getDocuments(); - foreach ($mappings as $name => $properties) { - if (\array_key_exists($name, $documents) === false) { - throw new \RuntimeException(\sprintf('No documents for mapping "%1$s" defined', $name)); + foreach ($mappings as $name => $properties) { + if (\array_key_exists($name, $documents) === false) { + throw new \RuntimeException(\sprintf('No documents for mapping "%1$s" defined', $name)); + } + $data = $documents[$name]; + $this->createDocuments($name, $properties, $data); } - $data = $documents[$name]; - $this->createDocuments($name, $properties, $data); + } catch (ResponseException $exception) { + static::fail(\sprintf( + "%s\nWith path: %s\nWith query: ---------------------\n%s\n---------------------------------\n", + $exception->getMessage(), + $exception->getRequest()->getPath(), + \json_encode($exception->getRequest()->toArray(), \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT) + )); } parent::setUp(); @@ -73,7 +78,7 @@ protected function getMappings(): array 'birthday' => ['type' => 'date'], ], ], - 'label' => ['type' => 'string'], + 'label' => ['type' => 'text'], 'pubdate' => ['type' => 'date'], 'pubdatetime' => ['type' => 'date'], 'status' => ['type' => 'integer'], @@ -81,7 +86,7 @@ protected function getMappings(): array 'items' => [ 'type' => 'nested', 'properties' => [ - 'label' => ['type' => 'string'], + 'label' => ['type' => 'text'], 'quantity' => ['type' => 'integer'], 'price' => ['type' => 'integer'], 'total' => ['type' => 'integer'], @@ -163,33 +168,36 @@ protected function getClient(): Client protected function createDocuments(string $name, array $properties, array $data): void { - // index - $client = $this->getClient(); - $index = $client->getIndex($name); - $index->create([ - 'mapping.single_type' => true, - ], ['recreate' => true]); - - // mapping - $type = $index->getType($name); - $mapping = new Mapping($type, $properties); - $mapping->send(); - - // documents - if (empty($data) === false) { - $documents = []; - - foreach ($data as $id => $item) { - $normalized = \array_combine(\array_keys($properties), $item); - $document = new Document($id, $normalized); - - if (isset($normalized['type']['parent'])) { - $document->setRouting($normalized['type']['parent']); + try { + // index + $client = $this->getClient(); + $index = $client->getIndex($name); + $index->create(['mappings' => ['properties' => $properties]], ['recreate' => true]); + $index->refresh(); + + // documents + if (empty($data) === false) { + $documents = []; + + foreach ($data as $id => $item) { + $normalized = \array_combine(\array_keys($properties), $item); + $document = new Document((string) $id, $normalized); + + if (isset($normalized['type']['parent'])) { + $document->setRouting($normalized['type']['parent']); + } + $documents[] = $document; } - $documents[] = $document; + $index->addDocuments($documents); + $index->refresh(); } - $type->addDocuments($documents); - $index->refresh(); + } catch (ResponseException $exception) { + static::fail(\sprintf( + "%s\nWith path: %s\nWith query: ---------------------\n%s\n---------------------------------\n", + $exception->getMessage(), + $exception->getRequest()->getPath(), + \json_encode($exception->getRequest()->toArray(), \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT) + )); } } @@ -203,9 +211,9 @@ protected function getFieldSet(bool $build = true): FieldSet $builder->add('customer-name', TextType::class); $builder->add('@customer-name', OrderFieldType::class); $builder->add('customer-birthday', BirthdayType::class, ['pattern' => 'yyyy-MM-dd']); - $builder->add('@customer-birthday', OrderFieldType::class); - $builder->add('@customer-pubdate', OrderFieldType::class); - $builder->add('@customer-note-pubdate', OrderFieldType::class); + $builder->add('@customer-birthday', OrderFieldType::class, ['type' => BirthdayType::class]); + $builder->add('@customer-pubdate', OrderFieldType::class, ['type' => DateType::class]); + $builder->add('@customer-note-pubdate', OrderFieldType::class, ['type' => DateType::class]); $builder->add('customer-comment', TextType::class); $builder->add('customer-comment-restricted', TextType::class); @@ -215,7 +223,7 @@ protected function getFieldSet(bool $build = true): FieldSet $builder->add('customer', IntegerType::class); $builder->add('label', TextType::class); $builder->add('pub-date', DateType::class, ['pattern' => 'yyyy-MM-dd']); - $builder->add('@pub-date', OrderFieldType::class); + $builder->add('@pub-date', OrderFieldType::class, ['type' => DateType::class]); $builder->add('pub-date-time', DateTimeType::class, ['pattern' => 'yyyy-MM-dd HH:mm:ss', 'allow_relative' => true]); $builder->add('status', ChoiceType::class, ['choices' => ['concept' => 0, 'published' => 1, 'paid' => 2, 'overdue' => 3]]); $builder->add('total', MoneyType::class); @@ -290,9 +298,7 @@ protected function assertDocumentsAreFound(SearchCondition $condition, array $ex $search = new Search($this->getClient()); foreach ($mappings as $mapping) { - $search - ->addIndex($mapping->indexName) - ->addType($mapping->typeName); + $search->addIndex($mapping->indexName); } try { @@ -300,7 +306,7 @@ protected function assertDocumentsAreFound(SearchCondition $condition, array $ex $documents = $results->getDocuments(); $foundIds = \array_map( static function (Document $document) { - return $document->getId(); + return (string) $document->getId(); }, $documents ); @@ -309,20 +315,18 @@ static function (Document $document) { "%s\nWith path: %s\nWith query: ---------------------\n%s\n---------------------------------\n", $exception->getMessage(), $search->getPath(), - \json_encode($query->toArray(), \JSON_PRETTY_PRINT) + \json_encode($query->toArray(), \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT) )); - - return; } - static::assertEquals( - $expectedIds, + static::assertSame( + \array_map('strval', $expectedIds), $foundIds, \sprintf( "Found these records instead: \n%s\n" . "With query: ---------------------\n%s\n---------------------------------\n", - \print_r($documents, true), - \json_encode($query->toArray(), \JSON_PRETTY_PRINT) + \var_export($documents, true), + \json_encode($query->toArray(), \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT) ) ); } diff --git a/lib/Elasticsearch/composer.json b/lib/Elasticsearch/composer.json index dc209e2c..120da916 100644 --- a/lib/Elasticsearch/composer.json +++ b/lib/Elasticsearch/composer.json @@ -23,7 +23,7 @@ "php": ">=7.4", "psr/simple-cache": "^1.0", "rollerworks/search": "^2.0@dev,>=2.0.0-BETA1", - "ruflin/elastica": "^4.0 || ^5.0 || ^6.0" + "ruflin/elastica": "^5.0 || ^6.0" }, "require-dev": { "moneyphp/money": "^3.0", diff --git a/lib/Symfony/SearchBundle/DependencyInjection/Compiler/ElasticaBundlePass.php b/lib/Symfony/SearchBundle/DependencyInjection/Compiler/ElasticaBundlePass.php deleted file mode 100644 index cadbd254..00000000 --- a/lib/Symfony/SearchBundle/DependencyInjection/Compiler/ElasticaBundlePass.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Rollerworks\Bundle\SearchBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * If FOS Elastica Bundle is detected, use its client as our client. - */ -class ElasticaBundlePass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - if (! $container->has('fos_elastica.client')) { - return; - } - - $container->setAlias('rollerworks_search.elasticsearch.client', 'fos_elastica.client'); - } -} diff --git a/lib/Symfony/SearchBundle/DependencyInjection/Compiler/ElasticaClientPass.php b/lib/Symfony/SearchBundle/DependencyInjection/Compiler/ElasticaClientPass.php new file mode 100644 index 00000000..ed468997 --- /dev/null +++ b/lib/Symfony/SearchBundle/DependencyInjection/Compiler/ElasticaClientPass.php @@ -0,0 +1,41 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Rollerworks\Bundle\SearchBundle\DependencyInjection\Compiler; + +use Elastica\Client as ElasticaClient; +use JoliCode\Elastically\Client as ElasticallyClient; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class ElasticaClientPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if ($container->has('fos_elastica.client')) { + $container->setAlias('rollerworks_search.elasticsearch.client', 'fos_elastica.client'); + + return; + } + + if ($container->has(ElasticaClient::class)) { + $container->setAlias('rollerworks_search.elasticsearch.client', ElasticaClient::class); + + return; + } + + if ($container->has(ElasticallyClient::class)) { + $container->setAlias('rollerworks_search.elasticsearch.client', ElasticallyClient::class); + } + } +} diff --git a/lib/Symfony/SearchBundle/Resources/config/elasticsearch.xml b/lib/Symfony/SearchBundle/Resources/config/elasticsearch.xml index 449be543..fe3779f2 100644 --- a/lib/Symfony/SearchBundle/Resources/config/elasticsearch.xml +++ b/lib/Symfony/SearchBundle/Resources/config/elasticsearch.xml @@ -41,5 +41,11 @@ + + + + + + diff --git a/lib/Symfony/SearchBundle/RollerworksSearchBundle.php b/lib/Symfony/SearchBundle/RollerworksSearchBundle.php index ec0eb229..93ad619a 100644 --- a/lib/Symfony/SearchBundle/RollerworksSearchBundle.php +++ b/lib/Symfony/SearchBundle/RollerworksSearchBundle.php @@ -26,6 +26,6 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new Compiler\ExporterPass()); $container->addCompilerPass(new Compiler\FieldSetRegistryPass()); $container->addCompilerPass(new Compiler\DoctrineOrmPass()); - $container->addCompilerPass(new Compiler\ElasticaBundlePass()); + $container->addCompilerPass(new Compiler\ElasticaClientPass()); } } diff --git a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/api_platform.yml b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/api_platform.yml index 08d9be83..b8dfd5c7 100644 --- a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/api_platform.yml +++ b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/api_platform.yml @@ -1,5 +1,6 @@ imports: - { resource: framework.yml } + - { resource: elasticsearch.yml } framework: router: @@ -49,12 +50,6 @@ doctrine: mappings: AppBundle: ~ -fos_elastica: - clients: - default: {host: localhost, port: 9200} - indexes: - app: ~ - api_platform: title: API Platform's demo description: | @@ -71,3 +66,10 @@ api_platform: yaml: ['application/x-yaml'] csv: ['text/csv'] html: ['text/html'] + +rollerworks_search: + api_platform: true + elasticsearch: true + doctrine: + dbal: true + orm: true diff --git a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/elasticsearch.yml b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/elasticsearch.yml index 22173842..8ed62cbf 100644 --- a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/elasticsearch.yml +++ b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/elasticsearch.yml @@ -7,3 +7,10 @@ rollerworks_search: dbal: false orm: false elasticsearch: true + +services: + 'Elastica\Client': + arguments: + - { host: localhost, port: 9200 } + - null + - '@logger' From cf5d060339143481803f5e097a8e7e4a24e0f8f4 Mon Sep 17 00:00:00 2001 From: Sebastiaan Stok Date: Sun, 8 Aug 2021 19:32:40 +0200 Subject: [PATCH 3/8] Allow Money v4.0 --- composer.json | 2 +- .../Tests/Extension/Core/Type/MoneyTypeTest.php | 16 ++++++++-------- lib/Core/composer.json | 2 +- lib/Doctrine/Orm/composer.json | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 47f4e99a..c2f92586 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,7 @@ "doctrine/doctrine-bundle": "^1.9.1 || ^2.0", "doctrine/orm": "^2.7.3", "matthiasnoback/symfony-dependency-injection-test": "^3.0 || ^4.1.1", - "moneyphp/money": "^3.2.0", + "moneyphp/money": "^3.2.0 || ^4.0", "phpunit/phpunit": "^9.5.7", "psr/simple-cache": "^1.0.0", "ruflin/elastica": "^7.0", diff --git a/lib/Core/Tests/Extension/Core/Type/MoneyTypeTest.php b/lib/Core/Tests/Extension/Core/Type/MoneyTypeTest.php index 39fdbdb9..36192b68 100644 --- a/lib/Core/Tests/Extension/Core/Type/MoneyTypeTest.php +++ b/lib/Core/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -48,12 +48,12 @@ public function pass_money_nl(): void FieldTransformationAssertion::assertThat($field) ->withInput('€ 12,20', 'EUR 12.20') - ->successfullyTransformsTo(new MoneyValue(Money::EUR(1220))) + ->successfullyTransformsTo(new MoneyValue(Money::EUR('1220'))) ->andReverseTransformsTo('€ 12,20', 'EUR 12.20'); FieldTransformationAssertion::assertThat($field) ->withInput('12,00', '12.00') - ->successfullyTransformsTo(new MoneyValue(Money::EUR(1200), false)) + ->successfullyTransformsTo(new MoneyValue(Money::EUR('1200'), false)) ->andReverseTransformsTo('12,00', '12.00'); } @@ -66,12 +66,12 @@ public function pass_money_de(): void FieldTransformationAssertion::assertThat($field) ->withInput('12,00 €', 'EUR 12.00') - ->successfullyTransformsTo(new MoneyValue(Money::EUR(1200))) + ->successfullyTransformsTo(new MoneyValue(Money::EUR('1200'))) ->andReverseTransformsTo('12,00 €', 'EUR 12.00'); FieldTransformationAssertion::assertThat($field) ->withInput('12,00', '12.00') - ->successfullyTransformsTo(new MoneyValue(Money::EUR(1200), false)) + ->successfullyTransformsTo(new MoneyValue(Money::EUR('1200'), false)) ->andReverseTransformsTo('12,00', '12.00'); } @@ -84,22 +84,22 @@ public function money_pattern_works_for_yen(): void FieldTransformationAssertion::assertThat($field) ->withInput('¥12,00', 'JPY 12.00') - ->successfullyTransformsTo(new MoneyValue(Money::JPY(12))) + ->successfullyTransformsTo(new MoneyValue(Money::JPY('12'))) ->andReverseTransformsTo('¥12', 'JPY 12'); FieldTransformationAssertion::assertThat($field) ->withInput('¥12', 'JPY 12') - ->successfullyTransformsTo(new MoneyValue(Money::JPY(12))) + ->successfullyTransformsTo(new MoneyValue(Money::JPY('12'))) ->andReverseTransformsTo('¥12', 'JPY 12'); FieldTransformationAssertion::assertThat($field) ->withInput('12', '12.00') - ->successfullyTransformsTo(new MoneyValue(Money::JPY(12), false)) + ->successfullyTransformsTo(new MoneyValue(Money::JPY('12'), false)) ->andReverseTransformsTo('12', '12'); FieldTransformationAssertion::assertThat($field) ->withInput('€12.00', 'EUR 12.00') - ->successfullyTransformsTo(new MoneyValue(Money::EUR(1200))) + ->successfullyTransformsTo(new MoneyValue(Money::EUR('1200'))) ->andReverseTransformsTo('€12.00', 'EUR 12.00'); } diff --git a/lib/Core/composer.json b/lib/Core/composer.json index 460e594f..dcf5e842 100644 --- a/lib/Core/composer.json +++ b/lib/Core/composer.json @@ -32,7 +32,7 @@ "moneyphp/money": "<3.2.0" }, "require-dev": { - "moneyphp/money": "^3.2.0", + "moneyphp/money": "^3.2.0 || ^4.0", "phpunit/phpunit": "^9.5", "symfony/phpunit-bridge": "^4.4 || ^5.0", "symfony/var-dumper": "^4.4 || ^5.0" diff --git a/lib/Doctrine/Orm/composer.json b/lib/Doctrine/Orm/composer.json index 45804512..e1fc6b06 100644 --- a/lib/Doctrine/Orm/composer.json +++ b/lib/Doctrine/Orm/composer.json @@ -26,7 +26,7 @@ "rollerworks/search-doctrine-dbal": "^2.0@dev,>=2.0.0-BETA1" }, "require-dev": { - "moneyphp/money": "^3.0.7", + "moneyphp/money": "^3.0.7 || ^4.0", "phpunit/phpunit": "^6.5.4", "symfony/phpunit-bridge": "^4.4 || ^5.0", "symfony/var-dumper": "^4.4 || ^5.0" From 32e9b5846549fba62f97c41d38a1fe817da3fd5f Mon Sep 17 00:00:00 2001 From: Sebastiaan Stok Date: Sun, 8 Aug 2021 20:38:16 +0200 Subject: [PATCH 4/8] Drop support for Symfony 4 --- .gitignore | 4 +- UPGRADE-2.0.md | 2 +- composer.json | 30 ++++----- .../Application/AppBundle/AppBundle.php | 20 ------ .../Functional/Application/AppKernel.php | 65 +++++++++---------- .../Application/config/api_platform.yml | 13 ++-- .../Application/config/framework.yml | 21 +++--- .../Application/config/search_processor.yml | 2 +- .../Tests/Functional/FunctionalTestCase.php | 8 +-- 9 files changed, 73 insertions(+), 92 deletions(-) delete mode 100644 lib/Symfony/SearchBundle/Tests/Functional/Application/AppBundle/AppBundle.php diff --git a/.gitignore b/.gitignore index 92a82f77..fb5de8c3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,7 @@ /.php_cs.cache build/** *.phar -var/ +/var/ + .phpunit.result.cache +/lib/Symfony/SearchBundle/Tests/Functional/Application/var/ diff --git a/UPGRADE-2.0.md b/UPGRADE-2.0.md index b760f782..6b8e61c9 100644 --- a/UPGRADE-2.0.md +++ b/UPGRADE-2.0.md @@ -3,7 +3,7 @@ UPGRADE FROM 2.0-BETA1 to 2.0-BETA2 * Support for PHP < 7.4 was dropped. - * Support for Symfony < 4.4 was dropped. + * Support for Symfony 4 was dropped. * Support for PHPUnit < 9.5 was dropped. diff --git a/composer.json b/composer.json index c2f92586..247b413c 100644 --- a/composer.json +++ b/composer.json @@ -18,9 +18,9 @@ "php": ">=7.4", "nesbot/carbon": "^2.38", "psr/container": "^1.0.0", - "symfony/intl": "^4.4 || ^5.0", - "symfony/options-resolver": "^4.4 || ^5.0", - "symfony/property-access": "^4.4 || ^5.0", + "symfony/intl": "^5.3", + "symfony/options-resolver": "^5.3", + "symfony/property-access": "^5.3", "symfony/string": "^5.1" }, "replace": { @@ -45,18 +45,18 @@ "phpunit/phpunit": "^9.5.7", "psr/simple-cache": "^1.0.0", "ruflin/elastica": "^7.0", - "symfony/asset": "^4.4 || ^5.0", - "symfony/browser-kit": "^4.4 || ^5.0", - "symfony/dom-crawler": "^4.4 || ^5.0", - "symfony/framework-bundle": "^4.4 || ^5.0", - "symfony/http-foundation": "^4.4 || ^5.0", - "symfony/phpunit-bridge": "^4.4 || ^5.0", - "symfony/routing": "^4.4 || ^5.0", - "symfony/templating": "^4.4 || ^5.0", - "symfony/translation": "^4.4 || ^5.0", - "symfony/twig-bundle": "^4.4 || ^5.0", - "symfony/validator": "^4.4 || ^5.0", - "symfony/var-dumper": "^4.4 || ^5.0" + "symfony/asset": "^5.3", + "symfony/browser-kit": "^5.3", + "symfony/dom-crawler": "^5.3", + "symfony/framework-bundle": "^5.3", + "symfony/http-foundation": "^5.3", + "symfony/phpunit-bridge": "^5.3", + "symfony/routing": "^5.3", + "symfony/templating": "^5.3", + "symfony/translation": "^5.3", + "symfony/twig-bundle": "^5.3", + "symfony/validator": "^5.3", + "symfony/var-dumper": "^5.3" }, "suggest": { "moneyphp/money": "To use the MoneyType" diff --git a/lib/Symfony/SearchBundle/Tests/Functional/Application/AppBundle/AppBundle.php b/lib/Symfony/SearchBundle/Tests/Functional/Application/AppBundle/AppBundle.php deleted file mode 100644 index ea9cf9ed..00000000 --- a/lib/Symfony/SearchBundle/Tests/Functional/Application/AppBundle/AppBundle.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Rollerworks\Bundle\SearchBundle\Tests\Functional\Application\AppBundle; - -use Symfony\Component\HttpKernel\Bundle\Bundle; - -final class AppBundle extends Bundle -{ -} diff --git a/lib/Symfony/SearchBundle/Tests/Functional/Application/AppKernel.php b/lib/Symfony/SearchBundle/Tests/Functional/Application/AppKernel.php index 7ba69039..f12b62a9 100644 --- a/lib/Symfony/SearchBundle/Tests/Functional/Application/AppKernel.php +++ b/lib/Symfony/SearchBundle/Tests/Functional/Application/AppKernel.php @@ -15,7 +15,9 @@ use ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; -use FOS\ElasticaBundle\FOSElasticaBundle; +use Rollerworks\Bundle\SearchBundle\RollerworksSearchBundle; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\TwigBundle\TwigBundle; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -24,16 +26,18 @@ class AppKernel extends Kernel { - private $config; + use MicroKernelTrait; - public function __construct($config, $debug = true) + private string $config; + + public function __construct(string $config, $debug = true) { if (! (new Filesystem())->isAbsolutePath($config)) { $config = __DIR__ . '/config/' . $config; } - if (! \file_exists($config)) { - throw new \RuntimeException(\sprintf('The config file "%s" does not exist.', $config)); + if (! file_exists($config)) { + throw new \RuntimeException(sprintf('The config file "%s" does not exist.', $config)); } $this->config = $config; @@ -41,30 +45,37 @@ public function __construct($config, $debug = true) parent::__construct('test', $debug); } - public function getName() + public function getProjectDir(): string { - return 'RSearch' . \mb_substr(\sha1($this->config), 0, 3); + return __DIR__; + } + + protected function getContainerClass(): string + { + $class = 'RSAppKernel' . ContainerBuilder::hash($this->config); + $class = str_replace('\\', '_', $class) . ucfirst($this->environment) . ($this->debug ? 'Debug' : '') . 'Container'; + + if (! preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $class)) { + throw new \InvalidArgumentException(sprintf('The environment "%s" contains invalid characters, it can only contain characters allowed in PHP class names.', $this->environment)); + } + + return $class; } public function registerBundles() { $bundles = [ - new \Symfony\Bundle\FrameworkBundle\FrameworkBundle(), + new FrameworkBundle(), //new \Symfony\Bundle\TwigBundle\TwigBundle(), - new \Rollerworks\Bundle\SearchBundle\RollerworksSearchBundle(), - new AppBundle\AppBundle(), + new RollerworksSearchBundle(), ]; - if (\class_exists(DoctrineBundle::class)) { + if (class_exists(DoctrineBundle::class)) { $bundles[] = new DoctrineBundle(); } - if (\class_exists(FOSElasticaBundle::class)) { - $bundles[] = new FOSElasticaBundle(); - } - - if (\mb_substr($this->config, -16) === 'api_platform.yml') { + if (mb_substr($this->config, -16) === 'api_platform.yml') { $bundles[] = new TwigBundle(); $bundles[] = new ApiPlatformBundle(); } @@ -72,31 +83,13 @@ public function registerBundles() return $bundles; } - protected function build(ContainerBuilder $container): void - { - $container->setParameter('kernel.root_dir', __DIR__); - } - - public function getRootDir() - { - if ($this->rootDir === null) { - $this->rootDir = \str_replace('\\', '/', __DIR__); - } - - return $this->rootDir; - } - public function registerContainerConfiguration(LoaderInterface $loader): void { $loader->load($this->config); } - public function getCacheDir() + public function getCacheDir(): string { - if (false === $tmpDir = \getenv('TMPDIR')) { - $tmpDir = \sys_get_temp_dir(); - } - - return \rtrim($tmpDir, '/\\') . '/rollerworks-search-' . \sha1(__DIR__) . '/' . \mb_substr(\sha1($this->config), 0, 6); + return $this->getProjectDir() . '/var/cache/' . mb_substr(sha1($this->config), 0, 6); } } diff --git a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/api_platform.yml b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/api_platform.yml index b8dfd5c7..2d0ccefc 100644 --- a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/api_platform.yml +++ b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/api_platform.yml @@ -5,7 +5,7 @@ imports: framework: router: enabled: true - resource: "%kernel.root_dir%/config/routing_api.yml" + resource: "%kernel.project_dir%/config/routing_api.yml" strict_requirements: "%kernel.debug%" validation: { enable_annotations: true } serializer: { enable_annotations: true } @@ -48,15 +48,20 @@ doctrine: naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware auto_mapping: false mappings: - AppBundle: ~ + App: + is_bundle: false + type: annotation + dir: '%kernel.project_dir%/AppBundle/Entity' + prefix: 'Rollerworks\\Bundle\\SearchBundle\\Tests\\Functional\\Application\\AppBundle\\Entity' + alias: AppBundle api_platform: title: API Platform's demo description: | This is a demo application of the [API Platform](https://api-platform.com) framework. [Its source code](https://github.com/api-platform/demo) includes various examples, check it out! - mapping: - paths: ['%kernel.root_dir%/AppBundle/Entity'] + mapping: + paths: ['%kernel.project_dir%/AppBundle/Entity'] formats: jsonld: ['application/ld+json'] diff --git a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/framework.yml b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/framework.yml index bd69f493..69e09c8c 100644 --- a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/framework.yml +++ b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/framework.yml @@ -1,17 +1,20 @@ framework: - translator: { fallback: en } - secret: test + translator: { fallback: en } + secret: test router: enabled: false - resource: "%kernel.root_dir%/config/routing.yml" + resource: "%kernel.project_dir%/config/routing.yml" strict_requirements: "%kernel.debug%" - form: false - csrf_protection: false - validation: { enable_annotations: false } - default_locale: en + form: false + csrf_protection: false + validation: { enable_annotations: false } + default_locale: en session: - storage_id: session.storage.filesystem - test: ~ + handler_id: null + cookie_secure: auto + cookie_samesite: lax + storage_factory_id: "session.storage.factory.mock_file" + test: true assets: false cache: diff --git a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/search_processor.yml b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/search_processor.yml index 85e310ff..a0ce2f77 100644 --- a/lib/Symfony/SearchBundle/Tests/Functional/Application/config/search_processor.yml +++ b/lib/Symfony/SearchBundle/Tests/Functional/Application/config/search_processor.yml @@ -4,7 +4,7 @@ imports: framework: router: enabled: true - resource: "%kernel.root_dir%/config/routing.yml" + resource: "%kernel.project_dir%/config/routing.yml" strict_requirements: "%kernel.debug%" rollerworks_search: diff --git a/lib/Symfony/SearchBundle/Tests/Functional/FunctionalTestCase.php b/lib/Symfony/SearchBundle/Tests/Functional/FunctionalTestCase.php index 058e7080..c1057ccf 100644 --- a/lib/Symfony/SearchBundle/Tests/Functional/FunctionalTestCase.php +++ b/lib/Symfony/SearchBundle/Tests/Functional/FunctionalTestCase.php @@ -13,6 +13,7 @@ namespace Rollerworks\Bundle\SearchBundle\Tests\Functional; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; abstract class FunctionalTestCase extends WebTestCase @@ -30,16 +31,13 @@ protected static function getKernelClass() return Application\AppKernel::class; } - /** - * @return \Symfony\Bundle\FrameworkBundle\Client - */ - protected static function newClient(array $options = [], array $server = []) + protected static function newClient(array $options = [], array $server = []): KernelBrowser { $client = static::createClient(\array_merge(['config' => 'default.yml'], $options), $server); $warmer = $client->getContainer()->get('cache_warmer'); - $warmer->warmUp($client->getContainer()->getParameter('kernel.cache_dir')); $warmer->enableOptionalWarmers(); + $warmer->warmUp($client->getContainer()->getParameter('kernel.cache_dir')); return $client; } From cd27c12aef0dfd1026d0cb0d0ee29f883ce54bd4 Mon Sep 17 00:00:00 2001 From: Sebastiaan Stok Date: Mon, 9 Aug 2021 13:24:32 +0200 Subject: [PATCH 5/8] Upgrade PHPStan (with baseline) PHPStan can now be added as composer dev requirement. This includes a baseline as there are too many errors to fix at this moment. --- Makefile | 4 +- composer.json | 5 + .../Orm/Tests/ColumnConversionStrategy.php | 21 - .../Tests/CachedConditionGeneratorTest.php | 5 +- phpstan-baseline.neon | 382 ++++++++++++++++++ phpstan.neon | 32 +- 6 files changed, 406 insertions(+), 43 deletions(-) delete mode 100644 lib/Doctrine/Orm/Tests/ColumnConversionStrategy.php create mode 100644 phpstan-baseline.neon diff --git a/Makefile b/Makefile index 5117edff..a6481768 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,8 @@ test-coverage: ensure docker-up sh -c "${QA_DOCKER_COMMAND} phpdbg -qrr /usr/local/bin/phpcov merge --clover build/logs/clover.xml build/cov" @$(MAKE) docker-down -phpstan: ensure - sh -c "${QA_DOCKER_COMMAND} phpstan analyse" +phpstan: + php -d memory_limit=1G vendor/bin/phpstan analyse cs: ensure sh -c "${QA_DOCKER_COMMAND} php-cs-fixer fix -vvv --diff" diff --git a/composer.json b/composer.json index 247b413c..e7e4ca18 100644 --- a/composer.json +++ b/composer.json @@ -40,8 +40,13 @@ "doctrine/dbal": "^2.10.3", "doctrine/doctrine-bundle": "^1.9.1 || ^2.0", "doctrine/orm": "^2.7.3", + "jangregor/phpstan-prophecy": "^0.8.1", "matthiasnoback/symfony-dependency-injection-test": "^3.0 || ^4.1.1", "moneyphp/money": "^3.2.0 || ^4.0", + "phpstan/phpstan": "^0.12.94", + "phpstan/phpstan-doctrine": "^0.12.42", + "phpstan/phpstan-phpunit": "^0.12.21", + "phpstan/phpstan-symfony": "^0.12.41", "phpunit/phpunit": "^9.5.7", "psr/simple-cache": "^1.0.0", "ruflin/elastica": "^7.0", diff --git a/lib/Doctrine/Orm/Tests/ColumnConversionStrategy.php b/lib/Doctrine/Orm/Tests/ColumnConversionStrategy.php deleted file mode 100644 index c57906b3..00000000 --- a/lib/Doctrine/Orm/Tests/ColumnConversionStrategy.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Rollerworks\Component\Search\Tests\Doctrine\Orm; - -use Rollerworks\Component\Search\Doctrine\Dbal\ColumnConversion; -use Rollerworks\Component\Search\Doctrine\Dbal\StrategySupportedConversion; - -interface ColumnConversionStrategy extends StrategySupportedConversion, ColumnConversion -{ -} diff --git a/lib/Elasticsearch/Tests/CachedConditionGeneratorTest.php b/lib/Elasticsearch/Tests/CachedConditionGeneratorTest.php index f5d87e82..3f7f9746 100644 --- a/lib/Elasticsearch/Tests/CachedConditionGeneratorTest.php +++ b/lib/Elasticsearch/Tests/CachedConditionGeneratorTest.php @@ -14,6 +14,7 @@ namespace Rollerworks\Component\Search\Tests\Elasticsearch; use Elastica\Query; +use PHPUnit\Framework\MockObject\MockObject; use Psr\SimpleCache\CacheInterface as Cache; use Rollerworks\Component\Search\Elasticsearch\CachedConditionGenerator; use Rollerworks\Component\Search\Elasticsearch\ConditionGenerator; @@ -36,12 +37,12 @@ final class CachedConditionGeneratorTest extends ElasticsearchTestCase private $cachedConditionGenerator; /** - * @var Cache|\PHPUnit_Framework_MockObject_MockObject + * @var Cache&MockObject */ private $cacheDriver; /** - * @var ConditionGenerator|\PHPUnit_Framework_MockObject_MockObject + * @var ConditionGenerator&MockObject */ private $conditionGenerator; diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 00000000..e532325d --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,382 @@ +parameters: + ignoreErrors: + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Validator\\\\ConstraintViolationInterface\\:\\:getConstraint\\(\\)\\.$#" + count: 1 + path: lib/ApiPlatform/Serializer/InvalidSearchConditionNormalizer.php + + - + message: "#^Right side of && is always true\\.$#" + count: 1 + path: lib/ApiPlatform/Serializer/InvalidSearchConditionNormalizer.php + + - + message: "#^Class ApiPlatform\\\\Core\\\\Tests\\\\Fixtures\\\\TestBundle\\\\Entity\\\\Dummy not found\\.$#" + count: 4 + path: lib/ApiPlatform/Tests/Doctrine/Orm/Extension/SearchExtensionTest.php + + - + message: "#^Class ApiPlatform\\\\Core\\\\Tests\\\\Fixtures\\\\TestBundle\\\\Entity\\\\RelatedDummy not found\\.$#" + count: 9 + path: lib/ApiPlatform/Tests/Doctrine/Orm/Extension/SearchExtensionTest.php + + - + message: "#^Class ApiPlatform\\\\Core\\\\Tests\\\\Fixtures\\\\TestBundle\\\\Entity\\\\ThirdLevel not found\\.$#" + count: 2 + path: lib/ApiPlatform/Tests/Doctrine/Orm/Extension/SearchExtensionTest.php + + - + message: "#^Method Rollerworks\\\\Component\\\\Search\\\\ApiPlatform\\\\Tests\\\\Mock\\\\FieldSetStub\\:\\:get\\(\\) should return Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig but return statement is missing\\.$#" + count: 1 + path: lib/ApiPlatform/Tests/Mock/FieldSetStub.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: lib/Core/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: lib/Core/Extension/Core/DataTransformer/LocalizedBirthdayTransformer.php + + - + message: "#^Parameter \\#1 \\$code of class Money\\\\Currency constructor expects non\\-empty\\-string, string given\\.$#" + count: 2 + path: lib/Core/Extension/Core/DataTransformer/MoneyToStringTransformer.php + + - + message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertSame\\(\\) with array\\('Group 1' \\=\\> array\\('A' \\=\\> 'a', 'B' \\=\\> 'b'\\), 'Group 2' \\=\\> array\\('C' \\=\\> 'c', 'D' \\=\\> 'd'\\)\\) and array\\ will always evaluate to false\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/ChoiceList/ArrayChoiceListTest.php + + - + message: "#^Parameter \\#1 \\$choices of class Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\ChoiceList\\\\View\\\\ChoiceListView constructor expects array\\, array\\ given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/ChoiceList/Factory/PropertyAccessDecoratorTest.php + + - + message: "#^Parameter \\#1 \\$choices of class Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\ChoiceList\\\\View\\\\ChoiceListView constructor expects array\\, array\\ given\\.$#" + count: 8 + path: lib/Core/Tests/Extension/Core/ChoiceList/Factory/PropertyAccessDecoratorTest.php + + - + message: "#^Parameter \\#2 \\$preferredChoices of class Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\ChoiceList\\\\View\\\\ChoiceListView constructor expects array\\, array\\ given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/ChoiceList/Factory/PropertyAccessDecoratorTest.php + + - + message: "#^Parameter \\#2 \\$preferredChoices of class Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\ChoiceList\\\\View\\\\ChoiceListView constructor expects array\\, array\\ given\\.$#" + count: 2 + path: lib/Core/Tests/Extension/Core/ChoiceList/Factory/PropertyAccessDecoratorTest.php + + - + message: "#^Call to method DateTimeImmutable\\:\\:setTimezone\\(\\) on a separate line has no effect\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$dateTime of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToLocalizedStringTransformer\\:\\:transform\\(\\) expects DateTimeImmutable\\|null, float given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$dateTime of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToLocalizedStringTransformer\\:\\:transform\\(\\) expects DateTimeImmutable\\|null, string given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToLocalizedStringTransformer\\:\\:reverseTransform\\(\\) expects string, int given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php + + - + message: "#^Static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertEquals\\(\\) invoked with 7 parameters, 2\\-3 required\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$dateTime of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToRfc3339Transformer\\:\\:transform\\(\\) expects DateTimeImmutable\\|null, string given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php + + - + message: "#^Parameter \\#1 \\$rfc3339 of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToRfc3339Transformer\\:\\:reverseTransform\\(\\) expects string, int given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php + + - + message: "#^You should use assertNull\\(\\) instead of assertSame\\(null, \\$actual\\)\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php + + - + message: "#^Call to method DateTimeImmutable\\:\\:setTimezone\\(\\) on a separate line has no effect\\.$#" + count: 2 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$dateTime of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToStringTransformer\\:\\:transform\\(\\) expects DateTimeImmutable\\|null, string given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToStringTransformer\\:\\:reverseTransform\\(\\) expects string, int given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php + + - + message: "#^Call to method DateTimeImmutable\\:\\:setTimezone\\(\\) on a separate line has no effect\\.$#" + count: 3 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php + + - + message: "#^Parameter \\#1 \\$dateTime of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToTimestampTransformer\\:\\:transform\\(\\) expects DateTimeImmutable\\|null, string given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\IntegerToLocalizedStringTransformer\\:\\:reverseTransform\\(\\) expects string, int given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\IntegerToStringTransformer\\:\\:reverseTransform\\(\\) expects string, array\\ given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/IntegerToStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$code of class Money\\\\Currency constructor expects non\\-empty\\-string, string given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\MoneyToLocalizedStringTransformer\\:\\:reverseTransform\\(\\) expects string\\|null, int given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\MoneyToLocalizedStringTransformer\\:\\:transform\\(\\) expects Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\Model\\\\MoneyValue\\|null, string given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$code of class Money\\\\Currency constructor expects non\\-empty\\-string, string given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/MoneyToStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\MoneyToStringTransformer\\:\\:reverseTransform\\(\\) expects string\\|null, int given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/MoneyToStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\MoneyToStringTransformer\\:\\:transform\\(\\) expects Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\Model\\\\MoneyValue\\|null, string given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/MoneyToStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\NumberToLocalizedStringTransformer\\:\\:reverseTransform\\(\\) expects string, int given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method Rollerworks\\\\Component\\\\Search\\\\Extension\\\\Core\\\\DataTransformer\\\\NumberToStringTransformer\\:\\:reverseTransform\\(\\) expects string, array\\ given\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/DataTransformer/NumberToStringTransformerTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 7 + path: lib/Core/Tests/Extension/Core/Type/ChoiceTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 2 + path: lib/Core/Tests/Extension/Core/Type/CountryTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/Type/CurrencyTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/Type/DateTimeTypeTest.php + + - + message: "#^Call to method DateTimeImmutable\\:\\:setTimezone\\(\\) on a separate line has no effect\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/Type/DateTimeTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 2 + path: lib/Core/Tests/Extension/Core/Type/DateTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/Type/IntegerTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 2 + path: lib/Core/Tests/Extension/Core/Type/LanguageTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/Type/LocaleTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/Type/MoneyTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/Type/NumberTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 3 + path: lib/Core/Tests/Extension/Core/Type/TimeTypeTest.php + + - + message: "#^Call to an undefined method Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\:\\:finalizeConfig\\(\\)\\.$#" + count: 1 + path: lib/Core/Tests/Extension/Core/Type/TimezoneTypeTest.php + + - + message: "#^Method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Field\\\\ResolvedFieldTypeTest\\:\\:getMockFieldType\\(\\) should return PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldType but returns PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" + count: 1 + path: lib/Core/Tests/Field/ResolvedFieldTypeTest.php + + - + message: "#^Method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\GenericFieldSetTest\\:\\:createFieldMock\\(\\) should return PHPUnit_Framework_MockObject_MockObject but returns PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig\\.$#" + count: 1 + path: lib/Core/Tests/GenericFieldSetTest.php + + - + message: "#^Parameter \\#1 \\$fields of class Rollerworks\\\\Component\\\\Search\\\\GenericFieldSet constructor expects array\\, array\\ given\\.$#" + count: 3 + path: lib/Core/Tests/GenericFieldSetTest.php + + - + message: "#^Return typehint of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\GenericFieldSetTest\\:\\:createFieldMock\\(\\) has invalid type PHPUnit_Framework_MockObject_MockObject\\.$#" + count: 1 + path: lib/Core/Tests/GenericFieldSetTest.php + + - + message: "#^Method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Mock\\\\FieldSetStub\\:\\:get\\(\\) should return Rollerworks\\\\Component\\\\Search\\\\Field\\\\FieldConfig but return statement is missing\\.$#" + count: 1 + path: lib/Core/Tests/Mock/FieldSetStub.php + + - + message: "#^Parameter \\#1 \\$compares of method Rollerworks\\\\Component\\\\Search\\\\Doctrine\\\\Dbal\\\\Query\\\\QueryGenerator\\:\\:processCompares\\(\\) expects array\\, array\\ given\\.$#" + count: 2 + path: lib/Doctrine/Dbal/Query/QueryGenerator.php + + - + message: "#^Parameter \\#1 \\$patternMatchers of method Rollerworks\\\\Component\\\\Search\\\\Doctrine\\\\Dbal\\\\Query\\\\QueryGenerator\\:\\:processPatternMatchers\\(\\) expects array\\, array\\ given\\.$#" + count: 2 + path: lib/Doctrine/Dbal/Query/QueryGenerator.php + + - + message: "#^Parameter \\#1 \\$ranges of method Rollerworks\\\\Component\\\\Search\\\\Doctrine\\\\Dbal\\\\Query\\\\QueryGenerator\\:\\:processRanges\\(\\) expects array\\, array\\ given\\.$#" + count: 2 + path: lib/Doctrine/Dbal/Query/QueryGenerator.php + + - + message: "#^Parameter \\#2 \\$cacheDriver of class Rollerworks\\\\Component\\\\Search\\\\Doctrine\\\\Dbal\\\\CachedConditionGenerator constructor expects Psr\\\\SimpleCache\\\\CacheInterface, PHPUnit\\\\Framework\\\\MockObject\\\\MockObject given\\.$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/CachedConditionGeneratorTest.php + + - + message: "#^Method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Functional\\\\FunctionalDbalTestCase\\:\\:getQuery\\(\\) should return string but return statement is missing\\.$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Functional/FunctionalDbalTestCase.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\ConnectionMock\\:\\:insert\\(\\) should be compatible with return type \\(int\\) of method Doctrine\\\\DBAL\\\\Connection\\:\\:insert\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/ConnectionMock.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\DatabasePlatformMock\\:\\:_getCommonIntegerTypeDeclarationSQL\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:_getCommonIntegerTypeDeclarationSQL\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/DatabasePlatformMock.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\DatabasePlatformMock\\:\\:getBigIntTypeDeclarationSQL\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getBigIntTypeDeclarationSQL\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/DatabasePlatformMock.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\DatabasePlatformMock\\:\\:getBlobTypeDeclarationSQL\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getBlobTypeDeclarationSQL\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/DatabasePlatformMock.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\DatabasePlatformMock\\:\\:getBooleanTypeDeclarationSQL\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getBooleanTypeDeclarationSQL\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/DatabasePlatformMock.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\DatabasePlatformMock\\:\\:getClobTypeDeclarationSQL\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getClobTypeDeclarationSQL\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/DatabasePlatformMock.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\DatabasePlatformMock\\:\\:getIntegerTypeDeclarationSQL\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getIntegerTypeDeclarationSQL\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/DatabasePlatformMock.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\DatabasePlatformMock\\:\\:getSmallIntTypeDeclarationSQL\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getSmallIntTypeDeclarationSQL\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/DatabasePlatformMock.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\DatabasePlatformMock\\:\\:getVarcharTypeDeclarationSQL\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getVarcharTypeDeclarationSQL\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/DatabasePlatformMock.php + + - + message: "#^Return type \\(void\\) of method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Dbal\\\\Mocks\\\\DatabasePlatformMock\\:\\:getVarcharTypeDeclarationSQLSnippet\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getVarcharTypeDeclarationSQLSnippet\\(\\)$#" + count: 1 + path: lib/Doctrine/Dbal/Tests/Mocks/DatabasePlatformMock.php + + - + message: "#^Property Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Orm\\\\CachedDqlConditionGeneratorTest\\:\\:\\$cacheDriver \\(PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Psr\\\\SimpleCache\\\\CacheInterface\\) does not accept Doctrine\\\\Common\\\\Cache\\\\Cache&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" + count: 1 + path: lib/Doctrine/Orm/Tests/CachedDqlConditionGeneratorTest.php + + - + message: "#^Offset 0 does not exist on array\\\\.$#" + count: 2 + path: lib/Doctrine/Orm/Tests/FieldConfigBuilderTest.php + + - + message: "#^Method Rollerworks\\\\Component\\\\Search\\\\Tests\\\\Doctrine\\\\Orm\\\\OrmTestCase\\:\\:getQuery\\(\\) should return Doctrine\\\\ORM\\\\QueryBuilder but return statement is missing\\.$#" + count: 1 + path: lib/Doctrine/Orm/Tests/OrmTestCase.php + + - + message: "#^Method Rollerworks\\\\Component\\\\Search\\\\Elasticsearch\\\\FieldMapping\\:\\:parseProperty\\(\\) should return array\\ but returns array\\\\|bool\\|string\\>\\|bool\\|string\\>\\|bool\\|string\\>\\|string\\|false\\|null\\>\\.$#" + count: 1 + path: lib/Elasticsearch/FieldMapping.php + + - + message: "#^PHPDoc tag @var above assignment does not specify variable name\\.$#" + count: 2 + path: lib/Elasticsearch/Tests/CachedConditionGeneratorTest.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: lib/Elasticsearch/Tests/QueryConditionGeneratorTest.php + diff --git a/phpstan.neon b/phpstan.neon index 35dfffd2..73321c90 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,31 +1,27 @@ includes: - - /tools/.composer/vendor-bin/phpstan/vendor/phpstan/phpstan-symfony/extension.neon - - /tools/.composer/vendor-bin/phpstan/vendor/phpstan/phpstan-doctrine/extension.neon - - /tools/.composer/vendor-bin/phpstan/vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-symfony/extension.neon + - vendor/phpstan/phpstan-doctrine/extension.neon + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/jangregor/phpstan-prophecy/extension.neon + + - vendor/phpstan/phpstan-phpunit/rules.neon + - phpstan-baseline.neon parameters: #reportUnmatchedIgnoredErrors: false #checkNullables: false + treatPhpDocTypesAsCertain: false tmpDir: %currentWorkingDirectory%/var/phpstan level: 5 paths: - ./lib - excludes_analyse: - - */lib/*/Tests/Fixtures/* - - %currentWorkingDirectory%/lib/*/Tests/** - - %currentWorkingDirectory%/lib/*/*/Tests/** + excludePaths: + - lib/*/Tests/Fixtures/* + - lib/Symfony/SearchBundle/Tests/Functional/Application ignoreErrors: - # ValueHolder guard there own correctness. A ValuesBag never returns a wrong object (collection). - - '#expects Rollerworks\\Component\\Search\\Value\\[a-zA-Z]+, Rollerworks\\Component\\Search\\Value\\ValueHolder given#' - - '#Call to an undefined method Rollerworks\\Component\\Search\\Value\\ValueHolder\:\:#' - - '#expects array, array given#i' - - # False positive - - '#Negated boolean expression is always false#' - - ## Symony Config - - '# Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition given#' - - '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition\:\:#' + - + path: lib/Symfony/SearchBundle/DependencyInjection/Compiler/ElasticaClientPass.php + message: "#^Class JoliCode\\\\Elastically\\\\Client not found\\.$#" From 0ccb9e7016ef1385019c693bec69649c8bedb3cf Mon Sep 17 00:00:00 2001 From: Sebastiaan Stok Date: Mon, 9 Aug 2021 15:24:43 +0200 Subject: [PATCH 6/8] Upgrade Php-cs-fixer Note: Actual CS fixes were not applied as this would cause to much noise --- .gitignore | 1 + .php-cs-fixer.dist.php | 84 ++++++++++++++++++++++++ .php_cs.dist | 114 --------------------------------- Makefile | 2 +- docker/Dockerfile-qa | 20 ------ lib/Core/Input/StringLexer.php | 14 ++-- 6 files changed, 93 insertions(+), 142 deletions(-) create mode 100644 .php-cs-fixer.dist.php delete mode 100644 .php_cs.dist delete mode 100644 docker/Dockerfile-qa diff --git a/.gitignore b/.gitignore index fb5de8c3..323f919b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ build/** .phpunit.result.cache /lib/Symfony/SearchBundle/Tests/Functional/Application/var/ +.php-cs-fixer.cache diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 00000000..f6847749 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,84 @@ + + +This source file is subject to the MIT license that is bundled +with this source code in the file LICENSE. +EOF; + +/** @var \Symfony\Component\Finder\Finder $finder */ +$finder = PhpCsFixer\Finder::create(); +$finder + ->in([__DIR__.'/lib']) + ->notPath('Symfony/SearchBundle/Tests/Functional/Application/var') + ->exclude('Fixtures') +; + +$config = new PhpCsFixer\Config(); +$config + ->setRiskyAllowed(true) + ->setRules([ + '@PhpCsFixer' => true, + '@PhpCsFixer:risky' => true, + '@Symfony' => true, + '@Symfony:risky' => true, + '@PHP74Migration' => true, + '@PHP74Migration:risky' => true, + '@PHPUnit84Migration:risky' => true, + '@DoctrineAnnotation' => true, + 'blank_line_before_statement' => [ + 'statements' => [ + 'break', + 'case', + 'continue', + 'declare', + 'default', + 'do', + 'exit', + 'for', + 'foreach', + 'goto', + 'if', + 'include', + 'include_once', + 'require', + 'require_once', + 'return', + 'switch', + 'throw', + 'try', + 'while', + ], + ], + 'comment_to_phpdoc' => ['ignored_tags' => ['codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd']], + 'concat_space' => ['spacing' => 'one'], + 'doctrine_annotation_array_assignment' => ['operator' => '='], + 'general_phpdoc_annotation_remove' => ['annotations' => [/*'author', */'since', 'package', 'subpackage']], + 'header_comment' => ['header' => $header], + 'list_syntax' => ['syntax' => 'short'], + 'mb_str_functions' => true, + 'method_argument_space' => ['on_multiline' => 'ignore'], + 'method_chaining_indentation' => false, + 'no_extra_blank_lines' => ['tokens' => ['extra', 'use_trait']], + 'no_superfluous_phpdoc_tags' => ['remove_inheritdoc' => true], + 'not_operator_with_successor_space' => true, + 'ordered_class_elements' => false, + 'ordered_imports' => true, + 'php_unit_method_casing' => ['case' => 'snake_case'], + 'php_unit_strict' => false, + 'php_unit_test_annotation' => ['style' => 'annotation'], + 'php_unit_test_class_requires_covers' => false, + 'phpdoc_to_comment' => false, + 'phpdoc_var_without_name' => false, + 'self_static_accessor' => true, + 'single_line_throw' => false, + 'static_lambda' => true, + 'strict_comparison' => false, + 'yoda_style' => ['equal' => false, 'identical' => false], + ]) + ->setFinder($finder); + +return $config; diff --git a/.php_cs.dist b/.php_cs.dist deleted file mode 100644 index e97c8810..00000000 --- a/.php_cs.dist +++ /dev/null @@ -1,114 +0,0 @@ - - -This source file is subject to the MIT license that is bundled -with this source code in the file LICENSE. -EOF; - -return PhpCsFixer\Config::create() - ->setRiskyAllowed(true) - ->setRules([ - '@PhpCsFixer' => true, - '@PhpCsFixer:risky' => true, - '@Symfony' => true, - '@Symfony:risky' => true, - '@PHP56Migration' => true, - '@PHP70Migration:risky' => true, - '@PHP71Migration:risky' => true, - //'@PHP73Migration' => true, - '@PHPUnit60Migration:risky' => true, - '@PHPUnit75Migration:risky' => true, - '@DoctrineAnnotation' => true, - 'array_syntax' => ['syntax' => 'short'], - 'blank_line_before_statement' => [ - 'statements' => [ - 'break', - 'case', - 'continue', - 'declare', - 'default', - 'die', - 'do', - 'exit', - 'for', - 'foreach', - 'goto', - 'if', - 'include', - 'include_once', - 'require', - 'require_once', - 'return', - 'switch', - 'throw', - 'try', - 'while', - 'yield', - ], - ], - 'braces' => [ - 'allow_single_line_closure' => true, - ], - 'concat_space' => [ - 'spacing' => 'one', - ], - 'comment_to_phpdoc' => [ - 'ignored_tags' => ['codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd'], - ], - 'doctrine_annotation_array_assignment' => [ - 'operator' => '=', - ], - 'final_static_access' => true, - 'general_phpdoc_annotation_remove' => [ - //'author', - 'since', - ], - 'header_comment' => ['header' => $header], - 'list_syntax' => [ - 'syntax' => 'short', - ], - 'mb_str_functions' => false, // Breaks the String lexer which needs to be aware of actual bytes - 'method_chaining_indentation' => false, - 'multiline_whitespace_before_semicolons' => ['strategy' => 'no_multi_line'], - 'native_function_invocation' => [ - 'strict' => true, - ], - 'no_extra_blank_lines' => [ - 'tokens' => ['extra', 'useTrait'], - ], - 'no_superfluous_phpdoc_tags' => true, - 'not_operator_with_successor_space' => true, - 'ordered_class_elements' => false, // Use the step-down structure approach - 'ordered_imports' => [ - 'imports_order' => ['class', 'const', 'function'], - ], - 'php_unit_method_casing' => ['case' => 'snake_case'], - 'php_unit_strict' => false, - 'php_unit_test_annotation' => [ - 'style' => 'annotation', - ], - 'php_unit_test_class_requires_covers' => false, - 'phpdoc_to_comment' => false, // This breaks for variable @var blocks - 'phpdoc_types_order' => [ - 'null_adjustment' => 'always_last', - ], - 'phpdoc_var_without_name' => false, // see phpdoc_to_comment - 'strict_comparison' => false, - 'single_line_throw' => false, - 'static_lambda' => false, // Breaks Prophecy promises - 'yoda_style' => [ - 'equal' => false, - 'identical' => false, - ], - ]) - ->setRiskyAllowed(true) - ->setFinder( - PhpCsFixer\Finder::create() - ->exclude('Fixtures') - ->in([__DIR__.'/lib']) - ) -; diff --git a/Makefile b/Makefile index a6481768..cd409a0c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -QA_DOCKER_IMAGE=jakzal/phpqa:1.58.9-php7.4-alpine +QA_DOCKER_IMAGE=jakzal/phpqa:1.59.1-php7.4-alpine QA_DOCKER_COMMAND=docker run --init -t --rm --user "$(shell id -u):$(shell id -g)" --volume /tmp/tmp-phpqa-$(shell id -u):/tmp --volume "$(shell pwd):/project" --workdir /project ${QA_DOCKER_IMAGE} dist: install cs-full phpstan test diff --git a/docker/Dockerfile-qa b/docker/Dockerfile-qa deleted file mode 100644 index ded1b9ba..00000000 --- a/docker/Dockerfile-qa +++ /dev/null @@ -1,20 +0,0 @@ -FROM jakzal/phpqa:alpine - -RUN set -xe \ - && apk add --update openssl ca-certificates \ - && apk add --no-cache --virtual .php-deps \ - libpq \ - icu-libs \ - git \ - && apk add --no-cache --virtual .build-deps \ - $PHPIZE_DEPS \ - postgresql-dev \ - icu-dev \ - && docker-php-ext-install \ - pdo_pgsql \ - pgsql \ - bcmath \ - intl \ - && { find /usr/local/lib -type f -print0 | xargs -0r --strip-all -p 2>/dev/null || true; } \ - && apk del .build-deps \ - && rm -rf /tmp/* /usr/local/lib/php/doc/* /var/cache/apk/* diff --git a/lib/Core/Input/StringLexer.php b/lib/Core/Input/StringLexer.php index 804df926..433d3564 100644 --- a/lib/Core/Input/StringLexer.php +++ b/lib/Core/Input/StringLexer.php @@ -47,7 +47,7 @@ public function parse(string $data, array $fieldLexers = []): void { $this->data = \str_replace(["\r\n", "\r"], "\n", $data); $this->valueLexers = $fieldLexers; - $this->end = \strlen($this->data); + $this->end = mb_strlen($this->data, '8bit'); $this->lineno = 1; $this->cursor = 0; $this->char = 0; @@ -62,7 +62,7 @@ public function skipWhitespace(): void { if (\preg_match('/\h+/A', $this->data, $match, 0, $this->cursor)) { $this->char += \mb_strlen($match[0]); - $this->cursor += \strlen($match[0]); + $this->cursor += mb_strlen($match[0], '8bit'); } } @@ -79,8 +79,8 @@ public function skipEmptyLines(): void public function moveCursor(string $text): void { $this->lineno += \mb_substr_count($text, "\n"); - $this->cursor += \strlen($text); $this->char += \mb_strlen($text); + $this->cursor += mb_strlen($text, '8bit'); } public function snapshot($force = false): void @@ -209,7 +209,7 @@ public function stringValue(string $allowedNext = ',;)'): string if ($this->data[$this->cursor] === '"') { $this->moveCursor('"'); - while ("\n" !== $c = \mb_substr($this->data, $this->char, 1)) { + while (($c = mb_substr($this->data, $this->char, 1)) !== "\n") { if ($c === '"') { if ($this->cursor + 1 === $this->end) { break; @@ -362,8 +362,8 @@ public function patternMatchValue(): array throw $this->createFormatException(StringLexerException::UNKNOWN_PATTERN_MATCH_FLAG); } - $negative = \strpos($match[1], '!') !== false; - $caseInsensitive = \strpos($match[1], 'i') !== false; + $negative = mb_strpos($match[1], '!') !== false; + $caseInsensitive = mb_strpos($match[1], 'i') !== false; } static $operatorToTypeMapping = [ @@ -442,7 +442,7 @@ private function regexOrSingleChar(string $data): ?string return null; } - if (\strlen($data) === 1) { + if (mb_strlen($data, '8bit') === 1) { return $data === $this->data[$this->cursor] ? $data : null; } From 62adba14662543dbc16849aa6480f53c30db3503 Mon Sep 17 00:00:00 2001 From: Sebastiaan Stok Date: Sun, 29 Aug 2021 15:32:50 +0200 Subject: [PATCH 7/8] Enable PHPStan annotation for pr's --- .github/workflows/ci.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a7589cbc..02fe22e5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -125,4 +125,5 @@ jobs: - name: Run PHP-QA run: | - make lint + make cs-full-check + vendor/bin/phpstan analyse --memory-limit=-1 --error-format=checkstyle | cs2pr From dc796855cca80bb769071d68ac92d2f2e6ee173a Mon Sep 17 00:00:00 2001 From: Sebastiaan Stok Date: Mon, 30 Aug 2021 15:52:22 +0200 Subject: [PATCH 8/8] Fix PHPUnit deprecations --- composer.json | 1 + .../Orm/Extension/SearchExtensionTest.php | 3 + .../Extension/SearchExtensionTest.php | 3 + ...efaultConfigurationMetadataFactoryTest.php | 3 + lib/Core/Test/SearchIntegrationTestCase.php | 3 + .../Factory/CachingFactoryDecoratorTest.php | 163 +++++++----------- .../BirthdayTransformerTest.php | 3 + .../LocalizedBirthdayTransformerTest.php | 3 + lib/Core/Tests/Field/TypeRegistryTest.php | 3 + lib/Core/Tests/GenericFieldSetBuilderTest.php | 3 + .../Tests/SearchConditionSerializerTest.php | 3 + .../Orm/Tests/FieldConfigBuilderTest.php | 3 + 12 files changed, 89 insertions(+), 105 deletions(-) diff --git a/composer.json b/composer.json index e7e4ca18..1750d3cc 100644 --- a/composer.json +++ b/composer.json @@ -43,6 +43,7 @@ "jangregor/phpstan-prophecy": "^0.8.1", "matthiasnoback/symfony-dependency-injection-test": "^3.0 || ^4.1.1", "moneyphp/money": "^3.2.0 || ^4.0", + "phpspec/prophecy-phpunit": "^2.0", "phpstan/phpstan": "^0.12.94", "phpstan/phpstan-doctrine": "^0.12.42", "phpstan/phpstan-phpunit": "^0.12.21", diff --git a/lib/ApiPlatform/Tests/Doctrine/Orm/Extension/SearchExtensionTest.php b/lib/ApiPlatform/Tests/Doctrine/Orm/Extension/SearchExtensionTest.php index b8bb9aad..d76fedaf 100644 --- a/lib/ApiPlatform/Tests/Doctrine/Orm/Extension/SearchExtensionTest.php +++ b/lib/ApiPlatform/Tests/Doctrine/Orm/Extension/SearchExtensionTest.php @@ -21,6 +21,7 @@ use Doctrine\ORM\QueryBuilder; use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; use Rollerworks\Component\Search\ApiPlatform\Doctrine\Orm\Extension\SearchExtension; use Rollerworks\Component\Search\Doctrine\Orm\CachedDqlConditionGenerator; use Rollerworks\Component\Search\Doctrine\Orm\DoctrineOrmFactory; @@ -33,6 +34,8 @@ /** @internal */ final class SearchExtensionTest extends TestCase { + use ProphecyTrait; + /** @test */ public function apply_to_collection_with_valid_condition(): void { diff --git a/lib/ApiPlatform/Tests/Elasticsearch/Extension/SearchExtensionTest.php b/lib/ApiPlatform/Tests/Elasticsearch/Extension/SearchExtensionTest.php index ca74252f..7ad41c03 100644 --- a/lib/ApiPlatform/Tests/Elasticsearch/Extension/SearchExtensionTest.php +++ b/lib/ApiPlatform/Tests/Elasticsearch/Extension/SearchExtensionTest.php @@ -24,6 +24,7 @@ use Elastica\Response; use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; use Rollerworks\Component\Search\ApiPlatform\Elasticsearch\Extension\SearchExtension; use Rollerworks\Component\Search\ApiPlatform\Tests\Fixtures\Dummy; use Rollerworks\Component\Search\Elasticsearch\CachedConditionGenerator; @@ -38,6 +39,8 @@ /** @internal */ final class SearchExtensionTest extends TestCase { + use ProphecyTrait; + /** @test */ public function apply_to_collection_with_valid_condition(): void { diff --git a/lib/ApiPlatform/Tests/Metadata/DefaultConfigurationMetadataFactoryTest.php b/lib/ApiPlatform/Tests/Metadata/DefaultConfigurationMetadataFactoryTest.php index 1596114f..7d2535bc 100644 --- a/lib/ApiPlatform/Tests/Metadata/DefaultConfigurationMetadataFactoryTest.php +++ b/lib/ApiPlatform/Tests/Metadata/DefaultConfigurationMetadataFactoryTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Rollerworks\Component\Search\ApiPlatform\Metadata\DefaultConfigurationMetadataFactory; /** @@ -23,6 +24,8 @@ */ final class DefaultConfigurationMetadataFactoryTest extends TestCase { + use ProphecyTrait; + /** @test */ public function it_merges_defaults_into_all_configs(): void { diff --git a/lib/Core/Test/SearchIntegrationTestCase.php b/lib/Core/Test/SearchIntegrationTestCase.php index 7f9f7fc4..865dd83d 100644 --- a/lib/Core/Test/SearchIntegrationTestCase.php +++ b/lib/Core/Test/SearchIntegrationTestCase.php @@ -14,6 +14,7 @@ namespace Rollerworks\Component\Search\Test; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Rollerworks\Component\Search\Exception\SearchException; use Rollerworks\Component\Search\Extension\Core\Type\IntegerType; use Rollerworks\Component\Search\Extension\Core\Type\TextType; @@ -34,6 +35,8 @@ */ abstract class SearchIntegrationTestCase extends TestCase { + use ProphecyTrait; + /** * @var SearchFactoryBuilder|null */ diff --git a/lib/Core/Tests/Extension/Core/ChoiceList/Factory/CachingFactoryDecoratorTest.php b/lib/Core/Tests/Extension/Core/ChoiceList/Factory/CachingFactoryDecoratorTest.php index c783063a..9b331f51 100644 --- a/lib/Core/Tests/Extension/Core/ChoiceList/Factory/CachingFactoryDecoratorTest.php +++ b/lib/Core/Tests/Extension/Core/ChoiceList/Factory/CachingFactoryDecoratorTest.php @@ -123,14 +123,13 @@ public function create_from_choices_different_choices($choice1, $choice2): void $list1 = $this->createMock(ChoiceList::class); $list2 = $this->createMock(ChoiceList::class); - $this->decoratedFactory->expects(self::at(0)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createListFromChoices') - ->with($choices1) - ->willReturn($list1); - $this->decoratedFactory->expects(self::at(1)) - ->method('createListFromChoices') - ->with($choices2) - ->willReturn($list2); + ->withConsecutive( + [$choices1], + [$choices2] + ) + ->willReturnOnConsecutiveCalls($list1, $list2); self::assertSame($list1, $this->factory->createListFromChoices($choices1)); self::assertSame($list2, $this->factory->createListFromChoices($choices2)); @@ -159,19 +158,13 @@ public function create_from_choices_different_value_closure(): void $choices = [1]; $list1 = $this->createMock(ChoiceList::class); $list2 = $this->createMock(ChoiceList::class); - $closure1 = static function (): void { - }; - $closure2 = static function (): void { - }; + $closure1 = static function (): void {}; + $closure2 = static function (): void {}; - $this->decoratedFactory->expects(self::at(0)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createListFromChoices') - ->with($choices, $closure1) - ->willReturn($list1); - $this->decoratedFactory->expects(self::at(1)) - ->method('createListFromChoices') - ->with($choices, $closure2) - ->willReturn($list2); + ->withConsecutive([$choices, $closure1], [$choices, $closure2]) + ->willReturnOnConsecutiveCalls($list1, $list2); self::assertSame($list1, $this->factory->createListFromChoices($choices, $closure1)); self::assertSame($list2, $this->factory->createListFromChoices($choices, $closure2)); @@ -200,14 +193,13 @@ public function create_from_loader_different_loader(): void $list1 = $this->createMock(ChoiceList::class); $list2 = $this->createMock(ChoiceList::class); - $this->decoratedFactory->expects(self::at(0)) - ->method('createListFromLoader') - ->with($loader1) - ->willReturn($list1); - $this->decoratedFactory->expects(self::at(1)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createListFromLoader') - ->with($loader2) - ->willReturn($list2); + ->withConsecutive( + [$loader1], + [$loader2] + ) + ->willReturnOnConsecutiveCalls($list1, $list2); self::assertSame($list1, $this->factory->createListFromLoader($loader1)); self::assertSame($list2, $this->factory->createListFromLoader($loader2)); @@ -241,14 +233,10 @@ public function create_from_loader_different_value_closure(): void $closure2 = static function (): void { }; - $this->decoratedFactory->expects(self::at(0)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createListFromLoader') - ->with($loader, $closure1) - ->willReturn($list1); - $this->decoratedFactory->expects(self::at(1)) - ->method('createListFromLoader') - ->with($loader, $closure2) - ->willReturn($list2); + ->withConsecutive([$loader, $closure1], [$loader, $closure2]) + ->willReturnOnConsecutiveCalls($list1, $list2); self::assertSame($list1, $this->factory->createListFromLoader($loader, $closure1)); self::assertSame($list2, $this->factory->createListFromLoader($loader, $closure2)); @@ -279,14 +267,10 @@ public function create_view_different_preferred_choices(): void $view1 = new ChoiceListView(); $view2 = new ChoiceListView(); - $this->decoratedFactory->expects(self::at(0)) - ->method('createView') - ->with($list, $preferred1) - ->willReturn($view1); - $this->decoratedFactory->expects(self::at(1)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createView') - ->with($list, $preferred2) - ->willReturn($view2); + ->withConsecutive([$list, $preferred1], [$list, $preferred2]) + ->willReturnOnConsecutiveCalls($view1, $view2); self::assertSame($view1, $this->factory->createView($list, $preferred1)); self::assertSame($view2, $this->factory->createView($list, $preferred2)); @@ -312,22 +296,16 @@ public function create_view_same_preferred_choices_closure(): void /** @test */ public function create_view_different_preferred_choices_closure(): void { - $preferred1 = static function (): void { - }; - $preferred2 = static function (): void { - }; + $preferred1 = static function (): void {}; + $preferred2 = static function (): void {}; $list = $this->createMock(ChoiceList::class); $view1 = new ChoiceListView(); $view2 = new ChoiceListView(); - $this->decoratedFactory->expects(self::at(0)) - ->method('createView') - ->with($list, $preferred1) - ->willReturn($view1); - $this->decoratedFactory->expects(self::at(1)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createView') - ->with($list, $preferred2) - ->willReturn($view2); + ->withConsecutive([$list, $preferred1], [$list, $preferred2]) + ->willReturnOnConsecutiveCalls($view1, $view2); self::assertSame($view1, $this->factory->createView($list, $preferred1)); self::assertSame($view2, $this->factory->createView($list, $preferred2)); @@ -353,22 +331,16 @@ public function create_view_same_label_closure(): void /** @test */ public function create_view_different_label_closure(): void { - $labels1 = static function (): void { - }; - $labels2 = static function (): void { - }; + $labels1 = static function (): void {}; + $labels2 = static function (): void {}; $list = $this->createMock(ChoiceList::class); $view1 = new ChoiceListView(); $view2 = new ChoiceListView(); - $this->decoratedFactory->expects(self::at(0)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createView') - ->with($list, null, $labels1) - ->willReturn($view1); - $this->decoratedFactory->expects(self::at(1)) - ->method('createView') - ->with($list, null, $labels2) - ->willReturn($view2); + ->withConsecutive([$list, null, $labels1], [$list, null, $labels2]) + ->willReturnOnConsecutiveCalls($view1, $view2); self::assertSame($view1, $this->factory->createView($list, null, $labels1)); self::assertSame($view2, $this->factory->createView($list, null, $labels2)); @@ -394,22 +366,16 @@ public function create_view_same_index_closure(): void /** @test */ public function create_view_different_index_closure(): void { - $index1 = static function (): void { - }; - $index2 = static function (): void { - }; + $index1 = static function (): void {}; + $index2 = static function (): void {}; $list = $this->createMock(ChoiceList::class); $view1 = new ChoiceListView(); $view2 = new ChoiceListView(); - $this->decoratedFactory->expects(self::at(0)) - ->method('createView') - ->with($list, null, null, $index1) - ->willReturn($view1); - $this->decoratedFactory->expects(self::at(1)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createView') - ->with($list, null, null, $index2) - ->willReturn($view2); + ->withConsecutive([$list, null, null, $index1], [$list, null, null, $index2]) + ->willReturnOnConsecutiveCalls($view1, $view2); self::assertSame($view1, $this->factory->createView($list, null, null, $index1)); self::assertSame($view2, $this->factory->createView($list, null, null, $index2)); @@ -435,22 +401,16 @@ public function create_view_same_group_by_closure(): void /** @test */ public function create_view_different_group_by_closure(): void { - $groupBy1 = static function (): void { - }; - $groupBy2 = static function (): void { - }; + $groupBy1 = static function (): void {}; + $groupBy2 = static function (): void {}; $list = $this->createMock(ChoiceList::class); $view1 = new ChoiceListView(); $view2 = new ChoiceListView(); - $this->decoratedFactory->expects(self::at(0)) - ->method('createView') - ->with($list, null, null, null, $groupBy1) - ->willReturn($view1); - $this->decoratedFactory->expects(self::at(1)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createView') - ->with($list, null, null, null, $groupBy2) - ->willReturn($view2); + ->withConsecutive([$list, null, null, null, $groupBy1], [$list, null, null, null, $groupBy2]) + ->willReturnOnConsecutiveCalls($view1, $view2); self::assertSame($view1, $this->factory->createView($list, null, null, null, $groupBy1)); self::assertSame($view2, $this->factory->createView($list, null, null, null, $groupBy2)); @@ -481,14 +441,13 @@ public function create_view_different_attributes(): void $view1 = new ChoiceListView(); $view2 = new ChoiceListView(); - $this->decoratedFactory->expects(self::at(0)) - ->method('createView') - ->with($list, null, null, null, null, $attr1) - ->willReturn($view1); - $this->decoratedFactory->expects(self::at(1)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createView') - ->with($list, null, null, null, null, $attr2) - ->willReturn($view2); + ->withConsecutive( + [$list, null, null, null, null, $attr1], + [$list, null, null, null, null, $attr2] + ) + ->willReturnOnConsecutiveCalls($view1, $view2); self::assertSame($view1, $this->factory->createView($list, null, null, null, null, $attr1)); self::assertSame($view2, $this->factory->createView($list, null, null, null, null, $attr2)); @@ -514,28 +473,22 @@ public function create_view_same_attributes_closure(): void /** @test */ public function create_view_different_attributes_closure(): void { - $attr1 = static function (): void { - }; - $attr2 = static function (): void { - }; + $attr1 = static function (): void {}; + $attr2 = static function (): void {}; $list = $this->createMock(ChoiceList::class); $view1 = new ChoiceListView(); $view2 = new ChoiceListView(); - $this->decoratedFactory->expects(self::at(0)) - ->method('createView') - ->with($list, null, null, null, null, $attr1) - ->willReturn($view1); - $this->decoratedFactory->expects(self::at(1)) + $this->decoratedFactory->expects(self::exactly(2)) ->method('createView') - ->with($list, null, null, null, null, $attr2) - ->willReturn($view2); + ->withConsecutive([$list, null, null, null, null, $attr1], [$list, null, null, null, null, $attr2]) + ->willReturnOnConsecutiveCalls($view1, $view2); self::assertSame($view1, $this->factory->createView($list, null, null, null, null, $attr1)); self::assertSame($view2, $this->factory->createView($list, null, null, null, null, $attr2)); } - public function provideSameChoices() + public function provideSameChoices(): array { $object = (object) ['foo' => 'bar']; @@ -548,7 +501,7 @@ public function provideSameChoices() ]; } - public function provideDistinguishedChoices() + public function provideDistinguishedChoices(): array { return [ [0, false], @@ -566,7 +519,7 @@ public function provideDistinguishedChoices() ]; } - public function provideSameKeyChoices() + public function provideSameKeyChoices(): array { // Only test types here that can be used as array keys return [ @@ -577,7 +530,7 @@ public function provideSameKeyChoices() ]; } - public function provideDistinguishedKeyChoices() + public function provideDistinguishedKeyChoices(): array { // Only test types here that can be used as array keys return [ diff --git a/lib/Core/Tests/Extension/Core/DataTransformer/BirthdayTransformerTest.php b/lib/Core/Tests/Extension/Core/DataTransformer/BirthdayTransformerTest.php index 343e2d3e..5d3bb6c1 100644 --- a/lib/Core/Tests/Extension/Core/DataTransformer/BirthdayTransformerTest.php +++ b/lib/Core/Tests/Extension/Core/DataTransformer/BirthdayTransformerTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; use Rollerworks\Component\Search\DataTransformer; use Rollerworks\Component\Search\Exception\TransformationFailedException; use Rollerworks\Component\Search\Extension\Core\DataTransformer\BirthdayTransformer; @@ -24,6 +25,8 @@ */ final class BirthdayTransformerTest extends TestCase { + use ProphecyTrait; + /** @test */ public function it_transforms_age_to_integer(): void { diff --git a/lib/Core/Tests/Extension/Core/DataTransformer/LocalizedBirthdayTransformerTest.php b/lib/Core/Tests/Extension/Core/DataTransformer/LocalizedBirthdayTransformerTest.php index a813397f..a4965b48 100644 --- a/lib/Core/Tests/Extension/Core/DataTransformer/LocalizedBirthdayTransformerTest.php +++ b/lib/Core/Tests/Extension/Core/DataTransformer/LocalizedBirthdayTransformerTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; use Rollerworks\Component\Search\DataTransformer; use Rollerworks\Component\Search\Exception\TransformationFailedException; use Rollerworks\Component\Search\Extension\Core\DataTransformer\LocalizedBirthdayTransformer; @@ -25,6 +26,8 @@ */ final class LocalizedBirthdayTransformerTest extends TestCase { + use ProphecyTrait; + protected function setUp(): void { parent::setUp(); diff --git a/lib/Core/Tests/Field/TypeRegistryTest.php b/lib/Core/Tests/Field/TypeRegistryTest.php index 4d79b799..d138a156 100644 --- a/lib/Core/Tests/Field/TypeRegistryTest.php +++ b/lib/Core/Tests/Field/TypeRegistryTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; use Rollerworks\Component\Search\Field\FieldType; use Rollerworks\Component\Search\Field\FieldTypeExtension; use Rollerworks\Component\Search\Field\GenericTypeRegistry; @@ -30,6 +31,8 @@ */ final class TypeRegistryTest extends TestCase { + use ProphecyTrait; + /** @test */ public function it_loads_types_from_extensions(): void { diff --git a/lib/Core/Tests/GenericFieldSetBuilderTest.php b/lib/Core/Tests/GenericFieldSetBuilderTest.php index 8efc9b4d..89b3f975 100644 --- a/lib/Core/Tests/GenericFieldSetBuilderTest.php +++ b/lib/Core/Tests/GenericFieldSetBuilderTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; use Rollerworks\Component\Search\Field\FieldConfig; use Rollerworks\Component\Search\Field\ResolvedFieldType; use Rollerworks\Component\Search\Field\SearchField; @@ -28,6 +29,8 @@ */ final class GenericFieldSetBuilderTest extends TestCase { + use ProphecyTrait; + /** * @var GenericFieldSetBuilder */ diff --git a/lib/Core/Tests/SearchConditionSerializerTest.php b/lib/Core/Tests/SearchConditionSerializerTest.php index a9ba7a02..26e8e544 100644 --- a/lib/Core/Tests/SearchConditionSerializerTest.php +++ b/lib/Core/Tests/SearchConditionSerializerTest.php @@ -14,6 +14,7 @@ namespace Rollerworks\Component\Search\Tests; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Rollerworks\Component\Search\Exception\InvalidArgumentException; use Rollerworks\Component\Search\Field\FieldConfig; use Rollerworks\Component\Search\GenericFieldSet; @@ -28,6 +29,8 @@ */ final class SearchConditionSerializerTest extends TestCase { + use ProphecyTrait; + /** * @var SearchConditionSerializer */ diff --git a/lib/Doctrine/Orm/Tests/FieldConfigBuilderTest.php b/lib/Doctrine/Orm/Tests/FieldConfigBuilderTest.php index c68061b6..00f83189 100644 --- a/lib/Doctrine/Orm/Tests/FieldConfigBuilderTest.php +++ b/lib/Doctrine/Orm/Tests/FieldConfigBuilderTest.php @@ -15,6 +15,7 @@ use Doctrine\DBAL\Types\Type as DbType; use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use Rollerworks\Component\Search\Doctrine\Orm\FieldConfigBuilder; use Rollerworks\Component\Search\Doctrine\Orm\OrmQueryField as QueryField; @@ -28,6 +29,8 @@ */ final class FieldConfigBuilderTest extends TestCase { + use ProphecyTrait; + public const CUSTOMER_CLASS = Fixtures\Entity\ECommerceCustomer::class; public const INVOICE_CLASS = Fixtures\Entity\ECommerceInvoice::class;