Passed
Pull Request — master (#21)
by kenny
02:05
created

FormatMapping::createPhoto()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 4
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace one;
4
5
use One\Model\Article;
6
use one\Model\Gallery;
7
use One\Model\Page;
8
use one\Model\Photo;
9
use One\Model\Video;
10
11
class FormatMapping
12
{
13
14
    /**
15
     * Possible attributes of JSON data
16
     * @var array
17
     */
18
    private $listAttributes;
19
20
    /**
21
     * JSON field constants
22
     */
23
    const JSON_PHOTO_FIELD = "photos";
24
25
    const JSON_PAGE_FIELD = "pages";
26
27
    const JSON_GALLERY_FIELD = "galleries";
28
29
    const JSON_VIDEO_FIELD = "videos";
30
31
    /**
32
     * Construct JSON attributes
33
     */
34
    public function __construct()
35
    {
36
        $this->listAttributes = array(
37
            Article::ATTACHMENT_FIELD_PHOTO => array(
38
                '_id', '_url', '_ratio', '_description', '_information',
39
            ),
40
            Article::ATTACHMENT_FIELD_PAGE => array(
41
                '_id', '_title', '_lead', '_body', '_source', '_order', '_cover',
42
            ),
43
            Article::ATTACHMENT_FIELD_GALLERY => array(
44
                '_id', '_lead', '_body', '_source', '_order', '_photo',
45
            ),
46
            Article::ATTACHMENT_FIELD_VIDEO => array(
47
                '_id', '_lead', '_body', '_source', '_order', '_cover',
48
            ),
49
        );
50
    }
51
52
    /**
53
     * map a single article to main attributes in Article Class
54
     * @param  string $singleJsonArticle JSON response
55
     * @return Article
56
     * @throws Exception
57
     */
58
    public function article($singleJsonArticle)
59
    {
60
        if (json_decode($singleJsonArticle, true)) {
61
            $dataArticle = json_decode($singleJsonArticle, true)['data'];
62
63
            $article = new Article(
64
65
                $title = $this->filterString($this->getValue('title', $dataArticle)),
66
67
                $body = $this->filterString($this->getValue('body', $dataArticle)),
68
69
                $source = $this->filterString($this->getValue('source', $dataArticle)),
70
71
                $uniqueId = $this->getValue('unique_id', $dataArticle),
72
73
                $typeId = $this->filterInteger($this->getValue('type_id', $dataArticle['type'])),
74
75
                $categoryId = $this->filterInteger($this->getValue(
76
                    'category_id',
77
                    $dataArticle['category']
78
                )),
79
80
                $reporter = $this->getValue('reporter', $dataArticle),
81
82
                $lead = $this->filterString($this->getValue('lead', $dataArticle)),
83
84
                $tags = $this->getValue('tag_name', $dataArticle['tags']),
85
86
                $publishedAt = $this->filterString($this->getValue('published_at', $dataArticle)),
87
88
                $identifier = $this->filterInteger($this->getValue('id', $dataArticle))
89
90
            );
91
92
            $attachmentConstants = array(
93
                Article::ATTACHMENT_FIELD_PHOTO, Article::ATTACHMENT_FIELD_PAGE,
94
                Article::ATTACHMENT_FIELD_GALLERY, Article::ATTACHMENT_FIELD_VIDEO,
95
            );
96
97
            $attachmentTypes = array(
98
                self::JSON_PHOTO_FIELD, self::JSON_PAGE_FIELD, self::JSON_GALLERY_FIELD,
99
                self::JSON_VIDEO_FIELD,
100
            );
101
102
            $attachmentAttributes = $this->lookUp($attachmentConstants);
103
104
            $this->generalAttachment($article, $attachmentConstants, $attachmentTypes, $attachmentAttributes, $dataArticle);
105
106
            return $article;
107
        }
108
109
        throw new \Exception("Empty or invalid JSON Response", 1);
110
    }
111
112
    /**
113
     * Create list attributes based on Article attachment type
114
     * @param  array $articleConstant
115
     * @return array
116
     */
117
    private function lookUp($articleConstant)
118
    {
119
        $copyListAttributes = $this->listAttributes;
120
121
        $lists = array_map(function ($singleConst) use ($copyListAttributes) {
122
            $res = $copyListAttributes[$singleConst];
123
            return array_map(function ($str) use ($singleConst) {
124
                return $singleConst . $str;
125
            }, $res);
126
        }, $articleConstant);
127
128
        return $lists;
129
    }
130
131
    /**
132
     * Attach attachments to article
133
     * @param  Article &$article
134
     * @param  array $attachmentConst
135
     * @param  array $attachmentype
136
     * @param  array $attributes
137
     * @param  array $dataArticle
138
     * @return void
139
     */
140
    private function generalAttachment(
141
        &$article,
142
        $attachmentConst,
143
        $attachmentype,
144
        $attributes,
145
        $dataArticle
146
    ) {
147
        $numOfAttachments = count($attachmentConst);
148
149
        for ($i = 0; $i < $numOfAttachments; $i++) {
150
            $attachments = $this->attachment($attachmentype[$i], $attributes[$i], $dataArticle);
151
152
            for ($j = 0; $j < $attachments['numberOfItems']; $j++) {
153
                $attachment = $attachments['attachments'][$j];
154
155
                $article->attach($attachmentConst[$i], $attachment);
156
            }
157
        }
158
    }
159
160
    /**
161
     * Attachment(s) of a single article
162
     * @param  string $attachmentType
163
     * @param  array $attributes
164
     * @param  assoc array $dataArticle
165
     * @return array attachments
166
     */
167
    private function attachment($attachmentType, $attributes, $dataArticle)
168
    {
169
        $data = $dataArticle[$attachmentType];
170
171
        $encoded = json_encode($data);
172
173
        $attachments = array();
174
175
        if ($this->filterArray($data)) {
176
            $decodedData = json_decode($encoded, true);
177
178
            $numberOfItems = count($decodedData);
179
180
            for ($i = 0; $i < $numberOfItems; $i++) {
181
                $item = $decodedData[$i];
182
183
                $attachment = $this->filterAttachmentObject(
184
                    $this->makeAttachmentObject(
185
                        $attachmentType,
186
                        $attributes,
187
                        $item
188
                    )
189
                );
190
191
                array_push($attachments, $attachment);
192
            }
193
        }
194
195
        $structure = array(
196
            'numberOfItems' => count($attachments),
197
            'attachments' => $attachments,
198
        );
199
200
        return $structure;
201
    }
202
203
    /**
204
     * Make attachment object
205
     * @param  string $attachmentType json field of attachment
206
     * @param  array  $attributes     attributes of attachment
207
     * @param  assoc array $item
208
     * @return object
209
     */
210
    private function makeAttachmentObject($attachmentType, $attributes, $item)
211
    {
212
        $numOfAttributes = count($attributes);
213
214
        $values = array();
215
216
        for ($i = 0; $i < $numOfAttributes; $i++) {
217
            $val = $this->getValue($attributes[$i], $item);
218
            $values[$attributes[$i]] = $val;
219
        }
220
221
        extract($values);
222
223
        switch ($attachmentType) {
224
        case self::JSON_PHOTO_FIELD:
225
            return $this->createPhoto($photo_url, $photo_ratio, '', '');
226
        case self::JSON_PAGE_FIELD:
227
            return $this->createPage(
228
                $page_title,
229
                $page_body,
230
                $page_source,
231
                $page_order,
232
                $page_cover,
233
                $page_lead
234
            );
235
        case self::JSON_GALLERY_FIELD:
236
            return $this->createGallery(
237
                $gallery_body,
238
                $gallery_order,
239
                $gallery_photo,
240
                $gallery_source,
241
                $gallery_lead
242
            );
243
        case self::JSON_VIDEO_FIELD:
244
            return $this->createVideo(
245
                $video_body,
246
                $video_source,
247
                $video_order,
248
                $video_cover,
249
                $video_lead
250
            );
251
        default:
252
            return null;
253
        }
254
    }
255
256
    /**
257
     * Create photo object
258
     * @param  array $values
259
     * @return Photo
260
     */
261
    private function createPhoto($url, $ratio, $desc, $info)
262
    {
263
        return new Photo(
264
            $url,
265
            $this->photoRatio($ratio),
266
            $desc,
267
            $info
268
        );
269
    }
270
271
    /**
272
     * Create page object
273
     * @param  array $values
274
     * @return Page
275
     */
276
    private function createPage($title, $body, $source, $order, $cover, $lead)
277
    {
278
        return new Page(
279
            $title,
280
            $body,
281
            $source,
282
            $order,
283
            $cover,
284
            $lead
285
        );
286
    }
287
288
    /**
289
     * Create Gallery object
290
     * @param  array $values
291
     * @return Gallery
292
     */
293
    private function createGallery($body, $order, $photo, $source, $lead)
294
    {
295
        return new Gallery(
296
            $body,
297
            $order,
298
            $photo,
299
            $source,
300
            $lead
301
        );
302
    }
303
304
    /**
305
     * Create Video object
306
     * @param  array $values
307
     * @return Video
308
     */
309
    private function createVideo($body, $source, $order, $cover, $lead)
310
    {
311
        return new Video(
312
313
            $body,
314
            $source,
315
            $order,
316
            $cover,
317
            $lead
318
        );
319
    }
320
321
    /**
322
     * Map ratio to photo ratio constants
323
     * @param   string $ratio
324
     * @return   string
325
     * @throws Exception
326
     */
327
    private function photoRatio($ratio)
328
    {
329
        if ($ratio == "1:1") {
330
            return Photo::RATIO_SQUARE;
331
        } elseif ($ratio == "2:1") {
332
            return Photo::RATIO_RECTANGLE;
333
        } elseif ($ratio == "3:2") {
334
            return Photo::RATIO_HEADLINE;
335
        } elseif ($ratio == "9:16") {
336
            return Photo::RATIO_VERTICAL;
337
        } elseif ($ratio == 'cover') {
338
            return Photo::RATIO_COVER;
339
        } else {
340
            throw new \Exception("Unknown ratio", 1);
341
        }
342
    }
343
344
    /**
345
     * Make sure value is integer
346
     * @param  mixed $int
347
     * @return int
348
     * @throws Exception
349
     */
350
    private function filterInteger($int)
351
    {
352
        if (is_int($int)) {
353
            return $int;
354
        }
355
        throw new \Exception("Invalid Integer", 1);
356
    }
357
358
    /**
359
     * Make sure string is not null or empty
360
     * @param   mixed $str
361
     * @return string if it is valid or exception
362
     * @throws Exception
363
     */
364
    private function filterString($str)
365
    {
366
        if (is_string($str) && strlen($str) > 0 && !is_null($str)) {
367
            return $str;
368
        }
369
        throw new \Exception("String required", 1);
370
    }
371
372
    /**
373
     * Make sure variable is type of array
374
     * @param  mixed $array
375
     * @return array
376
     * @throws Exception
377
     */
378
    private function filterArray($array)
379
    {
380
        if (is_array($array)) {
381
            return $array;
382
        }
383
        throw new \Exception("Array required", 1);
384
    }
385
386
    /**
387
     * Make sure attachment object not null
388
     * @param  mixed $object
389
     * @return object
390
     * @throws Exception
391
     */
392
    private function filterAttachmentObject($object)
393
    {
394
        if (!is_null($object)) {
395
            return $object;
396
        }
397
        throw new \Exception("Attachment object required", 1);
398
    }
399
400
    /**
401
     * Get value of array based on attributes(keys)
402
     * @param  mixed $attribute
403
     * @param  array $data
404
     * @return mixed
405
     */
406
    private function getValue($attribute, $data)
407
    {
408
        return isset($data[$attribute]) ? $data[$attribute] : null;
409
    }
410
}
411