Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3d1b3e9

Browse files
add new column/filter to article-controller (#722)
1 parent cedf414 commit 3d1b3e9

7 files changed

Lines changed: 433 additions & 17 deletions

File tree

Controller/ArticleController.php

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
use Sulu\Component\Security\Authorization\SecurityCheckerInterface;
5151
use Sulu\Component\Security\Authorization\SecurityCondition;
5252
use Sulu\Component\Security\SecuredControllerInterface;
53+
use Sulu\Component\Webspace\Manager\WebspaceManagerInterface;
5354
use Symfony\Component\Form\FormFactoryInterface;
5455
use Symfony\Component\HttpFoundation\Request;
5556
use Symfony\Component\HttpFoundation\Response;
@@ -119,6 +120,11 @@ class ArticleController extends AbstractRestController implements ClassResourceI
119120
*/
120121
private $documentInspector;
121122

123+
/**
124+
* @var WebspaceManagerInterface|null
125+
*/
126+
private $webspaceManager;
127+
122128
public function __construct(
123129
ViewHandlerInterface $viewHandler,
124130
DocumentManagerInterface $documentManager,
@@ -132,7 +138,8 @@ public function __construct(
132138
SecurityCheckerInterface $securityChecker,
133139
bool $displayTabAll,
134140
?TokenStorageInterface $tokenStorage = null,
135-
?DocumentInspector $documentInspector = null
141+
?DocumentInspector $documentInspector = null,
142+
?WebspaceManagerInterface $webspaceManager = null
136143
) {
137144
parent::__construct($viewHandler, $tokenStorage);
138145

@@ -147,10 +154,15 @@ public function __construct(
147154
$this->securityChecker = $securityChecker;
148155
$this->displayTabAll = $displayTabAll;
149156
$this->documentInspector = $documentInspector;
157+
$this->webspaceManager = $webspaceManager;
150158

151159
if (null === $this->documentInspector) {
152160
@trigger_deprecation('sulu/article-bundle', '2.5', 'Instantiating the ArticleController without the $documentInspector argument is deprecated!');
153161
}
162+
163+
if (null === $this->webspaceManager) {
164+
@trigger_deprecation('sulu/article-bundle', '2.6', 'Instantiating the ArticleController without the $webspaceManager argument is deprecated!');
165+
}
154166
}
155167

156168
/**
@@ -177,6 +189,9 @@ protected function getFieldDescriptors(): array
177189
->setSearchField('title')
178190
->setSearchability(FieldDescriptor::SEARCHABILITY_YES)
179191
->build(),
192+
'mainWebspace' => ElasticSearchFieldDescriptor::create('mainWebspace', 'public.main_webspace')
193+
->setSearchability(FieldDescriptor::SEARCHABILITY_NO)
194+
->build(),
180195
'creatorFullName' => ElasticSearchFieldDescriptor::create('creatorFullName', 'sulu_article.list.creator')
181196
->setSortField('creatorFullName.raw')
182197
->build(),
@@ -246,6 +261,7 @@ public function cgetAction(Request $request): Response
246261
* tagId?: string,
247262
* pageId?: string,
248263
* publishedState?: string,
264+
* mainWebspace?: string,
249265
* } $filter */
250266
$filter = $request->query->all()['filter'] ?? [];
251267

@@ -312,14 +328,20 @@ public function cgetAction(Request $request): Response
312328
$search->addQuery(new TermQuery('excerpt.tags.id', $tagId), BoolQuery::MUST);
313329
}
314330

315-
if ($pageId = $request->get('pageId', $filter['pageId'] ?? null)) {
316-
$search->addQuery(new TermQuery('parent_page_uuid', $pageId), BoolQuery::MUST);
331+
$pageIdFilter = $request->get('pageId', $filter['pageId'] ?? null);
332+
if (\is_string($pageIdFilter) && '' !== $pageIdFilter) {
333+
$search->addQuery(new TermQuery('parent_page_uuid', $pageIdFilter), BoolQuery::MUST);
317334
}
318335

319336
if ($workflowStage = $request->get('workflowStage', $filter['publishedState'] ?? null)) {
320337
$search->addQuery(new TermQuery('published_state', 'published' === $workflowStage), BoolQuery::MUST);
321338
}
322339

340+
$mainWebspaceFilter = $request->get('mainWebspace', $filter['mainWebspace'] ?? null);
341+
if (\is_string($mainWebspaceFilter) && '' !== $mainWebspaceFilter) {
342+
$search->addQuery(new TermQuery('main_webspace', $mainWebspaceFilter), BoolQuery::MUST);
343+
}
344+
323345
if ($this->getBooleanRequestParameter($request, 'exclude-shadows', false, false)) {
324346
$search->addQuery(new TermQuery('localization_state.state', 'shadow'), BoolQuery::MUST_NOT);
325347
}
@@ -376,9 +398,19 @@ function(FieldDescriptorInterface $fieldDescriptor) use ($fields) {
376398
$searchResult = $repository->findRaw($search);
377399
$result = [];
378400
foreach ($searchResult as $document) {
379-
$documentData = $this->normalize($document['_source'], $fieldDescriptors);
401+
if (!\is_array($document) || !isset($document['_source'])) {
402+
continue;
403+
}
404+
405+
/** @var array<string, mixed> $source */
406+
$source = $document['_source'];
407+
$documentData = $this->normalize($source, $fieldDescriptors);
380408
$documentData['ghostLocale'] = 'ghost' == $documentData['localizationState']['state'] ? $documentData['localizationState']['locale'] : null;
381409

410+
$mainWebspace = $source['main_webspace'] ?? null;
411+
$webspace = $this->webspaceManager && \is_string($mainWebspace) ? $this->webspaceManager->getWebspaceCollection()->getWebspace($mainWebspace) : null;
412+
$documentData['mainWebspace'] = $webspace ? $webspace->getName() : $mainWebspace;
413+
382414
if (false !== ($index = \array_search($documentData['id'], $ids))) {
383415
$result[$index] = $documentData;
384416
} else {

Metadata/ListMetadataVisitor.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Sulu\Bundle\AdminBundle\Metadata\ListMetadata\ListMetadataVisitorInterface;
1616
use Sulu\Component\Content\Compat\Structure\StructureBridge;
1717
use Sulu\Component\Content\Compat\StructureManagerInterface;
18+
use Sulu\Component\Webspace\Manager\WebspaceManagerInterface;
1819

1920
/**
2021
* @final
@@ -30,6 +31,11 @@ class ListMetadataVisitor implements ListMetadataVisitorInterface
3031
*/
3132
private $structureManager;
3233

34+
/**
35+
* @var WebspaceManagerInterface
36+
*/
37+
private $webspaceManager;
38+
3339
/**
3440
* @var array<string, array{
3541
* translation_key: string,
@@ -42,9 +48,13 @@ class ListMetadataVisitor implements ListMetadataVisitorInterface
4248
* translation_key: string,
4349
* }> $articleTypeConfigurations
4450
*/
45-
public function __construct(StructureManagerInterface $structureManager, array $articleTypeConfigurations)
46-
{
51+
public function __construct(
52+
StructureManagerInterface $structureManager,
53+
WebspaceManagerInterface $webspaceManager,
54+
array $articleTypeConfigurations
55+
) {
4756
$this->structureManager = $structureManager;
57+
$this->webspaceManager = $webspaceManager;
4858
$this->articleTypeConfigurations = $articleTypeConfigurations;
4959
}
5060

@@ -54,6 +64,30 @@ public function visitListMetadata(ListMetadata $listMetadata, string $key, strin
5464
return;
5565
}
5666

67+
$this->addMainWebspaceFilter($listMetadata);
68+
$this->adaptTypeFilter($listMetadata);
69+
}
70+
71+
protected function addMainWebspaceFilter(ListMetadata $listMetadata): void
72+
{
73+
$webspaceField = $listMetadata->getField('mainWebspace');
74+
75+
$webspaces = [];
76+
foreach ($this->webspaceManager->getWebspaceCollection() as $webspace) {
77+
$webspaces[$webspace->getKey()] = $webspace->getName();
78+
}
79+
80+
if (1 === \count($webspaces)) {
81+
$listMetadata->removeField('mainWebspace');
82+
83+
return;
84+
}
85+
86+
$webspaceField->setFilterTypeParameters(['options' => $webspaces]);
87+
}
88+
89+
protected function adaptTypeFilter(ListMetadata $listMetadata): void
90+
{
5791
$typeField = $listMetadata->getField('type');
5892

5993
$types = $this->getTypes();

Resources/config/lists/articles.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
visibility="always"
2727
translation="sulu_admin.title"
2828
/>
29+
<property
30+
name="mainWebspace"
31+
visibility="no"
32+
translation="sulu_article.main_webspace"
33+
>
34+
<filter type="select"/>
35+
</property>
2936
<property
3037
name="creatorFullName"
3138
visibility="no"

Resources/config/services.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
<argument>%sulu_article.display_tab_all%</argument>
5858
<argument type="service" id="security.token_storage"/>
5959
<argument type="service" id="sulu_document_manager.document_inspector"/>
60+
<argument type="service" id="sulu_core.webspace.webspace_manager"/>
6061

6162
<tag name="sulu.context" context="admin"/>
6263
</service>
@@ -541,6 +542,7 @@
541542
class="Sulu\Bundle\ArticleBundle\Metadata\ListMetadataVisitor"
542543
>
543544
<argument type="service" id="sulu.content.structure_manager"/>
545+
<argument type="service" id="sulu_core.webspace.webspace_manager" />
544546
<argument>%sulu_article.types%</argument>
545547

546548
<tag name="sulu_admin.list_metadata_visitor"/>

Tests/Functional/Controller/ArticleControllerTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,4 +1857,92 @@ private function getRoute($title)
18571857
{
18581858
return '/articles/' . Urlizer::urlize($title);
18591859
}
1860+
1861+
public function testCGetFilterByMainWebspace()
1862+
{
1863+
// Create article with custom webspace
1864+
$article1 = $this->testPost('Article in sulu_io');
1865+
$this->client->jsonRequest(
1866+
'PUT',
1867+
'/api/articles/' . $article1['id'] . '?locale=de',
1868+
[
1869+
'title' => 'Article in sulu_io',
1870+
'template' => 'default',
1871+
'mainWebspace' => 'sulu_io',
1872+
]
1873+
);
1874+
$this->flush();
1875+
1876+
// Create article with test webspace
1877+
$article2 = $this->testPost('Article in test');
1878+
$this->client->jsonRequest(
1879+
'PUT',
1880+
'/api/articles/' . $article2['id'] . '?locale=de',
1881+
[
1882+
'title' => 'Article in test',
1883+
'template' => 'default',
1884+
'mainWebspace' => 'test',
1885+
]
1886+
);
1887+
$this->flush();
1888+
1889+
// Filter by sulu_io webspace
1890+
$this->client->jsonRequest('GET', '/api/articles?locale=de&mainWebspace=sulu_io&fields=title,mainWebspace');
1891+
$this->assertHttpStatusCode(200, $this->client->getResponse());
1892+
$response = \json_decode($this->client->getResponse()->getContent(), true);
1893+
1894+
$this->assertEquals(1, $response['total']);
1895+
$this->assertCount(1, $response['_embedded']['articles']);
1896+
$this->assertEquals($article1['id'], $response['_embedded']['articles'][0]['id']);
1897+
1898+
// Filter by test webspace
1899+
$this->client->jsonRequest('GET', '/api/articles?locale=de&mainWebspace=test&fields=title,mainWebspace');
1900+
$this->assertHttpStatusCode(200, $this->client->getResponse());
1901+
$response = \json_decode($this->client->getResponse()->getContent(), true);
1902+
1903+
$this->assertEquals(1, $response['total']);
1904+
$this->assertCount(1, $response['_embedded']['articles']);
1905+
$this->assertEquals($article2['id'], $response['_embedded']['articles'][0]['id']);
1906+
}
1907+
1908+
public function testCGetMainWebspaceField()
1909+
{
1910+
$article = $this->testPost('Test Article');
1911+
$this->client->jsonRequest(
1912+
'PUT',
1913+
'/api/articles/' . $article['id'] . '?locale=de',
1914+
[
1915+
'title' => 'Test Article',
1916+
'template' => 'default',
1917+
'mainWebspace' => 'sulu_io',
1918+
]
1919+
);
1920+
$this->flush();
1921+
1922+
// Request with mainWebspace field
1923+
$this->client->jsonRequest('GET', '/api/articles?locale=de&fields=id,title,mainWebspace');
1924+
$this->assertHttpStatusCode(200, $this->client->getResponse());
1925+
$response = \json_decode($this->client->getResponse()->getContent(), true);
1926+
1927+
$this->assertEquals(1, $response['total']);
1928+
$this->assertArrayHasKey('mainWebspace', $response['_embedded']['articles'][0]);
1929+
1930+
// mainWebspace should contain the webspace name, not the key
1931+
$this->assertIsString($response['_embedded']['articles'][0]['mainWebspace']);
1932+
}
1933+
1934+
public function testCGetMainWebspaceWithNonExistentWebspace()
1935+
{
1936+
// Create article with custom webspace
1937+
$article = $this->testPost('Test Article');
1938+
$this->flush();
1939+
1940+
// Filter by non-existent webspace
1941+
$this->client->jsonRequest('GET', '/api/articles?locale=de&mainWebspace=nonexistent&fields=title,mainWebspace');
1942+
$this->assertHttpStatusCode(200, $this->client->getResponse());
1943+
$response = \json_decode($this->client->getResponse()->getContent(), true);
1944+
1945+
$this->assertEquals(0, $response['total']);
1946+
$this->assertCount(0, $response['_embedded']['articles']);
1947+
}
18601948
}

0 commit comments

Comments
 (0)