Passed
Push — develop ( 0d582f...ad1a9e )
by Jens
03:00
created

createDynamicBrickArrayForDocument()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 17
Code Lines 12

Duplication

Lines 17
Ratio 100 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 12
c 2
b 0
f 0
nc 2
nop 2
dl 17
loc 17
rs 9.2
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)
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...
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)
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...
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
}