From b78458cc30edd2f4f8ba9b6333f8f426a855a07b Mon Sep 17 00:00:00 2001 From: pmishev Date: Thu, 10 Oct 2024 19:38:55 +0100 Subject: [PATCH] Added support for Symfony^6.4 Removed support for PHP<8.1 Removed support for Symfony<5.4 Removed support for Monolog 1.* --- .github/workflows/phpunit-tests.yml | 47 +- .php-cs-fixer.dist.php | 3 +- README.md | 3 +- composer.json | 31 +- docker-compose.yml | 2 +- src/Annotation/Document.php | 19 +- src/Annotation/Property.php | 33 +- src/CacheWarmer/MetadataCacheWarmer.php | 29 +- src/Command/IndexBuildCommand.php | 9 +- src/Command/IndexCreateCommand.php | 9 +- src/DTO/BulkQueryItem.php | 27 +- src/DTO/IndicesToDocumentClasses.php | 10 +- .../Compiler/AddConnectionsPass.php | 2 +- .../Compiler/AddIndexManagersPass.php | 2 +- .../Compiler/SetCachePass.php | 2 +- src/DependencyInjection/Configuration.php | 2 +- .../SineflowElasticsearchExtension.php | 7 +- src/Document/AbstractDocument.php | 8 +- src/Document/MLProperty.php | 16 +- .../Provider/AbstractDoctrineProvider.php | 41 +- src/Document/Provider/AbstractProvider.php | 8 +- .../Provider/ElasticsearchProvider.php | 29 +- src/Document/Provider/ProviderInterface.php | 8 +- src/Document/Provider/ProviderRegistry.php | 29 +- src/Document/Repository/Repository.php | 27 +- src/Document/Repository/RepositoryFactory.php | 22 +- src/Event/PostCommitEvent.php | 21 +- src/Event/PrePersistEvent.php | 35 +- src/Exception/BulkRequestException.php | 20 +- src/Exception/DocumentConversionException.php | 3 - .../IndexOrAliasNotFoundException.php | 12 +- src/Exception/IndexRebuildingException.php | 13 +- .../InvalidIndexManagerException.php | 3 - src/Finder/Adapter/KnpPaginatorAdapter.php | 64 +-- src/Finder/Adapter/ScrollAdapter.php | 51 +- src/Finder/Finder.php | 58 +- src/Manager/ConnectionManager.php | 69 +-- src/Manager/IndexManager.php | 118 ++-- src/Manager/IndexManagerRegistry.php | 11 +- src/Mapping/Caser.php | 12 +- src/Mapping/DocumentLocator.php | 2 +- src/Mapping/DocumentMetadata.php | 7 +- src/Mapping/DocumentMetadataCollector.php | 35 +- src/Mapping/DocumentParser.php | 70 +-- src/Mapping/DumperInterface.php | 4 +- src/Profiler/ElasticsearchProfiler.php | 25 +- src/Profiler/Handler/CollectionHandler.php | 31 +- src/Result/DocumentConverter.php | 24 +- src/Result/DocumentIterator.php | 82 +-- src/Result/ObjectIterator.php | 43 +- tests/App/AppKernel.php | 7 +- .../Document/Provider/CustomerProvider.php | 7 +- .../Document/Provider/OrderProvider.php | 7 +- .../Mapping/DocumentMetadataCollectorTest.php | 525 +++++++++--------- .../Functional/Mapping/DocumentParserTest.php | 478 ++++++++-------- .../Result/DocumentConverterTest.php | 50 +- tests/Unit/Annotation/PropertyTest.php | 14 +- 57 files changed, 909 insertions(+), 1417 deletions(-) diff --git a/.github/workflows/phpunit-tests.yml b/.github/workflows/phpunit-tests.yml index aa95c42..f7802a9 100644 --- a/.github/workflows/phpunit-tests.yml +++ b/.github/workflows/phpunit-tests.yml @@ -48,39 +48,44 @@ jobs: - 'highest' php: - '8.1' - - '8.2' + - '8.3' elasticsearch: - - '7.17.13' + - '7.17.24' + - '8.15.2' symfony: - - '~5.0' + - '~6.0' include: - - php: '8.1' - symfony: '~5.0' + - php: '8.3' + symfony: '~6.0' elasticsearch: '8.0.1' experimental: false - - php: '8.1' - symfony: '~5.0' + - php: '8.3' + symfony: '~6.0' + elasticsearch: '8.0.1' + experimental: false + - php: '8.3' + symfony: '~6.0' elasticsearch: '8.1.3' # there are some bc in minor version https://www.elastic.co/guide/en/elasticsearch/reference/current/migrating-8.1.html#breaking-changes-8.1 experimental: false - - php: '8.1' - symfony: '~5.0' + - php: '8.3' + symfony: '~6.0' elasticsearch: '8.5.3' # there are some bc in minor version https://www.elastic.co/guide/en/elasticsearch/reference/current/migrating-8.5.html experimental: false - - php: '8.1' - symfony: '~5.0' + - php: '8.3' + symfony: '~6.0' elasticsearch: '8.6.2' # there are no bc in minor version https://www.elastic.co/guide/en/elasticsearch/reference/current/migrating-8.6.html experimental: false - - php: '8.1' - symfony: '~5.0' + - php: '8.3' + symfony: '~6.0' elasticsearch: '8.7.1' # there are no bc in minor version https://www.elastic.co/guide/en/elasticsearch/reference/current/migrating-8.7.html experimental: false - - php: '8.1' - symfony: '~5.0' + - php: '8.3' + symfony: '~6.0' elasticsearch: '8.8.0' # there are no bc in minor version https://www.elastic.co/guide/en/elasticsearch/reference/current/migrating-8.8.html experimental: false - php: '8.1' - symfony: '~6.0' - elasticsearch: '8.10.2' # newest version + symfony: '~5.0' + elasticsearch: '8.15.2' # newest version experimental: false fail-fast: false steps: @@ -115,10 +120,16 @@ jobs: - name: 'Run phpunit tests' run: | - vendor/bin/simple-phpunit --coverage-clover=tests/App/build/clover.xml 2>/dev/null + vendor/bin/simple-phpunit --coverage-clover=tests/App/build/clover.xml - name: Upload coverage results to Coveralls env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }} run: | vendor/bin/php-coveralls --coverage_clover=tests/App/build/clover.xml --json_path=tests/App/build/coveralls.json -v + + # Enable tmate debugging on failure for 15 minutes + - name: Setup tmate session + if: ${{ !env.ACT && failure() }} + uses: mxschmitt/action-tmate@v3 + timeout-minutes: 15 diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 3eb4e1f..945768c 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -17,6 +17,7 @@ // Indent '=>' operator 'binary_operator_spaces' => ['operators' => ['=>' => 'align_single_space_minimal']], // PSR12 imports order - 'ordered_imports' => ['imports_order' => ['class', 'function', 'const']], + 'ordered_imports' => ['imports_order' => ['class', 'function', 'const']], + 'phpdoc_separation' => true, ]) ; diff --git a/README.md b/README.md index 25e6367..4ac2699 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ Installation instructions and documentation of the bundle can be found [here](do ## Version matrix | ElasticsearchBundle | Elasticsearch | Symfony | PHP | -| ------------------- | -------------- | ----------- | ----------- | +|---------------------| -------------- |-------------|-------------| +| ~7.2 | >= 7.0 | 5.0+ | 8.1+ | | ~7.0 | >= 7.0 | 4.4+ / 5.0+ | 7.3+ / 8.0+ | | ~6.2 | >= 6.2, < 7.0 | 3.4+ / 4.0+ | 7.3+ | | ~6.1.0 | >= 6.0, < 6.2 | | | diff --git a/composer.json b/composer.json index cf9d7af..fb13ccc 100644 --- a/composer.json +++ b/composer.json @@ -11,31 +11,30 @@ } ], "require": { - "php": "^7.3 || ^8.0", - "psr/log": "^1.0", + "php": "^8.1", + "psr/log": "^2.0 || ^3.0", - "symfony/framework-bundle": "^4.4 || ^5.0", - "symfony/options-resolver": "^4.4 || ^5.0", - "symfony/config": "^4.4 || ^5.0", - "symfony/event-dispatcher": "^4.4 || ^5.0", - "symfony/translation": "^4.4 || ^5.0", - "symfony/console": "^4.4 || ^5.0", - "symfony/http-kernel": "^4.4 || ^5.0", - "symfony/event-dispatcher-contracts": "^1.1 || ^2.2", + "symfony/framework-bundle": "^5.4 || ^6.4", + "symfony/options-resolver": "^5.4 || ^6.4", + "symfony/config": "^5.4 || ^6.4", + "symfony/event-dispatcher": "^5.4 || ^6.4", + "symfony/translation": "^5.4 || ^6.4", + "symfony/console": "^5.4 || ^6.4", + "symfony/http-kernel": "^5.4 || ^6.4", + "symfony/event-dispatcher-contracts": "^3.5", "doctrine/annotations": "^1.2", "doctrine/cache": "^1.4", "elasticsearch/elasticsearch": "^7.0" }, "require-dev": { - "symfony/debug": "^4.4 || ^5.0", - "symfony/stopwatch": "^4.4 || ^5.0", - "symfony/phpunit-bridge": "^4.4 || ^5.0", - "symfony/browser-kit": "^4.4 || ^5.0", - "symfony/dotenv": "^4.4 || ^5.0", + "symfony/stopwatch": "^5.4 || ^6.4", + "symfony/phpunit-bridge": "^5.4 || ^6.4", + "symfony/browser-kit": "^5.4 || ^6.4", + "symfony/dotenv": "^5.4 || ^6.4", "doctrine/orm": "^2.6.3", - "monolog/monolog": "^1.0|^2.0|^3.0", + "monolog/monolog": "^2.0|^3.0", "knplabs/knp-paginator-bundle": "^4.0 || ^5.0", "friendsofphp/php-cs-fixer": "^3.34", "php-coveralls/php-coveralls": "^2.1", diff --git a/docker-compose.yml b/docker-compose.yml index b7166f8..7957ebc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: elasticsearch: - image: "docker.elastic.co/elasticsearch/elasticsearch:${ELASTICSEARCH_VERSION:-7.17.13}" + image: "docker.elastic.co/elasticsearch/elasticsearch:${ELASTICSEARCH_VERSION:-8.15.2}" container_name: sfes_elasticsearch environment: - discovery.type=single-node diff --git a/src/Annotation/Document.php b/src/Annotation/Document.php index 936946c..5a7fa6c 100644 --- a/src/Annotation/Document.php +++ b/src/Annotation/Document.php @@ -13,28 +13,19 @@ */ final class Document implements DumperInterface { - /** - * @var string - */ - public $repositoryClass; - - /** - * @var string - */ - public $providerClass; + public ?string $repositoryClass = null; + public ?string $providerClass = null; /** * Settings directly passed to Elasticsearch client as-is - * - * @var array */ - public $options; + public array $options = []; /** * {@inheritdoc} */ - public function dump(array $settings = []) + public function dump(array $settings = []): array { - return (array) $this->options; + return $this->options; } } diff --git a/src/Annotation/Property.php b/src/Annotation/Property.php index e05d0e2..c518194 100644 --- a/src/Annotation/Property.php +++ b/src/Annotation/Property.php @@ -18,59 +18,42 @@ final class Property implements DumperInterface public const DEFAULT_LANG_SUFFIX = 'default'; /** - * @var string - * * @Required */ - public $name; + public string $name; /** - * @var string - * * @Required */ - public $type; + public string $type; - /** - * @var bool - */ - public $multilanguage; + public bool $multilanguage = false; /** * Override mapping for the 'default' language field of multilanguage properties - * - * @var array */ - public $multilanguageDefaultOptions; + public array $multilanguageDefaultOptions = []; /** * The object name must be defined, if type is 'object' or 'nested' - * - * @var string Object name to map. */ - public $objectName; + public string $objectName; /** * Defines if related object will have one or multiple values. * If this value is set to true, ObjectIterator will be provided in the result, as opposed to an ObjectInterface object - * - * @var bool */ - public $multiple; + public bool $multiple = false; /** * Settings directly passed to Elasticsearch client as-is - * - * @var array */ - public $options; + public array $options = []; /** * Dumps property fields as array for index mapping - * - * @return array */ - public function dump(array $settings = []) + public function dump(array $settings = []): array { $result = (array) $this->options; diff --git a/src/CacheWarmer/MetadataCacheWarmer.php b/src/CacheWarmer/MetadataCacheWarmer.php index bd84471..74d5be1 100644 --- a/src/CacheWarmer/MetadataCacheWarmer.php +++ b/src/CacheWarmer/MetadataCacheWarmer.php @@ -4,44 +4,23 @@ use Sineflow\ElasticsearchBundle\Mapping\DocumentMetadataCollector; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -/** - * Class MetadataCacheWarmer - */ class MetadataCacheWarmer implements CacheWarmerInterface { - /** - * @var DocumentMetadataCollector - */ - private $metadataCollector; + private DocumentMetadataCollector $metadataCollector; public function __construct(DocumentMetadataCollector $metadataCollector) { $this->metadataCollector = $metadataCollector; } - /** - * @return bool - */ - public function isOptional() + public function isOptional(): bool { return true; } - /** - * @param string $cacheDir - * - * @return array - * - * @throws \Psr\Cache\InvalidArgumentException - */ - public function warmUp($cacheDir) + public function warmUp(string $cacheDir): array { - if ($this->metadataCollector instanceof WarmableInterface) { - return (array) $this->metadataCollector->warmUp($cacheDir); - } - - throw new \LogicException(\sprintf('The metadata collector "%s" cannot be warmed up because it does not implement "%s".', \get_debug_type($this->metadataCollector), WarmableInterface::class)); + return $this->metadataCollector->warmUp($cacheDir); } } diff --git a/src/Command/IndexBuildCommand.php b/src/Command/IndexBuildCommand.php index fd2fa87..d3397a7 100644 --- a/src/Command/IndexBuildCommand.php +++ b/src/Command/IndexBuildCommand.php @@ -16,10 +16,7 @@ class IndexBuildCommand extends Command { protected static $defaultName = 'sineflow:es:index:build'; - /** - * @var IndexManagerRegistry - */ - private $indexManagerRegistry; + private IndexManagerRegistry $indexManagerRegistry; public function __construct(IndexManagerRegistry $indexManagerRegistry) { @@ -31,7 +28,7 @@ public function __construct(IndexManagerRegistry $indexManagerRegistry) /** * {@inheritdoc} */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -59,7 +56,7 @@ protected function configure() /** * {@inheritdoc} */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $indexManagerName = $input->getArgument('index'); $indexManager = $this->indexManagerRegistry->get($indexManagerName); diff --git a/src/Command/IndexCreateCommand.php b/src/Command/IndexCreateCommand.php index 55b36aa..8b28f01 100644 --- a/src/Command/IndexCreateCommand.php +++ b/src/Command/IndexCreateCommand.php @@ -15,10 +15,7 @@ class IndexCreateCommand extends Command { protected static $defaultName = 'sineflow:es:index:create'; - /** - * @var IndexManagerRegistry - */ - private $indexManagerRegistry; + private IndexManagerRegistry $indexManagerRegistry; public function __construct(IndexManagerRegistry $indexManagerRegistry) { @@ -30,7 +27,7 @@ public function __construct(IndexManagerRegistry $indexManagerRegistry) /** * {@inheritdoc} */ - protected function configure() + protected function configure(): void { parent::configure(); @@ -46,7 +43,7 @@ protected function configure() /** * {@inheritdoc} */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $indexManagerName = $input->getArgument('index'); $indexManager = $this->indexManagerRegistry->get($indexManagerName); diff --git a/src/DTO/BulkQueryItem.php b/src/DTO/BulkQueryItem.php index 2762990..a9a8410 100644 --- a/src/DTO/BulkQueryItem.php +++ b/src/DTO/BulkQueryItem.php @@ -9,31 +9,16 @@ */ class BulkQueryItem { - /** - * @var string - */ - private $operation; - - /** - * @var string - */ - private $index; - - /** - * @var array - */ - private $query; - - /** - * @var array - */ - private $metaParams; + private string $operation; + private string $index; + private array $query; + private array $metaParams; /** * @param string $operation One of: index, update, delete, create. * @param string $index Elasticsearch index name. * @param array $query Bulk item query (aka optional_source in the ES docs) - * @param array $metaParams Additional params to pass with the meta data in the bulk request (_version, _routing, etc.) + * @param array $metaParams Additional params to pass with the metadata in the bulk request (_version, _routing, etc.) */ public function __construct(string $operation, string $index, array $query, array $metaParams = []) { @@ -72,7 +57,7 @@ public function getQuery(): array * * @param string|null $forceIndex If set, that will be the index used for the output bulk request */ - public function getLines($forceIndex = null): array + public function getLines(?string $forceIndex = null): array { $result = []; diff --git a/src/DTO/IndicesToDocumentClasses.php b/src/DTO/IndicesToDocumentClasses.php index dbdd00b..cd86bcf 100644 --- a/src/DTO/IndicesToDocumentClasses.php +++ b/src/DTO/IndicesToDocumentClasses.php @@ -9,10 +9,8 @@ class IndicesToDocumentClasses { /** * => - * - * @var array */ - private $documentClasses = []; + private array $documentClasses = []; /** * Set the document class for the physical index name @@ -21,7 +19,7 @@ class IndicesToDocumentClasses * `null` to be passed if there's only one index and we don't need the actual index name * @param string $documentClass The document class in short notation */ - public function set(?string $index, string $documentClass) + public function set(?string $index, string $documentClass): void { if (!$index) { if (!empty($this->documentClasses)) { @@ -40,10 +38,8 @@ public function set(?string $index, string $documentClass) * Get the document class for the physical index name * * @param string $index The name of the physical index in Elasticsearch - * - * @return string */ - public function get($index) + public function get(string $index): string { if (isset($this->documentClasses[$index])) { return $this->documentClasses[$index]; diff --git a/src/DependencyInjection/Compiler/AddConnectionsPass.php b/src/DependencyInjection/Compiler/AddConnectionsPass.php index 2be5b50..accd4a4 100644 --- a/src/DependencyInjection/Compiler/AddConnectionsPass.php +++ b/src/DependencyInjection/Compiler/AddConnectionsPass.php @@ -16,7 +16,7 @@ class AddConnectionsPass implements CompilerPassInterface /** * {@inheritdoc} */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { $connections = $container->getParameter('sfes.connections'); diff --git a/src/DependencyInjection/Compiler/AddIndexManagersPass.php b/src/DependencyInjection/Compiler/AddIndexManagersPass.php index 7c4e482..f470075 100644 --- a/src/DependencyInjection/Compiler/AddIndexManagersPass.php +++ b/src/DependencyInjection/Compiler/AddIndexManagersPass.php @@ -17,7 +17,7 @@ class AddIndexManagersPass implements CompilerPassInterface /** * {@inheritdoc} */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { $indices = $container->getParameter('sfes.indices'); diff --git a/src/DependencyInjection/Compiler/SetCachePass.php b/src/DependencyInjection/Compiler/SetCachePass.php index 6cac8d5..6e50114 100644 --- a/src/DependencyInjection/Compiler/SetCachePass.php +++ b/src/DependencyInjection/Compiler/SetCachePass.php @@ -15,7 +15,7 @@ class SetCachePass implements CompilerPassInterface /** * {@inheritdoc} */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { $customCachePool = $container->resolveEnvPlaceholders($container->getParameter('sfes.cache_pool'), true); diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index b624650..cf7a457 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -15,7 +15,7 @@ class Configuration implements ConfigurationInterface /** * {@inheritdoc} */ - public function getConfigTreeBuilder() + public function getConfigTreeBuilder(): TreeBuilder { $treeBuilder = new TreeBuilder('sineflow_elasticsearch'); $rootNode = $treeBuilder->getRootNode(); diff --git a/src/DependencyInjection/SineflowElasticsearchExtension.php b/src/DependencyInjection/SineflowElasticsearchExtension.php index 2a791f9..f4a65cd 100644 --- a/src/DependencyInjection/SineflowElasticsearchExtension.php +++ b/src/DependencyInjection/SineflowElasticsearchExtension.php @@ -14,10 +14,7 @@ */ class SineflowElasticsearchExtension extends Extension { - /** - * @return Configuration - */ - public function getConfiguration(array $config, ContainerBuilder $container) + public function getConfiguration(array $config, ContainerBuilder $container): Configuration { return new Configuration(); } @@ -25,7 +22,7 @@ public function getConfiguration(array $config, ContainerBuilder $container) /** * {@inheritdoc} */ - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container): void { $configuration = $this->getConfiguration($configs, $container); $config = $this->processConfiguration($configuration, $configs); diff --git a/src/Document/AbstractDocument.php b/src/Document/AbstractDocument.php index 981012d..fc8ad44 100644 --- a/src/Document/AbstractDocument.php +++ b/src/Document/AbstractDocument.php @@ -10,16 +10,12 @@ abstract class AbstractDocument implements DocumentInterface { /** - * @var string - * * @ES\Id */ - public $id; + public string|int|null $id = null; /** - * @var float - * * @ES\Score */ - public $score; + public ?float $score = null; } diff --git a/src/Document/MLProperty.php b/src/Document/MLProperty.php index bbdeaa3..41ae6ba 100644 --- a/src/Document/MLProperty.php +++ b/src/Document/MLProperty.php @@ -14,7 +14,7 @@ class MLProperty /** * @var string[] */ - private $values = []; + private array $values = []; public function __construct(array $values = []) { @@ -25,11 +25,8 @@ public function __construct(array $values = []) /** * Set value of property in given language - * - * @param string $value - * @param string $language */ - public function setValue($value, $language) + public function setValue(?string $value, string $language): void { $this->values[$language] = $value; } @@ -37,12 +34,9 @@ public function setValue($value, $language) /** * Gets value based on passed language, falling back on the default language, by default * - * @param string $language - * @param bool $fallbackToDefault If set and value for the requested language is missing, return default language value - * - * @return string|null + * @param bool $fallbackToDefault If set and value for the requested language is missing, return default language value */ - public function getValue($language, $fallbackToDefault = true) + public function getValue(string $language, bool $fallbackToDefault = true): ?string { if (isset($this->values[$language])) { return $this->values[$language]; @@ -56,7 +50,7 @@ public function getValue($language, $fallbackToDefault = true) /** * @return string[] */ - public function getValues() + public function getValues(): array { return $this->values; } diff --git a/src/Document/Provider/AbstractDoctrineProvider.php b/src/Document/Provider/AbstractDoctrineProvider.php index fe98d47..7792003 100644 --- a/src/Document/Provider/AbstractDoctrineProvider.php +++ b/src/Document/Provider/AbstractDoctrineProvider.php @@ -2,6 +2,7 @@ namespace Sineflow\ElasticsearchBundle\Document\Provider; +use Doctrine\Common\Persistence\Mapping\MappingException; use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Query; @@ -12,30 +13,24 @@ */ abstract class AbstractDoctrineProvider extends AbstractProvider { - /** - * @var EntityManagerInterface - */ - protected $em; + protected EntityManagerInterface $em; - /** - * @var Query - */ - protected $query; + protected Query $query; /** - * @var int How many records to retrieve from DB at once + * How many records to retrieve from DB at once */ - protected $batchSize = 1000; + protected int $batchSize = 1000; /** - * @var string The Doctrine entity name + * The Doctrine entity name */ - protected $doctrineEntityName; + protected string $doctrineEntityName; /** - * @var int How to hydrate doctrine results + * How to hydrate doctrine results */ - protected $sourceDataHydration = AbstractQuery::HYDRATE_OBJECT; + protected int $sourceDataHydration = AbstractQuery::HYDRATE_OBJECT; /** * @param string $documentClass The document class the provider is for @@ -47,7 +42,7 @@ public function __construct(string $documentClass, EntityManagerInterface $em) $this->em = $em; } - public function setBatchSize(int $batchSize) + public function setBatchSize(int $batchSize): void { $this->batchSize = $batchSize; } @@ -60,11 +55,11 @@ abstract public function getQuery(): Query; /** * Converts a Doctrine entity to Elasticsearch entity * - * @param mixed $entity A doctrine entity object or data array + * @param object|array $entity A doctrine entity object or data array * - * @return mixed An ES document entity object or document array + * @return DocumentInterface|array An ES document entity object or document array */ - abstract protected function getAsDocument($entity); + abstract protected function getAsDocument(object|array $entity): DocumentInterface|array; /** * Returns a PHP Generator for iterating over the full dataset of source data that is to be inserted in ES @@ -72,9 +67,9 @@ abstract protected function getAsDocument($entity); * * @return \Generator * - * @throws \Doctrine\Common\Persistence\Mapping\MappingException + * @throws MappingException */ - public function getDocuments() + public function getDocuments(): \Generator { \set_time_limit(3600); @@ -105,12 +100,8 @@ public function getDocuments() /** * Build and return a document entity from the data source * The returned data can be either a document entity or an array ready for direct sending to ES - * - * @param int|string $id - * - * @return DocumentInterface|array */ - public function getDocument($id) + public function getDocument(int|string $id): DocumentInterface|array|null { $entity = $this->em->getRepository($this->doctrineEntityName)->find($id); diff --git a/src/Document/Provider/AbstractProvider.php b/src/Document/Provider/AbstractProvider.php index a1e4cc6..3a3eb4b 100644 --- a/src/Document/Provider/AbstractProvider.php +++ b/src/Document/Provider/AbstractProvider.php @@ -15,17 +15,13 @@ abstract class AbstractProvider implements ProviderInterface * * @return \Generator */ - abstract public function getDocuments(); + abstract public function getDocuments(): \Generator; /** * Build and return a document entity from the data source * The returned data can be either a document entity or an array ready for direct sending to ES - * - * @param int|string $id - * - * @return DocumentInterface|array */ - abstract public function getDocument($id); + abstract public function getDocument(int|string $id): DocumentInterface|array|null; /** * Returns the number of Elasticsearch documents to persist in a single bulk request diff --git a/src/Document/Provider/ElasticsearchProvider.php b/src/Document/Provider/ElasticsearchProvider.php index ad0389c..83727fe 100644 --- a/src/Document/Provider/ElasticsearchProvider.php +++ b/src/Document/Provider/ElasticsearchProvider.php @@ -12,30 +12,27 @@ */ class ElasticsearchProvider extends AbstractProvider { - /** - * @var DocumentMetadataCollector - */ - protected $metadataCollector; + protected DocumentMetadataCollector $metadataCollector; /** - * @var string The index manager of the data source + * The index manager of the data source */ - protected $sourceIndexManager; + protected string|IndexManager $sourceIndexManager; /** - * @var string The document class the data is coming from + * The document class the data is coming from */ - protected $sourceDocumentClass; + protected string $sourceDocumentClass; /** - * @var string Specify how long a consistent view of the index should be maintained for a scrolled search + * Specify how long a consistent view of the index should be maintained for a scrolled search */ - protected $scrollTime = '5m'; + protected string $scrollTime = '5m'; /** - * @var int Number of documents in one chunk sent to ES + * Number of documents in one chunk sent to ES */ - protected $chunkSize = 500; + protected int $chunkSize = 500; /** * @param DocumentMetadataCollector $metadataCollector The metadata collector @@ -45,7 +42,7 @@ class ElasticsearchProvider extends AbstractProvider public function __construct( DocumentMetadataCollector $metadataCollector, IndexManager $sourceIndexManager, - string $sourceDocumentClass + string $sourceDocumentClass, ) { $this->metadataCollector = $metadataCollector; $this->sourceIndexManager = $sourceIndexManager; @@ -57,7 +54,7 @@ public function __construct( * * @return \Generator */ - public function getDocuments() + public function getDocuments(): \Generator { $repo = $this->sourceIndexManager->getRepository(); @@ -83,10 +80,8 @@ public function getDocuments() /** * Build and return a document from the data source, ready for insertion into ES - * - * @param int|string $id */ - public function getDocument($id): array + public function getDocument(int|string $id): array { $params = [ 'index' => $this->sourceIndexManager->getLiveIndex(), diff --git a/src/Document/Provider/ProviderInterface.php b/src/Document/Provider/ProviderInterface.php index 23ccf79..697335b 100644 --- a/src/Document/Provider/ProviderInterface.php +++ b/src/Document/Provider/ProviderInterface.php @@ -16,17 +16,13 @@ interface ProviderInterface * * @return \Generator */ - public function getDocuments(); + public function getDocuments(): \Generator; /** * Build and return a document entity from the data source * The returned data can be either a document entity or an array ready for direct sending to ES - * - * @param int|string $id - * - * @return DocumentInterface|array */ - public function getDocument($id); + public function getDocument(int|string $id): DocumentInterface|array|null; /** * Returns the number of Elasticsearch documents to persist in a single bulk request diff --git a/src/Document/Provider/ProviderRegistry.php b/src/Document/Provider/ProviderRegistry.php index 18f2f04..f70c562 100644 --- a/src/Document/Provider/ProviderRegistry.php +++ b/src/Document/Provider/ProviderRegistry.php @@ -2,6 +2,7 @@ namespace Sineflow\ElasticsearchBundle\Document\Provider; +use Psr\Cache\InvalidArgumentException; use Sineflow\ElasticsearchBundle\Manager\IndexManagerRegistry; use Sineflow\ElasticsearchBundle\Mapping\DocumentMetadataCollector; use Symfony\Component\DependencyInjection\ServiceLocator; @@ -11,34 +12,19 @@ */ class ProviderRegistry { - /** - * @var DocumentMetadataCollector - */ - private $documentMetadataCollector; + private DocumentMetadataCollector $documentMetadataCollector; - /** - * @var IndexManagerRegistry - */ - private $indexManagerRegistry; + private IndexManagerRegistry $indexManagerRegistry; - /** - * @var string - */ - private $selfProviderClass; + private string $selfProviderClass; - /** - * @var ServiceLocator - */ - private $serviceLocator; + private ServiceLocator $serviceLocator; - /** - * ProviderRegistry constructor. - */ public function __construct( ServiceLocator $serviceLocator, DocumentMetadataCollector $documentMetadataCollector, IndexManagerRegistry $indexManagerRegistry, - string $selfProviderClass + string $selfProviderClass, ) { $this->serviceLocator = $serviceLocator; $this->documentMetadataCollector = $documentMetadataCollector; @@ -46,6 +32,9 @@ public function __construct( $this->selfProviderClass = $selfProviderClass; } + /** + * @throws InvalidArgumentException + */ public function getCustomProviderForEntity(string $documentClass): ?ProviderInterface { $documentMetadata = $this->documentMetadataCollector->getDocumentMetadata($documentClass); diff --git a/src/Document/Repository/Repository.php b/src/Document/Repository/Repository.php index 93e7bca..1956c9b 100644 --- a/src/Document/Repository/Repository.php +++ b/src/Document/Repository/Repository.php @@ -2,34 +2,27 @@ namespace Sineflow\ElasticsearchBundle\Document\Repository; +use Sineflow\ElasticsearchBundle\Document\DocumentInterface; +use Sineflow\ElasticsearchBundle\Finder\Adapter\KnpPaginatorAdapter; +use Sineflow\ElasticsearchBundle\Finder\Adapter\ScrollAdapter; use Sineflow\ElasticsearchBundle\Finder\Finder; use Sineflow\ElasticsearchBundle\Manager\IndexManager; +use Sineflow\ElasticsearchBundle\Result\DocumentIterator; /** * Base entity repository class. */ class Repository { - /** - * @var IndexManager - */ - private $indexManager; + private IndexManager $indexManager; /** * The document class FQN or in short notation (e.g. App:Product) - * - * @var string */ - protected $documentClass; + protected string $documentClass; - /** - * @var Finder - */ - protected $finder; + protected Finder $finder; - /** - * Constructor. - */ public function __construct(IndexManager $indexManager, Finder $finder) { $this->indexManager = $indexManager; @@ -47,10 +40,8 @@ public function getIndexManager(): IndexManager * * @param string $id Document Id to find. * @param int $resultType Result type returned. - * - * @return mixed */ - public function getById(string $id, int $resultType = Finder::RESULTS_OBJECT) + public function getById(string $id, int $resultType = Finder::RESULTS_OBJECT): DocumentInterface|array|null { return $this->finder->get($this->documentClass, $id, $resultType); } @@ -65,7 +56,7 @@ public function getById(string $id, int $resultType = Finder::RESULTS_OBJECT) * * @return mixed */ - public function find(array $searchBody, int $resultsType = Finder::RESULTS_OBJECT, array $additionalRequestParams = [], int &$totalHits = null) + public function find(array $searchBody, int $resultsType = Finder::RESULTS_OBJECT, array $additionalRequestParams = [], ?int &$totalHits = null): array|KnpPaginatorAdapter|ScrollAdapter|DocumentIterator { return $this->finder->find([$this->documentClass], $searchBody, $resultsType, $additionalRequestParams, $totalHits); } diff --git a/src/Document/Repository/RepositoryFactory.php b/src/Document/Repository/RepositoryFactory.php index afa91cb..fd26d93 100644 --- a/src/Document/Repository/RepositoryFactory.php +++ b/src/Document/Repository/RepositoryFactory.php @@ -2,6 +2,7 @@ namespace Sineflow\ElasticsearchBundle\Document\Repository; +use Psr\Cache\InvalidArgumentException; use Sineflow\ElasticsearchBundle\Finder\Finder; use Sineflow\ElasticsearchBundle\Manager\IndexManager; use Sineflow\ElasticsearchBundle\Mapping\DocumentMetadata; @@ -12,30 +13,24 @@ */ class RepositoryFactory { - /** - * @var ServiceLocator - */ - private $container; + private ServiceLocator $container; - /** - * @var Finder - */ - private $finder; + private Finder $finder; /** * @var Repository[] */ - private $knownRepositories = []; + private array $knownRepositories = []; - /** - * RepositoryFactory constructor. - */ public function __construct(ServiceLocator $container, Finder $finder) { $this->container = $container; $this->finder = $finder; } + /** + * @throws InvalidArgumentException + */ public function getRepository(IndexManager $indexManager): Repository { $documentMetadata = $indexManager->getDocumentMetadata(); @@ -79,8 +74,7 @@ public function getRepository(IndexManager $indexManager): Repository private function createRepository(IndexManager $indexManager, DocumentMetadata $documentMetadata): Repository { $repositoryClass = $documentMetadata->getRepositoryClass() ?: Repository::class; - $repository = new $repositoryClass($indexManager, $this->finder); - return $repository; + return new $repositoryClass($indexManager, $this->finder); } } diff --git a/src/Event/PostCommitEvent.php b/src/Event/PostCommitEvent.php index e97963a..13357e2 100644 --- a/src/Event/PostCommitEvent.php +++ b/src/Event/PostCommitEvent.php @@ -10,15 +10,8 @@ */ class PostCommitEvent extends Event { - /** - * @var array - */ - private $bulkResponse; - - /** - * @var string - */ - private $connectionName; + private array $bulkResponse; + private string $connectionName; public function __construct(array $bulkResponse, ConnectionManager $connectionManager) { @@ -26,18 +19,12 @@ public function __construct(array $bulkResponse, ConnectionManager $connectionMa $this->connectionName = $connectionManager->getConnectionName(); } - /** - * @return array - */ - public function getBulkResponse() + public function getBulkResponse(): array { return $this->bulkResponse; } - /** - * @return string - */ - public function getConnectionName() + public function getConnectionName(): string { return $this->connectionName; } diff --git a/src/Event/PrePersistEvent.php b/src/Event/PrePersistEvent.php index c368152..e3d4fb4 100644 --- a/src/Event/PrePersistEvent.php +++ b/src/Event/PrePersistEvent.php @@ -6,25 +6,11 @@ use Sineflow\ElasticsearchBundle\Manager\ConnectionManager; use Symfony\Contracts\EventDispatcher\Event; -/** - * Class PrePersistEvent - */ class PrePersistEvent extends Event { - /** - * @var DocumentInterface - */ - private $document; - - /** - * @var string - */ - private $connectionName; - - /** - * @var int - */ - private $bulkOperationIndex; + private DocumentInterface $document; + private string $connectionName; + private int $bulkOperationIndex; public function __construct(DocumentInterface $document, ConnectionManager $connectionManager) { @@ -33,26 +19,17 @@ public function __construct(DocumentInterface $document, ConnectionManager $conn $this->bulkOperationIndex = $connectionManager->getBulkOperationsCount(); } - /** - * @return DocumentInterface - */ - public function getDocument() + public function getDocument(): DocumentInterface { return $this->document; } - /** - * @return string - */ - public function getConnectionName() + public function getConnectionName(): string { return $this->connectionName; } - /** - * @return int - */ - public function getBulkOperationIndex() + public function getBulkOperationIndex(): int { return $this->bulkOperationIndex; } diff --git a/src/Exception/BulkRequestException.php b/src/Exception/BulkRequestException.php index e291807..0a630fe 100644 --- a/src/Exception/BulkRequestException.php +++ b/src/Exception/BulkRequestException.php @@ -7,31 +7,21 @@ */ class BulkRequestException extends Exception { - private $bulkResponseItems = []; + private array $bulkResponseItems = []; + private array $bulkRequest = []; - private $bulkRequest = []; - - /** - * @param string $bulkResponseItems - */ - public function setBulkResponseItems($bulkResponseItems, array $bulkRequest) + public function setBulkResponseItems(array $bulkResponseItems, array $bulkRequest): void { $this->bulkResponseItems = $bulkResponseItems; $this->bulkRequest = $bulkRequest; } - /** - * @return array - */ - public function getBulkResponseItems() + public function getBulkResponseItems(): array { return $this->bulkResponseItems; } - /** - * @return array - */ - public function getBulkRequest() + public function getBulkRequest(): array { return $this->bulkRequest; } diff --git a/src/Exception/DocumentConversionException.php b/src/Exception/DocumentConversionException.php index d9542db..82e63ea 100644 --- a/src/Exception/DocumentConversionException.php +++ b/src/Exception/DocumentConversionException.php @@ -2,9 +2,6 @@ namespace Sineflow\ElasticsearchBundle\Exception; -/** - * Class DocumentConversionException - */ class DocumentConversionException extends Exception { } diff --git a/src/Exception/IndexOrAliasNotFoundException.php b/src/Exception/IndexOrAliasNotFoundException.php index 0a2796d..03ee28b 100644 --- a/src/Exception/IndexOrAliasNotFoundException.php +++ b/src/Exception/IndexOrAliasNotFoundException.php @@ -7,17 +7,9 @@ */ class IndexOrAliasNotFoundException extends Exception { - /** - * @var string - */ - private $indexOrAlias; + private string $indexOrAlias; - /** - * Constructor - * - * @param int $code - */ - public function __construct(string $indexOrAlias, bool $isAlias = false, $code = 0, \Throwable $previous = null) + public function __construct(string $indexOrAlias, bool $isAlias = false, int $code = 0, ?\Throwable $previous = null) { $this->indexOrAlias = $indexOrAlias; diff --git a/src/Exception/IndexRebuildingException.php b/src/Exception/IndexRebuildingException.php index c44b130..644315b 100644 --- a/src/Exception/IndexRebuildingException.php +++ b/src/Exception/IndexRebuildingException.php @@ -7,26 +7,19 @@ */ class IndexRebuildingException extends Exception { - /** - * @var array - */ - private $indicesInProgress; + private array $indicesInProgress; /** * @param array $indicesInProgress The physical indices, which are in the process of being built - * @param int $code */ - public function __construct(array $indicesInProgress, $code = 0, Exception $previous = null) + public function __construct(array $indicesInProgress, int $code = 0, ?Exception $previous = null) { parent::__construct(\sprintf('Index is currently being rebuilt as "%s"', \implode(', ', $indicesInProgress)), $code, $previous); $this->indicesInProgress = $indicesInProgress; } - /** - * @return array - */ - public function getIndices() + public function getIndices(): array { return $this->indicesInProgress; } diff --git a/src/Exception/InvalidIndexManagerException.php b/src/Exception/InvalidIndexManagerException.php index e51685d..d69728f 100644 --- a/src/Exception/InvalidIndexManagerException.php +++ b/src/Exception/InvalidIndexManagerException.php @@ -2,9 +2,6 @@ namespace Sineflow\ElasticsearchBundle\Exception; -/** - * Class InvalidIndexManagerException - */ class InvalidIndexManagerException extends Exception { } diff --git a/src/Finder/Adapter/KnpPaginatorAdapter.php b/src/Finder/Adapter/KnpPaginatorAdapter.php index d8eda4a..ecbf4ba 100644 --- a/src/Finder/Adapter/KnpPaginatorAdapter.php +++ b/src/Finder/Adapter/KnpPaginatorAdapter.php @@ -3,46 +3,18 @@ namespace Sineflow\ElasticsearchBundle\Finder\Adapter; use Sineflow\ElasticsearchBundle\Finder\Finder; +use Sineflow\ElasticsearchBundle\Result\DocumentIterator; -/** - * Class KnpPaginatorAdapter - */ class KnpPaginatorAdapter { - /** - * @var Finder - */ - private $finder; - - /** - * @var array - */ - private $documentClasses; - - /** - * @var array - */ - private $searchBody; - - /** - * @var int - */ - private $resultsType; - - /** - * @var array - */ - private $additionalRequestParams; - - /** - * @var int - */ - private $totalHits; - - /** - * @param int $resultsType - */ - public function __construct(Finder $finder, array $documentClasses, array $searchBody, $resultsType, array $additionalRequestParams = []) + private Finder $finder; + private array $documentClasses; + private array $searchBody; + private int $resultsType; + private array $additionalRequestParams; + private int $totalHits = 0; + + public function __construct(Finder $finder, array $documentClasses, array $searchBody, int $resultsType, array $additionalRequestParams = []) { $this->finder = $finder; $this->documentClasses = $documentClasses; @@ -52,25 +24,15 @@ public function __construct(Finder $finder, array $documentClasses, array $searc $this->additionalRequestParams = $additionalRequestParams; } - /** - * @return int - */ - public function getResultsType() + public function getResultsType(): int { return $this->resultsType; } /** * Return results for this page only - * - * @param int $offset - * @param int $count - * @param string $sortField - * @param string $sortDir - * - * @return mixed */ - public function getResults($offset, $count, $sortField = null, $sortDir = 'asc') + public function getResults(int $offset, int $count, ?string $sortField = null, string $sortDir = 'asc'): array|DocumentIterator { $searchBody = $this->searchBody; $searchBody['from'] = $offset; @@ -93,10 +55,8 @@ public function getResults($offset, $count, $sortField = null, $sortDir = 'asc') /** * Return the total hits from the executed getResults() - * - * @return int */ - public function getTotalHits() + public function getTotalHits(): int { return $this->totalHits; } diff --git a/src/Finder/Adapter/ScrollAdapter.php b/src/Finder/Adapter/ScrollAdapter.php index 69e9cf3..5b3f54d 100644 --- a/src/Finder/Adapter/ScrollAdapter.php +++ b/src/Finder/Adapter/ScrollAdapter.php @@ -4,56 +4,31 @@ use Sineflow\ElasticsearchBundle\Exception\Exception; use Sineflow\ElasticsearchBundle\Finder\Finder; +use Sineflow\ElasticsearchBundle\Result\DocumentIterator; /** * Class ScrollAdapter */ class ScrollAdapter { - /** - * @var Finder - */ - private $finder; - - /** - * @var array - */ - private $documentClasses; - - /** - * @var string - */ - private $scrollId; - - /** - * @var string - */ - private $scrollTime; - - /** - * @var int - */ - private $resultsType; - - /** - * @var int|null - */ - private $totalHits; + private Finder $finder; + private array $documentClasses; + private string $scrollId; + private string $scrollTime; + private int $resultsType; + private ?int $totalHits; /** * When a search query with a 'scroll' param is performed, not only the scroll id is returned, but also the * initial batch of results, so we'll cache those here to be returned on the first call to getNextScrollResults() - * - * @var array */ - private $initialResults; + private ?array $initialResults; /** - * @param array $rawResults The raw results from the initial search call - * @param int $resultsType - * @param string $scrollTime The value for the 'scroll' param in a scroll request + * @param array $rawResults The raw results from the initial search call + * @param string $scrollTime The value for the 'scroll' param in a scroll request */ - public function __construct(Finder $finder, array $documentClasses, $rawResults, $resultsType, $scrollTime) + public function __construct(Finder $finder, array $documentClasses, array $rawResults, int $resultsType, string $scrollTime) { $this->finder = $finder; $this->documentClasses = $documentClasses; @@ -66,10 +41,8 @@ public function __construct(Finder $finder, array $documentClasses, $rawResults, /** * Returns results from a scroll request - * - * @return mixed */ - public function getNextScrollResults() + public function getNextScrollResults(): array|DocumentIterator|false { // If this is the first call to this method, return the cached initial results from the search request if (null !== $this->initialResults) { diff --git a/src/Finder/Finder.php b/src/Finder/Finder.php index 30fa5e7..2e3b5cf 100644 --- a/src/Finder/Finder.php +++ b/src/Finder/Finder.php @@ -2,6 +2,8 @@ namespace Sineflow\ElasticsearchBundle\Finder; +use Psr\Cache\InvalidArgumentException; +use Sineflow\ElasticsearchBundle\Document\DocumentInterface; use Sineflow\ElasticsearchBundle\DTO\IndicesToDocumentClasses; use Sineflow\ElasticsearchBundle\Finder\Adapter\KnpPaginatorAdapter; use Sineflow\ElasticsearchBundle\Finder\Adapter\ScrollAdapter; @@ -27,28 +29,16 @@ class Finder public const SCROLL_TIME = '1m'; - /** - * @var DocumentMetadataCollector - */ - private $documentMetadataCollector; + private DocumentMetadataCollector $documentMetadataCollector; - /** - * @var IndexManagerRegistry - */ - private $indexManagerRegistry; + private IndexManagerRegistry $indexManagerRegistry; - /** - * @var DocumentConverter - */ - private $documentConverter; + private DocumentConverter $documentConverter; - /** - * Finder constructor. - */ public function __construct( DocumentMetadataCollector $documentMetadataCollector, IndexManagerRegistry $indexManagerRegistry, - DocumentConverter $documentConverter + DocumentConverter $documentConverter, ) { $this->documentMetadataCollector = $documentMetadataCollector; $this->indexManagerRegistry = $indexManagerRegistry; @@ -58,11 +48,11 @@ public function __construct( /** * Returns a document by identifier * - * @param string $documentClass FQN or short notation (i.e App:Product) + * @param string $documentClass FQN or short notation (i.e. App:Product) * - * @return mixed + * @throws InvalidArgumentException */ - public function get(string $documentClass, string $id, int $resultType = self::RESULTS_OBJECT) + public function get(string $documentClass, string $id, int $resultType = self::RESULTS_OBJECT): DocumentInterface|array|null { $indexManagerName = $this->documentMetadataCollector->getDocumentClassIndex($documentClass); @@ -80,16 +70,12 @@ public function get(string $documentClass, string $id, int $resultType = self::R return null; } - switch ($resultType & self::BITMASK_RESULT_TYPES) { - case self::RESULTS_OBJECT: - return $this->documentConverter->convertToDocument($rawDoc, $documentClass); - case self::RESULTS_ARRAY: - return $this->convertToNormalizedArray($rawDoc); - case self::RESULTS_RAW: - return $rawDoc; - default: - throw new \InvalidArgumentException('Wrong result type selected'); - } + return match ($resultType & self::BITMASK_RESULT_TYPES) { + self::RESULTS_OBJECT => $this->documentConverter->convertToDocument($rawDoc, $documentClass), + self::RESULTS_ARRAY => $this->convertToNormalizedArray($rawDoc), + self::RESULTS_RAW => $rawDoc, + default => throw new \InvalidArgumentException('Wrong result type selected'), + }; } /** @@ -99,11 +85,9 @@ public function get(string $documentClass, string $id, int $resultType = self::R * @param array $searchBody The body of the search request * @param int $resultsType Bitmask value determining how the results are returned * @param array $additionalRequestParams Additional params to pass to the ES client's search() method - * @param int $totalHits (out param) The total hits of the query response - * - * @return mixed + * @param int|null $totalHits (out param) The total hits of the query response */ - public function find(array $documentClasses, array $searchBody, $resultsType = self::RESULTS_OBJECT, array $additionalRequestParams = [], &$totalHits = null) + public function find(array $documentClasses, array $searchBody, int $resultsType = self::RESULTS_OBJECT, array $additionalRequestParams = [], ?int &$totalHits = null): array|KnpPaginatorAdapter|ScrollAdapter|DocumentIterator { if (($resultsType & self::BITMASK_RESULT_ADAPTERS) === self::ADAPTER_KNP) { return new KnpPaginatorAdapter($this, $documentClasses, $searchBody, $resultsType, $additionalRequestParams); @@ -151,10 +135,8 @@ public function find(array $documentClasses, array $searchBody, $resultsType = s * @param string $scrollTime The time to keep the scroll window open * @param int $resultsType Bitmask value determining how the results are returned * @param int|null $totalHits (out param) The total hits of the query response - * - * @return mixed */ - public function scroll(array $documentClasses, string &$scrollId, string $scrollTime = self::SCROLL_TIME, int $resultsType = self::RESULTS_OBJECT, int &$totalHits = null) + public function scroll(array $documentClasses, string &$scrollId, string $scrollTime = self::SCROLL_TIME, int $resultsType = self::RESULTS_OBJECT, ?int &$totalHits = null): array|bool|DocumentIterator { $client = $this->getConnection($documentClasses)->getClient(); @@ -232,10 +214,8 @@ public function getTargetIndices(array $documentClasses): array * @param array $raw The raw results as received from Elasticsearch * @param int $resultsType Bitmask value determining how the results are returned * @param string[] $documentClasses The ES entity classes that may be returned from the search - * - * @return array|DocumentIterator */ - public function parseResult(array $raw, int $resultsType, array $documentClasses = null) + public function parseResult(array $raw, int $resultsType, ?array $documentClasses = null): array|DocumentIterator { switch ($resultsType & self::BITMASK_RESULT_TYPES) { case self::RESULTS_OBJECT: diff --git a/src/Manager/ConnectionManager.php b/src/Manager/ConnectionManager.php index 8492a47..ba5073f 100644 --- a/src/Manager/ConnectionManager.php +++ b/src/Manager/ConnectionManager.php @@ -18,54 +18,33 @@ class ConnectionManager { /** - * @var string The unique connection manager name (the key from the index configuration) + * The unique connection manager name (the key from the index configuration) */ - protected $connectionName; + protected string $connectionName; - /** - * @var Client - */ - protected $client; + protected ?Client $client = null; - /** - * @var array - */ - protected $connectionSettings; + protected array $connectionSettings; /** * @var BulkQueryItem[] Container for bulk queries. */ - protected $bulkQueries; + protected array $bulkQueries; /** - * @var array Holder for consistency, refresh and replication parameters. + * Holder for consistency, refresh and replication parameters. */ - protected $bulkParams; + protected array $bulkParams; - /** - * @var LoggerInterface - */ - protected $logger; + protected ?LoggerInterface $logger = null; - /** - * @var LoggerInterface - */ - protected $tracer; + protected ?LoggerInterface $tracer = null; - /** - * @var bool - */ - protected $autocommit; + protected bool $autocommit; - /** - * @var EventDispatcherInterface - */ - protected $eventDispatcher; + protected ?EventDispatcherInterface $eventDispatcher; - /** - * @var bool - */ - protected $kernelDebug; + protected bool $kernelDebug; /** * @param string $connectionName The unique connection name @@ -82,7 +61,7 @@ public function __construct(string $connectionName, array $connectionSettings, b $this->kernelDebug = $kernelDebug; } - public function setLogger(LoggerInterface $logger) + public function setLogger(LoggerInterface $logger): void { $this->logger = $logger; } @@ -92,7 +71,7 @@ public function getLogger(): ?LoggerInterface return $this->logger; } - public function setTracer(LoggerInterface $tracer) + public function setTracer(LoggerInterface $tracer): void { $this->tracer = $tracer; } @@ -137,7 +116,7 @@ public function isAutocommit(): bool return $this->autocommit; } - public function setAutocommit(bool $autocommit) + public function setAutocommit(bool $autocommit): void { // If the autocommit mode is being turned on, commit any pending bulk items if (!$this->autocommit && $autocommit) { @@ -152,7 +131,7 @@ public function getEventDispatcher(): EventDispatcherInterface return $this->eventDispatcher; } - public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) + public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void { $this->eventDispatcher = $eventDispatcher; } @@ -163,9 +142,9 @@ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher) * @param string $operation One of: index, update, delete, create. * @param string $index Elasticsearch index name. * @param array $query Bulk item query (aka optional_source in the ES docs) - * @param array $metaParams Additional meta data params for the bulk item + * @param array $metaParams Additional metadata params for the bulk item */ - public function addBulkOperation(string $operation, string $index, array $query, array $metaParams = []) + public function addBulkOperation(string $operation, string $index, array $query, array $metaParams = []): void { $this->bulkQueries[] = new BulkQueryItem($operation, $index, $query, $metaParams); } @@ -186,7 +165,7 @@ public function getBulkOperationsCount(): int * ['refresh'] = (boolean) Refresh the index after performing the operation. * ['replication'] = (enum) Explicitly set the replication type. */ - public function setBulkParams(array $params) + public function setBulkParams(array $params): void { $this->bulkParams = $params; } @@ -201,7 +180,7 @@ public function setBulkParams(array $params) * * @throws BulkRequestException */ - public function commit(bool $forceRefresh = true) + public function commit(bool $forceRefresh = true): void { if (empty($this->bulkQueries)) { return; @@ -216,9 +195,7 @@ public function commit(bool $forceRefresh = true) $this->bulkQueries = []; - if ($this->eventDispatcher) { - $this->eventDispatcher->dispatch(new PostCommitEvent($response, $this), Events::POST_COMMIT); - } + $this->eventDispatcher?->dispatch(new PostCommitEvent($response, $this), Events::POST_COMMIT); if ($response['errors']) { $errorCount = $this->logBulkRequestErrors($response['items']); @@ -285,7 +262,7 @@ private function logBulkRequestErrors(array $responseItems): int /** * Refresh all indices, making any newly indexed documents immediately available for search */ - public function refresh() + public function refresh(): void { // Use an index wildcard to avoid deprecation warnings about accessing system indices // Passing this 'index' argument should not be necessary in ES8 @@ -298,7 +275,7 @@ public function refresh() * Causes a Lucene commit to happen * In most cases refresh() should be used instead, as this is a very expensive operation */ - public function flush() + public function flush(): void { $this->getClient()->indices()->flush(); } diff --git a/src/Manager/IndexManager.php b/src/Manager/IndexManager.php index d8808ec..f092b17 100644 --- a/src/Manager/IndexManager.php +++ b/src/Manager/IndexManager.php @@ -4,6 +4,7 @@ use Elasticsearch\Common\Exceptions\ElasticsearchException; use Elasticsearch\Common\Exceptions\Missing404Exception; +use Psr\Cache\InvalidArgumentException; use Sineflow\ElasticsearchBundle\Document\DocumentInterface; use Sineflow\ElasticsearchBundle\Document\Provider\ProviderInterface; use Sineflow\ElasticsearchBundle\Document\Provider\ProviderRegistry; @@ -28,74 +29,35 @@ class IndexManager { /** - * @var string The unique manager name (the key from the index configuration) + * The unique manager name (the key from the index configuration) */ - protected $managerName; + protected string $managerName; + protected ConnectionManager $connection; + protected DocumentMetadataCollector $metadataCollector; + protected ProviderRegistry $providerRegistry; + protected Finder $finder; + protected DocumentConverter $documentConverter; + protected RepositoryFactory $repositoryFactory; + protected ?array $indexMapping = null; + private array $indexSettings; + protected Repository $repository; /** - * @var ConnectionManager Elasticsearch connection. + * Whether to use index aliases */ - protected $connection; + protected bool $useAliases = true; /** - * @var DocumentMetadataCollector + * The alias where data should be read from */ - protected $metadataCollector; + protected string $readAlias; /** - * @var ProviderRegistry + * The alias where data should be written to */ - protected $providerRegistry; + protected string $writeAlias; - /** - * @var Finder - */ - protected $finder; - - /** - * @var DocumentConverter - */ - protected $documentConverter; - - /** - * @var RepositoryFactory - */ - protected $repositoryFactory; - - /** - * @var array - */ - protected $indexMapping; - - /** - * @var array - */ - private $indexSettings; - - /** - * @var Repository - */ - protected $repository; - - /** - * @var bool Whether to use index aliases - */ - protected $useAliases = true; - - /** - * @var string The alias where data should be read from - */ - protected $readAlias; - - /** - * @var string The alias where data should be written to - */ - protected $writeAlias; - - /** - * @var EventDispatcherInterface - */ - protected $eventDispatcher; + protected EventDispatcherInterface $eventDispatcher; public function __construct( string $managerName, @@ -105,7 +67,7 @@ public function __construct( ProviderRegistry $providerRegistry, Finder $finder, DocumentConverter $documentConverter, - RepositoryFactory $repositoryFactory + RepositoryFactory $repositoryFactory, ) { $this->managerName = $managerName; $this->connection = $connection; @@ -339,7 +301,7 @@ public function getLiveIndex(): string * * @throws Exception */ - public function createIndex() + public function createIndex(): void { if (true === $this->getUseAliases()) { // Make sure the read and write aliases do not exist already as aliases or physical indices @@ -376,7 +338,7 @@ public function createIndex() /** * Drops elasticsearch index(es). */ - public function dropIndex() + public function dropIndex(): void { try { if (true === $this->getUseAliases()) { @@ -401,7 +363,7 @@ public function dropIndex() * * @throws ElasticsearchException */ - public function rebuildIndex($deleteOld = false, $cancelExistingRebuild = false) + public function rebuildIndex(bool $deleteOld = false, bool $cancelExistingRebuild = false): void { try { if (false === $this->getUseAliases()) { @@ -461,10 +423,8 @@ public function rebuildIndex($deleteOld = false, $cancelExistingRebuild = false) /** * Rebuilds the data of a document and adds it to a bulk request for the next commit. * Depending on the connection autocommit mode, the change may be committed right away. - * - * @param string|int $id */ - public function reindex(string $id) + public function reindex(string|int $id): void { $documentClass = $this->getDocumentClass(); @@ -501,10 +461,8 @@ public function reindex(string $id) /** * Adds document removal to a bulk request for the next commit. * Depending on the connection autocommit mode, the removal may be committed right away. - * - * @param string $id Document ID to remove. */ - public function delete(string $id) + public function delete(string|int $id): void { $this->getConnection()->addBulkOperation( 'delete', @@ -521,13 +479,13 @@ public function delete(string $id) /** * Adds a document update to a bulk request for the next commit. * - * @param string $id Document id to update. - * @param array $fields Fields array to update (ignored if script is specified). - * @param null $script Script to update fields. - * @param array $queryParams Additional params to pass with the payload (upsert, doc_as_upsert, _source, etc.) - * @param array $metaParams Additional params to pass with the meta data in the bulk request (_version, _routing, etc.) + * @param string|int $id Document id to update. + * @param array $fields Fields array to update (ignored if script is specified). + * @param null $script Script to update fields. + * @param array $queryParams Additional params to pass with the payload (upsert, doc_as_upsert, _source, etc.) + * @param array $metaParams Additional params to pass with the meta data in the bulk request (_version, _routing, etc.) */ - public function update(string $id, array $fields = [], $script = null, array $queryParams = [], array $metaParams = []) + public function update(string|int $id, array $fields = [], $script = null, array $queryParams = [], array $metaParams = []): void { // Add the id of the updated document to the meta params for the bulk request $metaParams = \array_merge( @@ -562,9 +520,9 @@ public function update(string $id, array $fields = [], $script = null, array $qu * Depending on the connection autocommit mode, the update may be committed right away. * * @param DocumentInterface $document The document entity to index in ES - * @param array $metaParams Additional params to pass with the meta data in the bulk request (_version, _routing, etc.) + * @param array $metaParams Additional params to pass with the metadata in the bulk request (_version, _routing, etc.) */ - public function persist(DocumentInterface $document, array $metaParams = []) + public function persist(DocumentInterface $document, array $metaParams = []): void { if ($this->eventDispatcher) { $this->eventDispatcher->dispatch(new PrePersistEvent($document, $this->getConnection()), Events::PRE_PERSIST); @@ -581,7 +539,7 @@ public function persist(DocumentInterface $document, array $metaParams = []) * @param array $documentArray The document to index in ES * @param array $metaParams Additional params to pass with the meta data in the bulk request (_version, _routing, etc.) */ - public function persistRaw(array $documentArray, array $metaParams = []) + public function persistRaw(array $documentArray, array $metaParams = []): void { // Remove any read-only meta fields from array to be persisted unset($documentArray['_score']); @@ -601,7 +559,7 @@ public function persistRaw(array $documentArray, array $metaParams = []) /** * Created a new index with a unique name */ - protected function createNewIndexWithUniqueName(string $suffix = null): string + protected function createNewIndexWithUniqueName(?string $suffix = null): string { $settings = $this->getIndexMapping(); $newIndex = $this->getUniqueIndexName($suffix); @@ -616,7 +574,7 @@ protected function createNewIndexWithUniqueName(string $suffix = null): string * * @param string $oldIndex This is not used here but passed in case an overriding class may need it */ - protected function copyDataToNewIndex(string $newIndex, string $oldIndex) + protected function copyDataToNewIndex(string $newIndex, string $oldIndex): void { // Make sure we don't autocommit on every item in the bulk request $autocommit = $this->getConnection()->isAutocommit(); @@ -705,7 +663,7 @@ protected function getLiveIndexPreparedForRebuilding(bool $cancelExistingRebuild /** * Get document metadata * - * @throws \Psr\Cache\InvalidArgumentException + * @throws InvalidArgumentException */ public function getDocumentMetadata(): DocumentMetadata { @@ -715,7 +673,7 @@ public function getDocumentMetadata(): DocumentMetadata /** * Get FQN of document class managed by this index manager * - * @throws \Psr\Cache\InvalidArgumentException + * @throws InvalidArgumentException */ public function getDocumentClass(): string { diff --git a/src/Manager/IndexManagerRegistry.php b/src/Manager/IndexManagerRegistry.php index 6863b22..f84cca1 100644 --- a/src/Manager/IndexManagerRegistry.php +++ b/src/Manager/IndexManagerRegistry.php @@ -12,15 +12,8 @@ */ class IndexManagerRegistry { - /** - * @var DocumentMetadataCollector - */ - private $metadataCollector; - - /** - * @var ServiceLocator - */ - private $serviceLocator; + private DocumentMetadataCollector $metadataCollector; + private ServiceLocator $serviceLocator; /** * Constructor diff --git a/src/Mapping/Caser.php b/src/Mapping/Caser.php index 3148dfb..29a9e5c 100644 --- a/src/Mapping/Caser.php +++ b/src/Mapping/Caser.php @@ -9,24 +9,16 @@ class Caser { /** * Transforms string to camel case. - * - * @param string $string Text to transform. - * - * @return string */ - public static function camel($string) + public static function camel(string $string): string { return \lcfirst(\str_replace([' ', '_', '-'], '', \ucwords($string, ' _-'))); } /** * Transforms string to snake case. - * - * @param string $string Text to transform. - * - * @return string */ - public static function snake($string) + public static function snake(string $string): string { $string = \preg_replace('#([A-Z\d]+)([A-Z][a-z])#', '\1_\2', self::camel($string)); $string = \preg_replace('#([a-z\d])([A-Z])#', '\1_\2', $string); diff --git a/src/Mapping/DocumentLocator.php b/src/Mapping/DocumentLocator.php index 0a36f35..32830d0 100644 --- a/src/Mapping/DocumentLocator.php +++ b/src/Mapping/DocumentLocator.php @@ -10,7 +10,7 @@ class DocumentLocator /** * @var array All locations of Elasticsearch entities available in the application */ - private $entityLocations = []; + private array $entityLocations = []; /** * @param array $entityLocations Parameter sfes.entity_locations diff --git a/src/Mapping/DocumentMetadata.php b/src/Mapping/DocumentMetadata.php index 00abcac..96f12fa 100644 --- a/src/Mapping/DocumentMetadata.php +++ b/src/Mapping/DocumentMetadata.php @@ -12,10 +12,7 @@ class DocumentMetadata public const PROPERTY_ACCESS_PUBLIC = 1; public const PROPERTY_ACCESS_PRIVATE = 2; - /** - * @var array - */ - private $metadata; + private array $metadata; /** * Resolves metadata. @@ -31,7 +28,7 @@ public function __construct(array $metadata) /** * Configures options resolver. */ - protected function configureOptions(OptionsResolver $optionsResolver) + protected function configureOptions(OptionsResolver $optionsResolver): void { $optionsResolver->setRequired(['properties', 'fields', 'propertiesMetadata', 'repositoryClass', 'providerClass', 'className']); } diff --git a/src/Mapping/DocumentMetadataCollector.php b/src/Mapping/DocumentMetadataCollector.php index 3a6e0c2..d23b38e 100644 --- a/src/Mapping/DocumentMetadataCollector.php +++ b/src/Mapping/DocumentMetadataCollector.php @@ -2,6 +2,7 @@ namespace Sineflow\ElasticsearchBundle\Mapping; +use Psr\Cache\InvalidArgumentException; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\ItemInterface; @@ -22,31 +23,17 @@ class DocumentMetadataCollector implements WarmableInterface public const OBJECTS_CACHE_KEY_PREFIX = 'sfes.object_properties_metadata.'; /** - * @var array - * * => */ - private $documentClassToIndexManagerNames = []; + private array $documentClassToIndexManagerNames = []; - /** - * @var array - */ - private $indexManagers; + private array $indexManagers; - /** - * @var DocumentLocator - */ - private $documentLocator; + private DocumentLocator $documentLocator; - /** - * @var DocumentParser - */ - private $parser; + private DocumentParser $parser; - /** - * @var CacheInterface - */ - private $cache; + private CacheInterface $cache; /** * @param array $indexManagers The list of index managers defined @@ -75,13 +62,11 @@ public function __construct(array $indexManagers, DocumentLocator $documentLocat /** * Warms up the cache. * - * @param string $cacheDir - * * @return string[] * - * @throws \Psr\Cache\InvalidArgumentException + * @throws InvalidArgumentException */ - public function warmUp($cacheDir) + public function warmUp(string $cacheDir): array { // force cache generation foreach ($this->documentClassToIndexManagerNames as $documentClass => $indexManagerName) { @@ -102,7 +87,7 @@ public function warmUp($cacheDir) * Returns metadata for the specified document class name. * Class can also be specified in short notation (e.g App:Product) * - * @throws \Psr\Cache\InvalidArgumentException + * @throws InvalidArgumentException */ public function getDocumentMetadata(string $documentClass): DocumentMetadata { @@ -119,7 +104,7 @@ public function getDocumentMetadata(string $documentClass): DocumentMetadata * Returns metadata for the specified object class name * Class can also be specified in short notation (e.g App:ObjCategory) * - * @throws \Psr\Cache\InvalidArgumentException + * @throws InvalidArgumentException */ public function getObjectPropertiesMetadata(string $objectClass): array { diff --git a/src/Mapping/DocumentParser.php b/src/Mapping/DocumentParser.php index ec6693e..7fb5644 100644 --- a/src/Mapping/DocumentParser.php +++ b/src/Mapping/DocumentParser.php @@ -16,39 +16,33 @@ class DocumentParser { /** - * @var Reader Used to read document annotations. + * Used to read document annotations. */ - private $reader; + private Reader $reader; /** - * @var DocumentLocator Used to find documents. + * Used to find documents. */ - private $documentLocator; + private DocumentLocator $documentLocator; /** - * @var array Contains gathered objects which later adds to documents. + * Contains gathered objects which later adds to documents. */ - private $objects = []; + private array $objects = []; /** - * @var array Document properties metadata. + * Document properties metadata. */ - private $propertiesMetadata = []; + private array $propertiesMetadata = []; /** - * @var array Local cache for document properties. + * Local cache for document properties. */ - private $properties = []; + private array $properties = []; - /** - * @var string - */ - private $languageSeparator; + private string $languageSeparator; - /** - * @var array - */ - private $languages; + private array $languages; /** * @param Reader $reader Used for reading annotations @@ -68,11 +62,9 @@ public function __construct(Reader $reader, DocumentLocator $documentLocator, st /** * Parses document by used annotations and returns mapping for elasticsearch with some extra metadata. * - * @return array - * * @throws \ReflectionException */ - public function parse(\ReflectionClass $documentReflection, array $indexAnalyzers) + public function parse(\ReflectionClass $documentReflection, array $indexAnalyzers): array { $metadata = []; @@ -98,11 +90,9 @@ public function parse(\ReflectionClass $documentReflection, array $indexAnalyzer /** * Finds properties' metadata for every property used in document or inner/nested object * - * @return array - * * @throws \ReflectionException */ - public function getPropertiesMetadata(\ReflectionClass $documentReflection) + public function getPropertiesMetadata(\ReflectionClass $documentReflection): array { $className = $documentReflection->getName(); if (\array_key_exists($className, $this->propertiesMetadata)) { @@ -198,12 +188,8 @@ public function getPropertiesMetadata(\ReflectionClass $documentReflection) /** * Returns property annotation data from reader. - * - * @param \ReflectionProperty $property - * - * @return Property|null */ - private function getPropertyAnnotationData($property) + private function getPropertyAnnotationData(\ReflectionProperty $property): ?Property { /** @var Property $annotation */ $annotation = $this->reader->getPropertyAnnotation($property, Property::class); @@ -214,7 +200,7 @@ private function getPropertyAnnotationData($property) /** * Registers annotations to registry so that it could be used by reader. */ - private function registerAnnotations() + private function registerAnnotations(): void { $annotations = [ 'Document', @@ -231,10 +217,8 @@ private function registerAnnotations() /** * Returns all defined properties including private from parents. - * - * @return array */ - private function getDocumentPropertiesReflection(\ReflectionClass $documentReflection) + private function getDocumentPropertiesReflection(\ReflectionClass $documentReflection): array { if (\in_array($documentReflection->getName(), $this->properties)) { return $this->properties[$documentReflection->getName()]; @@ -266,11 +250,9 @@ private function getDocumentPropertiesReflection(\ReflectionClass $documentRefle * * @param \ReflectionClass $documentReflection Class to read properties from. * - * @return array - * * @throws \ReflectionException */ - private function getProperties(\ReflectionClass $documentReflection, array $indexAnalyzers = []) + private function getProperties(\ReflectionClass $documentReflection, array $indexAnalyzers = []): array { $mapping = []; /** @var \ReflectionProperty $property */ @@ -307,11 +289,9 @@ private function getProperties(\ReflectionClass $documentReflection, array $inde } /** - * @return array - * * @throws \ReflectionException */ - private function getPropertyMapping(Property $propertyAnnotation, string $language = null, array $indexAnalyzers = []) + private function getPropertyMapping(Property $propertyAnnotation, ?string $language = null, array $indexAnalyzers = []): array { $propertyMapping = $propertyAnnotation->dump([ 'language' => $language, @@ -331,13 +311,9 @@ private function getPropertyMapping(Property $propertyAnnotation, string $langua * * Loads from cache if it's already loaded. * - * @param string $objectName - * - * @return array - * * @throws \ReflectionException */ - private function getObjectMapping($objectName, array $indexAnalyzers = []) + private function getObjectMapping(string $objectName, array $indexAnalyzers = []): ?array { $className = $this->documentLocator->resolveClassName($objectName); @@ -353,13 +329,9 @@ private function getObjectMapping($objectName, array $indexAnalyzers = []) /** * Returns relation mapping by its reflection. * - * @param array $indexAnalyzers - * - * @return array|null - * * @throws \ReflectionException */ - private function getRelationMapping(\ReflectionClass $documentReflection, $indexAnalyzers = []) + private function getRelationMapping(\ReflectionClass $documentReflection, array $indexAnalyzers = []): ?array { if ($this->reader->getClassAnnotation($documentReflection, DocObject::class)) { return ['properties' => $this->getProperties($documentReflection, $indexAnalyzers)]; diff --git a/src/Mapping/DumperInterface.php b/src/Mapping/DumperInterface.php index 6a09fe5..8ce43b0 100644 --- a/src/Mapping/DumperInterface.php +++ b/src/Mapping/DumperInterface.php @@ -11,8 +11,6 @@ interface DumperInterface * Dumps properties into array. * * @param array $settings Options to configure dump output - * - * @return array */ - public function dump(array $settings = []); + public function dump(array $settings = []): array; } diff --git a/src/Profiler/ElasticsearchProfiler.php b/src/Profiler/ElasticsearchProfiler.php index 1362952..9b62e14 100644 --- a/src/Profiler/ElasticsearchProfiler.php +++ b/src/Profiler/ElasticsearchProfiler.php @@ -3,6 +3,7 @@ namespace Sineflow\ElasticsearchBundle\Profiler; use Monolog\Logger; +use Monolog\LogRecord; use Sineflow\ElasticsearchBundle\Profiler\Handler\CollectionHandler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -18,12 +19,12 @@ class ElasticsearchProfiler extends DataCollector /** * @var Logger[] Watched loggers. */ - private $loggers = []; + private array $loggers = []; /** * @var array Registered index managers. */ - private $indexManagers = []; + private array $indexManagers = []; /** * ElasticsearchProfiler constructor. @@ -36,7 +37,7 @@ public function __construct() /** * Adds logger to look for collector handler. */ - public function addLogger(Logger $logger) + public function addLogger(Logger $logger): void { $this->loggers[] = $logger; } @@ -44,7 +45,7 @@ public function addLogger(Logger $logger) /** * {@inheritDoc} */ - public function collect(Request $request, Response $response, \Throwable $exception = null) + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { $this->data['indexManagers'] = $this->cloneVar($this->indexManagers); @@ -61,7 +62,7 @@ public function collect(Request $request, Response $response, \Throwable $except /** * {@inheritDoc} */ - public function reset() + public function reset(): void { $this->data = [ 'indexManagers' => [], // The list of all defined index managers @@ -106,7 +107,7 @@ public function getIndexManagers(): array return $this->data['indexManagers']->getValue(); } - public function setIndexManagers(array $indexManagers) + public function setIndexManagers(array $indexManagers): void { foreach ($indexManagers as $name => $manager) { $this->indexManagers[$name] = \sprintf('sfes.index.%s', $name); @@ -123,8 +124,13 @@ public function getName(): string /** * Handles passed records. + * + * NOTE: Monolog 3.* passes an array of LogRecord objects instead of arrays, + * but for now we keep compatibility with 2.* as well + * + * @param LogRecord[]|array[] $records */ - private function handleRecords(array $records) + private function handleRecords(array $records): void { $this->data['queryCount'] += \count($records) / 2; $queryBody = ''; @@ -143,7 +149,10 @@ private function handleRecords(array $records) } } - private function addQuery(string $route, array $record, string $queryBody, string $rawRequest) + /** + * NOTE: The array typehint of $record is only for BC with Monolog 2.* + */ + private function addQuery(string $route, LogRecord|array $record, string $queryBody, string $rawRequest): void { $parsedUrl = \array_merge( [ diff --git a/src/Profiler/Handler/CollectionHandler.php b/src/Profiler/Handler/CollectionHandler.php index 39bf212..ccec05f 100644 --- a/src/Profiler/Handler/CollectionHandler.php +++ b/src/Profiler/Handler/CollectionHandler.php @@ -3,6 +3,7 @@ namespace Sineflow\ElasticsearchBundle\Profiler\Handler; use Monolog\Handler\AbstractProcessingHandler; +use Monolog\LogRecord; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; @@ -11,25 +12,13 @@ */ class CollectionHandler extends AbstractProcessingHandler { - /** - * @var array - */ - private $records = []; + private array $records = []; - /** - * @var RequestStack - */ - private $requestStack; + private RequestStack $requestStack; - /** - * @var bool - */ - private $backtraceEnabled; + private bool $backtraceEnabled; - /** - * @param bool $backtraceEnabled - */ - public function __construct(RequestStack $requestStack, $backtraceEnabled = false) + public function __construct(RequestStack $requestStack, bool $backtraceEnabled = false) { $this->requestStack = $requestStack; $this->backtraceEnabled = $backtraceEnabled; @@ -37,8 +26,10 @@ public function __construct(RequestStack $requestStack, $backtraceEnabled = fals /** * {@inheritdoc} + * + * NOTE: The array typehint of $record is only for BC with Monolog 2.* */ - protected function write(array $record): void + protected function write(LogRecord|array $record): void { $request = $this->requestStack->getCurrentRequest(); if ($request instanceof Request) { @@ -57,9 +48,9 @@ protected function write(array $record): void /** * Returns recorded data. * - * @return array + * @return LogRecord[] */ - public function getRecords() + public function getRecords(): array { return $this->records; } @@ -67,7 +58,7 @@ public function getRecords() /** * Clears recorded data. */ - public function clearRecords() + public function clearRecords(): void { $this->records = []; } diff --git a/src/Result/DocumentConverter.php b/src/Result/DocumentConverter.php index c180531..fa85453 100644 --- a/src/Result/DocumentConverter.php +++ b/src/Result/DocumentConverter.php @@ -2,6 +2,7 @@ namespace Sineflow\ElasticsearchBundle\Result; +use Psr\Cache\InvalidArgumentException; use Sineflow\ElasticsearchBundle\Document\DocumentInterface; use Sineflow\ElasticsearchBundle\Document\MLProperty; use Sineflow\ElasticsearchBundle\Document\ObjectInterface; @@ -14,15 +15,9 @@ */ class DocumentConverter { - /** - * @var DocumentMetadataCollector - */ - protected $metadataCollector; + protected DocumentMetadataCollector $metadataCollector; - /** - * @var string - */ - protected $languageSeparator; + protected string $languageSeparator; /** * Constructor. @@ -38,9 +33,9 @@ public function __construct(DocumentMetadataCollector $metadataCollector, string * * @param string $documentClass Document class FQN or in short notation (e.g. App:Product) * - * @return DocumentInterface + * @throws InvalidArgumentException */ - public function convertToDocument(array $rawData, string $documentClass) + public function convertToDocument(array $rawData, string $documentClass): DocumentInterface { // Get document metadata $metadata = $this->metadataCollector->getDocumentMetadata($documentClass); @@ -148,12 +143,11 @@ public function assignArrayToObject(array $array, ObjectInterface $object, array /** * Converts document or (nested) object to an array. * - * @param ObjectInterface $object A document or a (nested) object - * @param array $propertiesMetadata + * @param ObjectInterface $object A document or a (nested) object * - * @throws \ReflectionException + * @throws \ReflectionException|InvalidArgumentException */ - public function convertToArray(ObjectInterface $object, $propertiesMetadata = []): array + public function convertToArray(ObjectInterface $object, array $propertiesMetadata = []): array { if (empty($propertiesMetadata)) { $propertiesMetadata = $this->metadataCollector->getObjectPropertiesMetadata(\get_class($object)); @@ -205,7 +199,7 @@ public function convertToArray(ObjectInterface $object, $propertiesMetadata = [] * * @throws \InvalidArgumentException */ - private function checkObjectType(ObjectInterface $object, string $expectedClass) + private function checkObjectType(ObjectInterface $object, string $expectedClass): void { if (\get_class($object) !== $expectedClass) { throw new \InvalidArgumentException(\sprintf('Expected object of "%s", got "%s"', $expectedClass, \get_class($object))); diff --git a/src/Result/DocumentIterator.php b/src/Result/DocumentIterator.php index fc8f548..39fa7f4 100644 --- a/src/Result/DocumentIterator.php +++ b/src/Result/DocumentIterator.php @@ -10,42 +10,14 @@ */ class DocumentIterator implements \Countable, \Iterator { - /** - * @var array - */ - private $rawData; - - /** - * @var DocumentConverter - */ - private $documentConverter; - - /** - * @var IndicesToDocumentClasses - */ - private $indicesToDocumentClasses; - - /** - * @var array - */ - private $suggestions = []; - - /** - * @var array - */ - private $aggregations = []; - - /** - * @var array - */ - private $documents = []; - - /** - * Constructor. - * - * @param array $rawData - */ - public function __construct($rawData, DocumentConverter $documentConverter, IndicesToDocumentClasses $indicesToDocumentClasses) + private array $rawData; + private DocumentConverter $documentConverter; + private IndicesToDocumentClasses $indicesToDocumentClasses; + private array $suggestions = []; + private array $aggregations = []; + private array $documents = []; + + public function __construct(array $rawData, DocumentConverter $documentConverter, IndicesToDocumentClasses $indicesToDocumentClasses) { $this->rawData = $rawData; $this->documentConverter = $documentConverter; @@ -62,44 +34,30 @@ public function __construct($rawData, DocumentConverter $documentConverter, Indi } } - /** - * @return array - */ - public function getSuggestions() + public function getSuggestions(): array { return $this->suggestions; } - /** - * @return array - */ - public function getAggregations() + public function getAggregations(): array { return $this->aggregations; } /** * Returns total count of records matching the query. - * - * @return int */ - public function getTotalCount() + public function getTotalCount(): int { return $this->rawData['hits']['total']['value']; } - /** - * @return int - */ - public function count() + public function count(): int { return \count($this->documents); } - /** - * @return DocumentInterface - */ - public function current() + public function current(): ?DocumentInterface { return isset($this->documents[$this->key()]) ? $this->convertToDocument($this->documents[$this->key()]) : null; } @@ -107,7 +65,7 @@ public function current() /** * {@inheritdoc} */ - public function next() + public function next(): void { \next($this->documents); } @@ -115,7 +73,7 @@ public function next() /** * {@inheritdoc} */ - public function key() + public function key(): ?int { return \key($this->documents); } @@ -123,7 +81,7 @@ public function key() /** * {@inheritdoc} */ - public function valid() + public function valid(): bool { return null !== $this->key(); } @@ -131,7 +89,7 @@ public function valid() /** * {@inheritdoc} */ - public function rewind() + public function rewind(): void { \reset($this->documents); } @@ -139,13 +97,9 @@ public function rewind() /** * Converts raw array to document. * - * @param array $rawData - * - * @return DocumentInterface - * * @throws \LogicException */ - private function convertToDocument($rawData) + private function convertToDocument(array $rawData): DocumentInterface { $documentClass = $this->indicesToDocumentClasses->get($rawData['_index']); diff --git a/src/Result/ObjectIterator.php b/src/Result/ObjectIterator.php index e0d4a16..6ac96ee 100644 --- a/src/Result/ObjectIterator.php +++ b/src/Result/ObjectIterator.php @@ -9,24 +9,10 @@ */ class ObjectIterator implements \Countable, \Iterator { - /** - * @var array property metadata information. - */ - private $propertyMetadata; - - /** - * @var DocumentConverter - */ - private $documentConverter; + private array $propertyMetadata; + private DocumentConverter $documentConverter; + private array $objects; - /** - * @var array - */ - private $objects; - - /** - * Constructor. - */ public function __construct(DocumentConverter $documentConverter, array $rawData, array $propertyMetadata) { $this->documentConverter = $documentConverter; @@ -34,18 +20,12 @@ public function __construct(DocumentConverter $documentConverter, array $rawData $this->objects = $rawData; } - /** - * @return int - */ - public function count() + public function count(): int { return \count($this->objects); } - /** - * @return ObjectInterface - */ - public function current() + public function current(): ?ObjectInterface { return isset($this->objects[$this->key()]) ? $this->convertToObject($this->objects[$this->key()]) : null; } @@ -53,7 +33,7 @@ public function current() /** * {@inheritdoc} */ - public function next() + public function next(): void { \next($this->objects); } @@ -61,7 +41,7 @@ public function next() /** * {@inheritdoc} */ - public function key() + public function key(): int { return \key($this->objects); } @@ -69,7 +49,7 @@ public function key() /** * {@inheritdoc} */ - public function valid() + public function valid(): bool { return null !== $this->key(); } @@ -77,15 +57,12 @@ public function valid() /** * {@inheritdoc} */ - public function rewind() + public function rewind(): void { \reset($this->objects); } - /** - * {@inheritdoc} - */ - private function convertToObject($rawData) + private function convertToObject($rawData): ObjectInterface { return $this->documentConverter->assignArrayToObject( $rawData, diff --git a/tests/App/AppKernel.php b/tests/App/AppKernel.php index f058abf..941e1a9 100644 --- a/tests/App/AppKernel.php +++ b/tests/App/AppKernel.php @@ -10,9 +10,6 @@ use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\HttpKernel\Kernel; -/** - * AppKernel class. - */ class AppKernel extends Kernel { /** @@ -20,7 +17,7 @@ class AppKernel extends Kernel * * @return array */ - public function registerBundles() + public function registerBundles(): iterable { $bundles = [ new FrameworkBundle(), @@ -41,7 +38,7 @@ public function registerBundles() * * @throws \Exception */ - public function registerContainerConfiguration(LoaderInterface $loader) + public function registerContainerConfiguration(LoaderInterface $loader): void { $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); } diff --git a/tests/App/fixture/Acme/FooBundle/Document/Provider/CustomerProvider.php b/tests/App/fixture/Acme/FooBundle/Document/Provider/CustomerProvider.php index f904f13..62289f8 100644 --- a/tests/App/fixture/Acme/FooBundle/Document/Provider/CustomerProvider.php +++ b/tests/App/fixture/Acme/FooBundle/Document/Provider/CustomerProvider.php @@ -2,12 +2,13 @@ namespace Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Document\Provider; +use Sineflow\ElasticsearchBundle\Document\DocumentInterface; use Sineflow\ElasticsearchBundle\Document\Provider\AbstractProvider; use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Document\Customer; class CustomerProvider extends AbstractProvider { - private $fixedDocuments = [ + private array $fixedDocuments = [ 1 => [ 'id' => 1, 'name' => 'John', @@ -18,14 +19,14 @@ class CustomerProvider extends AbstractProvider ], ]; - public function getDocuments() + public function getDocuments(): \Generator { foreach ($this->fixedDocuments as $id => $data) { yield $this->getDocument($id); } } - public function getDocument($id) + public function getDocument(int|string $id): DocumentInterface|array|null { if (!isset($this->fixedDocuments[$id])) { return null; diff --git a/tests/App/fixture/Acme/FooBundle/Document/Provider/OrderProvider.php b/tests/App/fixture/Acme/FooBundle/Document/Provider/OrderProvider.php index 2254fd6..282c780 100644 --- a/tests/App/fixture/Acme/FooBundle/Document/Provider/OrderProvider.php +++ b/tests/App/fixture/Acme/FooBundle/Document/Provider/OrderProvider.php @@ -2,12 +2,13 @@ namespace Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Document\Provider; +use Sineflow\ElasticsearchBundle\Document\DocumentInterface; use Sineflow\ElasticsearchBundle\Document\Provider\AbstractProvider; use Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\FooBundle\Document\Order; class OrderProvider extends AbstractProvider { - private $fixedDocuments = [ + private array $fixedDocuments = [ 1 => [ 'id' => 1, 'order_time' => 1452250000, @@ -18,14 +19,14 @@ class OrderProvider extends AbstractProvider ], ]; - public function getDocuments() + public function getDocuments(): \Generator { foreach ($this->fixedDocuments as $id => $data) { yield $this->getDocument($id); } } - public function getDocument($id) + public function getDocument(int|string $id): DocumentInterface|array|null { if (!isset($this->fixedDocuments[$id])) { return null; diff --git a/tests/Functional/Mapping/DocumentMetadataCollectorTest.php b/tests/Functional/Mapping/DocumentMetadataCollectorTest.php index 078bd44..c235ac2 100644 --- a/tests/Functional/Mapping/DocumentMetadataCollectorTest.php +++ b/tests/Functional/Mapping/DocumentMetadataCollectorTest.php @@ -17,334 +17,311 @@ class DocumentMetadataCollectorTest extends AbstractContainerAwareTestCase { use AssertThrows; - /** - * @var DocumentMetadataCollector - */ - private $metadataCollector; - - /** - * @var array - */ - private $indexManagers; - - /** - * @var DocumentLocator - */ - private $docLocator; - - /** - * @var DocumentParser - */ - private $docParser; - - /** - * @var CacheInterface - */ - private $cache; - - /** - * @var CacheInterface - */ - private $nullCache; + private DocumentMetadataCollector $metadataCollector; + private array $indexManagers; + private DocumentLocator $docLocator; + private DocumentParser $docParser; + private CacheInterface $cache; + private CacheInterface $nullCache; /** * @var array Expected metadata for customer index */ - private $expectedCustomerMetadata = [ + private array $expectedCustomerMetadata = [ 'properties' => [ - 'name' => [ - 'type' => 'keyword', - ], - 'active' => [ - 'type' => 'boolean', - ], + 'name' => [ + 'type' => 'keyword', ], - 'fields' => [ + 'active' => [ + 'type' => 'boolean', ], + ], + 'fields' => [ + ], 'propertiesMetadata' => [ - 'name' => [ - 'propertyName' => 'name', - 'type' => 'keyword', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'active' => [ - 'propertyName' => 'active', - 'type' => 'boolean', - 'multilanguage' => null, - 'methods' => [ - 'getter' => 'isActive', - 'setter' => 'setActive', - ], - 'propertyAccess' => 2, - ], - '_id' => [ - 'propertyName' => 'id', - 'type' => 'keyword', - 'propertyAccess' => 1, - ], - '_score' => [ - 'propertyName' => 'score', - 'type' => 'float', - 'propertyAccess' => 1, - ], + 'name' => [ + 'propertyName' => 'name', + 'type' => 'keyword', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'active' => [ + 'propertyName' => 'active', + 'type' => 'boolean', + 'multilanguage' => null, + 'methods' => [ + 'getter' => 'isActive', + 'setter' => 'setActive', + ], + 'propertyAccess' => 2, ], + '_id' => [ + 'propertyName' => 'id', + 'type' => 'keyword', + 'propertyAccess' => 1, + ], + '_score' => [ + 'propertyName' => 'score', + 'type' => 'float', + 'propertyAccess' => 1, + ], + ], 'repositoryClass' => null, 'providerClass' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\FooBundle\\Document\\Provider\\CustomerProvider', 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\FooBundle\\Document\\Customer', ]; - private $expectedProductMetadata = [ + private array $expectedProductMetadata = [ 'properties' => [ - 'title' => [ - 'fields' => [ - 'raw' => [ - 'type' => 'keyword', - ], - 'title' => [ - 'type' => 'text', - ], - ], - 'type' => 'text', + 'title' => [ + 'fields' => [ + 'raw' => [ + 'type' => 'keyword', ], - 'description' => [ + 'title' => [ 'type' => 'text', ], - 'category' => [ - 'properties' => [ - 'id' => [ - 'type' => 'integer', - ], - 'title' => [ - 'type' => 'keyword', - ], - 'tags' => [ - 'properties' => [ - 'tagname' => [ - 'type' => 'text', - ], - ], - ], - ], + ], + 'type' => 'text', + ], + 'description' => [ + 'type' => 'text', + ], + 'category' => [ + 'properties' => [ + 'id' => [ + 'type' => 'integer', + ], + 'title' => [ + 'type' => 'keyword', ], - 'related_categories' => [ + 'tags' => [ 'properties' => [ - 'id' => [ - 'type' => 'integer', - ], - 'title' => [ - 'type' => 'keyword', - ], - 'tags' => [ - 'properties' => [ - 'tagname' => [ - 'type' => 'text', - ], - ], - ], + 'tagname' => [ + 'type' => 'text', ], + ], ], - 'price' => [ - 'type' => 'float', - ], - 'location' => [ - 'type' => 'geo_point', + ], + ], + 'related_categories' => [ + 'properties' => [ + 'id' => [ + 'type' => 'integer', ], - 'limited' => [ - 'type' => 'boolean', + 'title' => [ + 'type' => 'keyword', ], - 'released' => [ - 'type' => 'date', + 'tags' => [ + 'properties' => [ + 'tagname' => [ + 'type' => 'text', + ], + ], ], - 'ml_info-en' => [ + ], + ], + 'price' => [ + 'type' => 'float', + ], + 'location' => [ + 'type' => 'geo_point', + ], + 'limited' => [ + 'type' => 'boolean', + ], + 'released' => [ + 'type' => 'date', + ], + 'ml_info-en' => [ + 'analyzer' => 'en_analyzer', + 'fields' => [ + 'ngram' => [ + 'type' => 'text', 'analyzer' => 'en_analyzer', - 'fields' => [ - 'ngram' => [ - 'type' => 'text', - 'analyzer' => 'en_analyzer', - ], - ], - 'type' => 'text', ], - 'ml_info-fr' => [ + ], + 'type' => 'text', + ], + 'ml_info-fr' => [ + 'analyzer' => 'default_analyzer', + 'fields' => [ + 'ngram' => [ + 'type' => 'text', 'analyzer' => 'default_analyzer', - 'fields' => [ - 'ngram' => [ - 'type' => 'text', - 'analyzer' => 'default_analyzer', - ], - ], - 'type' => 'text', - ], - 'ml_info-default' => [ - 'type' => 'keyword', - 'ignore_above' => 256, - ], - 'ml_more_info-en' => [ - 'type' => 'text', - ], - 'ml_more_info-fr' => [ - 'type' => 'text', - ], - 'ml_more_info-default' => [ - 'type' => 'text', - 'index' => false, - ], - 'pieces_count' => [ - 'fields' => [ - 'count' => [ - 'type' => 'token_count', - 'analyzer' => 'whitespace', - ], - ], - 'type' => 'text', ], + ], + 'type' => 'text', ], - 'fields' => [ - 'dynamic' => 'strict', + 'ml_info-default' => [ + 'type' => 'keyword', + 'ignore_above' => 256, + ], + 'ml_more_info-en' => [ + 'type' => 'text', + ], + 'ml_more_info-fr' => [ + 'type' => 'text', + ], + 'ml_more_info-default' => [ + 'type' => 'text', + 'index' => false, ], + 'pieces_count' => [ + 'fields' => [ + 'count' => [ + 'type' => 'token_count', + 'analyzer' => 'whitespace', + ], + ], + 'type' => 'text', + ], + ], + 'fields' => [ + 'dynamic' => 'strict', + ], 'propertiesMetadata' => [ - 'title' => [ - 'propertyName' => 'title', - 'type' => 'text', + 'title' => [ + 'propertyName' => 'title', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'description' => [ + 'propertyName' => 'description', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'category' => [ + 'propertyName' => 'category', + 'type' => 'object', + 'multilanguage' => null, + 'multiple' => null, + 'propertiesMetadata' => [ + 'id' => [ + 'propertyName' => 'id', + 'type' => 'integer', 'multilanguage' => null, 'propertyAccess' => 1, ], - 'description' => [ - 'propertyName' => 'description', - 'type' => 'text', + 'title' => [ + 'propertyName' => 'title', + 'type' => 'keyword', 'multilanguage' => null, 'propertyAccess' => 1, ], - 'category' => [ - 'propertyName' => 'category', - 'type' => 'object', - 'multilanguage' => null, - 'multiple' => null, - 'propertiesMetadata' => [ - 'id' => [ - 'propertyName' => 'id', - 'type' => 'integer', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'title' => [ - 'propertyName' => 'title', - 'type' => 'keyword', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'tags' => [ - 'propertyName' => 'tags', - 'type' => 'object', - 'multilanguage' => null, - 'multiple' => true, - 'propertiesMetadata' => [ - 'tagname' => [ - 'propertyName' => 'tagName', - 'type' => 'text', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - ], - 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjTag', - 'propertyAccess' => 1, - ], - ], - 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjCategory', - 'propertyAccess' => 1, - ], - 'related_categories' => [ - 'propertyName' => 'relatedCategories', + 'tags' => [ + 'propertyName' => 'tags', 'type' => 'object', 'multilanguage' => null, 'multiple' => true, 'propertiesMetadata' => [ - 'id' => [ - 'propertyName' => 'id', - 'type' => 'integer', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'title' => [ - 'propertyName' => 'title', - 'type' => 'keyword', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'tags' => [ - 'propertyName' => 'tags', - 'type' => 'object', - 'multilanguage' => null, - 'multiple' => true, - 'propertiesMetadata' => [ - 'tagname' => [ - 'propertyName' => 'tagName', - 'type' => 'text', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - ], - 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjTag', - 'propertyAccess' => 1, - ], + 'tagname' => [ + 'propertyName' => 'tagName', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, ], - 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjCategory', + ], + 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjTag', 'propertyAccess' => 1, ], - 'price' => [ - 'propertyName' => 'price', - 'type' => 'float', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'location' => [ - 'propertyName' => 'location', - 'type' => 'geo_point', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'limited' => [ - 'propertyName' => 'limited', - 'type' => 'boolean', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'released' => [ - 'propertyName' => 'released', - 'type' => 'date', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'ml_info' => [ - 'propertyName' => 'mlInfo', - 'type' => 'text', - 'multilanguage' => true, - 'propertyAccess' => 1, - ], - 'ml_more_info' => [ - 'propertyName' => 'mlMoreInfo', - 'type' => 'text', - 'multilanguage' => true, - 'propertyAccess' => 1, - ], - 'pieces_count' => [ - 'propertyName' => 'tokenPiecesCount', - 'type' => 'text', + ], + 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjCategory', + 'propertyAccess' => 1, + ], + 'related_categories' => [ + 'propertyName' => 'relatedCategories', + 'type' => 'object', + 'multilanguage' => null, + 'multiple' => true, + 'propertiesMetadata' => [ + 'id' => [ + 'propertyName' => 'id', + 'type' => 'integer', 'multilanguage' => null, 'propertyAccess' => 1, ], - '_id' => [ - 'propertyName' => 'id', + 'title' => [ + 'propertyName' => 'title', 'type' => 'keyword', + 'multilanguage' => null, 'propertyAccess' => 1, ], - '_score' => [ - 'propertyName' => 'score', - 'type' => 'float', + 'tags' => [ + 'propertyName' => 'tags', + 'type' => 'object', + 'multilanguage' => null, + 'multiple' => true, + 'propertiesMetadata' => [ + 'tagname' => [ + 'propertyName' => 'tagName', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + ], + 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjTag', 'propertyAccess' => 1, ], + ], + 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjCategory', + 'propertyAccess' => 1, + ], + 'price' => [ + 'propertyName' => 'price', + 'type' => 'float', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'location' => [ + 'propertyName' => 'location', + 'type' => 'geo_point', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'limited' => [ + 'propertyName' => 'limited', + 'type' => 'boolean', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'released' => [ + 'propertyName' => 'released', + 'type' => 'date', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'ml_info' => [ + 'propertyName' => 'mlInfo', + 'type' => 'text', + 'multilanguage' => true, + 'propertyAccess' => 1, + ], + 'ml_more_info' => [ + 'propertyName' => 'mlMoreInfo', + 'type' => 'text', + 'multilanguage' => true, + 'propertyAccess' => 1, + ], + 'pieces_count' => [ + 'propertyName' => 'tokenPiecesCount', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + '_id' => [ + 'propertyName' => 'id', + 'type' => 'keyword', + 'propertyAccess' => 1, + ], + '_score' => [ + 'propertyName' => 'score', + 'type' => 'float', + 'propertyAccess' => 1, ], + ], 'repositoryClass' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\Repository\\ProductRepository', 'providerClass' => null, 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\Product', diff --git a/tests/Functional/Mapping/DocumentParserTest.php b/tests/Functional/Mapping/DocumentParserTest.php index 9b92637..d197187 100644 --- a/tests/Functional/Mapping/DocumentParserTest.php +++ b/tests/Functional/Mapping/DocumentParserTest.php @@ -7,15 +7,9 @@ use Sineflow\ElasticsearchBundle\Mapping\DocumentParser; use Sineflow\ElasticsearchBundle\Tests\AbstractContainerAwareTestCase; -/** - * Class DocumentParserTest - */ class DocumentParserTest extends AbstractContainerAwareTestCase { - /** - * @var DocumentParser - */ - private $documentParser; + private DocumentParser $documentParser; protected function setUp(): void { @@ -39,269 +33,269 @@ public function testParse() $reflection = new \ReflectionClass('Sineflow\ElasticsearchBundle\Tests\App\Fixture\Acme\BarBundle\Document\Product'); $indexAnalyzers = [ 'default_analyzer' => [ - 'type' => 'standard', - ], + 'type' => 'standard', + ], 'en_analyzer' => [ - 'type' => 'standard', - ], + 'type' => 'standard', + ], ]; $res = $this->documentParser->parse($reflection, $indexAnalyzers); $expected = [ 'properties' => [ - 'title' => [ - 'fields' => [ - 'raw' => [ - 'type' => 'keyword', - ], - 'title' => [ - 'type' => 'text', - ], - ], + 'title' => [ + 'fields' => [ + 'raw' => [ + 'type' => 'keyword', + ], + 'title' => [ 'type' => 'text', + ], ], - 'description' => [ - 'type' => 'text', - ], - 'category' => [ - 'properties' => [ - 'id' => [ - 'type' => 'integer', - ], - 'title' => [ - 'type' => 'keyword', - ], - 'tags' => [ - 'properties' => [ - 'tagname' => [ - 'type' => 'text', - ], - ], - ], - ], - ], - 'related_categories' => [ - 'properties' => [ - 'id' => [ - 'type' => 'integer', - ], - 'title' => [ - 'type' => 'keyword', - ], - 'tags' => [ - 'properties' => [ - 'tagname' => [ - 'type' => 'text', - ], - ], - ], - ], - ], - 'price' => [ - 'type' => 'float', - ], - 'location' => [ - 'type' => 'geo_point', - ], - 'limited' => [ - 'type' => 'boolean', - ], - 'released' => [ - 'type' => 'date', - ], - 'ml_info-en' => [ - 'analyzer' => 'en_analyzer', - 'fields' => [ - 'ngram' => [ - 'type' => 'text', - 'analyzer' => 'en_analyzer', - ], + 'type' => 'text', + ], + 'description' => [ + 'type' => 'text', + ], + 'category' => [ + 'properties' => [ + 'id' => [ + 'type' => 'integer', + ], + 'title' => [ + 'type' => 'keyword', + ], + 'tags' => [ + 'properties' => [ + 'tagname' => [ + 'type' => 'text', + ], ], - 'type' => 'text', + ], ], - 'ml_info-fr' => [ - 'analyzer' => 'default_analyzer', - 'fields' => [ - 'ngram' => [ - 'type' => 'text', - 'analyzer' => 'default_analyzer', - ], + ], + 'related_categories' => [ + 'properties' => [ + 'id' => [ + 'type' => 'integer', + ], + 'title' => [ + 'type' => 'keyword', + ], + 'tags' => [ + 'properties' => [ + 'tagname' => [ + 'type' => 'text', + ], ], - 'type' => 'text', - ], - 'ml_info-default' => [ - 'type' => 'keyword', - 'ignore_above' => 256, - ], - 'ml_more_info-en' => [ - 'type' => 'text', - ], - 'ml_more_info-fr' => [ - 'type' => 'text', + ], ], - 'ml_more_info-default' => [ - 'type' => 'text', - 'index' => false, + ], + 'price' => [ + 'type' => 'float', + ], + 'location' => [ + 'type' => 'geo_point', + ], + 'limited' => [ + 'type' => 'boolean', + ], + 'released' => [ + 'type' => 'date', + ], + 'ml_info-en' => [ + 'analyzer' => 'en_analyzer', + 'fields' => [ + 'ngram' => [ + 'type' => 'text', + 'analyzer' => 'en_analyzer', + ], ], - 'pieces_count' => [ - 'fields' => [ - 'count' => [ - 'type' => 'token_count', - 'analyzer' => 'whitespace', - ], - ], - 'type' => 'text', + 'type' => 'text', + ], + 'ml_info-fr' => [ + 'analyzer' => 'default_analyzer', + 'fields' => [ + 'ngram' => [ + 'type' => 'text', + 'analyzer' => 'default_analyzer', + ], ], + 'type' => 'text', ], - 'fields' => [ - 'dynamic' => 'strict', + 'ml_info-default' => [ + 'type' => 'keyword', + 'ignore_above' => 256, ], - 'propertiesMetadata' => [ - 'title' => [ - 'propertyName' => 'title', - 'type' => 'text', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'description' => [ - 'propertyName' => 'description', - 'type' => 'text', - 'multilanguage' => null, - 'propertyAccess' => 1, + 'ml_more_info-en' => [ + 'type' => 'text', + ], + 'ml_more_info-fr' => [ + 'type' => 'text', + ], + 'ml_more_info-default' => [ + 'type' => 'text', + 'index' => false, + ], + 'pieces_count' => [ + 'fields' => [ + 'count' => [ + 'type' => 'token_count', + 'analyzer' => 'whitespace', + ], ], - 'category' => [ - 'propertyName' => 'category', - 'type' => 'object', - 'multilanguage' => null, - 'multiple' => null, - 'propertiesMetadata' => [ - 'id' => [ - 'propertyName' => 'id', - 'type' => 'integer', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'title' => [ - 'propertyName' => 'title', - 'type' => 'keyword', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'tags' => [ - 'propertyName' => 'tags', - 'type' => 'object', - 'multilanguage' => null, - 'multiple' => true, - 'propertiesMetadata' => [ - 'tagname' => [ - 'propertyName' => 'tagName', - 'type' => 'text', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - ], - 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjTag', - 'propertyAccess' => 1, - ], - ], - 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjCategory', + 'type' => 'text', + ], + ], + 'fields' => [ + 'dynamic' => 'strict', + ], + 'propertiesMetadata' => [ + 'title' => [ + 'propertyName' => 'title', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'description' => [ + 'propertyName' => 'description', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'category' => [ + 'propertyName' => 'category', + 'type' => 'object', + 'multilanguage' => null, + 'multiple' => null, + 'propertiesMetadata' => [ + 'id' => [ + 'propertyName' => 'id', + 'type' => 'integer', + 'multilanguage' => null, 'propertyAccess' => 1, - ], - 'related_categories' => [ - 'propertyName' => 'relatedCategories', - 'type' => 'object', - 'multilanguage' => null, - 'multiple' => true, - 'propertiesMetadata' => [ - 'id' => [ - 'propertyName' => 'id', - 'type' => 'integer', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'title' => [ - 'propertyName' => 'title', - 'type' => 'keyword', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'tags' => [ - 'propertyName' => 'tags', - 'type' => 'object', - 'multilanguage' => null, - 'multiple' => true, - 'propertiesMetadata' => [ - 'tagname' => [ - 'propertyName' => 'tagName', - 'type' => 'text', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - ], - 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjTag', - 'propertyAccess' => 1, - ], + ], + 'title' => [ + 'propertyName' => 'title', + 'type' => 'keyword', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'tags' => [ + 'propertyName' => 'tags', + 'type' => 'object', + 'multilanguage' => null, + 'multiple' => true, + 'propertiesMetadata' => [ + 'tagname' => [ + 'propertyName' => 'tagName', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], ], - 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjCategory', + 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjTag', 'propertyAccess' => 1, + ], ], - 'price' => [ - 'propertyName' => 'price', - 'type' => 'float', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'location' => [ - 'propertyName' => 'location', - 'type' => 'geo_point', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'limited' => [ - 'propertyName' => 'limited', - 'type' => 'boolean', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'released' => [ - 'propertyName' => 'released', - 'type' => 'date', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - 'ml_info' => [ - 'propertyName' => 'mlInfo', - 'type' => 'text', - 'multilanguage' => true, + 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjCategory', + 'propertyAccess' => 1, + ], + 'related_categories' => [ + 'propertyName' => 'relatedCategories', + 'type' => 'object', + 'multilanguage' => null, + 'multiple' => true, + 'propertiesMetadata' => [ + 'id' => [ + 'propertyName' => 'id', + 'type' => 'integer', + 'multilanguage' => null, 'propertyAccess' => 1, ], - 'ml_more_info' => [ - 'propertyName' => 'mlMoreInfo', - 'type' => 'text', - 'multilanguage' => true, + 'title' => [ + 'propertyName' => 'title', + 'type' => 'keyword', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'tags' => [ + 'propertyName' => 'tags', + 'type' => 'object', + 'multilanguage' => null, + 'multiple' => true, + 'propertiesMetadata' => [ + 'tagname' => [ + 'propertyName' => 'tagName', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + ], + 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjTag', 'propertyAccess' => 1, ], - 'pieces_count' => [ - 'propertyName' => 'tokenPiecesCount', - 'type' => 'text', - 'multilanguage' => null, - 'propertyAccess' => 1, - ], - '_id' => [ - 'propertyName' => 'id', - 'type' => 'keyword', - 'propertyAccess' => 1, - ], - '_score' => [ - 'propertyName' => 'score', - 'type' => 'float', - 'propertyAccess' => 1, ], + 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\ObjCategory', + 'propertyAccess' => 1, + ], + 'price' => [ + 'propertyName' => 'price', + 'type' => 'float', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'location' => [ + 'propertyName' => 'location', + 'type' => 'geo_point', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'limited' => [ + 'propertyName' => 'limited', + 'type' => 'boolean', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'released' => [ + 'propertyName' => 'released', + 'type' => 'date', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + 'ml_info' => [ + 'propertyName' => 'mlInfo', + 'type' => 'text', + 'multilanguage' => true, + 'propertyAccess' => 1, + ], + 'ml_more_info' => [ + 'propertyName' => 'mlMoreInfo', + 'type' => 'text', + 'multilanguage' => true, + 'propertyAccess' => 1, + ], + 'pieces_count' => [ + 'propertyName' => 'tokenPiecesCount', + 'type' => 'text', + 'multilanguage' => null, + 'propertyAccess' => 1, + ], + '_id' => [ + 'propertyName' => 'id', + 'type' => 'keyword', + 'propertyAccess' => 1, + ], + '_score' => [ + 'propertyName' => 'score', + 'type' => 'float', + 'propertyAccess' => 1, ], - 'repositoryClass' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\Repository\\ProductRepository', - 'providerClass' => null, - 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\Product', + ], + 'repositoryClass' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\Repository\\ProductRepository', + 'providerClass' => null, + 'className' => 'Sineflow\\ElasticsearchBundle\\Tests\\App\\Fixture\\Acme\\BarBundle\\Document\\Product', ]; $this->assertEquals($expected, $res); diff --git a/tests/Functional/Result/DocumentConverterTest.php b/tests/Functional/Result/DocumentConverterTest.php index cd37378..6a24300 100644 --- a/tests/Functional/Result/DocumentConverterTest.php +++ b/tests/Functional/Result/DocumentConverterTest.php @@ -16,7 +16,7 @@ class DocumentConverterTest extends AbstractContainerAwareTestCase { use ArraySubsetAsserts; - private $fullDocArray = [ + private array $fullDocArray = [ '_id' => 'doc1', 'title' => 'Foo Product', 'category' => [ @@ -202,18 +202,18 @@ public function testConvertToDocumentWithSource() '_version' => 1, 'found' => true, '_source' => [ - 'title' => 'Foo Product', - 'category' => [ - 'title' => 'Bar', - ], - 'related_categories' => [ - 0 => [ - 'title' => 'Acme', - ], - ], - 'ml_info-en' => 'info in English', - 'ml_info-fr' => 'info in French', + 'title' => 'Foo Product', + 'category' => [ + 'title' => 'Bar', ], + 'related_categories' => [ + 0 => [ + 'title' => 'Acme', + ], + ], + 'ml_info-en' => 'info in English', + 'ml_info-fr' => 'info in French', + ], ]; $converter = $this->getContainer()->get('Sineflow\ElasticsearchBundle\Result\DocumentConverter'); @@ -237,20 +237,20 @@ public function testConvertToDocumentWithFields() '_id' => 'doc1', '_score' => 1, 'fields' => [ - 'title' => [ - 0 => 'Foo Product', - ], - 'related_categories.title' => [ - 0 => 'Acme', - 1 => 'Bar', - ], - 'category.title' => [ - 0 => 'Bar', - ], - 'ml_info-en' => [ - 0 => 'info in English', - ], + 'title' => [ + 0 => 'Foo Product', + ], + 'related_categories.title' => [ + 0 => 'Acme', + 1 => 'Bar', ], + 'category.title' => [ + 0 => 'Bar', + ], + 'ml_info-en' => [ + 0 => 'info in English', + ], + ], ]; /** @var DocumentConverter $converter */ diff --git a/tests/Unit/Annotation/PropertyTest.php b/tests/Unit/Annotation/PropertyTest.php index 5cbe007..8e21859 100644 --- a/tests/Unit/Annotation/PropertyTest.php +++ b/tests/Unit/Annotation/PropertyTest.php @@ -21,7 +21,7 @@ public function testDump() $type->type = 'mytype'; $type->multilanguage = false; $type->objectName = 'foo/bar'; - $type->multiple = null; + $type->multiple = false; $type->options = [ 'type' => 'this should not be set here', 'analyzer' => 'standard', @@ -51,7 +51,7 @@ public function testDumpML() $type->type = 'mytype'; $type->multilanguage = true; $type->objectName = 'foo/bar'; - $type->multiple = null; + $type->multiple = false; $type->options = [ 'copy_to' => '{lang}_all', 'analyzer' => '{lang}_analyzer', @@ -79,10 +79,10 @@ public function testDumpML() 'copy_to' => 'en_all', 'analyzer' => 'en_analyzer', 'fields' => [ - 'ngram' => [ - 'analyzer' => 'en_analyzer', - ], + 'ngram' => [ + 'analyzer' => 'en_analyzer', ], + ], 'type' => 'mytype', ], $type->dump($settings), @@ -101,7 +101,7 @@ public function testDumpNoAnalyzersException() $type->type = 'mytype'; $type->multilanguage = false; $type->objectName = 'foo/bar'; - $type->multiple = null; + $type->multiple = false; $type->options = [ 'analyzer' => '{lang}_analyzer', ]; @@ -125,7 +125,7 @@ public function testDumpNoDefaultException() $type->type = 'mytype'; $type->multilanguage = false; $type->objectName = 'foo/bar'; - $type->multiple = null; + $type->multiple = false; $type->options = [ 'analyzer' => '{lang}_analyzer', ];