Passed
Push — develop ( 64430e...0d582f )
by Jens
03:42
created

createDynamicBrickArrayForDocument()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 17
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 24
rs 8.5125
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
    private static function createDynamicBrickArrayForDocument($postValues, $documentObj)
99
    {
100
        $documentObj->dynamicBricks = array();
101
        $purifier = self::getPurifier();
102
        if (isset($postValues['dynamicBricks'])) {
103
            foreach ($postValues['dynamicBricks'] as $brickTypeSlug => $brick) {
104
                foreach ($brick as $brickContent) {
105
                    $brickObj = new \stdClass();
106
                    $brickObj->type = $brickTypeSlug;
107
                    foreach ($brickContent as $fieldKey => $fieldValues) {
108
                        foreach ($fieldValues as $valueKey => $value) {
109
                            $fieldValues[$valueKey] = $purifier->purify($value);
110
                        }
111
                        $brickContent[$fieldKey] = $fieldValues;
112
                    }
113
                    $brickObj->fields = $brickContent;
114
                    $dynamicBricks = $documentObj->dynamicBricks;
115
                    $dynamicBricks[] = $brickObj;
116
                    $documentObj->dynamicBricks = $dynamicBricks;
117
                }
118
            }
119
        }
120
        return $documentObj;
121
    }
122
123
    /**
124
     * @param $staticBricks
125
     * @param $brickSlug
126
     *
127
     * @return array
128
     */
129
    private static function getStaticBrickAndSetMultiple($staticBricks, $brickSlug)
130
    {
131
        $staticBrick = null;
132
        $multiple = false;
133
        foreach ($staticBricks as $staticBrick) {
134
            if ($staticBrick->slug === $brickSlug) {
135
                $multiple = $staticBrick->multiple;
136
                break;
137
            }
138
        }
139
140
        return array($staticBrick, $multiple);
141
    }
142
143
    /**
144
     * @param $staticBrick
145
     * @param $brickInstance
146
     *
147
     * @return \stdClass
148
     */
149
    private static function createBrick($staticBrick, $brickInstance)
150
    {
151
        $brickObj = new \stdClass();
152
        $brickObj->fields = new \stdClass();
153
        $brickObj->type = $staticBrick->brickSlug;
154
155
        foreach ($brickInstance['fields'] as $fieldName => $fieldValues) {
156
            $purifier = self::getPurifier();
157
            foreach ($fieldValues as $fieldKey => $value) {
158
                $fieldValues[$fieldKey] = $purifier->purify($value);
159
            }
160
            $brickObj->fields->$fieldName = $fieldValues;
161
        }
162
163
        return $brickObj;
164
    }
165
166
    /**
167
     * @param $documentObj
168
     * @param $brick
169
     * @param $staticBrick
170
     * @param $brickSlug
171
     *
172
     * @return mixed
173
     */
174
    private static function addMultipleBricks($documentObj, $brick, $staticBrick, $brickSlug)
175
    {
176
        $brickArray = array();
177
        foreach ($brick as $brickInstance) {
178
            $brickObj = self::createBrick($staticBrick, $brickInstance);
179
            $brickArray[] = $brickObj;
180
        }
181
182
        $bricks = $documentObj->bricks;
183
        $bricks[$brickSlug] = $brickArray;
184
        $documentObj->bricks = $bricks;
185
186
        return $documentObj;
187
    }
188
189
    /**
190
     * @param $documentObj
191
     * @param $brick
192
     * @param $brickSlug
193
     *
194
     * @return mixed
195
     */
196
    private static function addSingleBrick($documentObj, $brick, $brickSlug)
197
    {
198
        $bricks = $documentObj->bricks;
199
200
        $purifier = self::getPurifier();
201
        foreach ($brick['fields'] as $fieldKey => $values) {
202
            foreach ($values as $valueKey => $value) {
203
                $values[$valueKey] = $purifier->purify($value);
204
            }
205
            $brick['fields'][$fieldKey] = $values;
206
        }
207
        $bricks[$brickSlug] = $brick;
208
209
        $documentObj->bricks = $bricks;
210
        return $documentObj;
211
    }
212
213
    /**
214
     * @return HTMLPurifier
215
     */
216
    private static function getPurifier()
217
    {
218
        if (self::$purifier instanceof HTMLPurifier) {
219
            return self::$purifier;
220
        }
221
        $config = HTMLPurifier_Config::createDefault();
222
        $config->set('URI.DisableExternalResources', false);
223
        $config->set('URI.DisableResources', false);
224
        $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');
225
        $config->set('Attr.AllowedFrameTargets', array('_blank'));
226
        $config->set('HTML.AllowedAttributes', 'src, alt, href, target');
227
        $config->set('URI.AllowedSchemes', array('data' => true, 'http' => true, 'https' => true));
228
        self::$purifier = new HTMLPurifier($config);
229
        return self::$purifier;
230
    }
231
232
    private static function isRichTextField($key, $documentType)
233
    {
234
        foreach ($documentType->fields as $fieldObj) {
235
            if ($fieldObj->slug === $key && $fieldObj->type === 'Rich Text') {
236
                return true;
237
            }
238
        }
239
        return false;
240
    }
241
242
    /**
243
     * @param $postValues
244
     * @param $documentType
245
     * @return array
246
     */
247
    private static function sanitizeFields($postValues, $documentType)
248
    {
249
        if (isset($postValues['fields'])) {
250
            $purifier = self::getPurifier();
251
            foreach ($postValues['fields'] as $key => $field) {
252
                if (self::isRichTextField($key, $documentType)) {
253
                    foreach ($field as $fieldKey => $value) {
254
                        $newValue = $purifier->purify($value);
255
                        $field[$fieldKey] = $newValue;
256
                    }
257
                    $postValues['fields'][$key] = $field;
258
                }
259
260
            }
261
            $fields = $postValues['fields'];
262
        } else {
263
            $fields = array();
264
        }
265
        return $fields;
266
    }
267
}