Completed
Pull Request — develop (#206)
by Wachter
14:04
created

PageTreeRepository::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 4
1
<?php
2
3
/*
4
 * This file is part of Sulu.
5
 *
6
 * (c) MASSIVE ART WebServices 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\PageTree;
13
14
use Sulu\Bundle\ArticleBundle\Content\PageTreeRouteContentType;
15
use Sulu\Bundle\ArticleBundle\Document\ArticleDocument;
16
use Sulu\Bundle\ArticleBundle\Document\ArticleInterface;
17
use Sulu\Bundle\ContentBundle\Document\BasePageDocument;
18
use Sulu\Component\Content\Document\WorkflowStage;
19
use Sulu\Component\Content\Metadata\Factory\StructureMetadataFactoryInterface;
20
use Sulu\Component\Content\Metadata\PropertyMetadata;
21
use Sulu\Component\Content\Metadata\StructureMetadata;
22
use Sulu\Component\DocumentManager\DocumentInspector;
23
use Sulu\Component\DocumentManager\DocumentManagerInterface;
24
use Sulu\Component\DocumentManager\PropertyEncoder;
25
26
/**
27
 * Update the route of articles synchronously.
28
 */
29
class PageTreeRepository implements PageTreeUpdaterInterface, PageTreeMoverInterface
30
{
31
    const ROUTE_PROPERTY = 'routePath';
32
    const TAG_NAME = 'sulu_article.article_route';
33
34
    /**
35
     * @var DocumentManagerInterface
36
     */
37
    private $documentManager;
38
39
    /**
40
     * @var StructureMetadataFactoryInterface
41
     */
42
    protected $metadataFactory;
43
44
    /**
45
     * @var PropertyEncoder
46
     */
47
    protected $propertyEncoder;
48
49
    /**
50
     * @var DocumentInspector
51
     */
52
    protected $documentInspector;
53
54
    /**
55
     * @param DocumentManagerInterface $documentManager
56
     * @param StructureMetadataFactoryInterface $metadataFactory
57
     * @param PropertyEncoder $propertyEncoder
58
     * @param DocumentInspector $documentInspector
59
     */
60
    public function __construct(
61
        DocumentManagerInterface $documentManager,
62
        StructureMetadataFactoryInterface $metadataFactory,
63
        PropertyEncoder $propertyEncoder,
64
        DocumentInspector $documentInspector
65
    ) {
66
        $this->documentManager = $documentManager;
67
        $this->metadataFactory = $metadataFactory;
68
        $this->propertyEncoder = $propertyEncoder;
69
        $this->documentInspector = $documentInspector;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75 View Code Duplication
    public function update(BasePageDocument $document)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
76
    {
77
        $articles = $this->findLinkedArticles('page', $document->getUuid(), $document->getLocale());
78
        foreach ($articles as $article) {
79
            $this->updateArticle($article, $document);
0 ignored issues
show
Compatibility introduced by
$article of type object<Sulu\Bundle\Artic...ument\ArticleInterface> is not a sub-type of object<Sulu\Bundle\Artic...cument\ArticleDocument>. It seems like you assume a concrete implementation of the interface Sulu\Bundle\ArticleBundl...cument\ArticleInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
80
        }
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 View Code Duplication
    public function move($source, BasePageDocument $document)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
87
    {
88
        $articles = $this->findLinkedArticles('page-path', $source, $document->getLocale());
89
        foreach ($articles as $article) {
90
            $this->updateArticle($article, $document);
0 ignored issues
show
Compatibility introduced by
$article of type object<Sulu\Bundle\Artic...ument\ArticleInterface> is not a sub-type of object<Sulu\Bundle\Artic...cument\ArticleDocument>. It seems like you assume a concrete implementation of the interface Sulu\Bundle\ArticleBundl...cument\ArticleInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
91
        }
92
    }
93
94
    /**
95
     * Find articles linked to the given page.
96
     *
97
     * @param string $field
98
     * @param string $value
99
     * @param string $locale
100
     *
101
     * @return ArticleInterface[]
102
     */
103
    private function findLinkedArticles($field, $value, $locale)
104
    {
105
        $where = [];
106
        foreach ($this->metadataFactory->getStructures('article') as $metadata) {
107
            $property = $this->getRoutePathPropertyName($metadata);
108
            if (null === $property || PageTreeRouteContentType::NAME !== $property->getType()) {
109
                continue;
110
            }
111
112
            $where[] = sprintf(
113
                '([%s] = "%s" AND [%s-%s] = "%s")',
114
                $this->propertyEncoder->localizedSystemName('template', $locale),
115
                $metadata->getName(),
116
                $this->propertyEncoder->localizedContentName($property->getName(), $locale),
117
                $field,
118
                $value
119
            );
120
        }
121
122
        if (0 === count($where)) {
123
            return [];
124
        }
125
126
        $query = $this->documentManager->createQuery(
127
            sprintf(
128
                'SELECT * FROM [nt:unstructured] WHERE [jcr:mixinTypes] = "sulu:article" AND (%s)',
129
                implode(' OR ', $where)
130
            ),
131
            $locale
132
        );
133
134
        return $query->execute();
135
    }
136
137
    /**
138
     * Update route of given article.
139
     *
140
     * @param ArticleDocument $article
141
     * @param BasePageDocument $document
142
     */
143
    private function updateArticle(ArticleDocument $article, BasePageDocument $document)
144
    {
145
        $locale = $document->getLocale();
146
        $resourceSegment = $document->getResourceSegment();
147
148
        $property = $this->getRoutePathPropertyNameByStructureType($article->getStructureType());
149
        $propertyName = $this->propertyEncoder->localizedContentName($property->getName(), $locale);
150
151
        $node = $this->documentInspector->getNode($article);
152
        $node->setProperty($propertyName . '-page', $document->getUuid());
153
        $node->setProperty($propertyName . '-page-path', $resourceSegment);
154
155
        $suffix = $node->getPropertyValueWithDefault($propertyName . '-suffix', null);
156
        if ($suffix) {
157
            $path = rtrim($resourceSegment, '/') . '/' . $suffix;
158
            $node->setProperty($propertyName, $path);
159
            $article->setRoutePath($path);
160
        }
161
162
        if (WorkflowStage::PUBLISHED === $article->getWorkflowStage()) {
163
            $this->documentManager->publish($article, $locale);
164
        }
165
    }
166
167
    /**
168
     * Returns "routePath" property.
169
     *
170
     * @param string $structureType
171
     *
172
     * @return PropertyMetadata
173
     */
174 View Code Duplication
    private function getRoutePathPropertyNameByStructureType($structureType)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
175
    {
176
        $metadata = $this->metadataFactory->getStructureMetadata('article', $structureType);
177
        if ($metadata->hasTag(self::TAG_NAME)) {
178
            return $metadata->getPropertyByTagName(self::TAG_NAME);
179
        }
180
181
        return $metadata->getProperty(self::ROUTE_PROPERTY);
182
    }
183
184
    /**
185
     * Returns "routePath" property.
186
     *
187
     * @param StructureMetadata $metadata
188
     *
189
     * @return PropertyMetadata
190
     */
191 View Code Duplication
    private function getRoutePathPropertyName(StructureMetadata $metadata)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
192
    {
193
        if ($metadata->hasTag(self::TAG_NAME)) {
194
            return $metadata->getPropertyByTagName(self::TAG_NAME);
195
        }
196
197
        if (!$metadata->hasProperty(self::ROUTE_PROPERTY)) {
198
            return;
199
        }
200
201
        return $metadata->getProperty(self::ROUTE_PROPERTY);
202
    }
203
}
204