Completed
Push — develop ( 73e5fc...9c1818 )
by Wachter
41:05 queued 26:13
created

ArticleSitemapProvider::setAlternatives()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 0
cts 4
cp 0
rs 9.6666
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
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) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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