1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* User: jensk |
4
|
|
|
* Date: 13-3-2017 |
5
|
|
|
* Time: 16:24 |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace CloudControl\Cms\storage\factories; |
9
|
|
|
|
10
|
|
|
use CloudControl\Cms\cc\StringUtil; |
11
|
|
|
use CloudControl\Cms\storage\entities\Document; |
12
|
|
|
use CloudControl\Cms\storage\storage\DocumentTypesStorage; |
13
|
|
|
use HTMLPurifier; |
14
|
|
|
use HTMLPurifier_Config; |
15
|
|
|
|
16
|
|
|
class DocumentFactory |
17
|
|
|
{ |
18
|
|
|
private static $purifier; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @param array $postValues |
22
|
|
|
* @param DocumentTypesStorage $documentTypesStorage |
23
|
|
|
* |
24
|
|
|
* @return \CloudControl\Cms\storage\entities\Document |
25
|
|
|
*/ |
26
|
|
|
public static function createDocumentFromPostValues($postValues, DocumentTypesStorage $documentTypesStorage) |
27
|
|
|
{ |
28
|
|
|
$postValues = utf8Convert($postValues); |
29
|
|
|
$documentType = $documentTypesStorage->getDocumentTypeBySlug($postValues['documentType']); |
30
|
|
|
|
31
|
|
|
$staticBricks = $documentType->bricks; |
32
|
|
|
|
33
|
|
|
$documentObj = self::createInitialDocumentObject($postValues, $documentType); |
34
|
|
|
|
35
|
|
|
$fields = self::sanitizeFields($postValues, $documentType); |
36
|
|
|
|
37
|
|
|
$documentObj->fields = $fields; |
38
|
|
|
$documentObj->bricks = array(); |
39
|
|
|
|
40
|
|
|
$documentObj = self::createBrickArrayForDocument($postValues, $documentObj, $staticBricks); |
41
|
|
|
$documentObj = self::createDynamicBrickArrayForDocument($postValues, $documentObj); |
42
|
|
|
|
43
|
|
|
return $documentObj; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @param array $postValues |
48
|
|
|
* @param \stdClass $documentType |
49
|
|
|
* |
50
|
|
|
* @return Document |
51
|
|
|
*/ |
52
|
|
|
private static function createInitialDocumentObject($postValues, $documentType) |
53
|
|
|
{ |
54
|
|
|
$documentObj = new Document(); |
55
|
|
|
$documentObj->title = $postValues['title']; |
56
|
|
|
$documentObj->slug = StringUtil::slugify($postValues['title']); |
57
|
|
|
$documentObj->type = 'document'; |
58
|
|
|
$documentObj->documentType = $documentType->title; |
59
|
|
|
$documentObj->documentTypeSlug = $documentType->slug; |
60
|
|
|
$documentObj->state = isset($postValues['state']) ? 'published' : 'unpublished'; |
61
|
|
|
$documentObj->lastModificationDate = time(); |
62
|
|
|
$documentObj->creationDate = isset($postValues['creationDate']) ? (int)$postValues['creationDate'] : time(); |
63
|
|
|
$documentObj->lastModifiedBy = $_SESSION['cloudcontrol']->username; |
64
|
|
|
|
65
|
|
|
return $documentObj; |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* @param array $postValues |
70
|
|
|
* @param Document $documentObj |
71
|
|
|
* @param array $staticBricks |
72
|
|
|
* |
73
|
|
|
* @return Document |
74
|
|
|
*/ |
75
|
|
|
private static function createBrickArrayForDocument($postValues, $documentObj, $staticBricks) |
76
|
|
|
{ |
77
|
|
|
if (isset($postValues['bricks'])) { |
78
|
|
|
foreach ($postValues['bricks'] as $brickSlug => $brick) { |
79
|
|
|
// Find the current bricktype and check if its multiple |
80
|
|
|
list($staticBrick, $multiple) = self::getStaticBrickAndSetMultiple($staticBricks, $brickSlug); |
81
|
|
|
|
82
|
|
|
if ($multiple) { |
83
|
|
|
$documentObj = self::addMultipleBricks($documentObj, $brick, $staticBrick, $brickSlug); |
84
|
|
|
} else { |
85
|
|
|
$documentObj = self::addSingleBrick($documentObj, $brick, $brickSlug); |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
return $documentObj; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @param array $postValues |
94
|
|
|
* @param Document $documentObj |
95
|
|
|
* |
96
|
|
|
* @return Document |
97
|
|
|
*/ |
98
|
|
View Code Duplication |
private static function createDynamicBrickArrayForDocument($postValues, $documentObj) |
|
|
|
|
99
|
|
|
{ |
100
|
|
|
$documentObj->dynamicBricks = array(); |
101
|
|
|
if (isset($postValues['dynamicBricks'])) { |
102
|
|
|
foreach ($postValues['dynamicBricks'] as $brickTypeSlug => $brick) { |
103
|
|
|
foreach ($brick as $brickContent) { |
104
|
|
|
$brickObj = new \stdClass(); |
105
|
|
|
$brickObj->type = $brickTypeSlug; |
106
|
|
|
$brickObj->fields = self::sanitizeBrickContent($brickContent); |
107
|
|
|
$dynamicBricks = $documentObj->dynamicBricks; |
108
|
|
|
$dynamicBricks[] = $brickObj; |
109
|
|
|
$documentObj->dynamicBricks = $dynamicBricks; |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
return $documentObj; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* @param $staticBricks |
118
|
|
|
* @param $brickSlug |
119
|
|
|
* |
120
|
|
|
* @return array |
121
|
|
|
*/ |
122
|
|
|
private static function getStaticBrickAndSetMultiple($staticBricks, $brickSlug) |
123
|
|
|
{ |
124
|
|
|
$staticBrick = null; |
125
|
|
|
$multiple = false; |
126
|
|
|
foreach ($staticBricks as $staticBrick) { |
127
|
|
|
if ($staticBrick->slug === $brickSlug) { |
128
|
|
|
$multiple = $staticBrick->multiple; |
129
|
|
|
break; |
130
|
|
|
} |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
return array($staticBrick, $multiple); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* @param $staticBrick |
138
|
|
|
* @param $brickInstance |
139
|
|
|
* |
140
|
|
|
* @return \stdClass |
141
|
|
|
*/ |
142
|
|
View Code Duplication |
private static function createBrick($staticBrick, $brickInstance) |
|
|
|
|
143
|
|
|
{ |
144
|
|
|
$brickObj = new \stdClass(); |
145
|
|
|
$brickObj->fields = new \stdClass(); |
146
|
|
|
$brickObj->type = $staticBrick->brickSlug; |
147
|
|
|
|
148
|
|
|
foreach ($brickInstance['fields'] as $fieldName => $fieldValues) { |
149
|
|
|
$purifier = self::getPurifier(); |
150
|
|
|
foreach ($fieldValues as $fieldKey => $value) { |
151
|
|
|
$fieldValues[$fieldKey] = $purifier->purify($value); |
152
|
|
|
} |
153
|
|
|
$brickObj->fields->$fieldName = $fieldValues; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
return $brickObj; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* @param $documentObj |
161
|
|
|
* @param $brick |
162
|
|
|
* @param $staticBrick |
163
|
|
|
* @param $brickSlug |
164
|
|
|
* |
165
|
|
|
* @return mixed |
166
|
|
|
*/ |
167
|
|
|
private static function addMultipleBricks($documentObj, $brick, $staticBrick, $brickSlug) |
168
|
|
|
{ |
169
|
|
|
$brickArray = array(); |
170
|
|
|
foreach ($brick as $brickInstance) { |
171
|
|
|
$brickObj = self::createBrick($staticBrick, $brickInstance); |
172
|
|
|
$brickArray[] = $brickObj; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
$bricks = $documentObj->bricks; |
176
|
|
|
$bricks[$brickSlug] = $brickArray; |
177
|
|
|
$documentObj->bricks = $bricks; |
178
|
|
|
|
179
|
|
|
return $documentObj; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* @param $documentObj |
184
|
|
|
* @param $brick |
185
|
|
|
* @param $brickSlug |
186
|
|
|
* |
187
|
|
|
* @return mixed |
188
|
|
|
*/ |
189
|
|
|
private static function addSingleBrick($documentObj, $brick, $brickSlug) |
190
|
|
|
{ |
191
|
|
|
$bricks = $documentObj->bricks; |
192
|
|
|
|
193
|
|
|
$purifier = self::getPurifier(); |
194
|
|
|
foreach ($brick['fields'] as $fieldKey => $values) { |
195
|
|
|
foreach ($values as $valueKey => $value) { |
196
|
|
|
$values[$valueKey] = $purifier->purify($value); |
197
|
|
|
} |
198
|
|
|
$brick['fields'][$fieldKey] = $values; |
199
|
|
|
} |
200
|
|
|
$bricks[$brickSlug] = $brick; |
201
|
|
|
|
202
|
|
|
$documentObj->bricks = $bricks; |
203
|
|
|
return $documentObj; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* @return HTMLPurifier |
208
|
|
|
*/ |
209
|
|
|
private static function getPurifier() |
210
|
|
|
{ |
211
|
|
|
if (self::$purifier instanceof HTMLPurifier) { |
212
|
|
|
return self::$purifier; |
213
|
|
|
} |
214
|
|
|
$config = HTMLPurifier_Config::createDefault(); |
215
|
|
|
$config->set('URI.DisableExternalResources', false); |
216
|
|
|
$config->set('URI.DisableResources', false); |
217
|
|
|
$config->set('HTML.Allowed', 'u,p,b,i,a,p,strong,em,li,ul,ol,div[align],br,img,table,tr,td,th,tbody,thead,strike,sub,sup'); |
218
|
|
|
$config->set('Attr.AllowedFrameTargets', array('_blank')); |
219
|
|
|
$config->set('HTML.AllowedAttributes', 'src, alt, href, target'); |
220
|
|
|
$config->set('URI.AllowedSchemes', array('data' => true, 'http' => true, 'https' => true)); |
221
|
|
|
self::$purifier = new HTMLPurifier($config); |
222
|
|
|
return self::$purifier; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
private static function isRichTextField($key, $documentType) |
226
|
|
|
{ |
227
|
|
|
foreach ($documentType->fields as $fieldObj) { |
228
|
|
|
if ($fieldObj->slug === $key && $fieldObj->type === 'Rich Text') { |
229
|
|
|
return true; |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
return false; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* @param $postValues |
237
|
|
|
* @param $documentType |
238
|
|
|
* @return array |
239
|
|
|
*/ |
240
|
|
|
private static function sanitizeFields($postValues, $documentType) |
241
|
|
|
{ |
242
|
|
|
$fields = array(); |
243
|
|
|
if (isset($postValues['fields'])) { |
244
|
|
|
$purifier = self::getPurifier(); |
245
|
|
|
foreach ($postValues['fields'] as $key => $field) { |
246
|
|
|
if (self::isRichTextField($key, $documentType)) { |
247
|
|
|
foreach ($field as $fieldKey => $value) { |
248
|
|
|
$newValue = $purifier->purify($value); |
249
|
|
|
$field[$fieldKey] = $newValue; |
250
|
|
|
} |
251
|
|
|
$postValues['fields'][$key] = $field; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
} |
255
|
|
|
$fields = $postValues['fields']; |
256
|
|
|
} |
257
|
|
|
return $fields; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* @param $brickContent |
262
|
|
|
* @return mixed |
263
|
|
|
*/ |
264
|
|
|
private static function sanitizeBrickContent($brickContent) |
265
|
|
|
{ |
266
|
|
|
$purifier = self::getPurifier(); |
267
|
|
|
foreach ($brickContent as $fieldKey => $fieldValues) { |
268
|
|
|
foreach ($fieldValues as $valueKey => $value) { |
269
|
|
|
$fieldValues[$valueKey] = $purifier->purify($value); |
270
|
|
|
} |
271
|
|
|
$brickContent[$fieldKey] = $fieldValues; |
272
|
|
|
} |
273
|
|
|
return $brickContent; |
274
|
|
|
} |
275
|
|
|
} |
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.