Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EZP-31569: Implemented Repository filtering #54

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use eZ\Publish\Core\Repository\Helper\RelationProcessor;
use eZ\Publish\Core\Repository\Mapper;
use eZ\Publish\Core\Search\Common\BackgroundIndexer;
use eZ\Publish\SPI\Persistence\Filter\Content\Handler as ContentFilteringHandler;
use eZ\Publish\SPI\Persistence\Filter\Location\Handler as LocationFilteringHandler;
use eZ\Publish\SPI\Persistence\Handler as PersistenceHandler;
use eZ\Publish\SPI\Repository\Strategy\ContentThumbnail\ThumbnailStrategy;
use eZ\Publish\SPI\Repository\Validator\ContentValidator;
Expand Down Expand Up @@ -84,7 +86,9 @@ public function buildRepository(
Mapper\ContentMapper $contentMapper,
ContentValidator $contentValidator,
LimitationService $limitationService,
PermissionService $permissionService
PermissionService $permissionService,
ContentFilteringHandler $contentFilteringHandler,
LocationFilteringHandler $locationFilteringHandler
): Repository {
$config = $this->container->get('ezpublish.api.repository_configuration_provider')->getRepositoryConfig();

Expand All @@ -105,6 +109,8 @@ public function buildRepository(
$limitationService,
$this->languageResolver,
$permissionService,
$contentFilteringHandler,
$locationFilteringHandler,
[
'role' => [
'policyMap' => $this->policyMap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use eZ\Publish\Core\MVC\Symfony\MVCEvents;
use eZ\Publish\Core\QueryType\QueryType;
use eZ\Publish\SPI\MVC\EventSubscriber\ConfigScopeChangeSubscriber;
use eZ\Publish\SPI\Repository\Values\Filter\CriterionQueryBuilder as FilteringCriterionQueryBuilder;
use eZ\Publish\SPI\Repository\Values\Filter\SortClauseQueryBuilder as FilteringSortClauseQueryBuilder;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\Filesystem\Filesystem;
Expand Down Expand Up @@ -141,18 +143,7 @@ public function load(array $configs, ContainerBuilder $container)

$this->buildPolicyMap($container);

$container->registerForAutoconfiguration(QueryType::class)
->addTag(QueryTypePass::QUERY_TYPE_SERVICE_TAG);

$container->registerForAutoconfiguration(ConfigScopeChangeSubscriber::class)
->addTag(
'kernel.event_listener',
['method' => 'onConfigScopeChange', 'event' => MVCEvents::CONFIG_SCOPE_CHANGE]
)
->addTag(
'kernel.event_listener',
['method' => 'onConfigScopeChange', 'event' => MVCEvents::CONFIG_SCOPE_RESTORE]
);
$this->registerForAutoConfiguration($container);
}

/**
Expand Down Expand Up @@ -579,4 +570,26 @@ private function handleUrlWildcards(array $config, ContainerBuilder $container,
$loader->load('url_wildcard.yml');
}
}

private function registerForAutoConfiguration(ContainerBuilder $container): void
{
$container->registerForAutoconfiguration(QueryType::class)
->addTag(QueryTypePass::QUERY_TYPE_SERVICE_TAG);

$container->registerForAutoconfiguration(ConfigScopeChangeSubscriber::class)
->addTag(
'kernel.event_listener',
['method' => 'onConfigScopeChange', 'event' => MVCEvents::CONFIG_SCOPE_CHANGE]
)
->addTag(
'kernel.event_listener',
['method' => 'onConfigScopeChange', 'event' => MVCEvents::CONFIG_SCOPE_RESTORE]
);

$container->registerForAutoconfiguration(FilteringCriterionQueryBuilder::class)
->addTag(ServiceTags::FILTERING_CRITERION_QUERY_BUILDER);

$container->registerForAutoconfiguration(FilteringSortClauseQueryBuilder::class)
->addTag(ServiceTags::FILTERING_SORT_CLAUSE_QUERY_BUILDER);
}
}
27 changes: 27 additions & 0 deletions eZ/Bundle/EzPublishCoreBundle/DependencyInjection/ServiceTags.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace eZ\Bundle\EzPublishCoreBundle\DependencyInjection;

/**
* "Enum" for the Symfony Service tag names provided by the Extension.
*/
class ServiceTags
{
/**
* Auto-configured tag name for
* {@see \eZ\Publish\SPI\Repository\Values\Filter\CriterionQueryBuilder}.
*/
public const FILTERING_CRITERION_QUERY_BUILDER = 'ezplatform.filter.criterion.query_builder';

/**
* Auto-configured tag name for
* {@see \eZ\Publish\SPI\Repository\Values\Filter\SortClauseQueryBuilder}.
*/
public const FILTERING_SORT_CLAUSE_QUERY_BUILDER = 'ezplatform.filter.sort_clause.query_builder';
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\Parser\Common;
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\Parser\Content;
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\EzPublishCoreExtension;
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\ServiceTags;
use eZ\Bundle\EzPublishCoreBundle\Tests\DependencyInjection\Stub\Filter\CustomCriterionQueryBuilder;
use eZ\Bundle\EzPublishCoreBundle\Tests\DependencyInjection\Stub\Filter\CustomSortClauseQueryBuilder;
use eZ\Bundle\EzPublishCoreBundle\Tests\DependencyInjection\Stub\QueryTypeBundle\QueryType\TestQueryType;
use eZ\Bundle\EzPublishCoreBundle\Tests\DependencyInjection\Stub\StubPolicyProvider;
use eZ\Publish\SPI\Repository\Values\Filter;
use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Compiler\CheckExceptionOnInvalidReferenceBehaviorPass;
Expand Down Expand Up @@ -787,6 +791,49 @@ public function testQueryTypeAutomaticConfiguration(): void
);
}

/**
* Test automatic configuration of services implementing Criterion & SortClause Filtering Query
* Builders.
*
* @dataProvider getFilteringQueryBuilderData
*
* @see \eZ\Publish\SPI\Repository\Values\Filter\CriterionQueryBuilder
* @see \eZ\Publish\SPI\Repository\Values\Filter\SortClauseQueryBuilder
*/
public function testFilteringQueryBuildersAutomaticConfiguration(
string $classFQCN,
string $tagName
): void {
$definition = new Definition($classFQCN);
$definition->setAutoconfigured(true);
$this->setDefinition($classFQCN, $definition);

$this->load();

$this->compileCoreContainer();

$this->assertContainerBuilderHasServiceDefinitionWithTag(
$classFQCN,
$tagName
);
}

/**
* Data provider for {@see testFilteringQueryBuildersAutomaticConfiguration}.
*/
public function getFilteringQueryBuilderData(): iterable
{
yield Filter\CriterionQueryBuilder::class => [
CustomCriterionQueryBuilder::class,
ServiceTags::FILTERING_CRITERION_QUERY_BUILDER,
];

yield Filter\SortClauseQueryBuilder::class => [
CustomSortClauseQueryBuilder::class,
ServiceTags::FILTERING_SORT_CLAUSE_QUERY_BUILDER,
];
}

/**
* Prepare Core Container for compilation by mocking required parameters and compile it.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace eZ\Bundle\EzPublishCoreBundle\Tests\DependencyInjection\Stub\Filter;

use eZ\Publish\SPI\Persistence\Filter\Doctrine\FilteringQueryBuilder;
use eZ\Publish\SPI\Repository\Values\Filter\CriterionQueryBuilder;
use eZ\Publish\SPI\Repository\Values\Filter\FilteringCriterion;

/**
* Stub for EzPublishCoreExtensionTest::testFilteringQueryBuildersAutomaticConfiguration
* ({@see \eZ\Bundle\EzPublishCoreBundle\Tests\DependencyInjection\EzPublishCoreExtensionTest::testFilteringQueryBuildersAutomaticConfiguration}).
*/
class CustomCriterionQueryBuilder implements CriterionQueryBuilder
{
public function accepts(FilteringCriterion $criterion): bool
{
return true;
}

public function buildQueryConstraint(
FilteringQueryBuilder $queryBuilder,
FilteringCriterion $criterion
): ?string {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace eZ\Bundle\EzPublishCoreBundle\Tests\DependencyInjection\Stub\Filter;

use eZ\Publish\SPI\Persistence\Filter\Doctrine\FilteringQueryBuilder;
use eZ\Publish\SPI\Repository\Values\Filter\FilteringSortClause;
use eZ\Publish\SPI\Repository\Values\Filter\SortClauseQueryBuilder;

/**
* Stub for EzPublishCoreExtensionTest::testFilteringQueryBuildersAutomaticConfiguration
* ({@see \eZ\Bundle\EzPublishCoreBundle\Tests\DependencyInjection\EzPublishCoreExtensionTest::testFilteringQueryBuildersAutomaticConfiguration}).
*/
class CustomSortClauseQueryBuilder implements SortClauseQueryBuilder
{
public function accepts(FilteringSortClause $sortClause): bool
{
return true;
}

public function buildQuery(
FilteringQueryBuilder $queryBuilder,
FilteringSortClause $sortClause
): void {
// Do nothing
}
}
11 changes: 11 additions & 0 deletions eZ/Publish/API/Repository/ContentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
use eZ\Publish\API\Repository\Values\User\User;
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
use eZ\Publish\API\Repository\Values\ValueObject;
use eZ\Publish\API\Repository\Values\Content\ContentList;
use eZ\Publish\API\Repository\Values\Filter\Filter;

/**
* This class provides service methods for managing content.
Expand Down Expand Up @@ -557,4 +559,13 @@ public function newContentUpdateStruct(): ContentUpdateStruct;
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
*/
public function validate(ValueObject $object, array $context, ?array $fieldIdentifiersToValidate = null): array;

/**
* Fetch Content items from the Repository filtered by the given conditions.
*
* @param string[] $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;
}
10 changes: 10 additions & 0 deletions eZ/Publish/API/Repository/LocationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
use eZ\Publish\API\Repository\Values\Content\Location;
use eZ\Publish\API\Repository\Values\Content\VersionInfo;
use eZ\Publish\API\Repository\Values\Filter\Filter;

/**
* Location service, used for complex subtree operations.
Expand Down Expand Up @@ -245,4 +246,13 @@ public function getAllLocationsCount(): int;
* @return \eZ\Publish\API\Repository\Values\Content\Location[]
*/
public function loadAllLocations(int $offset = 0, int $limit = 25): array;

/**
* Fetch a LocationList from the Repository filtered by the given conditions.
*
* @param string[] $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): LocationList;
}
11 changes: 11 additions & 0 deletions eZ/Publish/API/Repository/PermissionCriterionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

namespace eZ\Publish\API\Repository;

use eZ\Publish\API\Repository\Values\Content\Query\Criterion;

/**
* This service provides methods for resolving criterion permissions.
*
Expand All @@ -28,4 +30,13 @@ interface PermissionCriterionResolver
* @return bool|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
*/
public function getPermissionsCriterion(string $module = 'content', string $function = 'read', ?array $targets = null);

/**
* Get composite Criterion for Querying permissions.
*
* {@see \eZ\Publish\API\Repository\Values\Content\Query\Criterion\MatchAll}
* and {@see \eZ\Publish\API\Repository\Values\Content\Query\Criterion\MatchNone} are returned
* for a user with full and no access respectively.
*/
public function getQueryPermissionsCriterion(): Criterion;
}
36 changes: 28 additions & 8 deletions eZ/Publish/API/Repository/Tests/BaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
use eZ\Publish\API\Repository\Exceptions\ForbiddenException;
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use eZ\Publish\API\Repository\Tests\PHPUnitConstraint\AllValidationErrorsOccur as PHPUnitConstraintAllValidationErrorsOccur;
use eZ\Publish\API\Repository\Tests\PHPUnitConstraint\ValidationErrorOccurs as PHPUnitConstraintValidationErrorOccurs;
use eZ\Publish\API\Repository\Tests\SetupFactory\Legacy;
use eZ\Publish\API\Repository\Values\Content\Content;
use eZ\Publish\API\Repository\Values\Content\Language;
Expand Down Expand Up @@ -687,7 +685,7 @@ protected function assertValidationErrorOccurs(
ContentFieldValidationException $exception,
string $expectedValidationErrorMessage
): void {
$constraint = new PHPUnitConstraintValidationErrorOccurs($expectedValidationErrorMessage);
$constraint = new PHPUnitConstraint\ValidationErrorOccurs($expectedValidationErrorMessage);

self::assertThat($exception, $constraint);
}
Expand All @@ -702,27 +700,40 @@ protected function assertAllValidationErrorsOccur(
ContentFieldValidationException $exception,
array $expectedValidationErrorMessages
): void {
$constraint = new PHPUnitConstraintAllValidationErrorsOccur(
$constraint = new PHPUnitConstraint\AllValidationErrorsOccur(
$expectedValidationErrorMessages
);

self::assertThat($exception, $constraint);
}

protected function assertContentItemEquals(
Content $expected,
Content $actual,
string $message
): void {
$constraint = new PHPUnitConstraint\ContentItemEquals($expected);

self::assertThat($actual, $constraint, $message);
}

/**
* Create 'folder' Content.
*
* @param array $names Folder names in the form of <code>['&lt;language_code&gt;' => '&lt;name&gt;']</code>
* @param int $parentLocationId
* @param int|null $parentLocationId
*
* @return \eZ\Publish\API\Repository\Values\Content\Content published Content
*
* @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
protected function createFolder(array $names, $parentLocationId)
{
public function createFolder(
array $names,
?int $parentLocationId = null,
?string $remoteId = null
): Content {
$repository = $this->getRepository(false);
$contentService = $repository->getContentService();
$contentTypeService = $repository->getContentTypeService();
Expand All @@ -737,12 +748,21 @@ protected function createFolder(array $names, $parentLocationId)
$contentTypeService->loadContentTypeByIdentifier('folder'),
$mainLanguageCode
);
$struct->remoteId = $remoteId;
foreach ($names as $languageCode => $translatedName) {
$struct->setField('name', $translatedName, $languageCode);
}

$locationCreateStructList = [];
if (null !== $parentLocationId) {
$locationCreateStructList[] = $locationService->newLocationCreateStruct(
$parentLocationId
);
}

$contentDraft = $contentService->createContent(
$struct,
[$locationService->newLocationCreateStruct($parentLocationId)]
$locationCreateStructList
);

return $contentService->publishVersion($contentDraft->versionInfo);
Expand Down
Loading