|
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\Document\Serializer; |
|
13
|
|
|
|
|
14
|
|
|
use JMS\Serializer\EventDispatcher\Events; |
|
15
|
|
|
use JMS\Serializer\EventDispatcher\EventSubscriberInterface; |
|
16
|
|
|
use JMS\Serializer\EventDispatcher\ObjectEvent; |
|
17
|
|
|
use ProxyManager\Factory\LazyLoadingValueHolderFactory; |
|
18
|
|
|
use ProxyManager\Proxy\LazyLoadingInterface; |
|
19
|
|
|
use ProxyManager\Proxy\VirtualProxyInterface; |
|
20
|
|
|
use Sulu\Bundle\ArticleBundle\Document\ArticleDocument; |
|
21
|
|
|
use Sulu\Bundle\ArticleBundle\Document\ArticleInterface; |
|
22
|
|
|
use Sulu\Bundle\ArticleBundle\Document\ArticlePageDocument; |
|
23
|
|
|
use Sulu\Component\Content\Compat\StructureInterface; |
|
24
|
|
|
use Sulu\Component\Content\Compat\StructureManagerInterface; |
|
25
|
|
|
use Sulu\Component\Content\ContentTypeManagerInterface; |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* Extends serializer with addtional functionallity to prepare article(-page) data. |
|
29
|
|
|
*/ |
|
30
|
|
|
class ArticleWebsiteSubscriber implements EventSubscriberInterface |
|
31
|
|
|
{ |
|
32
|
|
|
/** |
|
33
|
|
|
* @var StructureManagerInterface |
|
34
|
|
|
*/ |
|
35
|
|
|
private $structureManager; |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* @var ContentTypeManagerInterface |
|
39
|
|
|
*/ |
|
40
|
|
|
private $contentTypeManager; |
|
41
|
|
|
|
|
42
|
|
|
/** |
|
43
|
|
|
* @var LazyLoadingValueHolderFactory |
|
44
|
|
|
*/ |
|
45
|
|
|
private $proxyFactory; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* @param StructureManagerInterface $structureManager |
|
49
|
|
|
* @param ContentTypeManagerInterface $contentTypeManager |
|
50
|
|
|
* @param LazyLoadingValueHolderFactory $proxyFactory |
|
51
|
|
|
*/ |
|
52
|
|
|
public function __construct( |
|
53
|
|
|
StructureManagerInterface $structureManager, |
|
54
|
|
|
ContentTypeManagerInterface $contentTypeManager, |
|
55
|
|
|
LazyLoadingValueHolderFactory $proxyFactory |
|
56
|
|
|
) { |
|
57
|
|
|
$this->structureManager = $structureManager; |
|
58
|
|
|
$this->contentTypeManager = $contentTypeManager; |
|
59
|
|
|
$this->proxyFactory = $proxyFactory; |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* {@inheritdoc} |
|
64
|
|
|
*/ |
|
65
|
|
|
public static function getSubscribedEvents() |
|
66
|
|
|
{ |
|
67
|
|
|
return [ |
|
68
|
|
|
[ |
|
69
|
|
|
'event' => Events::POST_SERIALIZE, |
|
70
|
|
|
'format' => 'array', |
|
71
|
|
|
'method' => 'resolveContentOnPostSerialize', |
|
72
|
|
|
], |
|
73
|
|
|
[ |
|
74
|
|
|
'event' => Events::POST_SERIALIZE, |
|
75
|
|
|
'format' => 'array', |
|
76
|
|
|
'method' => 'resolveContentForArticleOnPostSerialize', |
|
77
|
|
|
], |
|
78
|
|
|
[ |
|
79
|
|
|
'event' => Events::POST_SERIALIZE, |
|
80
|
|
|
'format' => 'array', |
|
81
|
|
|
'method' => 'resolveContentForArticlePageOnPostSerialize', |
|
82
|
|
|
], |
|
83
|
|
|
[ |
|
84
|
|
|
'event' => Events::POST_SERIALIZE, |
|
85
|
|
|
'format' => 'array', |
|
86
|
|
|
'method' => 'appendPageData', |
|
87
|
|
|
], |
|
88
|
|
|
]; |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
/** |
|
92
|
|
|
* Resolve content on serialization. |
|
93
|
|
|
* |
|
94
|
|
|
* @param ObjectEvent $event |
|
95
|
|
|
*/ |
|
96
|
|
|
public function resolveContentOnPostSerialize(ObjectEvent $event) |
|
97
|
|
|
{ |
|
98
|
|
|
$article = $event->getObject(); |
|
99
|
|
|
$visitor = $event->getVisitor(); |
|
100
|
|
|
$context = $event->getContext(); |
|
101
|
|
|
|
|
102
|
|
|
if (!$article instanceof ArticleInterface || !$context->attributes->containsKey('website')) { |
|
103
|
|
|
return; |
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
|
|
$visitor->addData('uuid', $context->accept($article->getArticleUuid())); |
|
107
|
|
|
$visitor->addData('pageUuid', $context->accept($article->getPageUuid())); |
|
108
|
|
|
$visitor->addData('extension', $context->accept($article->getExtensionsData()->toArray())); |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
|
|
/** |
|
112
|
|
|
* Append page data. |
|
113
|
|
|
* |
|
114
|
|
|
* @param ObjectEvent $event |
|
115
|
|
|
*/ |
|
116
|
|
|
public function appendPageData(ObjectEvent $event) |
|
117
|
|
|
{ |
|
118
|
|
|
$article = $event->getObject(); |
|
119
|
|
|
$visitor = $event->getVisitor(); |
|
120
|
|
|
$context = $event->getContext(); |
|
121
|
|
|
|
|
122
|
|
|
if ($article instanceof ArticlePageDocument) { |
|
123
|
|
|
$article = $article->getParent(); |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
if (!$article instanceof ArticleDocument || !$context->attributes->containsKey('website')) { |
|
127
|
|
|
return; |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
$pageNumber = 1; |
|
131
|
|
|
if ($context->attributes->containsKey('pageNumber')) { |
|
132
|
|
|
$pageNumber = $context->attributes->get('pageNumber')->get(); |
|
133
|
|
|
} |
|
134
|
|
|
|
|
135
|
|
|
$visitor->addData('page', $pageNumber); |
|
136
|
|
|
$visitor->addData('pages', $context->accept($article->getPages())); |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
/** |
|
140
|
|
|
* Resolve content on serialization. |
|
141
|
|
|
* |
|
142
|
|
|
* @param ObjectEvent $event |
|
143
|
|
|
*/ |
|
144
|
|
|
public function resolveContentForArticleOnPostSerialize(ObjectEvent $event) |
|
145
|
|
|
{ |
|
146
|
|
|
$article = $event->getObject(); |
|
147
|
|
|
$visitor = $event->getVisitor(); |
|
148
|
|
|
$context = $event->getContext(); |
|
149
|
|
|
|
|
150
|
|
|
if (!$article instanceof ArticleDocument || !$context->attributes->containsKey('website')) { |
|
151
|
|
|
return; |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
$children = $article->getChildren(); |
|
155
|
|
|
|
|
156
|
|
|
if (null !== $children && $context->attributes->containsKey('pageNumber')) { |
|
157
|
|
|
$pages = array_values(iterator_to_array($children)); |
|
158
|
|
|
$pageNumber = $context->attributes->get('pageNumber')->get(); |
|
159
|
|
|
if ($pageNumber !== 1) { |
|
160
|
|
|
$article = $pages[$pageNumber - 2]; |
|
161
|
|
|
} |
|
162
|
|
|
} |
|
163
|
|
|
|
|
164
|
|
|
$content = $this->resolve($article); |
|
165
|
|
|
foreach ($content as $name => $value) { |
|
166
|
|
|
$visitor->addData($name, $value); |
|
167
|
|
|
} |
|
168
|
|
|
} |
|
169
|
|
|
|
|
170
|
|
|
/** |
|
171
|
|
|
* Resolve content on serialization. |
|
172
|
|
|
* |
|
173
|
|
|
* @param ObjectEvent $event |
|
174
|
|
|
*/ |
|
175
|
|
|
public function resolveContentForArticlePageOnPostSerialize(ObjectEvent $event) |
|
176
|
|
|
{ |
|
177
|
|
|
$article = $event->getObject(); |
|
178
|
|
|
$visitor = $event->getVisitor(); |
|
179
|
|
|
$context = $event->getContext(); |
|
180
|
|
|
|
|
181
|
|
|
if (!$article instanceof ArticlePageDocument || !$context->attributes->containsKey('website')) { |
|
182
|
|
|
return; |
|
183
|
|
|
} |
|
184
|
|
|
|
|
185
|
|
|
$content = $this->resolve($article); |
|
186
|
|
|
foreach ($content as $name => $value) { |
|
187
|
|
|
$visitor->addData($name, $value); |
|
188
|
|
|
} |
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
/** |
|
192
|
|
|
* Returns content and view of article. |
|
193
|
|
|
* |
|
194
|
|
|
* @param ArticleInterface $article |
|
195
|
|
|
* |
|
196
|
|
|
* @return array |
|
197
|
|
|
*/ |
|
198
|
|
|
private function resolve(ArticleInterface $article) |
|
199
|
|
|
{ |
|
200
|
|
|
$structure = $this->structureManager->getStructure($article->getStructureType(), 'article'); |
|
201
|
|
|
$structure->setDocument($article); |
|
202
|
|
|
|
|
203
|
|
|
$data = $article->getStructure()->toArray(); |
|
204
|
|
|
|
|
205
|
|
|
return [ |
|
206
|
|
|
'content' => $this->createContentProxy($structure, $data), |
|
207
|
|
|
'view' => $this->createViewProxy($structure, $data), |
|
208
|
|
|
]; |
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
|
|
/** |
|
212
|
|
|
* Create content-proxy for given structure. |
|
213
|
|
|
* |
|
214
|
|
|
* @param StructureInterface $structure |
|
215
|
|
|
* @param array $data |
|
216
|
|
|
* |
|
217
|
|
|
* @return VirtualProxyInterface |
|
218
|
|
|
*/ |
|
219
|
|
View Code Duplication |
private function createContentProxy($structure, $data) |
|
|
|
|
|
|
220
|
|
|
{ |
|
221
|
|
|
return $this->proxyFactory->createProxy( |
|
222
|
|
|
\ArrayObject::class, |
|
223
|
|
|
function ( |
|
224
|
|
|
&$wrappedObject, |
|
225
|
|
|
LazyLoadingInterface $proxy, |
|
226
|
|
|
$method, |
|
227
|
|
|
array $parameters, |
|
228
|
|
|
&$initializer |
|
229
|
|
|
) use ($structure, $data) { |
|
230
|
|
|
$content = []; |
|
231
|
|
|
foreach ($structure->getProperties(true) as $child) { |
|
232
|
|
|
if (array_key_exists($child->getName(), $data)) { |
|
233
|
|
|
$child->setValue($data[$child->getName()]); |
|
234
|
|
|
} |
|
235
|
|
|
|
|
236
|
|
|
$contentType = $this->contentTypeManager->get($child->getContentTypeName()); |
|
237
|
|
|
$content[$child->getName()] = $contentType->getContentData($child); |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
$initializer = null; |
|
241
|
|
|
$wrappedObject = new \ArrayObject($content); |
|
242
|
|
|
|
|
243
|
|
|
return true; |
|
244
|
|
|
} |
|
245
|
|
|
); |
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
|
/** |
|
249
|
|
|
* Create view-proxy for given structure. |
|
250
|
|
|
* |
|
251
|
|
|
* @param StructureInterface $structure |
|
252
|
|
|
* @param array $data |
|
253
|
|
|
* |
|
254
|
|
|
* @return VirtualProxyInterface |
|
255
|
|
|
*/ |
|
256
|
|
View Code Duplication |
private function createViewProxy($structure, array $data) |
|
|
|
|
|
|
257
|
|
|
{ |
|
258
|
|
|
return $this->proxyFactory->createProxy( |
|
259
|
|
|
\ArrayObject::class, |
|
260
|
|
|
function ( |
|
261
|
|
|
&$wrappedObject, |
|
262
|
|
|
LazyLoadingInterface $proxy, |
|
263
|
|
|
$method, |
|
264
|
|
|
array $parameters, |
|
265
|
|
|
&$initializer |
|
266
|
|
|
) use ($structure, $data) { |
|
267
|
|
|
$view = []; |
|
268
|
|
|
foreach ($structure->getProperties(true) as $child) { |
|
269
|
|
|
if (array_key_exists($child->getName(), $data)) { |
|
270
|
|
|
$child->setValue($data[$child->getName()]); |
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
$contentType = $this->contentTypeManager->get($child->getContentTypeName()); |
|
274
|
|
|
$view[$child->getName()] = $contentType->getViewData($child); |
|
275
|
|
|
} |
|
276
|
|
|
|
|
277
|
|
|
$initializer = null; |
|
278
|
|
|
$wrappedObject = new \ArrayObject($view); |
|
279
|
|
|
|
|
280
|
|
|
return true; |
|
281
|
|
|
} |
|
282
|
|
|
); |
|
283
|
|
|
} |
|
284
|
|
|
} |
|
285
|
|
|
|
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.