Passed
Pull Request — master (#21)
by kenny
02:01
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
124
            return $res = array_map(function ($str) use ($singleConst) {
0 ignored issues
show
Unused Code introduced by
The assignment to $res is dead and can be removed.
Loading history...
125
                return $singleConst . $str;
126
            }, $res);
127
        }, $articleConstant);
128
129
        return $lists;
130
    }
131
132
    /**
133
     * Attach attachments to article
134
     * @param  Article &$article
135
     * @param  array $attachmentConst
136
     * @param  array $attachmentype
137
     * @param  array $attributes
138
     * @param  array $dataArticle
139
     * @return void
140
     */
141
    private function generalAttachment(
142
        &$article,
143
        $attachmentConst,
144
        $attachmentype,
145
        $attributes,
146
        $dataArticle
147
    ) {
148
        $numOfAttachments = count($attachmentConst);
149
150
        for ($i = 0; $i < $numOfAttachments; $i++) {
151
            $attachments = $this->attachment($attachmentype[$i], $attributes[$i], $dataArticle);
152
153
            for ($j = 0; $j < $attachments['numberOfItems']; $j++) {
154
                $attachment = $attachments['attachments'][$j];
155
156
                $article->attach($attachmentConst[$i], $attachment);
157
            }
158
        }
159
    }
160
161
    /**
162
     * Attachment(s) of a single article
163
     * @param  string $attachmentType
164
     * @param  array $attributes
165
     * @param  assoc array $dataArticle
166
     * @return array attachments
167
     */
168
    private function attachment($attachmentType, $attributes, $dataArticle)
169
    {
170
        $data = $dataArticle[$attachmentType];
171
172
        $encoded = json_encode($data);
173
174
        $attachments = array();
175
176
        if ($this->filterArray($data)) {
177
            $decodedData = json_decode($encoded, true);
178
179
            $numberOfItems = count($decodedData);
180
181
            for ($i = 0; $i < $numberOfItems; $i++) {
182
                $item = $decodedData[$i];
183
184
                $attachment = $this->filterAttachmentObject($this->makeAttachmentObject($attachmentType, $attributes, $item));
185
186
                array_push($attachments, $attachment);
187
            }
188
        }
189
190
        $structure = array(
191
            'numberOfItems' => count($attachments),
192
            'attachments' => $attachments,
193
        );
194
195
        return $structure;
196
    }
197
198
    /**
199
     * Make attachment object
200
     * @param  string $attachmentType json field of attachment
201
     * @param  array  $attributes     attributes of attachment
202
     * @param  assoc array $item
203
     * @return object
204
     */
205
    private function makeAttachmentObject($attachmentType, $attributes, $item)
206
    {
207
        $numOfAttributes = count($attributes);
208
209
        $values = array();
210
211
        for ($i = 0; $i < $numOfAttributes; $i++) {
212
            $val = $this->getValue($attributes[$i], $item);
213
            $values[$attributes[$i]] = $val;
214
        }
215
216
        extract($values);
217
218
        if ($attachmentType == 'photos') {
219
            return $this->createPhoto($photo_url, $photo_ratio, '', '');
220
        } elseif ($attachmentType == 'pages') {
221
            return $this->createPage($page_title, $page_body, $page_source, $page_order, $page_cover, $page_lead);
222
        } elseif ($attachmentType == 'galleries') {
223
            return $this->createGallery($gallery_body, $gallery_order, $gallery_photo, $gallery_source, $gallery_lead);
224
        } elseif ($attachmentType == 'videos') {
225
            return $this->createVideo($video_body, $video_source, $video_order, $video_cover, $video_lead);
226
        }
227
        return null;
228
    }
229
230
    /**
231
     * Create photo object
232
     * @param  array $values
233
     * @return Photo
234
     */
235
    private function createPhoto($url, $ratio, $desc, $info)
236
    {
237
        return new Photo(
238
            $url,
239
            $this->photoRatio($ratio),
240
            $desc,
241
            $info
242
        );
243
    }
244
245
    /**
246
     * Create page object
247
     * @param  array $values
248
     * @return Page
249
     */
250
    private function createPage($title, $body, $source, $order, $cover, $lead)
251
    {
252
        return new Page(
253
            $title,
254
            $body,
255
            $source,
256
            $order,
257
            $cover,
258
            $lead
259
        );
260
    }
261
262
    /**
263
     * Create Gallery object
264
     * @param  array $values
265
     * @return Gallery
266
     */
267
    private function createGallery($body, $order, $photo, $source, $lead)
268
    {
269
        return new Gallery(
270
            $body,
271
            $order,
272
            $photo,
273
            $source,
274
            $lead
275
        );
276
    }
277
278
    /**
279
     * Create Video object
280
     * @param  array $values
281
     * @return Video
282
     */
283
    private function createVideo($body, $source, $order, $cover, $lead)
284
    {
285
        return new Video(
286
287
            $body,
288
            $source,
289
            $order,
290
            $cover,
291
            $lead
292
        );
293
    }
294
295
    /**
296
     * Map ratio to photo ratio constants
297
     * @param   string $ratio
298
     * @return   string
299
     * @throws Exception
300
     */
301
    private function photoRatio($ratio)
302
    {
303
        if ($ratio == "1:1") {
304
            return Photo::RATIO_SQUARE;
305
        } elseif ($ratio == "2:1") {
306
            return Photo::RATIO_RECTANGLE;
307
        } elseif ($ratio == "3:2") {
308
            return Photo::RATIO_HEADLINE;
309
        } elseif ($ratio == "9:16") {
310
            return Photo::RATIO_VERTICAL;
311
        } elseif ($ratio == 'cover') {
312
            return Photo::RATIO_COVER;
313
        } else {
314
            throw new \Exception("Unknown ratio", 1);
315
        }
316
    }
317
318
    /**
319
     * Make sure value is integer
320
     * @param  mixed $int
321
     * @return int
322
     * @throws Exception
323
     */
324
    private function filterInteger($int)
325
    {
326
        if (is_int($int)) {
327
            return $int;
328
        }
329
        throw new \Exception("Invalid Integer", 1);
330
    }
331
332
    /**
333
     * Make sure string is not null or empty
334
     * @param   mixed $str
335
     * @return string if it is valid or exception
336
     * @throws Exception
337
     */
338
    private function filterString($str)
339
    {
340
        if (is_string($str) && strlen($str) > 0 && !is_null($str)) {
341
            return $str;
342
        }
343
        throw new \Exception("String required", 1);
344
    }
345
346
    /**
347
     * Make sure variable is type of array
348
     * @param  mixed $array
349
     * @return array
350
     * @throws Exception
351
     */
352
    private function filterArray($array)
353
    {
354
        if (is_array($array)) {
355
            return $array;
356
        }
357
        throw new \Exception("Array required", 1);
358
    }
359
360
    /**
361
     * Make sure attachment object not null
362
     * @param  mixed $object
363
     * @return object
364
     * @throws Exception
365
     */
366
    private function filterAttachmentObject($object)
367
    {
368
        if (!is_null($object)) {
369
            return $object;
370
        }
371
        throw new \Exception("Attachment object required", 1);
372
    }
373
374
    /**
375
     * Get value of array based on attributes(keys)
376
     * @param  mixed $attribute
377
     * @param  array $data
378
     * @return mixed
379
     */
380
    private function getValue($attribute, $data)
381
    {
382
        return isset($data[$attribute]) ? $data[$attribute] : null;
383
    }
384
}
385