diff --git a/phpstan-baseline-7.4.neon b/phpstan-baseline-7.4.neon index 33547e3bc3..6f857e7ed6 100644 --- a/phpstan-baseline-7.4.neon +++ b/phpstan-baseline-7.4.neon @@ -60,12 +60,6 @@ parameters: count: 1 path: src/bundle/Core/Features/Context/UserContext.php - - - message: '#^PHPDoc tag @throws with type Psr\\Cache\\InvalidArgumentException is not subtype of Throwable$#' - identifier: throws.notThrowable - count: 1 - path: src/bundle/Core/Imagine/Cache/AliasGeneratorDecorator.php - - message: '#^Parameter \#2 \$str of function fwrite expects string, string\|false given\.$#' identifier: argument.type @@ -191,37 +185,6 @@ parameters: identifier: argument.type count: 1 path: src/lib/MVC/Symfony/Matcher/ContentBased/UrlAlias.php - - - - message: '#^PHPDoc tag @throws with type Psr\\Cache\\InvalidArgumentException is not subtype of Throwable$#' - identifier: throws.notThrowable - count: 1 - path: src/lib/Persistence/Cache/ContentTypeHandler.php - - - - message: '#^PHPDoc tag @throws with type Psr\\Cache\\CacheException is not subtype of Throwable$#' - identifier: throws.notThrowable - count: 1 - path: src/lib/Persistence/Cache/SettingHandler.php - - - - message: '#^PHPDoc tag @throws with type Psr\\Cache\\InvalidArgumentException is not subtype of Throwable$#' - identifier: throws.notThrowable - count: 2 - path: src/lib/Persistence/Cache/SettingHandler.php - - - - message: '#^PHPDoc tag @throws with type Ibexa\\Core\\Base\\Exceptions\\BadStateException\|Psr\\Cache\\InvalidArgumentException is not subtype of Throwable$#' - identifier: throws.notThrowable - count: 1 - path: src/lib/Persistence/Cache/UrlAliasHandler.php - - - - message: '#^PHPDoc tag @throws with type Psr\\Cache\\InvalidArgumentException is not subtype of Throwable$#' - identifier: throws.notThrowable - count: 1 - path: src/lib/Persistence/Cache/UrlWildcardHandler.php - - message: '#^Cannot access property \$ownerDocument on DOMElement\|false\.$#' identifier: property.nonObject @@ -456,18 +419,6 @@ parameters: count: 3 path: tests/integration/Core/Repository/RoleServiceTest.php - - - message: '#^Parameter \#1 \$class of class ReflectionProperty constructor expects object\|string, class\-string\|false given\.$#' - identifier: argument.type - count: 4 - path: tests/integration/Core/Repository/SearchServiceLocationTest.php - - - - message: '#^Parameter \#1 \$class of class ReflectionProperty constructor expects object\|string, class\-string\|false given\.$#' - identifier: argument.type - count: 4 - path: tests/integration/Core/Repository/SearchServiceTest.php - - message: '#^Parameter \#1 \$str of function md5 expects string, int\<1, max\> given\.$#' identifier: argument.type @@ -480,12 +431,6 @@ parameters: count: 1 path: tests/lib/MVC/Symfony/Security/UserWrappedTest.php - - - message: '#^Method Ibexa\\Tests\\Core\\MVC\\Symfony\\Templating\\Twig\\Extension\\FileSystemTwigIntegrationTestCase\:\:doIntegrationTest\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: tests/lib/MVC/Symfony/Templating/Twig/Extension/FileSystemTwigIntegrationTestCase.php - - message: '#^Parameter \#1 \$function of function call_user_func_array expects callable\(\)\: mixed, array\{mixed, string\} given\.$#' identifier: argument.type diff --git a/phpstan-baseline-gte-8.0.neon b/phpstan-baseline-gte-8.0.neon index bf7a5398fc..d2e4085a60 100644 --- a/phpstan-baseline-gte-8.0.neon +++ b/phpstan-baseline-gte-8.0.neon @@ -413,19 +413,6 @@ parameters: identifier: argument.type count: 1 path: tests/integration/Core/Repository/RoleServiceTest.php - - - - message: '#^Parameter \#1 \$class of class ReflectionProperty constructor expects object\|string, class\-string\|false given\.$#' - identifier: argument.type - count: 4 - path: tests/integration/Core/Repository/SearchServiceLocationTest.php - - - - message: '#^Parameter \#1 \$class of class ReflectionProperty constructor expects object\|string, class\-string\|false given\.$#' - identifier: argument.type - count: 4 - path: tests/integration/Core/Repository/SearchServiceTest.php - - message: '#^Parameter \#1 \$string of function md5 expects string, int\<1, max\> given\.$#' identifier: argument.type diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index b81f64ba80..6cedc78f98 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -18060,12 +18060,6 @@ parameters: count: 1 path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/AuthorConverter.php - - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt1 \(int\) on left side of \?\? is not nullable\.$#' - identifier: nullCoalesce.property - count: 1 - path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/AuthorConverter.php - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldValue\:\:\$sortKeyString \(string\) does not accept bool\|float\|int\|string\|null\.$#' identifier: assign.propertyType @@ -18523,7 +18517,7 @@ parameters: path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/IntegerConverter.php - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt3 \(int\) does not accept array\|bool\|float\|int\|string\|null\.$#' + message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt3 \(int\|null\) does not accept array\|bool\|float\|int\|string\|null\.$#' identifier: assign.propertyType count: 1 path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/IntegerConverter.php @@ -18534,6 +18528,12 @@ parameters: count: 1 path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/IntegerConverter.php + - + message: '#^Strict comparison using \=\=\= between false and false will always evaluate to true\.$#' + identifier: identical.alwaysTrue + count: 1 + path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/IntegerConverter.php + - message: '#^Method Ibexa\\Core\\Persistence\\Legacy\\Content\\FieldValue\\Converter\\KeywordConverter\:\:toFieldDefinition\(\) has no return type specified\.$#' identifier: missingType.return @@ -18918,18 +18918,6 @@ parameters: count: 1 path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/TextLineConverter.php - - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt1 \(int\) in isset\(\) is not nullable\.$#' - identifier: isset.property - count: 1 - path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/TextLineConverter.php - - - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt2 \(int\) in isset\(\) is not nullable\.$#' - identifier: isset.property - count: 1 - path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/TextLineConverter.php - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataText1 \(string\) does not accept array\|bool\|float\|int\|string\|null\.$#' identifier: assign.propertyType @@ -19002,12 +18990,6 @@ parameters: count: 1 path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/UrlConverter.php - - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt2 \(int\) does not accept null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/UserConverter.php - - message: '#^Method Ibexa\\Core\\Persistence\\Legacy\\Content\\FieldValue\\ConverterRegistry\:\:__construct\(\) has parameter \$converterMap with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue @@ -21006,30 +20988,6 @@ parameters: count: 1 path: src/lib/Persistence/Legacy/Content/Type/Mapper.php - - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt1 \(int\) does not accept int\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Persistence/Legacy/Content/Type/Mapper.php - - - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt2 \(int\) does not accept int\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Persistence/Legacy/Content/Type/Mapper.php - - - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt3 \(int\) does not accept int\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Persistence/Legacy/Content/Type/Mapper.php - - - - message: '#^Property Ibexa\\Core\\Persistence\\Legacy\\Content\\StorageFieldDefinition\:\:\$dataInt4 \(int\) does not accept int\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Persistence/Legacy/Content/Type/Mapper.php - - message: '#^Method Ibexa\\Core\\Persistence\\Legacy\\Content\\Type\\MemoryCachingHandler\:\:getSearchableFieldMap\(\) should return array\ but returns array\|object\.$#' identifier: return.type diff --git a/src/bundle/Core/Imagine/Cache/AliasGeneratorDecorator.php b/src/bundle/Core/Imagine/Cache/AliasGeneratorDecorator.php index c05f7c6e6e..f959e130aa 100644 --- a/src/bundle/Core/Imagine/Cache/AliasGeneratorDecorator.php +++ b/src/bundle/Core/Imagine/Cache/AliasGeneratorDecorator.php @@ -69,7 +69,7 @@ public function __construct( * * @return \Ibexa\Contracts\Core\Variation\Values\Variation * - * @throws \Psr\Cache\InvalidArgumentException + * @throws \Psr\Cache\InvalidArgumentException&\Throwable */ public function getVariation(Field $field, VersionInfo $versionInfo, $variationName, array $parameters = []) { diff --git a/src/lib/Persistence/Cache/ContentTypeHandler.php b/src/lib/Persistence/Cache/ContentTypeHandler.php index be6c28fbce..eece3e1cf7 100644 --- a/src/lib/Persistence/Cache/ContentTypeHandler.php +++ b/src/lib/Persistence/Cache/ContentTypeHandler.php @@ -612,7 +612,7 @@ function () { * * @return \Ibexa\Contracts\Core\Persistence\Content\Type * - * @throws \Psr\Cache\InvalidArgumentException + * @throws \Psr\Cache\InvalidArgumentException&\Throwable */ public function removeContentTypeTranslation(int $contentTypeId, string $languageCode): Type { diff --git a/src/lib/Persistence/Cache/SettingHandler.php b/src/lib/Persistence/Cache/SettingHandler.php index ea295842f5..08dfc415e8 100644 --- a/src/lib/Persistence/Cache/SettingHandler.php +++ b/src/lib/Persistence/Cache/SettingHandler.php @@ -21,7 +21,7 @@ public function create(string $group, string $identifier, string $serializedValu } /** - * @throws \Psr\Cache\InvalidArgumentException + * @throws \Psr\Cache\InvalidArgumentException&\Throwable */ public function update(string $group, string $identifier, string $serializedValue): Setting { @@ -35,7 +35,7 @@ public function update(string $group, string $identifier, string $serializedValu } /** - * @throws \Psr\Cache\CacheException + * @throws \Psr\Cache\CacheException&\Throwable */ public function load(string $group, string $identifier): Setting { @@ -57,7 +57,7 @@ public function load(string $group, string $identifier): Setting } /** - * @throws \Psr\Cache\InvalidArgumentException + * @throws (\Psr\Cache\InvalidArgumentException&\Throwable) */ public function delete(string $group, string $identifier): void { diff --git a/src/lib/Persistence/Cache/UrlAliasHandler.php b/src/lib/Persistence/Cache/UrlAliasHandler.php index 0edfaeb3f6..492ceb874e 100644 --- a/src/lib/Persistence/Cache/UrlAliasHandler.php +++ b/src/lib/Persistence/Cache/UrlAliasHandler.php @@ -490,7 +490,7 @@ public function deleteCorruptedUrlAliases() * @param int $locationId * * @throws \Ibexa\Core\Base\Exceptions\BadStateException - * @throws \Psr\Cache\InvalidArgumentException + * @throws \Psr\Cache\InvalidArgumentException&\Throwable */ public function repairBrokenUrlAliasesForLocation(int $locationId) { diff --git a/src/lib/Persistence/Cache/UrlWildcardHandler.php b/src/lib/Persistence/Cache/UrlWildcardHandler.php index fb92a76ba7..3f624595c4 100644 --- a/src/lib/Persistence/Cache/UrlWildcardHandler.php +++ b/src/lib/Persistence/Cache/UrlWildcardHandler.php @@ -45,7 +45,7 @@ public function create($sourceUrl, $destinationUrl, $forward = false) /** * {@inheritdoc} * - * @throws \Psr\Cache\InvalidArgumentException + * @throws \Psr\Cache\InvalidArgumentException&\Throwable */ public function update( int $id, diff --git a/src/lib/Persistence/Legacy/Content/StorageFieldDefinition.php b/src/lib/Persistence/Legacy/Content/StorageFieldDefinition.php index e5a283184c..7f60306438 100644 --- a/src/lib/Persistence/Legacy/Content/StorageFieldDefinition.php +++ b/src/lib/Persistence/Legacy/Content/StorageFieldDefinition.php @@ -41,28 +41,28 @@ class StorageFieldDefinition extends ValueObject /** * Data int 1. * - * @var int + * @var int|null */ public $dataInt1; /** * Data int 2. * - * @var int + * @var int|null */ public $dataInt2; /** * Data int 3. * - * @var int + * @var int|null */ public $dataInt3; /** * Data int 4. * - * @var int + * @var int|null */ public $dataInt4; diff --git a/src/lib/Repository/Mapper/ContentDomainMapper.php b/src/lib/Repository/Mapper/ContentDomainMapper.php index 466651f733..4233caa2be 100644 --- a/src/lib/Repository/Mapper/ContentDomainMapper.php +++ b/src/lib/Repository/Mapper/ContentDomainMapper.php @@ -639,7 +639,9 @@ public function buildContentDomainObjectsOnSearchResult(SearchResult $result, ar } else { $missingContentList[] = $hit->valueObject; unset($result->searchHits[$key]); - --$result->totalCount; + if ($result->totalCount !== null) { + --$result->totalCount; + } } } @@ -684,7 +686,9 @@ public function buildLocationDomainObjectsOnSearchResult(SearchResult $result, a } else { $missingLocations[] = $hit->valueObject; unset($result->searchHits[$key]); - --$result->totalCount; + if ($result->totalCount !== null) { + --$result->totalCount; + } } } diff --git a/src/lib/Resources/settings/repository/inner.yml b/src/lib/Resources/settings/repository/inner.yml index 8b5e99afcf..ba1aa96f22 100644 --- a/src/lib/Resources/settings/repository/inner.yml +++ b/src/lib/Resources/settings/repository/inner.yml @@ -157,6 +157,7 @@ services: alias: 'Ibexa\Core\Repository\ProxyFactory\ProxyGenerator' Ibexa\Core\Repository\ProxyFactory\ProxyDomainMapperFactory: + lazy: 'Ibexa\Contracts\Core\Repository\Repository\ProxyDomainMapperFactoryInterface' arguments: $proxyGenerator: '@Ibexa\Core\Repository\ProxyFactory\ProxyGeneratorInterface' diff --git a/tests/integration/Core/Repository/SearchServiceLocationTest.php b/tests/integration/Core/Repository/SearchServiceLocationTest.php index 374ae91784..7eaef0d41c 100644 --- a/tests/integration/Core/Repository/SearchServiceLocationTest.php +++ b/tests/integration/Core/Repository/SearchServiceLocationTest.php @@ -1398,12 +1398,16 @@ protected function assertQueryFixture(LocationQuery $query, $fixture, $closure = if ($ignoreScore) { foreach ([$fixture, $result] as $result) { - $property = new \ReflectionProperty(get_class($result), 'maxScore'); + $resultClass = get_class($result); + self::assertIsString($resultClass); + $property = new \ReflectionProperty($resultClass, 'maxScore'); $property->setAccessible(true); $property->setValue($result, 0.0); foreach ($result->searchHits as $hit) { - $property = new \ReflectionProperty(get_class($hit), 'score'); + $hitClass = get_class($hit); + self::assertIsString($hitClass); + $property = new \ReflectionProperty($hitClass, 'score'); $property->setAccessible(true); $property->setValue($hit, 0.0); } @@ -1412,11 +1416,14 @@ protected function assertQueryFixture(LocationQuery $query, $fixture, $closure = foreach ([$fixture, $result] as $set) { foreach ($set->searchHits as $hit) { - $property = new \ReflectionProperty(get_class($hit), 'index'); + $hitClass = get_class($hit); + self::assertIsString($hitClass); + + $property = new \ReflectionProperty($hitClass, 'index'); $property->setAccessible(true); $property->setValue($hit, null); - $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation'); + $property = new \ReflectionProperty($hitClass, 'matchedTranslation'); $property->setAccessible(true); $property->setValue($hit, null); } @@ -1432,13 +1439,20 @@ protected function assertQueryFixture(LocationQuery $query, $fixture, $closure = /** * Show a simplified view of the search result for manual introspection. - * - * @return string */ - protected function printResult(SearchResult $result) + protected function printResult(SearchResult $result): string { $printed = ''; foreach ($result->searchHits as $hit) { + if (!isset($hit->valueObject['title'], $hit->valueObject['id'])) { + continue; + } + + $printed .= sprintf( + "%s: %s\n", + $hit->valueObject['title'], + $hit->valueObject['description'] + ); $printed .= sprintf(" - %s (%s)\n", $hit->valueObject['title'], $hit->valueObject['id']); } diff --git a/tests/integration/Core/Repository/SearchServiceTest.php b/tests/integration/Core/Repository/SearchServiceTest.php index 151b6a4bfa..ad41cac19b 100644 --- a/tests/integration/Core/Repository/SearchServiceTest.php +++ b/tests/integration/Core/Repository/SearchServiceTest.php @@ -23,6 +23,8 @@ use Ibexa\Contracts\Core\Test\Repository\SetupFactory\Legacy; use Ibexa\Tests\Core\Repository\Common; use Ibexa\Tests\Solr\SetupFactory\LegacySetupFactory as LegacySolrSetupFactory; +use ReflectionProperty; +use RuntimeException; /** * Test case for operations in the SearchService. @@ -1272,7 +1274,7 @@ public function testFindNoPerformCount() public function testFindNoPerformCountException() { - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); if (!$this->isRunningOnLegacySetup()) { $this->markTestSkipped('Only applicable to Legacy/DB based search'); @@ -1318,7 +1320,7 @@ public function testFindLocationsNoPerformCount() public function testFindLocationsNoPerformCountException() { - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); if (!$this->isRunningOnLegacySetup()) { $this->markTestSkipped('Only applicable to Legacy/DB based search'); @@ -4771,12 +4773,16 @@ protected function assertQueryFixture( if ($ignoreScore) { foreach ([$fixture, $result] as $set) { - $property = new \ReflectionProperty(get_class($set), 'maxScore'); + $setClass = get_class($set); + self::assertIsString($setClass); + $property = new ReflectionProperty($setClass, 'maxScore'); $property->setAccessible(true); $property->setValue($set, 0.0); foreach ($set->searchHits as $hit) { - $property = new \ReflectionProperty(get_class($hit), 'score'); + $hitClass = get_class($hit); + self::assertIsString($hitClass); + $property = new ReflectionProperty($hitClass, 'score'); $property->setAccessible(true); $property->setValue($hit, 0.0); } @@ -4785,11 +4791,13 @@ protected function assertQueryFixture( foreach ([$fixture, $result] as $set) { foreach ($set->searchHits as $hit) { - $property = new \ReflectionProperty(get_class($hit), 'index'); + $hitClass = get_class($hit); + self::assertIsString($hitClass); + $property = new ReflectionProperty($hitClass, 'index'); $property->setAccessible(true); $property->setValue($hit, null); - $property = new \ReflectionProperty(get_class($hit), 'matchedTranslation'); + $property = new ReflectionProperty($hitClass, 'matchedTranslation'); $property->setAccessible(true); $property->setValue($hit, null); @@ -4854,7 +4862,7 @@ protected function simplifySearchResult(SearchResult $result) break; default: - throw new \RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject)); + throw new RuntimeException('Unknown search result hit type: ' . get_class($hit->valueObject)); } } } diff --git a/tests/lib/MVC/Symfony/Templating/Twig/Extension/FileSystemTwigIntegrationTestCase.php b/tests/lib/MVC/Symfony/Templating/Twig/Extension/FileSystemTwigIntegrationTestCase.php index cca6652886..b44eb405d4 100644 --- a/tests/lib/MVC/Symfony/Templating/Twig/Extension/FileSystemTwigIntegrationTestCase.php +++ b/tests/lib/MVC/Symfony/Templating/Twig/Extension/FileSystemTwigIntegrationTestCase.php @@ -27,7 +27,7 @@ abstract class FileSystemTwigIntegrationTestCase extends IntegrationTestCase * Overrides the default implementation to use the chain loader so that * templates used internally are correctly loaded. */ - protected function doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs, $deprecation = '') + protected function doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs, $deprecation = ''): void { if ($condition) { eval('$ret = ' . $condition . ';'); diff --git a/tests/lib/Repository/Service/Mock/SearchTest.php b/tests/lib/Repository/Service/Mock/SearchTest.php index 848c431a57..74bf885637 100644 --- a/tests/lib/Repository/Service/Mock/SearchTest.php +++ b/tests/lib/Repository/Service/Mock/SearchTest.php @@ -244,7 +244,9 @@ public function testFindContentWhenDomainMapperThrowsException() ->with($this->equalTo($result), $this->equalTo([])) ->willReturnCallback(static function (SearchResult $spiResult) use ($info) { unset($spiResult->searchHits[0]); - --$spiResult->totalCount; + if ($spiResult->totalCount !== null) { + --$spiResult->totalCount; + } return [$info]; }); @@ -828,7 +830,9 @@ public function testFindLocationsBackgroundIndexerWhenDomainMapperThrowsExceptio ->with($this->equalTo($result)) ->willReturnCallback(static function (SearchResult $spiResult) use ($location) { unset($spiResult->searchHits[0]); - --$spiResult->totalCount; + if ($spiResult->totalCount !== null) { + --$spiResult->totalCount; + } return [$location]; });