Skip to content

Commit

Permalink
Replace ContentBundleLinkProvider with own ArticleLinkProvider (#702)
Browse files Browse the repository at this point in the history
  • Loading branch information
Prokyonn authored Nov 14, 2024
1 parent d412072 commit d88794f
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 32 deletions.
7 changes: 5 additions & 2 deletions src/Infrastructure/Doctrine/Repository/ArticleRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,10 @@ public function findIdentifiersBy(array $filters = [], array $sortBy = []): iter
$queryBuilder->select('DISTINCT article.uuid');

// we need to select the fields which are used in the order by clause
/** @var OrderBy $orderBy */
foreach ($queryBuilder->getDQLPart('orderBy') as $orderBy) {

/** @var OrderBy[] $orderBys */
$orderBys = $queryBuilder->getDQLPart('orderBy');
foreach ($orderBys as $orderBy) {
$queryBuilder->addSelect(\explode(' ', $orderBy->getParts()[0])[0]);
}

Expand Down Expand Up @@ -198,6 +200,7 @@ public function remove(ArticleInterface $article): void
* @param array{
* uuid?: 'asc'|'desc',
* title?: 'asc'|'desc',
* created?: 'asc'|'desc',
* } $sortBy
* @param array{
* article_admin?: bool,
Expand Down
49 changes: 40 additions & 9 deletions src/Infrastructure/Sulu/Content/ArticleDataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Sulu\Component\SmartContent\DataProviderAliasInterface;
use Sulu\Component\SmartContent\DataProviderInterface;
use Sulu\Component\SmartContent\DataProviderResult;
use Sulu\Component\SmartContent\DatasourceItemInterface;

class ArticleDataProvider implements DataProviderInterface, DataProviderAliasInterface
{
Expand Down Expand Up @@ -65,20 +66,23 @@ protected function getConfigurationBuilder(): BuilderInterface
public function getDefaultPropertyParameter(): array
{
return [
'type' => new PropertyParameter('type', null),
'type' => new PropertyParameter('type', ''),
'ignoreWebspaces' => new PropertyParameter('ignoreWebspaces', false),
];
}

public function resolveDataItems(array $filters, array $propertyParameter, array $options = [], $limit = null, $page = 1, $pageSize = null)
{
[$filters, $sortBy] = $this->resolveFilters($filters, $propertyParameter, $page, $options['locale']);
/** @var string $locale */
$locale = $options['locale'];
[$filters, $sortBy] = $this->resolveFilters($filters, $propertyParameter, $page, $locale);

$dimensionAttributes = [
'locale' => $options['locale'],
'locale' => $locale,
'stage' => $this->showDrafts ? DimensionContentInterface::STAGE_DRAFT : DimensionContentInterface::STAGE_LIVE,
];

/** @var string[] $identifiers */
$identifiers = $this->articleRepository->findIdentifiersBy(
filters: \array_merge($dimensionAttributes, $filters),
sortBy: $sortBy
Expand All @@ -105,13 +109,16 @@ public function resolveDataItems(array $filters, array $propertyParameter, array

public function resolveResourceItems(array $filters, array $propertyParameter, array $options = [], $limit = null, $page = 1, $pageSize = null): DataProviderResult
{
[$filters, $sortBy] = $this->resolveFilters($filters, $propertyParameter, $page, $options['locale']);
/** @var string $locale */
$locale = $options['locale'];
[$filters, $sortBy] = $this->resolveFilters($filters, $propertyParameter, $page, $locale);

$dimensionAttributes = [
'locale' => $options['locale'],
'locale' => $locale,
'stage' => $this->showDrafts ? DimensionContentInterface::STAGE_DRAFT : DimensionContentInterface::STAGE_LIVE,
];

/** @var string[] $identifiers */
$identifiers = $this->articleRepository->findIdentifiersBy(
filters: \array_merge($dimensionAttributes, $filters),
sortBy: $sortBy
Expand All @@ -127,6 +134,7 @@ public function resolveResourceItems(array $filters, array $propertyParameter, a
foreach ($articles as $article) {
$dimensionContent = $this->contentManager->resolve($article, $dimensionAttributes);
$result[] = $this->contentManager->normalize($dimensionContent);

$this->articleReferenceStore->add($article->getId());
}
$hasNextPage = \count($result) > ($pageSize ?? $limit);
Expand All @@ -135,7 +143,30 @@ public function resolveResourceItems(array $filters, array $propertyParameter, a
}

/**
* @param array{
* categories?: int[],
* categoryOperator?: 'or'|'and',
* tags?: string[],
* tagOperator?: 'or'|'and',
* limitResult?: int,
* sortBy?: string,
* sortMethod?: 'asc'|'desc',
* ...
* } $filters
* @param array<string, PropertyParameter> $propertyParameter
*
* @return array{
* array{
* locale: string,
* categoryIds?: int[],
* categoryOperator?: 'AND'|'OR',
* tagIds?: int[],
* tagOperator?: 'AND'|'OR',
* limit?: int,
* page: int
* },
* array<string, 'asc'|'desc'>
* }
*/
protected function resolveFilters(
array $filters, array $propertyParameter, int $page, string $locale): array
Expand All @@ -148,13 +179,13 @@ protected function resolveFilters(
$filter['categoryIds'] = $filters['categories'];
}
if (isset($filters['categoryOperator'])) {
$filter['categoryOperator'] = $filters['categoryOperator'];
$filter['categoryOperator'] = \strtoupper($filters['categoryOperator']);
}
if (isset($filters['tags'])) {
$filter['tagIds'] = $filters['tags'];
}
if (isset($filters['tagOperator'])) {
$filter['tagOperator'] = $filters['tagOperator'];
$filter['tagOperator'] = \strtoupper($filters['tagOperator']);
}
if (isset($filters['limitResult']) || isset($propertyParameter['max_per_page'])) {
$filter['limit'] = (int) ($filters['limitResult'] ?? $propertyParameter['max_per_page']->getValue());
Expand All @@ -168,9 +199,9 @@ protected function resolveFilters(
return [$filter, $sortBy];
}

public function resolveDatasource($datasource, array $propertyParameter, array $options): void
public function resolveDatasource($datasource, array $propertyParameter, array $options): ?DatasourceItemInterface
{
return;
return null;
}

public function getAlias()
Expand Down
63 changes: 46 additions & 17 deletions src/Infrastructure/Sulu/Content/ArticleLinkProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,43 +13,72 @@

namespace Sulu\Article\Infrastructure\Sulu\Content;

use Doctrine\ORM\EntityManagerInterface;
use Sulu\Article\Domain\Model\ArticleDimensionContentInterface;
use Sulu\Article\Domain\Model\ArticleInterface;
use Sulu\Article\Domain\Repository\ArticleRepositoryInterface;
use Sulu\Bundle\ContentBundle\Content\Application\ContentManager\ContentManagerInterface;
use Sulu\Bundle\ContentBundle\Content\Infrastructure\Sulu\Link\ContentLinkProvider;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface;
use Sulu\Bundle\MarkupBundle\Markup\Link\LinkConfiguration;
use Sulu\Bundle\MarkupBundle\Markup\Link\LinkConfigurationBuilder;
use Sulu\Component\Content\Metadata\Factory\StructureMetadataFactoryInterface;
use Sulu\Bundle\MarkupBundle\Markup\Link\LinkItem;
use Sulu\Bundle\MarkupBundle\Markup\Link\LinkProviderInterface;
use Sulu\Bundle\WebsiteBundle\ReferenceStore\ReferenceStoreInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
* @extends ContentLinkProvider<ArticleDimensionContentInterface, ArticleInterface>
*/
class ArticleLinkProvider extends ContentLinkProvider
class ArticleLinkProvider implements LinkProviderInterface
{
public function __construct(
ContentManagerInterface $contentManager,
StructureMetadataFactoryInterface $structureMetadataFactory,
EntityManagerInterface $entityManager,
private readonly ContentManagerInterface $contentManager,
private readonly ArticleRepositoryInterface $articleRepository,
private readonly ReferenceStoreInterface $articleReferenceStore,
private readonly TranslatorInterface $translator,
) {
parent::__construct($contentManager, $structureMetadataFactory, $entityManager, ArticleInterface::class);
}

public function getConfiguration(): LinkConfiguration
{
return LinkConfigurationBuilder::create()
->setTitle('Example')
->setTitle($this->translator->trans('sulu_article.articles', [], 'admin'))
->setResourceKey(ArticleInterface::RESOURCE_KEY)
->setListAdapter('table')
->setDisplayProperties(['id'])
->setOverlayTitle('Select Example')
->setEmptyText('No example selected')
->setOverlayTitle($this->translator->trans('sulu_article.selection_overlay_title', [], 'admin'))
->setEmptyText($this->translator->trans('sulu_article.no_article_selected', [], 'admin'))
->setIcon('su-document')
->getLinkConfiguration();
}

protected function getEntityIdField(): string
public function preload(array $hrefs, $locale, $published = true)
{
return 'uuid';
$dimensionAttributes = [
'locale' => $locale,
'stage' => $published ? DimensionContentInterface::STAGE_LIVE : DimensionContentInterface::STAGE_DRAFT,
];

$articles = $this->articleRepository->findBy(
filters: [...$dimensionAttributes, 'uuids' => $hrefs],
selects: [ArticleRepositoryInterface::GROUP_SELECT_ARTICLE_WEBSITE => true]
);

$result = [];
foreach ($articles as $article) {
$dimensionContent = $this->contentManager->resolve($article, $dimensionAttributes);
$this->articleReferenceStore->add($article->getId());

/** @var string|null $url */
$url = $dimensionContent->getTemplateData()['url'] ?? null;
if (null === $url) {
// TODO what to do when there is no url?
continue;
}

$result[] = new LinkItem(
$article->getUuid(),
(string) $dimensionContent->getTitle(),
$url,
$published
);
}

return $result;
}
}
7 changes: 4 additions & 3 deletions src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,10 @@ public function loadExtension(array $config, ContainerConfigurator $container, C
$services->set('sulu_article.article_link_provider')
->class(ArticleLinkProvider::class)
->args([
new Reference('sulu_content.content_manager'), // TODO link provider should not build on manager
new Reference('sulu_page.structure.factory'),
new Reference('doctrine.orm.entity_manager'),
new Reference('sulu_content.content_manager'),
new Reference('sulu_article.article_repository'),
new Reference('sulu_article.article_reference_store'),
new Reference('translator'),
])
->tag('sulu.link.provider', ['alias' => 'article']);

Expand Down
2 changes: 1 addition & 1 deletion tests/Traits/AssertSnapshotTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ trait AssertSnapshotTrait
*/
protected function assertResponseSnapshot(
string $snapshotPatternFilename,
$actualResponse,
$actualResponse,
int $statusCode = 200,
string $message = ''
): void {
Expand Down

0 comments on commit d88794f

Please sign in to comment.