|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/* |
|
4
|
|
|
* This file is part of Sulu. |
|
5
|
|
|
* |
|
6
|
|
|
* (c) Sulu GmbH |
|
7
|
|
|
* |
|
8
|
|
|
* This source file is subject to the MIT license that is bundled |
|
9
|
|
|
* with this source code in the file LICENSE. |
|
10
|
|
|
*/ |
|
11
|
|
|
|
|
12
|
|
|
namespace Sulu\Bundle\ArticleBundle\Sitemap; |
|
13
|
|
|
|
|
14
|
|
|
use ONGR\ElasticsearchBundle\Service\Manager; |
|
15
|
|
|
use ONGR\ElasticsearchBundle\Service\Repository; |
|
16
|
|
|
use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery; |
|
17
|
|
|
use ONGR\ElasticsearchDSL\Query\TermLevel\TermQuery; |
|
18
|
|
|
use Sulu\Bundle\ArticleBundle\Document\ArticleViewDocumentInterface; |
|
19
|
|
|
use Sulu\Bundle\ArticleBundle\Document\Index\DocumentFactoryInterface; |
|
20
|
|
|
use Sulu\Bundle\WebsiteBundle\Sitemap\Sitemap; |
|
21
|
|
|
use Sulu\Bundle\WebsiteBundle\Sitemap\SitemapAlternateLink; |
|
22
|
|
|
use Sulu\Bundle\WebsiteBundle\Sitemap\SitemapProviderInterface; |
|
23
|
|
|
use Sulu\Bundle\WebsiteBundle\Sitemap\SitemapUrl; |
|
24
|
|
|
use Sulu\Component\Webspace\Manager\WebspaceManagerInterface; |
|
25
|
|
|
|
|
26
|
|
|
/** |
|
27
|
|
|
* Integrates articles into sitemap. |
|
28
|
|
|
*/ |
|
29
|
|
|
class ArticleSitemapProvider implements SitemapProviderInterface |
|
30
|
|
|
{ |
|
31
|
|
|
/** |
|
32
|
|
|
* @var Manager |
|
33
|
|
|
*/ |
|
34
|
|
|
private $manager; |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* @var DocumentFactoryInterface |
|
38
|
|
|
*/ |
|
39
|
|
|
private $documentFactory; |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* @var WebspaceManagerInterface |
|
43
|
|
|
*/ |
|
44
|
|
|
private $webspaceManager; |
|
45
|
|
|
|
|
46
|
|
|
public function __construct( |
|
47
|
|
|
Manager $manager, |
|
48
|
|
|
DocumentFactoryInterface $documentFactory, |
|
49
|
|
|
WebspaceManagerInterface $webspaceManager |
|
50
|
|
|
) { |
|
51
|
|
|
$this->manager = $manager; |
|
52
|
|
|
$this->documentFactory = $documentFactory; |
|
53
|
|
|
$this->webspaceManager = $webspaceManager; |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* {@inheritdoc} |
|
58
|
|
|
*/ |
|
59
|
|
|
public function build($page, $scheme, $host) |
|
60
|
|
|
{ |
|
61
|
|
|
$repository = $this->manager->getRepository($this->documentFactory->getClass('article')); |
|
62
|
|
|
|
|
63
|
|
|
$webspaceKeys = $this->getWebspaceKeysByHost($host); |
|
64
|
|
|
|
|
65
|
|
|
$result = []; |
|
66
|
|
|
$from = 0; |
|
67
|
|
|
$size = 1000; |
|
68
|
|
|
|
|
69
|
|
|
do { |
|
70
|
|
|
$bulk = $this->getBulk($repository, $webspaceKeys, $from, $size); |
|
71
|
|
|
/** @var SitemapUrl[] $alternatives */ |
|
72
|
|
|
$sitemapUrlListByUuid = []; |
|
73
|
|
|
|
|
74
|
|
|
/** @var ArticleViewDocumentInterface $item */ |
|
75
|
|
|
foreach ($bulk as $item) { |
|
76
|
|
|
// Get all webspace keys which are for the current document and current selected webspaces |
|
77
|
|
|
$itemWebspaceKeys = array_intersect( |
|
78
|
|
|
array_merge([$item->getMainWebspace()], $item->getAdditionalWebspaces()), |
|
79
|
|
|
$webspaceKeys |
|
80
|
|
|
); |
|
81
|
|
|
|
|
82
|
|
|
foreach ($itemWebspaceKeys as $itemWebspaceKey) { |
|
83
|
|
|
$url = $this->buildUrl($item, $scheme, $host, $itemWebspaceKey); |
|
84
|
|
|
|
|
85
|
|
|
$result[] = $url; |
|
86
|
|
|
|
|
87
|
|
|
$alternativeUrlsKey = $itemWebspaceKey . '__' . $item->getUuid(); |
|
88
|
|
|
if (!isset($sitemapUrlListByUuid[$alternativeUrlsKey])) { |
|
89
|
|
|
$sitemapUrlListByUuid[$alternativeUrlsKey] = []; |
|
90
|
|
|
} |
|
91
|
|
|
|
|
92
|
|
|
$sitemapUrlListByUuid[$alternativeUrlsKey] = $this->setAlternatives( |
|
93
|
|
|
$sitemapUrlListByUuid[$alternativeUrlsKey], |
|
94
|
|
|
$url |
|
95
|
|
|
); |
|
96
|
|
|
} |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
$from += $size; |
|
100
|
|
|
} while ($bulk->count() > $from && $from < static::PAGE_SIZE); |
|
101
|
|
|
|
|
102
|
|
|
return $result; |
|
103
|
|
|
} |
|
104
|
|
|
|
|
105
|
|
|
protected function buildUrl(ArticleViewDocumentInterface $articleView, $scheme, $host, $webspaceKey) |
|
106
|
|
|
{ |
|
107
|
|
|
return new SitemapUrl( |
|
108
|
|
|
$this->findUrl($articleView, $scheme, $host, $webspaceKey), |
|
109
|
|
|
$articleView->getLocale(), |
|
110
|
|
|
$articleView->getChanged() |
|
111
|
|
|
); |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
/** |
|
115
|
|
|
* @return string |
|
116
|
|
|
*/ |
|
117
|
|
|
private function findUrl(ArticleViewDocumentInterface $articleView, $scheme, $host, $webspaceKey) |
|
118
|
|
|
{ |
|
119
|
|
|
return $this->webspaceManager->findUrlByResourceLocator( |
|
120
|
|
|
$articleView->getRoutePath(), |
|
121
|
|
|
null, |
|
122
|
|
|
$articleView->getLocale(), |
|
123
|
|
|
$webspaceKey, |
|
124
|
|
|
$host, |
|
125
|
|
|
$scheme |
|
126
|
|
|
); |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
|
|
/** |
|
130
|
|
|
* Set alternatives to sitemap url. |
|
131
|
|
|
* |
|
132
|
|
|
* @param SitemapUrl[] $sitemapUrlList |
|
133
|
|
|
* @param SitemapUrl $sitemapUrl |
|
134
|
|
|
* |
|
135
|
|
|
* @return SitemapUrl[] |
|
136
|
|
|
*/ |
|
137
|
|
|
private function setAlternatives(array $sitemapUrlList, SitemapUrl $sitemapUrl) |
|
138
|
|
|
{ |
|
139
|
|
|
foreach ($sitemapUrlList as $sitemapUrlFromList) { |
|
140
|
|
|
// Add current as alternative to exist. |
|
141
|
|
|
$sitemapUrlFromList->addAlternateLink( |
|
142
|
|
|
new SitemapAlternateLink($sitemapUrl->getLoc(), $sitemapUrl->getLocale()) |
|
143
|
|
|
); |
|
144
|
|
|
|
|
145
|
|
|
// Add others as alternative to current. |
|
146
|
|
|
$sitemapUrl->addAlternateLink( |
|
147
|
|
|
new SitemapAlternateLink($sitemapUrlFromList->getLoc(), $sitemapUrlFromList->getLocale()) |
|
148
|
|
|
); |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
$sitemapUrlList[] = $sitemapUrl; |
|
152
|
|
|
|
|
153
|
|
|
return $sitemapUrlList; |
|
154
|
|
|
} |
|
155
|
|
|
|
|
156
|
|
|
private function getBulk(Repository $repository, $webspaceKeys, $from, $size) |
|
157
|
|
|
{ |
|
158
|
|
|
$search = $repository->createSearch() |
|
159
|
|
|
->addQuery(new TermQuery('seo.hide_in_sitemap', 'false')) |
|
160
|
|
|
->setFrom($from) |
|
161
|
|
|
->setSize($size); |
|
162
|
|
|
|
|
163
|
|
|
$webspaceQuery = new BoolQuery(); |
|
164
|
|
View Code Duplication |
foreach ($webspaceKeys as $webspaceKey) { |
|
|
|
|
|
|
165
|
|
|
$webspaceQuery->add(new TermQuery('main_webspace', $webspaceKey), BoolQuery::SHOULD); |
|
166
|
|
|
$webspaceQuery->add(new TermQuery('additional_webspaces', $webspaceKey), BoolQuery::SHOULD); |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
$search->addQuery($webspaceQuery); |
|
170
|
|
|
|
|
171
|
|
|
return $repository->findDocuments($search); |
|
172
|
|
|
} |
|
173
|
|
|
|
|
174
|
|
|
/** |
|
175
|
|
|
* {@inheritdoc} |
|
176
|
|
|
*/ |
|
177
|
|
|
public function createSitemap($scheme, $host) |
|
178
|
|
|
{ |
|
179
|
|
|
return new Sitemap($this->getAlias(), $this->getMaxPage($scheme, $host)); |
|
180
|
|
|
} |
|
181
|
|
|
|
|
182
|
|
|
/** |
|
183
|
|
|
* {@inheritdoc} |
|
184
|
|
|
*/ |
|
185
|
|
|
public function getMaxPage($schema, $host) |
|
186
|
|
|
{ |
|
187
|
|
|
$repository = $this->manager->getRepository($this->documentFactory->getClass('article')); |
|
188
|
|
|
$search = $repository->createSearch() |
|
189
|
|
|
->addQuery(new TermQuery('seo.hide_in_sitemap', 'false')); |
|
190
|
|
|
|
|
191
|
|
|
$webspaceKeys = $this->getWebspaceKeysByHost($host); |
|
192
|
|
|
|
|
193
|
|
|
$webspaceQuery = new BoolQuery(); |
|
194
|
|
View Code Duplication |
foreach ($webspaceKeys as $webspaceKey) { |
|
|
|
|
|
|
195
|
|
|
$webspaceQuery->add(new TermQuery('main_webspace', $webspaceKey), BoolQuery::SHOULD); |
|
196
|
|
|
$webspaceQuery->add(new TermQuery('additional_webspaces', $webspaceKey), BoolQuery::SHOULD); |
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
|
|
return ceil($repository->count($search) / static::PAGE_SIZE); |
|
200
|
|
|
} |
|
201
|
|
|
|
|
202
|
|
|
/** |
|
203
|
|
|
* @return string[] |
|
204
|
|
|
*/ |
|
205
|
|
|
private function getWebspaceKeysByHost(string $host): array |
|
206
|
|
|
{ |
|
207
|
|
|
$portalInformations = $this->webspaceManager->findPortalInformationsByHostIncludingSubdomains($host); |
|
208
|
|
|
|
|
209
|
|
|
$webspaceKeys = []; |
|
210
|
|
|
foreach ($portalInformations as $portalInformation) { |
|
211
|
|
|
$webspaceKeys[] = $portalInformation->getWebspaceKey(); |
|
212
|
|
|
} |
|
213
|
|
|
|
|
214
|
|
|
return $webspaceKeys; |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
public function getAlias() |
|
218
|
|
|
{ |
|
219
|
|
|
return 'articles'; |
|
220
|
|
|
} |
|
221
|
|
|
} |
|
222
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.