diff --git a/phpstan-baseline-7.4.neon b/phpstan-baseline-7.4.neon new file mode 100644 index 0000000000..9b8ecc1c33 --- /dev/null +++ b/phpstan-baseline-7.4.neon @@ -0,0 +1,486 @@ +parameters: + ignoreErrors: + - + message: "#^Parameter \\#1 \\$input of function array_keys expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/ApiLoader/StorageConnectionFactory.php + + - + message: "#^Parameter \\#1 \\$input of function array_filter expects array, iterable\\ given\\.$#" + count: 1 + path: src/bundle/Core/Command/CleanupVersionsCommand.php + + - + message: "#^Parameter \\#1 \\$input of function array_slice expects array, iterable\\ given\\.$#" + count: 1 + path: src/bundle/Core/Command/CleanupVersionsCommand.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: src/bundle/Core/Command/CleanupVersionsCommand.php + + - + message: "#^Parameter \\#2 \\$str of function fwrite expects string, string\\|false given\\.$#" + count: 1 + path: src/bundle/Core/Command/ResizeOriginalImagesCommand.php + + - + message: "#^Parameter \\#2 \\$parameters of function call_user_func_array expects array\\, array\\\\> given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Compiler/ConsoleCacheWarmupPass.php + + - + message: "#^Method Ibexa\\\\Bundle\\\\Core\\\\DependencyInjection\\\\Compiler\\\\InjectEntityManagerMappingsPass\\:\\:getEntityMapForConfigurationService\\(\\) should return array but returns array\\|false\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Compiler/InjectEntityManagerMappingsPass.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$args of function array_merge expects array, Ibexa\\\\Contracts\\\\Core\\\\SiteAccess\\\\ConfigResolverInterface given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Configuration/ChainConfigResolver.php + + - + message: "#^Parameter \\#1 \\$str of function strtolower expects string, string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Configuration/ConfigResolver.php + + - + message: "#^Parameter \\#1 \\$stack of function array_shift expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Configuration/Parser/Languages.php + + - + message: "#^Parameter \\#1 \\$arr1 of function array_merge expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Configuration/SiteAccessAware/Contextualizer.php + + - + message: "#^Parameter \\#1 \\$arr1 of function array_merge expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/IbexaCoreExtension.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: src/bundle/Core/Features/Context/ContentPreviewContext.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: src/bundle/Core/Features/Context/UserContext.php + + - + message: "#^PHPDoc tag @throws with type Psr\\\\Cache\\\\InvalidArgumentException is not subtype of Throwable$#" + count: 1 + path: src/bundle/Core/Imagine/Cache/AliasGeneratorDecorator.php + + - + message: "#^Parameter \\#2 \\$str of function fwrite expects string, string\\|false given\\.$#" + count: 1 + path: src/bundle/Core/Imagine/IORepositoryResolver.php + + - + message: "#^Parameter \\#1 \\$fp of function fclose expects resource, resource\\|false given\\.$#" + count: 1 + path: src/bundle/IO/BinaryStreamResponse.php + + - + message: "#^Parameter \\#2 \\$dest of function stream_copy_to_stream expects resource, resource\\|false given\\.$#" + count: 1 + path: src/bundle/IO/BinaryStreamResponse.php + + - + message: "#^Parameter \\#3 \\$count of class LimitIterator constructor expects int, int\\|null given\\.$#" + count: 1 + path: src/bundle/IO/Migration/FileLister/BinaryFileLister.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: src/bundle/IO/Migration/FileLister/FileRowReader/LegacyStorageFileRowReader.php + + - + message: "#^Parameter \\#3 \\$count of class LimitIterator constructor expects int, int\\|null given\\.$#" + count: 1 + path: src/bundle/IO/Migration/FileLister/ImageFileLister.php + + - + message: "#^Parameter \\#1 \\$input of function array_keys expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/LegacySearchEngine/ApiLoader/ConnectionFactory.php + + - + message: "#^Parameter \\#1 \\$input of function array_filter expects array, array\\\\|false given\\.$#" + count: 1 + path: src/bundle/RepositoryInstaller/Installer/DbBasedInstaller.php + + - + message: "#^Parameter \\#1 \\$object_or_string of function is_a expects object\\|string, string\\|null given\\.$#" + count: 1 + path: src/lib/Base/Container/Compiler/FieldTypeRegistryPass.php + + - + message: "#^Parameter \\#1 \\$object_or_string of function is_subclass_of expects object\\|string, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/lib/Base/Container/Compiler/Storage/ExternalStorageRegistryPass.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/lib/FieldType/Author/SearchField.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: src/lib/FieldType/BinaryBase/BinaryBaseStorage/Gateway/DoctrineStorage.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: src/lib/FieldType/BinaryBase/PathGenerator/LegacyPathGenerator.php + + - + message: "#^Parameter \\#1 \\$arr1 of function array_merge expects array, array\\|bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: src/lib/FieldType/Image/ImageStorage.php + + - + message: "#^Parameter \\#1 \\$input of function array_flip expects array\\, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/lib/FieldType/Selection/SearchField.php + + - + message: "#^Parameter \\#1 \\$str of function mb_substr expects string, string\\|false given\\.$#" + count: 1 + path: src/lib/FieldType/TextBlock/SearchField.php + + - + message: "#^Parameter \\#1 \\$str of function mb_substr expects string, string\\|false given\\.$#" + count: 1 + path: src/lib/FieldType/TextBlock/Type.php + + - + message: "#^Parameter \\#1 \\$input of function array_keys expects array, iterable\\ given\\.$#" + count: 1 + path: src/lib/Limitation/LanguageLimitationType.php + + - + message: "#^Parameter \\#1 \\$input of function array_keys expects array, array\\|ArrayObject\\<\\(int\\|string\\), mixed\\>\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/lib/MVC/Symfony/Component/Serializer/AbstractPropertyWhitelistNormalizer.php + + - + message: "#^Parameter \\#1 \\$input of function array_keys expects array, iterable\\ given\\.$#" + count: 1 + path: src/lib/MVC/Symfony/FieldType/RelationList/ParameterProvider.php + + - + message: "#^Parameter \\#1 \\$arr1 of function array_merge expects array, iterable\\ given\\.$#" + count: 1 + path: src/lib/MVC/Symfony/Matcher/ContentBased/UrlAlias.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$args of function array_merge expects array, iterable\\ given\\.$#" + 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$#" + count: 1 + path: src/lib/Persistence/Cache/ContentTypeHandler.php + + - + message: "#^PHPDoc tag @throws with type Psr\\\\Cache\\\\CacheException is not subtype of Throwable$#" + count: 1 + path: src/lib/Persistence/Cache/SettingHandler.php + + - + message: "#^PHPDoc tag @throws with type Psr\\\\Cache\\\\InvalidArgumentException is not subtype of Throwable$#" + 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$#" + count: 1 + path: src/lib/Persistence/Cache/UrlAliasHandler.php + + - + message: "#^PHPDoc tag @throws with type Psr\\\\Cache\\\\InvalidArgumentException is not subtype of Throwable$#" + count: 1 + path: src/lib/Persistence/Cache/UrlWildcardHandler.php + + - + message: "#^Parameter \\#2 \\$pieces of function implode expects array, array\\|bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/CountryConverter.php + + - + message: "#^Parameter \\#2 \\$pieces of function implode expects array, array\\|float\\|int\\\\|int\\<1, max\\>\\|string\\|true given\\.$#" + count: 1 + path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/CountryConverter.php + + - + message: "#^Cannot access property \\$ownerDocument on DOMElement\\|false\\.$#" + count: 2 + path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/ImageConverter.php + + - + message: "#^Parameter \\#1 \\$input of class Ibexa\\\\Core\\\\FieldType\\\\FieldSettings constructor expects array\\|object, array\\|null given\\.$#" + count: 1 + path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/SerializableConverter.php + + - + message: "#^Parameter \\#1 \\$input of function array_keys expects array, iterable\\ given\\.$#" + count: 2 + path: src/lib/Persistence/Legacy/Content/Language/MaskGenerator.php + + - + message: "#^Method Ibexa\\\\Core\\\\Persistence\\\\Legacy\\\\Content\\\\UrlAlias\\\\Gateway\\\\DoctrineDatabase\\:\\:filterOriginalAliases\\(\\) should return array but returns array\\|false\\.$#" + count: 1 + path: src/lib/Persistence/Legacy/Content/UrlAlias/Gateway/DoctrineDatabase.php + + - + message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false\\|null given\\.$#" + count: 1 + path: src/lib/Persistence/TransformationProcessor/DefinitionBased/Parser.php + + - + message: "#^Parameter \\#1 \\$string of function substr expects string, string\\|false\\|null given\\.$#" + count: 2 + path: src/lib/Persistence/TransformationProcessor/DefinitionBased/Parser.php + + - + message: "#^Parameter \\#2 \\$subject of function preg_match expects string, string\\|false\\|null given\\.$#" + count: 1 + path: src/lib/Persistence/TransformationProcessor/DefinitionBased/Parser.php + + - + message: "#^Parameter \\#1 \\$ascii of function chr expects int, float\\|int given\\.$#" + count: 1 + path: src/lib/Persistence/TransformationProcessor/PcreCompiler.php + + - + message: "#^Parameter \\#1 \\$hexadecimal_number of function hexdec expects string, string\\|null given\\.$#" + count: 1 + path: src/lib/Persistence/TransformationProcessor/PcreCompiler.php + + - + message: "#^Parameter \\#1 \\$str of function md5 expects string, string\\|false given\\.$#" + count: 4 + path: src/lib/Repository/Mapper/ContentMapper.php + + - + message: "#^Parameter \\#1 \\$autoload_function of function spl_autoload_register expects callable\\(string\\)\\: void, ProxyManager\\\\Autoloader\\\\AutoloaderInterface given\\.$#" + count: 1 + path: src/lib/Repository/ProxyFactory/ProxyGenerator.php + + - + message: "#^Parameter \\#2 \\$arr2 of function array_diff expects array, array\\|null given\\.$#" + count: 1 + path: src/lib/Repository/RoleService.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: src/lib/Repository/UserService.php + + - + message: "#^Parameter \\#1 \\$array of function reset expects array\\|object, null given\\.$#" + count: 3 + path: src/lib/Search/Common/FieldNameResolver.php + + - + message: "#^Parameter \\#1 \\$input of function array_keys expects array, string given\\.$#" + count: 3 + path: src/lib/Search/Common/FieldNameResolver.php + + - + message: "#^Parameter \\#1 \\$str of function trim expects string, bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: src/lib/Search/Legacy/Content/Gateway/CriterionHandler/Ancestor.php + + - + message: "#^Parameter \\#1 \\$str of function trim expects string, bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: src/lib/Search/Legacy/Content/Location/Gateway/CriterionHandler/Ancestor.php + + - + message: "#^Parameter \\#1 \\$object of method ReflectionProperty\\:\\:getValue\\(\\) expects object, object\\|null given\\.$#" + count: 1 + path: tests/bundle/Core/DependencyInjection/Compiler/SlugConverterConfigurationPassTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$args of function array_merge_recursive expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php + + - + message: "#^Parameter \\#1 \\$str of function trim expects string, string\\|null given\\.$#" + count: 1 + path: tests/bundle/Core/EventListener/BackwardCompatibleCommandListenerTest.php + + - + message: "#^Parameter \\#2 \\$start of function substr expects int, int\\<1, max\\>\\|false given\\.$#" + count: 1 + path: tests/bundle/Core/EventListener/SiteAccessListenerTest.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: tests/bundle/Core/Routing/DefaultRouterTest.php + + - + message: "#^Parameter \\#1 \\$fp of function fclose expects resource, resource\\|false given\\.$#" + count: 1 + path: tests/integration/Core/IO/BinarydataHandler/FlysystemTest.php + + - + message: "#^Parameter \\#1 \\$str1 of function strcmp expects string, bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: tests/integration/Core/Repository/BaseTest.php + + - + message: "#^Parameter \\#2 \\$str2 of function strcmp expects string, bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: tests/integration/Core/Repository/BaseTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 4 + path: tests/integration/Core/Repository/ContentServiceAuthorizationTest.php + + - + message: "#^Parameter \\#1 \\$array_arg of function usort expects TArray of array, iterable\\ given\\.$#" + count: 2 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$input of function array_keys expects array, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$input of function array_values expects array\\, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$str of function md5 expects string, float given\\.$#" + count: 3 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 2 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentTypeServiceTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/LanguageServiceMaximumSupportedLanguagesTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 2 + path: tests/integration/Core/Repository/LanguageServiceTest.php + + - + message: "#^Parameter \\#1 \\$input of function array_filter expects array, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/LocationServiceTest.php + + - + message: "#^Parameter \\#1 \\$input of function array_keys expects array, iterable\\ given\\.$#" + count: 3 + path: tests/integration/Core/Repository/LocationServiceTest.php + + - + message: "#^Parameter \\#1 \\$input of function array_filter expects array, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/PermissionResolverTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/Regression/EZP21798Test.php + + - + message: "#^Parameter \\#1 \\$arr1 of function array_merge expects array, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/RoleServiceTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/RoleServiceTest.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 3 + path: tests/integration/Core/Repository/RoleServiceTest.php + + - + message: "#^Parameter \\#1 \\$str of function md5 expects string, int\\<1, max\\> given\\.$#" + count: 1 + path: tests/integration/Core/Repository/Values/User/Limitation/BaseLimitationTest.php + + - + message: "#^Parameter \\#1 \\$str of function md5 expects string, float given\\.$#" + count: 1 + path: tests/lib/MVC/Symfony/Security/UserWrappedTest.php + + - + message: "#^Parameter \\#1 \\$function of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{mixed, string\\} given\\.$#" + count: 3 + path: tests/lib/Persistence/Cache/AbstractCacheHandlerTest.php + + - + message: "#^Parameter \\#1 \\$function of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{mixed, string\\} given\\.$#" + count: 3 + path: tests/lib/Persistence/Cache/AbstractInMemoryCacheHandlerTest.php + + - + message: "#^Parameter \\#1 \\$function of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{mixed, 'publish'\\} given\\.$#" + count: 1 + path: tests/lib/Persistence/Cache/ContentTypeHandlerTest.php + + - + message: "#^Parameter \\#1 \\$arr1 of function array_merge expects array, iterable given\\.$#" + count: 1 + path: tests/lib/Persistence/Legacy/Filter/BaseCriterionVisitorQueryBuilderTestCase.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$args of function array_merge expects array, iterable\\ given\\.$#" + count: 1 + path: tests/lib/Persistence/Legacy/Filter/BaseCriterionVisitorQueryBuilderTestCase.php + + - + message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 12 + path: tests/lib/Repository/Service/Mock/UrlAliasTest.php + + - + message: "#^Parameter \\#1 \\$array_arg of function key expects array\\|object, string given\\.$#" + count: 4 + path: tests/lib/Search/FieldNameResolverTest.php diff --git a/phpstan-baseline-gte-8.0.neon b/phpstan-baseline-gte-8.0.neon new file mode 100644 index 0000000000..f4d695d9ca --- /dev/null +++ b/phpstan-baseline-gte-8.0.neon @@ -0,0 +1,456 @@ +parameters: + ignoreErrors: + - + message: "#^Parameter \\#1 \\$array of function array_keys expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/ApiLoader/StorageConnectionFactory.php + + - + message: "#^Parameter \\#1 \\$array of function array_filter expects array, iterable\\ given\\.$#" + count: 1 + path: src/bundle/Core/Command/CleanupVersionsCommand.php + + - + message: "#^Parameter \\#1 \\$array of function array_slice expects array, iterable\\ given\\.$#" + count: 1 + path: src/bundle/Core/Command/CleanupVersionsCommand.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: src/bundle/Core/Command/CleanupVersionsCommand.php + + - + message: "#^Parameter \\#2 \\$data of function fwrite expects string, string\\|false given\\.$#" + count: 1 + path: src/bundle/Core/Command/ResizeOriginalImagesCommand.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$arrays of function array_merge expects array, Ibexa\\\\Contracts\\\\Core\\\\SiteAccess\\\\ConfigResolverInterface given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Configuration/ChainConfigResolver.php + + - + message: "#^Parameter \\#1 \\$string of function strtolower expects string, string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Configuration/ConfigResolver.php + + - + message: "#^Parameter \\#1 \\$array of function array_shift expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Configuration/Parser/Languages.php + + - + message: "#^Parameter \\#1 \\.\\.\\.\\$arrays of function array_merge expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/Configuration/SiteAccessAware/Contextualizer.php + + - + message: "#^Parameter \\#1 \\.\\.\\.\\$arrays of function array_merge expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/Core/DependencyInjection/IbexaCoreExtension.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int\\|null, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: src/bundle/Core/Features/Context/ContentPreviewContext.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: src/bundle/Core/Features/Context/UserContext.php + + - + message: "#^Parameter \\#2 \\$data of function fwrite expects string, string\\|false given\\.$#" + count: 1 + path: src/bundle/Core/Imagine/IORepositoryResolver.php + + - + message: "#^Method Ibexa\\\\Bundle\\\\Core\\\\URLChecker\\\\Handler\\\\HTTPHandler\\:\\:createCurlHandlerForUrl\\(\\) should return resource but returns \\(CurlHandle\\|false\\)\\.$#" + count: 1 + path: src/bundle/Core/URLChecker/Handler/HTTPHandler.php + + - + message: "#^Parameter \\#1 \\$handle of function curl_getinfo expects CurlHandle, resource given\\.$#" + count: 1 + path: src/bundle/Core/URLChecker/Handler/HTTPHandler.php + + - + message: "#^Parameter \\#2 \\$handle of function curl_multi_add_handle expects CurlHandle, resource given\\.$#" + count: 2 + path: src/bundle/Core/URLChecker/Handler/HTTPHandler.php + + - + message: "#^Parameter \\#1 \\$stream of function fclose expects resource, resource\\|false given\\.$#" + count: 1 + path: src/bundle/IO/BinaryStreamResponse.php + + - + message: "#^Parameter \\#2 \\$to of function stream_copy_to_stream expects resource, resource\\|false given\\.$#" + count: 1 + path: src/bundle/IO/BinaryStreamResponse.php + + - + message: "#^Parameter \\#3 \\$limit of class LimitIterator constructor expects int, int\\|null given\\.$#" + count: 1 + path: src/bundle/IO/Migration/FileLister/BinaryFileLister.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int\\|null, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: src/bundle/IO/Migration/FileLister/FileRowReader/LegacyStorageFileRowReader.php + + - + message: "#^Parameter \\#3 \\$limit of class LimitIterator constructor expects int, int\\|null given\\.$#" + count: 1 + path: src/bundle/IO/Migration/FileLister/ImageFileLister.php + + - + message: "#^Parameter \\#1 \\$array of function array_keys expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/bundle/LegacySearchEngine/ApiLoader/ConnectionFactory.php + + - + message: "#^Parameter \\#1 \\$array of function array_filter expects array, array\\\\|false given\\.$#" + count: 1 + path: src/bundle/RepositoryInstaller/Installer/DbBasedInstaller.php + + - + message: "#^Parameter \\#1 \\$object_or_class of function is_a expects object\\|string, string\\|null given\\.$#" + count: 1 + path: src/lib/Base/Container/Compiler/FieldTypeRegistryPass.php + + - + message: "#^Parameter \\#1 \\$object_or_class of function is_subclass_of expects object\\|string, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/lib/Base/Container/Compiler/Storage/ExternalStorageRegistryPass.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/lib/FieldType/Author/SearchField.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int\\|null, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: src/lib/FieldType/BinaryBase/BinaryBaseStorage/Gateway/DoctrineStorage.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int\\|null, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: src/lib/FieldType/BinaryBase/PathGenerator/LegacyPathGenerator.php + + - + message: "#^Parameter \\#1 \\.\\.\\.\\$arrays of function array_merge expects array, array\\|bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: src/lib/FieldType/Image/ImageStorage.php + + - + message: "#^Parameter \\#1 \\$array of function array_flip expects array\\, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/lib/FieldType/Selection/SearchField.php + + - + message: "#^Parameter \\#1 \\$string of function mb_substr expects string, string\\|false given\\.$#" + count: 1 + path: src/lib/FieldType/TextBlock/SearchField.php + + - + message: "#^Parameter \\#1 \\$string of function mb_substr expects string, string\\|false given\\.$#" + count: 1 + path: src/lib/FieldType/TextBlock/Type.php + + - + message: "#^Parameter \\#1 \\$array of function array_keys expects array, iterable\\ given\\.$#" + count: 1 + path: src/lib/Limitation/LanguageLimitationType.php + + - + message: "#^Parameter \\#1 \\$array of function array_keys expects array, array\\|ArrayObject\\<\\(int\\|string\\), mixed\\>\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: src/lib/MVC/Symfony/Component/Serializer/AbstractPropertyWhitelistNormalizer.php + + - + message: "#^Parameter \\#1 \\$array of function array_keys expects array, iterable\\ given\\.$#" + count: 1 + path: src/lib/MVC/Symfony/FieldType/RelationList/ParameterProvider.php + + - + message: "#^Parameter \\#1 \\.\\.\\.\\$arrays of function array_merge expects array, iterable\\ given\\.$#" + count: 1 + path: src/lib/MVC/Symfony/Matcher/ContentBased/UrlAlias.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$arrays of function array_merge expects array, iterable\\ given\\.$#" + count: 1 + path: src/lib/MVC/Symfony/Matcher/ContentBased/UrlAlias.php + + - + message: "#^Parameter \\#2 \\$array of function implode expects array\\|null, array\\|bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/CountryConverter.php + + - + message: "#^Parameter \\#2 \\$array of function implode expects array\\|null, array\\|float\\|int\\\\|int\\<1, max\\>\\|string\\|true given\\.$#" + count: 1 + path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/CountryConverter.php + + - + message: "#^Parameter \\#1 \\$array of class Ibexa\\\\Core\\\\FieldType\\\\FieldSettings constructor expects array\\|object, array\\|null given\\.$#" + count: 1 + path: src/lib/Persistence/Legacy/Content/FieldValue/Converter/SerializableConverter.php + + - + message: "#^Parameter \\#1 \\$array of function array_keys expects array, iterable\\ given\\.$#" + count: 2 + path: src/lib/Persistence/Legacy/Content/Language/MaskGenerator.php + + - + message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|null given\\.$#" + count: 1 + path: src/lib/Persistence/TransformationProcessor/DefinitionBased/Parser.php + + - + message: "#^Parameter \\#1 \\$string of function substr expects string, string\\|null given\\.$#" + count: 2 + path: src/lib/Persistence/TransformationProcessor/DefinitionBased/Parser.php + + - + message: "#^Parameter \\#2 \\$subject of function preg_match expects string, string\\|null given\\.$#" + count: 1 + path: src/lib/Persistence/TransformationProcessor/DefinitionBased/Parser.php + + - + message: "#^Parameter \\#1 \\$codepoint of function chr expects int, float\\|int given\\.$#" + count: 1 + path: src/lib/Persistence/TransformationProcessor/PcreCompiler.php + + - + message: "#^Parameter \\#1 \\$hex_string of function hexdec expects string, string\\|null given\\.$#" + count: 1 + path: src/lib/Persistence/TransformationProcessor/PcreCompiler.php + + - + message: "#^Parameter \\#1 \\$string of function md5 expects string, string\\|false given\\.$#" + count: 4 + path: src/lib/Repository/Mapper/ContentMapper.php + + - + message: "#^Parameter \\#1 \\$callback of function spl_autoload_register expects \\(callable\\(string\\)\\: void\\)\\|null, ProxyManager\\\\Autoloader\\\\AutoloaderInterface given\\.$#" + count: 1 + path: src/lib/Repository/ProxyFactory/ProxyGenerator.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$arrays of function array_diff expects array, array\\|null given\\.$#" + count: 1 + path: src/lib/Repository/RoleService.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: src/lib/Repository/UserService.php + + - + message: "#^Parameter \\#1 \\$array of function array_keys expects array, string given\\.$#" + count: 3 + path: src/lib/Search/Common/FieldNameResolver.php + + - + message: "#^Parameter \\#1 \\$string of function trim expects string, bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: src/lib/Search/Legacy/Content/Gateway/CriterionHandler/Ancestor.php + + - + message: "#^Parameter \\#1 \\$string of function trim expects string, bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: src/lib/Search/Legacy/Content/Location/Gateway/CriterionHandler/Ancestor.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$arrays of function array_merge_recursive expects array, array\\|bool\\|float\\|int\\|string\\|null given\\.$#" + count: 1 + path: tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php + + - + message: "#^Parameter \\#1 \\$string of function trim expects string, string\\|null given\\.$#" + count: 1 + path: tests/bundle/Core/EventListener/BackwardCompatibleCommandListenerTest.php + + - + message: "#^Parameter \\#2 \\$offset of function substr expects int, int\\<1, max\\>\\|false given\\.$#" + count: 1 + path: tests/bundle/Core/EventListener/SiteAccessListenerTest.php + + - + message: "#^Parameter \\#3 \\$length of function substr expects int\\|null, int\\<0, max\\>\\|false given\\.$#" + count: 1 + path: tests/bundle/Core/Routing/DefaultRouterTest.php + + - + message: "#^Parameter \\#1 \\$stream of function fclose expects resource, resource\\|false given\\.$#" + count: 1 + path: tests/integration/Core/IO/BinarydataHandler/FlysystemTest.php + + - + message: "#^Parameter \\#1 \\$string1 of function strcmp expects string, bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: tests/integration/Core/Repository/BaseTest.php + + - + message: "#^Parameter \\#2 \\$string2 of function strcmp expects string, bool\\|float\\|int\\|string given\\.$#" + count: 1 + path: tests/integration/Core/Repository/BaseTest.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 4 + path: tests/integration/Core/Repository/ContentServiceAuthorizationTest.php + + - + message: "#^Parameter \\#1 \\$array of function array_keys expects array, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$array of function array_values expects array\\, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$array of function usort expects TArray of array, iterable\\ given\\.$#" + count: 2 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$string of function md5 expects string, float given\\.$#" + count: 3 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 2 + path: tests/integration/Core/Repository/ContentServiceTest.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/ContentTypeServiceTest.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/LanguageServiceMaximumSupportedLanguagesTest.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 2 + path: tests/integration/Core/Repository/LanguageServiceTest.php + + - + message: "#^Parameter \\#1 \\$array of function array_filter expects array, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/LocationServiceTest.php + + - + message: "#^Parameter \\#1 \\$array of function array_keys expects array, iterable\\ given\\.$#" + count: 3 + path: tests/integration/Core/Repository/LocationServiceTest.php + + - + message: "#^Parameter \\#1 \\$array of function array_filter expects array, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/PermissionResolverTest.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/Regression/EZP21798Test.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/RoleServiceTest.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 3 + path: tests/integration/Core/Repository/RoleServiceTest.php + + - + message: "#^Parameter \\#1 \\.\\.\\.\\$arrays of function array_merge expects array, iterable\\ given\\.$#" + count: 1 + path: tests/integration/Core/Repository/RoleServiceTest.php + + - + message: "#^Parameter \\#1 \\$class of class ReflectionProperty constructor expects object\\|string, class\\-string\\|false given\\.$#" + count: 4 + path: tests/integration/Core/Repository/SearchServiceLocationTest.php + + - + message: "#^Parameter \\#1 \\$class of class ReflectionProperty constructor expects object\\|string, class\\-string\\|false given\\.$#" + count: 4 + path: tests/integration/Core/Repository/SearchServiceTest.php + + - + message: "#^Parameter \\#1 \\$string of function md5 expects string, int\\<1, max\\> given\\.$#" + count: 1 + path: tests/integration/Core/Repository/Values/User/Limitation/BaseLimitationTest.php + + - + message: "#^Parameter \\#1 \\$string of function md5 expects string, float given\\.$#" + count: 1 + path: tests/lib/MVC/Symfony/Security/UserWrappedTest.php + + - + message: "#^Parameter \\#1 \\$callback of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{mixed, string\\} given\\.$#" + count: 3 + path: tests/lib/Persistence/Cache/AbstractCacheHandlerTest.php + + - + message: "#^Parameter \\#1 \\$callback of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{mixed, string\\} given\\.$#" + count: 3 + path: tests/lib/Persistence/Cache/AbstractInMemoryCacheHandlerTest.php + + - + message: "#^Parameter \\#1 \\$callback of function call_user_func_array expects callable\\(\\)\\: mixed, array\\{mixed, 'publish'\\} given\\.$#" + count: 1 + path: tests/lib/Persistence/Cache/ContentTypeHandlerTest.php + + - + message: "#^Parameter \\#1 \\.\\.\\.\\$arrays of function array_merge expects array, iterable given\\.$#" + count: 1 + path: tests/lib/Persistence/Legacy/Filter/BaseCriterionVisitorQueryBuilderTestCase.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$arrays of function array_merge expects array, iterable\\ given\\.$#" + count: 1 + path: tests/lib/Persistence/Legacy/Filter/BaseCriterionVisitorQueryBuilderTestCase.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, iterable\\ given\\.$#" + count: 12 + path: tests/lib/Repository/Service/Mock/UrlAliasTest.php + + - + message: "#^Trying to invoke Closure\\|null but it might not be a callable\\.$#" + count: 2 + path: tests/lib/Repository/SiteAccessAware/AbstractServiceTest.php + + - + message: "#^Parameter \\#1 \\$array of function key expects array\\|object, string given\\.$#" + count: 4 + path: tests/lib/Search/FieldNameResolverTest.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 073eaa9b24..56bb887a4f 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -5400,11 +5400,6 @@ parameters: count: 1 path: src/contracts/Persistence/User/Policy.php - - - message: "#^Method Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\ContentService\\:\\:loadContentByContentInfo\\(\\) has parameter \\$languages with no value type specified in iterable type array\\.$#" - count: 1 - path: src/contracts/Repository/ContentService.php - - message: "#^Method Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\ContentService\\:\\:validate\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#" count: 1 @@ -5415,21 +5410,6 @@ parameters: count: 1 path: src/contracts/Repository/ContentService.php - - - message: "#^PHPDoc tag @param for parameter \\$contentId with type mixed is not subtype of native type int\\.$#" - count: 1 - path: src/contracts/Repository/ContentService.php - - - - message: "#^PHPDoc tag @param has invalid value \\(\\\\Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Content\\\\Language\\|null if not set the draft is created with the initialLanguage code of the source version or if not present with the main language\\.\\)\\: Unexpected token \"if\", expected variable at offset 870$#" - count: 1 - path: src/contracts/Repository/ContentService.php - - - - message: "#^Method Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Decorator\\\\ContentServiceDecorator\\:\\:loadContentByContentInfo\\(\\) has parameter \\$languages with no value type specified in iterable type array\\.$#" - count: 1 - path: src/contracts/Repository/Decorator/ContentServiceDecorator.php - - message: "#^Method Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Decorator\\\\ContentServiceDecorator\\:\\:validate\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#" count: 1 @@ -8431,7 +8411,7 @@ parameters: path: src/lib/Base/Utils/DeprecationWarnerInterface.php - - message: "#^Parameter \\#1 \\$locations of class Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Events\\\\Content\\\\DeleteContentEvent constructor expects array, array\\|iterable\\ given\\.$#" + message: "#^Parameter \\#1 \\$locations of class Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Events\\\\Content\\\\DeleteContentEvent constructor expects array, array\\|iterable\\ given\\.$#" count: 1 path: src/lib/Event/ContentService.php @@ -18980,11 +18960,6 @@ parameters: count: 1 path: src/lib/Repository/ContentService.php - - - message: "#^Method Ibexa\\\\Core\\\\Repository\\\\ContentService\\:\\:loadContentByContentInfo\\(\\) has parameter \\$languages with no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Repository/ContentService.php - - message: "#^Method Ibexa\\\\Core\\\\Repository\\\\ContentService\\:\\:loadContentByRemoteId\\(\\) has parameter \\$languages with no value type specified in iterable type array\\.$#" count: 1 @@ -19036,7 +19011,7 @@ parameters: path: src/lib/Repository/ContentService.php - - message: "#^Parameter \\#3 \\$prioritizedLanguages of method Ibexa\\\\Core\\\\Repository\\\\Mapper\\\\ContentDomainMapper\\:\\:buildContentDomainObjectFromPersistence\\(\\) expects array\\, array\\\\|null given\\.$#" + message: "#^Parameter \\#3 \\$prioritizedLanguages of method Ibexa\\\\Core\\\\Repository\\\\Mapper\\\\ContentDomainMapper\\:\\:buildContentDomainObjectFromPersistence\\(\\) expects array\\, array\\\\|null given\\.$#" count: 1 path: src/lib/Repository/ContentService.php @@ -19985,11 +19960,6 @@ parameters: count: 1 path: src/lib/Repository/SettingService.php - - - message: "#^Method Ibexa\\\\Core\\\\Repository\\\\SiteAccessAware\\\\ContentService\\:\\:loadContentByContentInfo\\(\\) has parameter \\$languages with no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Repository/SiteAccessAware/ContentService.php - - message: "#^Method Ibexa\\\\Core\\\\Repository\\\\SiteAccessAware\\\\ContentService\\:\\:validate\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#" count: 1 @@ -26756,7 +26726,7 @@ parameters: path: tests/integration/Core/Repository/ContentServiceTest.php - - message: "#^Method Ibexa\\\\Tests\\\\Integration\\\\Core\\\\Repository\\\\ContentServiceTest\\:\\:testLoadVersions\\(\\) should return array\\ but returns iterable\\\\.$#" + message: "#^Method Ibexa\\\\Tests\\\\Integration\\\\Core\\\\Repository\\\\ContentServiceTest\\:\\:testLoadVersions\\(\\) should return array\\ but returns iterable\\\\.$#" count: 1 path: tests/integration/Core/Repository/ContentServiceTest.php @@ -53606,7 +53576,7 @@ parameters: path: tests/lib/Repository/Decorator/ContentServiceDecoratorTest.php - - message: "#^Parameter \\#1 \\$contentIds of method Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\ContentService\\:\\:loadContentInfoList\\(\\) expects array\\, array\\ given\\.$#" + message: "#^Parameter \\#1 \\$contentIds of method Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\ContentService\\:\\:loadContentInfoList\\(\\) expects array\\, array\\ given\\.$#" count: 1 path: tests/lib/Repository/Decorator/ContentServiceDecoratorTest.php diff --git a/src/contracts/Persistence/Content/Location/Handler.php b/src/contracts/Persistence/Content/Location/Handler.php index 5a0d45abbe..078783dd0b 100644 --- a/src/contracts/Persistence/Content/Location/Handler.php +++ b/src/contracts/Persistence/Content/Location/Handler.php @@ -216,6 +216,11 @@ public function create(CreateStruct $location); */ public function removeSubtree($locationId); + /** + * Removes all draft contents that have no location assigned to them under the given parent location. + */ + public function deleteChildrenDrafts(int $locationId): void; + /** * Set section on all content objects in the subtree. * Only main locations will be updated. diff --git a/src/contracts/Repository/ContentService.php b/src/contracts/Repository/ContentService.php index 02ffa68135..be8943d8a3 100644 --- a/src/contracts/Repository/ContentService.php +++ b/src/contracts/Repository/ContentService.php @@ -38,23 +38,19 @@ interface ContentService * * To load fields use loadContent * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to read the content - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - if the content with the given id does not exist - * - * @param int $contentId - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to read the content. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if the content with the given id doesn't exist. */ public function loadContentInfo(int $contentId): ContentInfo; /** * Bulk-load ContentInfo items by id's. * - * Note: It does not throw exceptions on load, just skips erroneous (NotFound or Unauthorized) ContentInfo items. + * Note: It doesn't throw exceptions on load, just skips erroneous (NotFound or Unauthorized) ContentInfo items. * - * @param int[] $contentIds + * @param array $contentIds * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo[] list of ContentInfo with Content Ids as keys + * @return array List of ContentInfo with content ids as keys */ public function loadContentInfoList(array $contentIds): iterable; @@ -63,49 +59,39 @@ public function loadContentInfoList(array $contentIds): iterable; * * To load fields use loadContent * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to read the content - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - if the content with the given remote id does not exist - * - * @param string $remoteId - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to read the content. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if the content with the given remote id doesn't exist. */ public function loadContentInfoByRemoteId(string $remoteId): ContentInfo; /** * Loads a version info of the given content object. * - * If no version number is given, the method returns the current version + * If no version number is given, the method returns the current version. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - if the version with the given number does not exist - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if the version with the given number doesn't exist. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo * @param int|null $versionNo the version number. If not given the current version is returned. - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo */ public function loadVersionInfo(ContentInfo $contentInfo, ?int $versionNo = null): VersionInfo; /** * Loads a version info of the given content object id. * - * If no version number is given, the method returns the current version + * If no version number is given, the method returns the current version. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - if the version with the given number does not exist - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if the version with the given number doesn't exist. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version. * - * @param int $contentId * @param int|null $versionNo the version number. If not given the current version is returned. - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo */ public function loadVersionInfoById(int $contentId, ?int $versionNo = null): VersionInfo; /** * Bulk-load VersionInfo items by the list of ContentInfo Value Objects. * - * @param array<\Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo> $contentInfoList + * @param array $contentInfoList * * @return array List of VersionInfo items with Content Ids as keys * @@ -120,30 +106,24 @@ public function loadVersionInfoListByContentInfo(array $contentInfoList): array; * * If no version number is given, the method returns the current version * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - if version with the given number does not exist - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if version with the given number doesn't exist. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo - * @param array $languages A language priority, filters returned fields and is used as prioritized language code on + * @param array $languages A language priority, filters returned fields and is used as prioritized language code on * returned value object. If not given all languages are returned. - * @param int|null $versionNo the version number. If not given the current version is returned from $contentInfo - * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content + * @param int|null $versionNo The version number. If not given the current version is returned from $contentInfo. + * @param bool $useAlwaysAvailable Add Main language to $languages if true (default) and if {@see ContentInfo::$alwaysAvailable} is true. */ public function loadContentByContentInfo(ContentInfo $contentInfo, array $languages = null, ?int $versionNo = null, bool $useAlwaysAvailable = true): Content; /** * Loads content in the version given by version info. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to load this version. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo * @param string[] $languages A language priority, filters returned fields and is used as prioritized language code on * returned value object. If not given all languages are returned. - * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content + * @param bool $useAlwaysAvailable Add Main language to $languages if true (default) and if {@see ContentInfo::$alwaysAvailable} is true. */ public function loadContentByVersionInfo(VersionInfo $versionInfo, array $languages = null, bool $useAlwaysAvailable = true): Content; @@ -152,16 +132,15 @@ public function loadContentByVersionInfo(VersionInfo $versionInfo, array $langua * * If no version number is given, the method returns the current version * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if the content or version with the given id and languages does not exist - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException If the user has no access to read content and in case of un-published content: read versions + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if the content or version with the given id and languages doesn't exist. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user lacks: + * - `content/read` permission for published content, or + * - `content/read` and `content/versionread` permissions for draft content. * - * @param mixed $contentId - * @param string[] $languages A language priority, filters returned fields and is used as prioritized language code on + * @param array $languages A language priority, filters returned fields and is used as prioritized language code on * returned value object. If not given all languages are returned. - * @param int|null $versionNo the version number. If not given the current version is returned - * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content + * @param int|null $versionNo The version number. If not given the current version is returned. + * @param bool $useAlwaysAvailable Add Main language to $languages if true (default) and if {@see ContentInfo::$alwaysAvailable} is true. */ public function loadContent(int $contentId, array $languages = null, ?int $versionNo = null, bool $useAlwaysAvailable = true): Content; @@ -170,33 +149,32 @@ public function loadContent(int $contentId, array $languages = null, ?int $versi * * If no version is given, the method returns the current version * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException - if the content or version with the given remote id does not exist - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException If the user has no access to read content and in case of un-published content: read versions + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if the content or version with the given remote id doesn't exist. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user lacks: + * - `content/read` permission for published content, or + * - `content/read` and `content/versionread` permissions for draft content. * - * @param string $remoteId * @param string[] $languages A language priority, filters returned fields and is used as prioritized language code on * returned value object. If not given all languages are returned. * @param int|null $versionNo the version number. If not given the current version is returned - * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content + * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if {@see ContentInfo::$alwaysAvailable} is true. */ public function loadContentByRemoteId(string $remoteId, array $languages = null, ?int $versionNo = null, bool $useAlwaysAvailable = true): Content; /** * Bulk-load Content items by the list of ContentInfo Value Objects. * - * Note: it does not throw exceptions on load, just ignores erroneous Content item. + * Note: it doesn't throw exceptions on load, just ignores erroneous Content item. * Moreover, since the method works on pre-loaded ContentInfo list, it is assumed that user is * allowed to access every Content on the list. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo[] $contentInfoList - * @param string[] $languages A language priority, filters returned fields and is used as prioritized language code on + * @param array $contentInfoList + * @param array $languages A language priority, filters returned fields and is used as prioritized language code on * returned value object. If not given all languages are returned. - * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if alwaysAvailable is true, + * @param bool $useAlwaysAvailable Add Main language to \$languages if true (default) and if {@see ContentInfo::$alwaysAvailable} is true, * unless all languages have been asked for. * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content[] list of Content items with Content Ids as keys + * @return array List of Content items with Content Ids as keys */ public function loadContentListByContentInfo(array $contentInfoList, array $languages = [], bool $useAlwaysAvailable = true): iterable; @@ -205,49 +183,43 @@ public function loadContentListByContentInfo(array $contentInfoList, array $lang * * If a different userId is given in $contentCreateStruct it is assigned to the given user * but this required special rights for the authenticated user - * (this is useful for content staging where the transfer process does not + * (this is useful for content staging where the transfer process doesn't * have to authenticate with the user which created the content object in the source server). * The user has to publish the draft if it should be visible. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to create the content in the given location + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to create the content in the given location. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if there is a provided remote ID which exists in the system or multiple Locations * are under the same parent or if the a field value is not accepted by the field type - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException if a field in the $contentCreateStruct is not valid - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException if a required field is missing or is set to an empty value + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException if a field in the $contentCreateStruct is not valid. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException if a required field is missing or is set to an empty value. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentCreateStruct $contentCreateStruct - * @param \Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct[] $locationCreateStructs an array of {@see \Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct} for each location parent under which a location should be created for the content + * @param \Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct[] $locationCreateStructs An array of {@see \Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct} for each location parent under which a location should be created for the content. * While optional, it's highly recommended to use Locations for content as a lot of features in the system is usually tied to the tree structure (including default Role policies). * @param string[]|null $fieldIdentifiersToValidate List of field identifiers for partial validation or null * for case of full validation. Empty identifiers array is equal to no validation. * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content - the newly created content draft + * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content The newly created content draft. */ public function createContent(ContentCreateStruct $contentCreateStruct, array $locationCreateStructs = [], ?array $fieldIdentifiersToValidate = null): Content; /** * Updates the metadata. * - * See {@see ContentMetadataUpdateStruct} of a content object - to update fields use updateContent + * To update fields, use {@see ContentService::updateContent()}. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to update the content meta data - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if the remoteId in $contentMetadataUpdateStruct is set but already exists + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to update the content metadata. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if the remoteId in $contentMetadataUpdateStruct is set but already exists. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentMetadataUpdateStruct $contentMetadataUpdateStruct - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content the content with the updated attributes + * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content The content with the updated attributes. */ public function updateContentMetadata(ContentInfo $contentInfo, ContentMetadataUpdateStruct $contentMetadataUpdateStruct): Content; /** * Deletes a content object including all its versions and locations including their subtrees. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to delete the content (in one of the locations of the given content object) - * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to delete the content (in one of the locations of the given content object). * - * @return int[] Affected Location Id's (List of Locations of the Content that was deleted) + * @return array Affected Location IDs (List of Location IDs of the Content that was deleted). */ public function deleteContent(ContentInfo $contentInfo): iterable; @@ -258,14 +230,12 @@ public function deleteContent(ContentInfo $contentInfo): iterable; * 4.x: The draft is created with the initialLanguage code of the source version or if not present with the main language. * It can be changed on updating the version. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the current-user is not allowed to create the draft + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the current user is not allowed to create the draft. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo - * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo|null $versionInfo - * @param \Ibexa\Contracts\Core\Repository\Values\User\User|null $creator Used as creator of the draft if given - otherwise uses current-user - * @param \Ibexa\Contracts\Core\Repository\Values\Content\Language|null if not set the draft is created with the initialLanguage code of the source version or if not present with the main language. + * @param \Ibexa\Contracts\Core\Repository\Values\User\User|null $creator Used as creator of the draft if given; otherwise uses current user. + * @param \Ibexa\Contracts\Core\Repository\Values\Content\Language|null $language If not set the draft is created with the initialLanguage code of the source version or if not present with the main language. * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content - the newly created content draft + * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content The newly created content draft. */ public function createContentDraft( ContentInfo $contentInfo, @@ -277,11 +247,11 @@ public function createContentDraft( /** * Counts drafts for a user. * - * If no user is given the number of drafts for the authenticated user are returned + * If no user is given the number of drafts for the authenticated user are returned. * - * @param \Ibexa\Contracts\Core\Repository\Values\User\User $user The user to load drafts for, if defined, otherwise drafts for current-user + * @param \Ibexa\Contracts\Core\Repository\Values\User\User $user The user to load drafts for, if defined, otherwise drafts for current user. * - * @return int The number of drafts ({@see VersionInfo}) owned by the given user + * @return int The number of drafts ({@see VersionInfo}) owned by the given user. * * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException */ @@ -290,33 +260,27 @@ public function countContentDrafts(?User $user = null): int; /** * Loads drafts for a user when content is not in the trash. The list is sorted by modification date. * - * If no user is given the drafts for the authenticated user are returned + * If no user is given the drafts for the authenticated user are returned. * * @since 7.5.5 * - * @param \Ibexa\Contracts\Core\Repository\Values\User\User|null $user The user to load drafts for, if defined, otherwise drafts for current-user - * @param int $offset - * @param int $limit - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\ContentDraftList + * @param \Ibexa\Contracts\Core\Repository\Values\User\User|null $user The user to load drafts for, if defined; otherwise drafts for current user. */ public function loadContentDraftList(?User $user = null, int $offset = 0, int $limit = -1): ContentDraftList; /** * Updates the fields of a draft. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to update this version - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException if a field in the $contentUpdateStruct is not valid - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException if a required field is set to an empty value - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if a field value is not accepted by the field type + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to update this version. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentFieldValidationException if a field in the $contentUpdateStruct is not valid. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\ContentValidationException if a required field is set to an empty value. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if a field value is not accepted by the field type. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentUpdateStruct $contentUpdateStruct - * @param string[]|null $fieldIdentifiersToValidate List of field identifiers for partial validation or null + * @param array|null $fieldIdentifiersToValidate List of field identifiers for partial validation or null * for case of full validation. Empty identifiers array is equal to no validation. * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content the content draft with the updated fields + * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content The content draft with the updated fields. */ public function updateContent(VersionInfo $versionInfo, ContentUpdateStruct $contentUpdateStruct, ?array $fieldIdentifiersToValidate = null): Content; @@ -328,18 +292,15 @@ public function updateContent(VersionInfo $versionInfo, ContentUpdateStruct $con * * @todo Introduce null|int ContentType->versionArchiveLimit to be able to let admins override this per type. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to publish this version - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to publish this version. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo - * @param string[] $translations List of language codes of translations which will be included + * @param array $translations List of language codes of translations which will be included * in a published version. - * By default all translations from the current version will be published. - * If the list is provided but does not cover all currently published translations, + * By default, all translations from the current version will be published. + * If the list is provided but doesn't cover all currently published translations, * the missing ones will be copied from the currently published version, * overriding those in the current version. - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content */ public function publishVersion(VersionInfo $versionInfo, array $translations = Language::ALL): Content; @@ -347,23 +308,18 @@ public function publishVersion(VersionInfo $versionInfo, array $translations = L * Removes the given version. * * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is in - * published state or is a last version of Content in non draft state - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to remove this version - * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo + * published state or is a last version of Content in non-draft state. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to remove this version. */ public function deleteVersion(VersionInfo $versionInfo): void; /** * Loads all versions for the given content. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to list versions - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if the given status is invalid - * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo - * @param int|null $status + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to list versions. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if the given status is invalid. * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo[] an array of {@see \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo} sorted by creation date + * @return array An array of {@see \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo} sorted by creation date. */ public function loadVersions(ContentInfo $contentInfo, ?int $status = null): iterable; @@ -371,13 +327,9 @@ public function loadVersions(ContentInfo $contentInfo, ?int $status = null): ite * Copies the content to a new location. If no version is given, * all versions are copied, otherwise only the given version. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to copy the content to the given location + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to copy the content to the given location. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo - * @param \Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct $destinationLocationCreateStruct the target location where the content is copied to - * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content + * @param \Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct $destinationLocationCreateStruct The target location where the content is copied to. */ public function copyContent(ContentInfo $contentInfo, LocationCreateStruct $destinationLocationCreateStruct, ?VersionInfo $versionInfo = null): Content; @@ -409,9 +361,7 @@ public function countRelations(VersionInfo $versionInfo, ?RelationType $type = n /** * Counts all incoming relations for the given content object. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo - * - * @return int The number of reverse relations ({@see \Ibexa\Contracts\Core\Repository\Values\Content\Relation}) + * @return int The number of reverse relations ({@see Relation}). */ public function countReverseRelations(ContentInfo $contentInfo, ?RelationType $type = null): int; @@ -420,9 +370,9 @@ public function countReverseRelations(ContentInfo $contentInfo, ?RelationType $t * * The relations come only from published versions of the source content objects * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to read this version + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to read this version. * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Relation[] + * @return array */ public function loadReverseRelations(ContentInfo $contentInfo, ?RelationType $type = null): iterable; @@ -430,8 +380,7 @@ public function loadReverseRelations(ContentInfo $contentInfo, ?RelationType $ty * Loads all incoming relations for a content object. * * The relations come only from published versions of the source content objects. - * If the user is not allowed to read specific version then UnauthorizedRelationListItem is returned - * {@see \Ibexa\Contracts\Core\Repository\Values\Content\RelationList\Item\UnauthorizedRelationListItem} + * If the user is not allowed to read specific version then {@see \Ibexa\Contracts\Core\Repository\Values\Content\RelationList\Item\UnauthorizedRelationListItem} is returned */ public function loadReverseRelationList( ContentInfo $contentInfo, @@ -441,30 +390,31 @@ public function loadReverseRelationList( ): RelationList; /** - * Adds a relation of type common. + * Adds a common relation. * * The source of the relation is the content and version - * referenced by $versionInfo. + * referenced by $sourceVersion. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to edit this version - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed to edit this version. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $sourceVersion - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $destinationContent the destination of the relation + * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $sourceVersion The source content's version in relation with the destination. + * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $destinationContent The destination of the relation. * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Relation the newly created relation + * @return \Ibexa\Contracts\Core\Repository\Values\Content\Relation The newly created relation. + * + * @see Relation::COMMON */ public function addRelation(VersionInfo $sourceVersion, ContentInfo $destinationContent): Relation; /** - * Removes a relation of type COMMON from a draft. + * Removes a common relation from a draft. * - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed edit this version - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if there is no relation of type COMMON for the given destination + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed edit this version. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the version is not a draft. + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if there is no relation of type {@see Relation::COMMON} for the given destination. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $sourceVersion - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $destinationContent + * @see Relation::COMMON */ public function deleteRelation(VersionInfo $sourceVersion, ContentInfo $destinationContent): void; @@ -477,12 +427,9 @@ public function deleteRelation(VersionInfo $sourceVersion, ContentInfo $destinat * is the Main Translation of a Content Item. * @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException if the user is not allowed * to delete the content (in one of the locations of the given Content Item). - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if languageCode argument + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if $languageCode argument * is invalid for the given content. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo - * @param string $languageCode - * * @since 6.13 */ public function deleteTranslation(ContentInfo $contentInfo, string $languageCode): void; @@ -490,7 +437,7 @@ public function deleteTranslation(ContentInfo $contentInfo, string $languageCode /** * Delete specified Translation from a Content Draft. * - * When using together with ContentService::publishVersion() method, make sure to not provide deleted translation + * When using together with {@see ContentService::publishVersion()} method, make sure to not provide deleted translation * in translations array, as it is going to be copied again from published version. * * @throws \Ibexa\Contracts\Core\Repository\Exceptions\BadStateException if the specified Translation @@ -499,12 +446,12 @@ public function deleteTranslation(ContentInfo $contentInfo, string $languageCode * to edit the Content (in one of the locations of the given Content Object). * @throws \Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException if languageCode argument * is invalid for the given Draft. - * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if specified Version was not found + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException if specified Version was not found. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo Content Version Draft - * @param string $languageCode Language code of the Translation to be removed + * @param \Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo $versionInfo Content Version Draft. + * @param string $languageCode Language code of the Translation to be removed. * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content Content Draft w/o the specified Translation + * @return \Ibexa\Contracts\Core\Repository\Values\Content\Content Content Draft without the specified Translation. * * @since 6.12 */ @@ -512,49 +459,38 @@ public function deleteTranslationFromDraft(VersionInfo $versionInfo, string $lan /** * Hides Content by making all the Locations appear hidden. - * It does not persist hidden state on Location object itself. * - * Content hidden by this API can be revealed by revealContent API. + * It doesn't persist hidden state on Location object itself. * - * @see ContentService::revealContent() + * Content hidden by this API can be revealed by {@see ContentService::revealContent()} API. * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo + * @see ContentService::revealContent() */ public function hideContent(ContentInfo $contentInfo): void; /** * Reveals Content hidden by hideContent API. + * * Locations which were hidden before hiding Content will remain hidden. * * @see ContentService::hideContent() - * - * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo */ public function revealContent(ContentInfo $contentInfo): void; /** * Instantiates a new content create struct object. * - * alwaysAvailable is set to the ContentType's defaultAlwaysAvailable - * - * @param \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType $contentType - * @param string $mainLanguageCode - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\ContentCreateStruct + * {@see ContentCreateStruct::$alwaysAvailable} is set to the {@see ContentType::$defaultAlwaysAvailable}. */ public function newContentCreateStruct(ContentType $contentType, string $mainLanguageCode): ContentCreateStruct; /** * Instantiates a new content meta data update struct. - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\ContentMetadataUpdateStruct */ public function newContentMetadataUpdateStruct(): ContentMetadataUpdateStruct; /** * Instantiates a new content update struct. - * - * @return \Ibexa\Contracts\Core\Repository\Values\Content\ContentUpdateStruct */ public function newContentUpdateStruct(): ContentUpdateStruct; @@ -562,7 +498,7 @@ public function newContentUpdateStruct(): ContentUpdateStruct; * Validates given content related ValueObject returning field errors structure as a result. * * @param array $context Additional context parameters to be used by validators. - * @param string[]|null $fieldIdentifiersToValidate List of field identifiers for partial validation or null + * @param array|null $fieldIdentifiersToValidate List of field identifiers for partial validation, or null * for case of full validation. Empty identifiers array is equal to no validation. * * @return array Validation errors grouped by field definition and language code, in format: @@ -573,18 +509,20 @@ public function newContentUpdateStruct(): ContentUpdateStruct; public function validate(ValueObject $object, array $context, ?array $fieldIdentifiersToValidate = null): array; /** - * Fetch Content items from the Repository filtered by the given conditions. + * Fetches Content items from the Repository filtered by the given conditions. * - * @param string[] $languages a list of language codes to be added as additional constraints. + * @param array $languages A list of language codes to be added as additional constraints. * If skipped, by default, unless SiteAccessAware layer has been disabled, languages set * for a SiteAccess in a current context will be used. */ public function find(Filter $filter, ?array $languages = null): ContentList; /** - * Count total number of items returned by {@see ContentService::find()} method. + * Gets the total number of fetchable Content items. + * + * Counts total number of items returned by {@see ContentService::find()} with the same parameters. * - * @param string[] $languages a list of language codes to be added as additional constraints. + * @param array $languages A list of language codes to be added as additional constraints. * If skipped, by default, unless SiteAccessAware layer has been disabled, languages set * for a SiteAccess in a current context will be used. */ diff --git a/src/contracts/Test/IbexaKernelTestTrait.php b/src/contracts/Test/IbexaKernelTestTrait.php index fb36233104..309db68f89 100644 --- a/src/contracts/Test/IbexaKernelTestTrait.php +++ b/src/contracts/Test/IbexaKernelTestTrait.php @@ -19,6 +19,7 @@ use Ibexa\Contracts\Core\Repository\RoleService; use Ibexa\Contracts\Core\Repository\SearchService; use Ibexa\Contracts\Core\Repository\SectionService; +use Ibexa\Contracts\Core\Repository\TrashService; use Ibexa\Contracts\Core\Repository\URLAliasService; use Ibexa\Contracts\Core\Repository\UserService; use Ibexa\Contracts\Core\Test\Persistence\Fixture\FixtureImporter; @@ -170,6 +171,11 @@ protected static function getUrlAliasService(): URLAliasService return self::getServiceByClassName(URLAliasService::class); } + protected static function getTrashService(): TrashService + { + return self::getServiceByClassName(TrashService::class); + } + protected static function setAnonymousUser(): void { $anonymousUserId = 10; diff --git a/src/contracts/Test/IbexaTestKernel.php b/src/contracts/Test/IbexaTestKernel.php index 05498302ba..4274d26a9f 100644 --- a/src/contracts/Test/IbexaTestKernel.php +++ b/src/contracts/Test/IbexaTestKernel.php @@ -92,6 +92,7 @@ class IbexaTestKernel extends Kernel implements IbexaTestKernelInterface Repository\TokenService::class, Repository\URLAliasService::class, Repository\BookmarkService::class, + Repository\TrashService::class, Handler::class, ]; diff --git a/src/lib/Persistence/Cache/LocationHandler.php b/src/lib/Persistence/Cache/LocationHandler.php index aaf4ba161e..78a4be91db 100644 --- a/src/lib/Persistence/Cache/LocationHandler.php +++ b/src/lib/Persistence/Cache/LocationHandler.php @@ -416,6 +416,20 @@ public function removeSubtree($locationId) return $return; } + public function deleteChildrenDrafts(int $locationId): void + { + $this->logger->logCall(__METHOD__, ['location' => $locationId]); + + $this->persistenceHandler->locationHandler()->deleteChildrenDrafts($locationId); + + $this->cache->invalidateTags([ + $this->cacheIdentifierGenerator->generateTag( + self::LOCATION_PATH_IDENTIFIER, + [$locationId], + ), + ]); + } + /** * {@inheritdoc} */ diff --git a/src/lib/Persistence/Legacy/Content/Handler.php b/src/lib/Persistence/Legacy/Content/Handler.php index 1a8ef9d195..6672a4fbcc 100644 --- a/src/lib/Persistence/Legacy/Content/Handler.php +++ b/src/lib/Persistence/Legacy/Content/Handler.php @@ -653,6 +653,7 @@ public function deleteContent($contentId) $this->removeRawContent($contentId); } else { foreach ($contentLocations as $locationId) { + $this->treeHandler->deleteChildrenDrafts($locationId); $this->treeHandler->removeSubtree($locationId); } } diff --git a/src/lib/Persistence/Legacy/Content/Location/Gateway.php b/src/lib/Persistence/Legacy/Content/Location/Gateway.php index 75da7c235d..84a4e021d1 100644 --- a/src/lib/Persistence/Legacy/Content/Location/Gateway.php +++ b/src/lib/Persistence/Legacy/Content/Location/Gateway.php @@ -112,6 +112,13 @@ abstract public function loadParentLocationsDataForDraftContent(int $contentId): */ abstract public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array; + /** + * Finds draft contents created under the given parent location. + * + * @return array + */ + abstract public function getSubtreeChildrenDraftContentIds(int $sourceId): array; + abstract public function getSubtreeSize(string $path): int; /** diff --git a/src/lib/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php b/src/lib/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php index 1387db0560..592c4488d1 100644 --- a/src/lib/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php +++ b/src/lib/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php @@ -239,6 +239,29 @@ public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array : $results; } + /** + * @return array + * + * @throws \Doctrine\DBAL\Exception + * @throws \Doctrine\DBAL\Driver\Exception + */ + public function getSubtreeChildrenDraftContentIds(int $sourceId): array + { + $query = $this->connection->createQueryBuilder(); + $query + ->select('contentobject_id') + ->from('eznode_assignment', 'n') + ->innerJoin('n', 'ezcontentobject', 'c', 'n.contentobject_id = c.id') + ->andWhere('n.parent_node = :parentNode') + ->andWhere('c.status = :status') + ->setParameter(':parentNode', $sourceId, ParameterType::INTEGER) + ->setParameter(':status', ContentInfo::STATUS_DRAFT, ParameterType::INTEGER); + + $statement = $query->execute(); + + return $statement->fetchFirstColumn(); + } + public function getSubtreeSize(string $path): int { $query = $this->createNodeQueryBuilder([$this->dbPlatform->getCountExpression('node_id')]); diff --git a/src/lib/Persistence/Legacy/Content/Location/Gateway/ExceptionConversion.php b/src/lib/Persistence/Legacy/Content/Location/Gateway/ExceptionConversion.php index 267fd9e9f5..3eb53f2f5e 100644 --- a/src/lib/Persistence/Legacy/Content/Location/Gateway/ExceptionConversion.php +++ b/src/lib/Persistence/Legacy/Content/Location/Gateway/ExceptionConversion.php @@ -107,6 +107,18 @@ public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array } } + /** + * @return array + */ + public function getSubtreeChildrenDraftContentIds(int $sourceId): array + { + try { + return $this->innerGateway->getSubtreeChildrenDraftContentIds($sourceId); + } catch (PDOException $e) { + throw DatabaseException::wrap($e); + } + } + public function getSubtreeSize(string $path): int { try { diff --git a/src/lib/Persistence/Legacy/Content/Location/Handler.php b/src/lib/Persistence/Legacy/Content/Location/Handler.php index 6fe93eae46..dfcb28fac3 100644 --- a/src/lib/Persistence/Legacy/Content/Location/Handler.php +++ b/src/lib/Persistence/Legacy/Content/Location/Handler.php @@ -547,6 +547,11 @@ public function removeSubtree($locationId) $this->treeHandler->removeSubtree($locationId); } + public function deleteChildrenDrafts(int $locationId): void + { + $this->treeHandler->deleteChildrenDrafts($locationId); + } + /** * Set section on all content objects in the subtree. * diff --git a/src/lib/Persistence/Legacy/Content/TreeHandler.php b/src/lib/Persistence/Legacy/Content/TreeHandler.php index e48f433fe6..6b375e376f 100644 --- a/src/lib/Persistence/Legacy/Content/TreeHandler.php +++ b/src/lib/Persistence/Legacy/Content/TreeHandler.php @@ -216,6 +216,26 @@ public function removeSubtree($locationId) $this->locationGateway->deleteNodeAssignment($contentId); } + /** + * Removes draft contents assigned to the given parent location and its descendant locations. + * + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException + */ + public function deleteChildrenDrafts(int $locationId): void + { + $subLocations = $this->locationGateway->getChildren($locationId); + foreach ($subLocations as $subLocation) { + $this->deleteChildrenDrafts($subLocation['node_id']); + } + + // Fetch child draft content ids + $subtreeChildrenDraftIds = $this->locationGateway->getSubtreeChildrenDraftContentIds($locationId); + + foreach ($subtreeChildrenDraftIds as $contentId) { + $this->removeRawContent($contentId); + } + } + /** * Set section on all content objects in the subtree. * diff --git a/src/lib/Repository/TrashService.php b/src/lib/Repository/TrashService.php index 02ce266f3f..92291e5ef9 100644 --- a/src/lib/Repository/TrashService.php +++ b/src/lib/Repository/TrashService.php @@ -146,6 +146,7 @@ public function trash(Location $location): ?APITrashItem $this->repository->beginTransaction(); try { + $this->persistenceHandler->locationHandler()->deleteChildrenDrafts($location->id); $spiTrashItem = $this->persistenceHandler->trashHandler()->trashSubtree($location->id); $this->persistenceHandler->urlAliasHandler()->locationDeleted($location->id); $this->repository->commit(); diff --git a/tests/integration/Core/Repository/ContentService/DeleteContentTest.php b/tests/integration/Core/Repository/ContentService/DeleteContentTest.php new file mode 100644 index 0000000000..e1dd1faf7a --- /dev/null +++ b/tests/integration/Core/Repository/ContentService/DeleteContentTest.php @@ -0,0 +1,111 @@ +prepareContentStructure(); + + $contentService->deleteContent($folder->getContentInfo()); + + $contentInfos = $contentService->loadContentInfoList([ + $draft1->getId(), + $draft2->getId(), + $draft3->getId(), + $draftSecondDepth->getId(), + ]); + + self::assertEmpty($contentInfos); + } + + /** + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\Exception + */ + public function testTrashLocationDeletesChildrenDrafts(): void + { + $trashService = self::getTrashService(); + $contentService = self::getContentService(); + + [$folder, $draft1, $draft2, $draft3, $draftSecondDepth] = $this->prepareContentStructure(); + + $folderMainLocationId = $folder->getVersionInfo()->getContentInfo()->getMainLocationId(); + Assert::assertIsNumeric($folderMainLocationId); + + $locationToTrash = self::getLocationService()->loadLocation($folderMainLocationId); + + $trashService->trash($locationToTrash); + + $contentInfos = $contentService->loadContentInfoList([ + $draft1->getId(), + $draft2->getId(), + $draft3->getId(), + $draftSecondDepth->getId(), + ]); + + self::assertEmpty($contentInfos); + } + + /** + * @return array + */ + private function prepareContentStructure(): array + { + $folder = $this->createFolder(['eng-GB' => 'Folder'], 2); + $folderMainLocationId = $folder->getVersionInfo()->getContentInfo()->getMainLocationId(); + Assert::assertIsNumeric($folderMainLocationId); + + $childFolder = $this->createFolder( + ['eng-GB' => 'Child folder'], + $folderMainLocationId, + ); + $childFolderMainLocationId = $childFolder->getVersionInfo()->getContentInfo()->getMainLocationId(); + Assert::assertIsNumeric($childFolderMainLocationId); + + $secondDepthChildFolder = $this->createFolder( + ['eng-GB' => 'Second depth folder'], + $childFolderMainLocationId, + ); + $secondDepthChildFolderLocationId = $secondDepthChildFolder + ->getVersionInfo() + ->getContentInfo() + ->getMainLocationId() + ; + Assert::assertIsNumeric($secondDepthChildFolderLocationId); + + $draft1 = $this->createFolderDraft(['eng-GB' => 'Folder draft 1'], $folderMainLocationId); + $draft2 = $this->createFolderDraft(['eng-GB' => 'Folder draft 2'], $childFolderMainLocationId); + $draft3 = $this->createFolderDraft(['eng-GB' => 'Folder draft 3'], $childFolderMainLocationId); + $draftSecondDepth = $this->createFolderDraft( + ['eng-GB' => 'Folder draft 4'], + $secondDepthChildFolderLocationId, + ); + + return [ + $folder, + $draft1, + $draft2, + $draft3, + $draftSecondDepth, + ]; + } +} diff --git a/tests/lib/Persistence/Cache/LocationHandlerTest.php b/tests/lib/Persistence/Cache/LocationHandlerTest.php index 918a49166a..87a68a7836 100644 --- a/tests/lib/Persistence/Cache/LocationHandlerTest.php +++ b/tests/lib/Persistence/Cache/LocationHandlerTest.php @@ -68,6 +68,7 @@ public function providerForUnCachedMethods(): array ['c-4', 'ragl-4'], ], ['removeSubtree', [12], [['location_path', [12], false]], null, ['lp-12']], + ['deleteChildrenDrafts', [12], [['location_path', [12], false]], null, ['lp-12']], ['setSectionForSubtree', [12, 2], [['location_path', [12], false]], null, ['lp-12']], ['changeMainLocation', [4, 12], [['content', [4], false]], null, ['c-4']], ['countLocationsByContent', [4]], diff --git a/tests/lib/Persistence/Legacy/Content/LocationHandlerTest.php b/tests/lib/Persistence/Legacy/Content/LocationHandlerTest.php index 860ea9fcf6..50dd1c4eca 100644 --- a/tests/lib/Persistence/Legacy/Content/LocationHandlerTest.php +++ b/tests/lib/Persistence/Legacy/Content/LocationHandlerTest.php @@ -454,6 +454,18 @@ public function testRemoveSubtree() $handler->removeSubtree(42); } + public function testDeleteChildrenDrafts(): void + { + $handler = $this->getLocationHandler(); + + $this->treeHandler + ->expects(self::once()) + ->method('deleteChildrenDrafts') + ->with(42); + + $handler->deleteChildrenDrafts(42); + } + /** * Test for the copySubtree() method. */ diff --git a/tests/lib/Persistence/Legacy/Content/TreeHandlerTest.php b/tests/lib/Persistence/Legacy/Content/TreeHandlerTest.php index 5e5adc6b9e..f1d185bf1a 100644 --- a/tests/lib/Persistence/Legacy/Content/TreeHandlerTest.php +++ b/tests/lib/Persistence/Legacy/Content/TreeHandlerTest.php @@ -401,6 +401,61 @@ public function testLoadLocation() self::assertTrue($location instanceof Location); } + public function testDeleteChildrenDraftsRecursive(): void + { + $locationGatewayMock = $this->getLocationGatewayMock(); + $contentGatewayMock = $this->getContentGatewayMock(); + $contentMapperMock = $this->getContentMapperMock(); + + $locationGatewayMock + ->expects(self::exactly(3)) + ->method('getChildren') + ->willReturnMap([ + [42, [ + ['node_id' => 201], + ['node_id' => 202], + ]], + [201, []], + [202, []], + ]); + + $locationGatewayMock + ->expects(self::exactly(3)) + ->method('getSubtreeChildrenDraftContentIds') + ->willReturnMap([ + [201, [101]], + [202, [102]], + [42, [99]], + ]); + + $contentGatewayMock + ->expects(self::exactly(3)) + ->method('loadContentInfo') + ->willReturnMap([ + [101, ['main_node_id' => 201]], + [102, ['main_node_id' => 202]], + [99, ['main_node_id' => 42]], + ]); + + $contentMapperMock + ->expects(self::exactly(3)) + ->method('extractContentInfoFromRow') + ->willReturnCallback(static function (array $row): ContentInfo { + return new ContentInfo(['mainLocationId' => $row['main_node_id']]); + }); + + $contentGatewayMock + ->expects(self::exactly(3)) + ->method('deleteContent') + ->willReturnCallback(static function (int $contentId): void { + self::assertContains($contentId, [99, 101, 102]); + }); + + $treeHandler = $this->getTreeHandler(); + + $treeHandler->deleteChildrenDrafts(42); + } + /** @var \PHPUnit\Framework\MockObject\MockObject|\Ibexa\Core\Persistence\Legacy\Content\Location\Gateway */ protected $locationGatewayMock;