From e0aaf034ab1cbbc48ce3b8b5f5d057e52c7cd90b Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Tue, 30 Jul 2024 15:59:51 +0200 Subject: [PATCH 1/4] Fix LinkProvider alias and enhance articles list view (#5) --- UPGRADE.md | 10 ++ config/lists/articles.xml | 93 +++++++++++++++++++ .../Symfony/HttpKernel/SuluArticleBundle.php | 2 +- 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index 0465c7e5..088b5292 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -2,6 +2,16 @@ ## 3.x +### Article user settings updated + +Due to the refactoring of the new content bundle storage, the user settings for articles must be erased to avoid conflicts. + +Execute the following SQL query to delete the user settings: +```mysql +DELETE FROM `se_user_settings` + WHERE `se_user_settings`.`settingsKey` LIKE '%article%' +``` + ### Elasticsearch Bundle need to be required The SuluArticleBundle defines not longer its dependency to `handcraftedinthealps/elasticsearch-bundle` because diff --git a/config/lists/articles.xml b/config/lists/articles.xml index a2c26773..1595233f 100644 --- a/config/lists/articles.xml +++ b/config/lists/articles.xml @@ -2,6 +2,27 @@ articles + + + %sulu.model.user.class% + Sulu\Article\Domain\Model\ArticleInterface.creator + + + %sulu.model.contact.class% + %sulu.model.user.class%.contact + + + + + %sulu.model.user.class% + Sulu\Article\Domain\Model\ArticleInterface.changer + + + %sulu.model.contact.class% + %sulu.model.user.class%.contact + + + dimensionContent @@ -29,6 +50,13 @@ + + + authorEntity + dimensionContent.author + + + @@ -54,6 +82,71 @@ + + + firstName + authorEntity + + + + + lastName + authorEntity + + + + + + + + + + + + created + Sulu\Article\Domain\Model\ArticleInterface + + + + + changed + Sulu\Article\Domain\Model\ArticleInterface + + + + + + firstName + %sulu.model.contact.class% + + + + + lastName + %sulu.model.contact.class% + + + + + + + + firstName + %sulu.model.contact.class% + + + + + lastName + %sulu.model.contact.class% + + + + + locale dimensionContent diff --git a/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php b/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php index 34a8886f..d711b191 100644 --- a/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php +++ b/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php @@ -224,7 +224,7 @@ public function loadExtension(array $config, ContainerConfigurator $container, C new Reference('sulu_page.structure.factory'), new Reference('doctrine.orm.entity_manager'), ]) - ->tag('sulu.link.provider', ['alias' => ArticleInterface::RESOURCE_KEY]); + ->tag('sulu.link.provider', ['alias' => 'article']); // Smart Content services $services->set('sulu_article.article_data_provider_repository') From f823d36b14c59b3c438fe5e99569f1752965e9df Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Wed, 24 Jul 2024 12:43:06 +0200 Subject: [PATCH 2/4] Add POC for ArticleDataProvider --- .../Doctrine/Repository/ArticleRepository.php | 2 + .../Sulu/Content/ArticleDataProvider.php | 149 ++++++++++++++++++ .../Symfony/HttpKernel/SuluArticleBundle.php | 26 +-- 3 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 src/Infrastructure/Sulu/Content/ArticleDataProvider.php diff --git a/src/Infrastructure/Doctrine/Repository/ArticleRepository.php b/src/Infrastructure/Doctrine/Repository/ArticleRepository.php index d3eda575..0579d1f9 100644 --- a/src/Infrastructure/Doctrine/Repository/ArticleRepository.php +++ b/src/Infrastructure/Doctrine/Repository/ArticleRepository.php @@ -238,6 +238,8 @@ private function createQueryBuilder(array $filters, array $sortBy = [], array $s ); } + + // TODO add sortBys // selects diff --git a/src/Infrastructure/Sulu/Content/ArticleDataProvider.php b/src/Infrastructure/Sulu/Content/ArticleDataProvider.php new file mode 100644 index 00000000..69062874 --- /dev/null +++ b/src/Infrastructure/Sulu/Content/ArticleDataProvider.php @@ -0,0 +1,149 @@ +getConfigurationBuilder()->getConfiguration(); + } + + /** + * Create new configuration-builder. + */ + protected function getConfigurationBuilder(): BuilderInterface + { + $builder = Builder::create() + ->enableTags() + ->enableCategories() + ->enableLimit() + ->enablePagination() + ->enablePresentAs() + ->enableSorting( + [ + ['column' => 'published', 'title' => 'sulu_admin.published'], + ['column' => 'authored', 'title' => 'sulu_admin.authored'], + ['column' => 'created', 'title' => 'sulu_admin.created'], + ['column' => 'title.raw', 'title' => 'sulu_admin.title'], + ['column' => 'author_full_name.raw', 'title' => 'sulu_admin.author'], + ] + ); + +// if (\method_exists($builder, 'enableTypes')) { +// $builder->enableTypes($this->getTypes()); +// } + + return $builder; + } + + public function getDefaultPropertyParameter(): array + { + return [ + 'type' => new PropertyParameter('type', null), + 'ignoreWebspaces' => new PropertyParameter('ignoreWebspaces', false), + ]; + } + + public function resolveDataItems(array $filters, array $propertyParameter, array $options = [], $limit = null, $page = 1, $pageSize = null) + { + [$filter, $sortBy] = $this->resolveFilters($filters, $page, $options['locale']); + $articles = $this->articleRepository->findBy( + $filter, + $sortBy, + [ + ArticleRepositoryInterface::GROUP_SELECT_ARTICLE_ADMIN + ] + ); + $articles = iterator_to_array($articles); + + return new DataProviderResult($articles, false); + } + + public function resolveResourceItems(array $filters, array $propertyParameter, array $options = [], $limit = null, $page = 1, $pageSize = null): DataProviderResult + { + [$filters, $sortBy] = $this->resolveFilters($filters, $page, $options['locale']); + + $dimensionAttributes = [ + 'locale' => $options['locale'], + 'stage' => DimensionContentInterface::STAGE_LIVE, + ]; + + $limit = $filters['limit'] ?? 0; + + $articles = $this->articleRepository->findBy( + filters: array_merge($dimensionAttributes, $filters), + sortBy: $sortBy, + selects: [ArticleRepositoryInterface::GROUP_SELECT_ARTICLE_WEBSITE => true] + ); + + $result = []; + foreach ($articles as $article) { + $dimensionContent = $this->contentManager->resolve($article, $dimensionAttributes); + $result[] = $this->contentManager->normalize($dimensionContent); + } + $hasNextPage = count($result) > ($pageSize ?? $limit); + return new DataProviderResult($result, $hasNextPage); + } + + protected function resolveFilters(array $filters, int $page, string $locale): array + { + $filter = [ + 'locale' => $locale, + ]; + $sortBy = []; + if (isset($filters['categories'])) { + $filter['categoryIds'] = $filters['categories']; + } + if (isset($filters['categoryOperator'])) { + $filter['categoryOperator'] = $filters['categoryOperator']; + } + if (isset($filters['tags'])) { + $filter['tagIds'] = $filters['tags']; + } + if (isset($filters['tagOperator'])) { + $filter['tagOperator'] = $filters['tagOperator']; + } + if (isset($filters['limitResult'])) { + $filter['limit'] = (int)$filters['limitResult']; + } + $filter['page'] = $page; + + if (isset($filters['sortBy']) && isset($filters['sortMethod'])) { + $sortBy[$filters['sortBy']] = $filters['sortMethod']; + } + + return [$filter, $sortBy]; + } + + public function resolveDatasource($datasource, array $propertyParameter, array $options) + { + $test = 123; + } + + public function getAlias() + { + return 'article'; + } +} diff --git a/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php b/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php index d711b191..5bc3f7b9 100644 --- a/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php +++ b/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php @@ -23,6 +23,7 @@ use Sulu\Article\Infrastructure\Sulu\Content\ArticleSitemapProvider; use Sulu\Article\Infrastructure\Sulu\Content\ArticleTeaserProvider; use Sulu\Article\Infrastructure\Sulu\Content\SingleArticleSelectionContentType; +use Sulu\Article\Infrastructure\Sulu\Content\ArticleDataProvider; use Sulu\Article\UserInterface\Controller\Admin\ArticleController; use Sulu\Bundle\ContentBundle\Content\Infrastructure\Sulu\Preview\ContentObjectProvider; use Sulu\Bundle\ContentBundle\Content\Infrastructure\Sulu\Search\ContentSearchMetadataProvider; @@ -226,16 +227,6 @@ public function loadExtension(array $config, ContainerConfigurator $container, C ]) ->tag('sulu.link.provider', ['alias' => 'article']); - // Smart Content services - $services->set('sulu_article.article_data_provider_repository') - ->class(ContentDataProviderRepository::class) // TODO this should not be handled via Content Bundle instead own service which uses the ArticleRepository - ->args([ - new Reference('sulu_content.content_manager'), - new Reference('doctrine.orm.entity_manager'), - '%sulu_document_manager.show_drafts%', - ArticleInterface::class, - ]); - $services->set('sulu_article.article_reference_store') ->class(ReferenceStore::class) ->tag('sulu_website.reference_store', ['alias' => ArticleInterface::RESOURCE_KEY]); @@ -258,11 +249,20 @@ public function loadExtension(array $config, ContainerConfigurator $container, C ]) ->tag('sulu.content.type', ['alias' => 'article_selection']); + // Smart Content services + $services->set('sulu_article.article_data_provider_repository') + ->class(ContentDataProviderRepository::class) // TODO this should not be handled via Content Bundle instead own service which uses the ArticleRepository + ->args([ + new Reference('sulu_content.content_manager'), + new Reference('doctrine.orm.entity_manager'), + '%sulu_document_manager.show_drafts%', + ArticleInterface::class, + ]); + $services->set('sulu_article.article_data_provider') - ->class(ContentDataProvider::class) // TODO this should not be handled via Content Bundle instead own service which uses the ArticleRepository + ->class(ArticleDataProvider::class) // TODO this should not be handled via Content Bundle instead own service which uses the ArticleRepository ->args([ - new Reference('sulu_article.article_data_provider_repository'), - new Reference('sulu_core.array_serializer'), + new Reference('sulu_article.article_repository'), new Reference('sulu_content.content_manager'), new Reference('sulu_article.article_reference_store'), ]) From 9dafda132f866a78ac56cea383434314a2555fd8 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Wed, 31 Jul 2024 12:48:11 +0200 Subject: [PATCH 3/4] Add ArticleDataProvider --- DependencyInjection/Configuration.php | 1 - DependencyInjection/SuluArticleExtension.php | 1 - .../Exception/ArticleNotFoundException.php | 2 +- .../Repository/ArticleRepositoryInterface.php | 25 ++++++ .../Doctrine/Repository/ArticleRepository.php | 62 +++++++++++++-- .../Sulu/Content/ArticleDataProvider.php | 76 +++++++++++++------ .../Content/ArticleSelectionContentType.php | 19 +++-- .../Sulu/Content/ArticleSitemapProvider.php | 9 +++ .../SingleArticleSelectionContentType.php | 19 +++-- .../Symfony/HttpKernel/SuluArticleBundle.php | 27 ++++--- .../Controller/Admin/ArticleController.php | 2 + 11 files changed, 183 insertions(+), 60 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index dd2cf7a3..7aeba302 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -14,7 +14,6 @@ use Sulu\Bundle\ArticleBundle\Document\ArticlePageViewObject; use Sulu\Bundle\ArticleBundle\Document\ArticleViewDocument; use Sulu\Bundle\ArticleBundle\Domain\Model\Article; -use Sulu\Bundle\ArticleBundle\Domain\Model\ArticleDimensionContent; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; diff --git a/DependencyInjection/SuluArticleExtension.php b/DependencyInjection/SuluArticleExtension.php index 56282a70..fee6c318 100644 --- a/DependencyInjection/SuluArticleExtension.php +++ b/DependencyInjection/SuluArticleExtension.php @@ -328,7 +328,6 @@ public function load(array $configs, ContainerBuilder $container) $storage = $config['storage']; $container->setParameter('sulu_article.article_storage', $storage); - $container->setParameter('sulu_article.default_main_webspace', $config['default_main_webspace']); $container->setParameter('sulu_article.default_additional_webspaces', $config['default_additional_webspaces']); $container->setParameter('sulu_article.types', $config['types']); diff --git a/src/Domain/Exception/ArticleNotFoundException.php b/src/Domain/Exception/ArticleNotFoundException.php index 000b59bf..1b7ccd91 100644 --- a/src/Domain/Exception/ArticleNotFoundException.php +++ b/src/Domain/Exception/ArticleNotFoundException.php @@ -28,7 +28,7 @@ class ArticleNotFoundException extends \Exception /** * @param array $filters */ - public function __construct(array $filters, int $code = 0, \Throwable $previous = null) + public function __construct(array $filters, int $code = 0, ?\Throwable $previous = null) { $this->model = ArticleInterface::class; diff --git a/src/Domain/Repository/ArticleRepositoryInterface.php b/src/Domain/Repository/ArticleRepositoryInterface.php index d446dd0f..3a8e445f 100644 --- a/src/Domain/Repository/ArticleRepositoryInterface.php +++ b/src/Domain/Repository/ArticleRepositoryInterface.php @@ -100,6 +100,31 @@ public function findOneBy(array $filters, array $selects = []): ?ArticleInterfac */ public function findBy(array $filters = [], array $sortBy = [], array $selects = []): iterable; + /** + * @param array{ + * uuid?: string, + * uuids?: string[], + * locale?: string, + * stage?: string, + * categoryIds?: int[], + * categoryKeys?: string[], + * categoryOperator?: 'AND'|'OR', + * tagIds?: int[], + * tagNames?: string[], + * tagOperator?: 'AND'|'OR', + * templateKeys?: string[], + * page?: int, + * limit?: int, + * } $filters + * @param array{ + * id?: 'asc'|'desc', + * title?: 'asc'|'desc', + * } $sortBy + * + * @return iterable + */ + public function findIdentifiersBy(array $filters = [], array $sortBy = []): iterable; + /** * @param array{ * uuid?: string, diff --git a/src/Infrastructure/Doctrine/Repository/ArticleRepository.php b/src/Infrastructure/Doctrine/Repository/ArticleRepository.php index 0579d1f9..26cee9c6 100644 --- a/src/Infrastructure/Doctrine/Repository/ArticleRepository.php +++ b/src/Infrastructure/Doctrine/Repository/ArticleRepository.php @@ -14,6 +14,7 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\NoResultException; +use Doctrine\ORM\Query\Expr\OrderBy; use Doctrine\ORM\QueryBuilder; use Sulu\Article\Domain\Exception\ArticleNotFoundException; use Sulu\Article\Domain\Model\ArticleDimensionContentInterface; @@ -149,6 +150,23 @@ public function findBy(array $filters = [], array $sortBy = [], array $selects = } } + public function findIdentifiersBy(array $filters = [], array $sortBy = []): iterable + { + $queryBuilder = $this->createQueryBuilder($filters, $sortBy); + + $queryBuilder->select('DISTINCT article.uuid'); + + /** @var OrderBy $orderBy */ + foreach ($queryBuilder->getDQLPart('orderBy') as $orderBy) { + $queryBuilder->addSelect(\explode(' ', $orderBy->getParts()[0])[0]); + } + + /** @var iterable $identifiers */ + $identifiers = $queryBuilder->getQuery()->getResult(); + + return $identifiers; + } + public function add(ArticleInterface $article): void { $this->entityManager->persist($article); @@ -238,19 +256,26 @@ private function createQueryBuilder(array $filters, array $sortBy = [], array $s ); } - - - // TODO add sortBys + if ([] !== $sortBy) { + foreach ($sortBy as $field => $order) { + if ('uuid' === $field) { + $queryBuilder->addOrderBy('article.uuid', $order); + } elseif ('created' === $field) { + $queryBuilder->addOrderBy('article.created', $order); + } elseif (\in_array($field, ['title', 'authored', 'workflowPublished'])) { + $this->joinDimensionContent($queryBuilder, 'article'); + + $queryBuilder->addOrderBy('dimensionContent.' . $field, $order); + } + } + } // selects if ($selects[self::SELECT_ARTICLE_CONTENT] ?? null) { /** @var array $contentSelects */ $contentSelects = $selects[self::SELECT_ARTICLE_CONTENT]; - $queryBuilder->leftJoin( - 'article.dimensionContents', - 'dimensionContent' - ); + $this->joinDimensionContent($queryBuilder, 'article'); $this->dimensionContentQueryEnhancer->addSelects( $queryBuilder, @@ -262,4 +287,27 @@ private function createQueryBuilder(array $filters, array $sortBy = [], array $s return $queryBuilder; } + + private function joinDimensionContent(QueryBuilder $queryBuilder, string $alias): void + { + if (!$this->isJoinAlreadyPresent($queryBuilder, 'dimensionContent')) { + $queryBuilder->leftJoin( + $alias . '.dimensionContents', + 'dimensionContent' + ); + } + } + + private function isJoinAlreadyPresent(QueryBuilder $queryBuilder, string $alias): bool + { + foreach ($queryBuilder->getDQLPart('join') as $joins) { + foreach ($joins as $join) { + if ($join->getAlias() === $alias) { + return true; + } + } + } + + return false; + } } diff --git a/src/Infrastructure/Sulu/Content/ArticleDataProvider.php b/src/Infrastructure/Sulu/Content/ArticleDataProvider.php index 69062874..16de3959 100644 --- a/src/Infrastructure/Sulu/Content/ArticleDataProvider.php +++ b/src/Infrastructure/Sulu/Content/ArticleDataProvider.php @@ -1,5 +1,14 @@ enablePresentAs() ->enableSorting( [ - ['column' => 'published', 'title' => 'sulu_admin.published'], + ['column' => 'workflowPublished', 'title' => 'sulu_admin.published'], ['column' => 'authored', 'title' => 'sulu_admin.authored'], ['column' => 'created', 'title' => 'sulu_admin.created'], - ['column' => 'title.raw', 'title' => 'sulu_admin.title'], - ['column' => 'author_full_name.raw', 'title' => 'sulu_admin.author'], + ['column' => 'title', 'title' => 'sulu_admin.title'], ] ); -// if (\method_exists($builder, 'enableTypes')) { -// $builder->enableTypes($this->getTypes()); -// } + // if (\method_exists($builder, 'enableTypes')) { + // $builder->enableTypes($this->getTypes()); + // } return $builder; } @@ -68,17 +75,35 @@ public function getDefaultPropertyParameter(): array public function resolveDataItems(array $filters, array $propertyParameter, array $options = [], $limit = null, $page = 1, $pageSize = null) { - [$filter, $sortBy] = $this->resolveFilters($filters, $page, $options['locale']); + [$filters, $sortBy] = $this->resolveFilters($filters, $page, $options['locale']); + + $dimensionAttributes = [ + 'locale' => $options['locale'], + 'stage' => $this->showDrafts ? DimensionContentInterface::STAGE_DRAFT : DimensionContentInterface::STAGE_LIVE, + ]; + + $identifiers = $this->articleRepository->findIdentifiersBy( + filters: \array_merge($dimensionAttributes, $filters), + sortBy: $sortBy + ); + $articles = $this->articleRepository->findBy( - $filter, - $sortBy, - [ - ArticleRepositoryInterface::GROUP_SELECT_ARTICLE_ADMIN - ] + filters: \array_merge($dimensionAttributes, ['uuids' => $identifiers]), + sortBy: $sortBy, + selects: [ArticleRepositoryInterface::GROUP_SELECT_ARTICLE_ADMIN => true] ); - $articles = iterator_to_array($articles); - return new DataProviderResult($articles, false); + $result = []; + foreach ($articles as $article) { + $dimensionContent = $this->contentManager->resolve($article, $dimensionAttributes); + $result[] = [ + 'id' => $article->getId(), + 'title' => $dimensionContent->getTitle(), + ]; + } + $hasNextPage = \count($result) > ($pageSize ?? $limit); + + return new DataProviderResult($result, $hasNextPage); } public function resolveResourceItems(array $filters, array $propertyParameter, array $options = [], $limit = null, $page = 1, $pageSize = null): DataProviderResult @@ -87,13 +112,16 @@ public function resolveResourceItems(array $filters, array $propertyParameter, a $dimensionAttributes = [ 'locale' => $options['locale'], - 'stage' => DimensionContentInterface::STAGE_LIVE, + 'stage' => $this->showDrafts ? DimensionContentInterface::STAGE_DRAFT : DimensionContentInterface::STAGE_LIVE, ]; - $limit = $filters['limit'] ?? 0; + $identifiers = $this->articleRepository->findIdentifiersBy( + filters: \array_merge($dimensionAttributes, $filters), + sortBy: $sortBy + ); $articles = $this->articleRepository->findBy( - filters: array_merge($dimensionAttributes, $filters), + filters: \array_merge($dimensionAttributes, ['uuids' => $identifiers]), sortBy: $sortBy, selects: [ArticleRepositoryInterface::GROUP_SELECT_ARTICLE_WEBSITE => true] ); @@ -102,8 +130,10 @@ 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); + $hasNextPage = \count($result) > ($pageSize ?? $limit); + return new DataProviderResult($result, $hasNextPage); } @@ -126,7 +156,7 @@ protected function resolveFilters(array $filters, int $page, string $locale): ar $filter['tagOperator'] = $filters['tagOperator']; } if (isset($filters['limitResult'])) { - $filter['limit'] = (int)$filters['limitResult']; + $filter['limit'] = (int) $filters['limitResult']; } $filter['page'] = $page; diff --git a/src/Infrastructure/Sulu/Content/ArticleSelectionContentType.php b/src/Infrastructure/Sulu/Content/ArticleSelectionContentType.php index 04463ee8..e0eff423 100644 --- a/src/Infrastructure/Sulu/Content/ArticleSelectionContentType.php +++ b/src/Infrastructure/Sulu/Content/ArticleSelectionContentType.php @@ -1,9 +1,17 @@ referenceStore = $referenceStore; $this->contentManager = $contentManager; @@ -50,7 +57,6 @@ public function getContentData(PropertyInterface $property) ArticleRepositoryInterface::GROUP_SELECT_ARTICLE_WEBSITE => true, ]); - $result = []; foreach ($article as $article) { $dimensionContent = $this->contentManager->resolve($article, $dimensionAttributes); @@ -60,7 +66,6 @@ public function getContentData(PropertyInterface $property) \ksort($result); return \array_values($result); - } public function preResolve(PropertyInterface $property) diff --git a/src/Infrastructure/Sulu/Content/ArticleSitemapProvider.php b/src/Infrastructure/Sulu/Content/ArticleSitemapProvider.php index fa489fd2..23d92310 100644 --- a/src/Infrastructure/Sulu/Content/ArticleSitemapProvider.php +++ b/src/Infrastructure/Sulu/Content/ArticleSitemapProvider.php @@ -1,5 +1,14 @@ articleRepository = $articleRepository; @@ -54,8 +62,8 @@ public function getContentData(PropertyInterface $property) ArticleRepositoryInterface::GROUP_SELECT_ARTICLE_WEBSITE => true, ]); - $dimensionContent = $this->contentManager->resolve($article, $dimensionAttributes); + return $this->contentManager->normalize($dimensionContent); } @@ -69,4 +77,3 @@ public function preResolve(PropertyInterface $property) $this->referenceStore->add($uuid); } } - diff --git a/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php b/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php index 5bc3f7b9..abf1bc5a 100644 --- a/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php +++ b/src/Infrastructure/Symfony/HttpKernel/SuluArticleBundle.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/* + * This file is part of Sulu. + * + * (c) Sulu GmbH + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + namespace Sulu\Article\Infrastructure\Symfony\HttpKernel; use Sulu\Article\Application\Mapper\ArticleContentMapper; @@ -18,17 +27,15 @@ use Sulu\Article\Domain\Repository\ArticleRepositoryInterface; use Sulu\Article\Infrastructure\Doctrine\Repository\ArticleRepository; use Sulu\Article\Infrastructure\Sulu\Admin\ArticleAdmin; +use Sulu\Article\Infrastructure\Sulu\Content\ArticleDataProvider; use Sulu\Article\Infrastructure\Sulu\Content\ArticleLinkProvider; use Sulu\Article\Infrastructure\Sulu\Content\ArticleSelectionContentType; use Sulu\Article\Infrastructure\Sulu\Content\ArticleSitemapProvider; use Sulu\Article\Infrastructure\Sulu\Content\ArticleTeaserProvider; use Sulu\Article\Infrastructure\Sulu\Content\SingleArticleSelectionContentType; -use Sulu\Article\Infrastructure\Sulu\Content\ArticleDataProvider; use Sulu\Article\UserInterface\Controller\Admin\ArticleController; use Sulu\Bundle\ContentBundle\Content\Infrastructure\Sulu\Preview\ContentObjectProvider; use Sulu\Bundle\ContentBundle\Content\Infrastructure\Sulu\Search\ContentSearchMetadataProvider; -use Sulu\Bundle\ContentBundle\Content\Infrastructure\Sulu\SmartContent\Provider\ContentDataProvider; -use Sulu\Bundle\ContentBundle\Content\Infrastructure\Sulu\SmartContent\Repository\ContentDataProviderRepository; use Sulu\Bundle\PersistenceBundle\DependencyInjection\PersistenceExtensionTrait; use Sulu\Bundle\PersistenceBundle\PersistenceBundleTrait; use Sulu\Bundle\WebsiteBundle\ReferenceStore\ReferenceStore; @@ -236,7 +243,7 @@ public function loadExtension(array $config, ContainerConfigurator $container, C ->args([ new Reference('sulu_article.article_repository'), new Reference('sulu_content.content_manager'), - new Reference('sulu_article.article_reference_store') + new Reference('sulu_article.article_reference_store'), ]) ->tag('sulu.content.type', ['alias' => 'single_article_selection']); @@ -245,26 +252,18 @@ public function loadExtension(array $config, ContainerConfigurator $container, C ->args([ new Reference('sulu_article.article_repository'), new Reference('sulu_content.content_manager'), - new Reference('sulu_article.article_reference_store') + new Reference('sulu_article.article_reference_store'), ]) ->tag('sulu.content.type', ['alias' => 'article_selection']); // Smart Content services - $services->set('sulu_article.article_data_provider_repository') - ->class(ContentDataProviderRepository::class) // TODO this should not be handled via Content Bundle instead own service which uses the ArticleRepository - ->args([ - new Reference('sulu_content.content_manager'), - new Reference('doctrine.orm.entity_manager'), - '%sulu_document_manager.show_drafts%', - ArticleInterface::class, - ]); - $services->set('sulu_article.article_data_provider') ->class(ArticleDataProvider::class) // TODO this should not be handled via Content Bundle instead own service which uses the ArticleRepository ->args([ new Reference('sulu_article.article_repository'), new Reference('sulu_content.content_manager'), new Reference('sulu_article.article_reference_store'), + '%sulu_document_manager.show_drafts%', ]) ->tag('sulu.smart_content.data_provider', ['alias' => ArticleInterface::RESOURCE_KEY]); diff --git a/src/UserInterface/Controller/Admin/ArticleController.php b/src/UserInterface/Controller/Admin/ArticleController.php index c36f24ce..a56847c9 100644 --- a/src/UserInterface/Controller/Admin/ArticleController.php +++ b/src/UserInterface/Controller/Admin/ArticleController.php @@ -231,11 +231,13 @@ private function handleAction(Request $request, string $uuid): ?ArticleInterface (string) $request->query->get('src'), (string) $request->query->get('dest') ); + /** @see Sulu\Article\Application\MessageHandler\CopyLocaleArticleMessageHandler */ /** @var null */ return $this->handle(new Envelope($message, [new EnableFlushStamp()])); } else { $message = new ApplyWorkflowTransitionArticleMessage(['uuid' => $uuid], $this->getLocale($request), $action); + /** @see Sulu\Article\Application\MessageHandler\ApplyWorkflowTransitionArticleMessageHandler */ /** @var null */ return $this->handle(new Envelope($message, [new EnableFlushStamp()])); From b3546c71554976857da9e38f04710035d2e675b5 Mon Sep 17 00:00:00 2001 From: Prokyonn Date: Thu, 8 Aug 2024 09:16:44 +0200 Subject: [PATCH 4/4] Update provider --- .../Doctrine/Repository/ArticleRepository.php | 43 ++++++------------- .../Sulu/Content/ArticleDataProvider.php | 9 ++-- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/src/Infrastructure/Doctrine/Repository/ArticleRepository.php b/src/Infrastructure/Doctrine/Repository/ArticleRepository.php index 26cee9c6..3712b5d5 100644 --- a/src/Infrastructure/Doctrine/Repository/ArticleRepository.php +++ b/src/Infrastructure/Doctrine/Repository/ArticleRepository.php @@ -156,6 +156,7 @@ 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) { $queryBuilder->addSelect(\explode(' ', $orderBy->getParts()[0])[0]); @@ -246,13 +247,17 @@ private function createQueryBuilder(array $filters, array $sortBy = [], array $s $queryBuilder->setFirstResult($offset); } - if (\array_key_exists('locale', $filters) // should also work with locale = null - && \array_key_exists('stage', $filters)) { + if ( + (\array_key_exists('locale', $filters) // should also work with locale = null + && \array_key_exists('stage', $filters)) + || ([] === $filters && [] !== $sortBy) // if no filters are set, but sortBy is set, we need to set the sorting + ) { $this->dimensionContentQueryEnhancer->addFilters( $queryBuilder, 'article', $this->articleDimensionContentClassName, - $filters + $filters, + $sortBy ); } @@ -262,10 +267,6 @@ private function createQueryBuilder(array $filters, array $sortBy = [], array $s $queryBuilder->addOrderBy('article.uuid', $order); } elseif ('created' === $field) { $queryBuilder->addOrderBy('article.created', $order); - } elseif (\in_array($field, ['title', 'authored', 'workflowPublished'])) { - $this->joinDimensionContent($queryBuilder, 'article'); - - $queryBuilder->addOrderBy('dimensionContent.' . $field, $order); } } } @@ -275,7 +276,10 @@ private function createQueryBuilder(array $filters, array $sortBy = [], array $s /** @var array $contentSelects */ $contentSelects = $selects[self::SELECT_ARTICLE_CONTENT]; - $this->joinDimensionContent($queryBuilder, 'article'); + $queryBuilder->leftJoin( + 'article.dimensionContents', + 'dimensionContent' + ); $this->dimensionContentQueryEnhancer->addSelects( $queryBuilder, @@ -287,27 +291,4 @@ private function createQueryBuilder(array $filters, array $sortBy = [], array $s return $queryBuilder; } - - private function joinDimensionContent(QueryBuilder $queryBuilder, string $alias): void - { - if (!$this->isJoinAlreadyPresent($queryBuilder, 'dimensionContent')) { - $queryBuilder->leftJoin( - $alias . '.dimensionContents', - 'dimensionContent' - ); - } - } - - private function isJoinAlreadyPresent(QueryBuilder $queryBuilder, string $alias): bool - { - foreach ($queryBuilder->getDQLPart('join') as $joins) { - foreach ($joins as $join) { - if ($join->getAlias() === $alias) { - return true; - } - } - } - - return false; - } } diff --git a/src/Infrastructure/Sulu/Content/ArticleDataProvider.php b/src/Infrastructure/Sulu/Content/ArticleDataProvider.php index 16de3959..3eb2ca12 100644 --- a/src/Infrastructure/Sulu/Content/ArticleDataProvider.php +++ b/src/Infrastructure/Sulu/Content/ArticleDataProvider.php @@ -55,13 +55,10 @@ protected function getConfigurationBuilder(): BuilderInterface ['column' => 'authored', 'title' => 'sulu_admin.authored'], ['column' => 'created', 'title' => 'sulu_admin.created'], ['column' => 'title', 'title' => 'sulu_admin.title'], + ['column' => 'author', 'title' => 'sulu_admin.author'], ] ); - // if (\method_exists($builder, 'enableTypes')) { - // $builder->enableTypes($this->getTypes()); - // } - return $builder; } @@ -167,9 +164,9 @@ protected function resolveFilters(array $filters, int $page, string $locale): ar return [$filter, $sortBy]; } - public function resolveDatasource($datasource, array $propertyParameter, array $options) + public function resolveDatasource($datasource, array $propertyParameter, array $options): void { - $test = 123; + return; } public function getAlias()