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

FormatMapping::photoRatio()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 6
nop 1
dl 0
loc 14
rs 9.2222
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($this->makeAttachmentObject($attachmentType, $attributes, $item));
184
185
                array_push($attachments, $attachment);
186
            }
187
        }
188
189
        $structure = array(
190
            'numberOfItems' => count($attachments),
191
            'attachments' => $attachments,
192
        );
193
194
        return $structure;
195
    }
196
197
    /**
198
     * Make attachment object
199
     * @param  string $attachmentType json field of attachment
200
     * @param  array  $attributes     attributes of attachment
201
     * @param  assoc array $item
202
     * @return object
203
     */
204
    private function makeAttachmentObject($attachmentType, $attributes, $item)
205
    {
206
        $numOfAttributes = count($attributes);
207
208
        $values = array();
209
210
        for ($i = 0; $i < $numOfAttributes; $i++) {
211
            $val = $this->getValue($attributes[$i], $item);
212
            $values[$attributes[$i]] = $val;
213
        }
214
215
        extract($values);
216
217
        if ($attachmentType == 'photos') {
218
            return $this->createPhoto($photo_url, $photo_ratio, '', '');
219
        } elseif ($attachmentType == 'pages') {
220
            return $this->createPage($page_title, $page_body, $page_source, $page_order, $page_cover, $page_lead);
221
        } elseif ($attachmentType == 'galleries') {
222
            return $this->createGallery($gallery_body, $gallery_order, $gallery_photo, $gallery_source, $gallery_lead);
223
        } elseif ($attachmentType == 'videos') {
224
            return $this->createVideo($video_body, $video_source, $video_order, $video_cover, $video_lead);
225
        }
226
        return null;
227
    }
228
229
    /**
230
     * Create photo object
231
     * @param  array $values
232
     * @return Photo
233
     */
234
    private function createPhoto($url, $ratio, $desc, $info)
235
    {
236
        return new Photo(
237
            $url,
238
            $this->photoRatio($ratio),
239
            $desc,
240
            $info
241
        );
242
    }
243
244
    /**
245
     * Create page object
246
     * @param  array $values
247
     * @return Page
248
     */
249
    private function createPage($title, $body, $source, $order, $cover, $lead)
250
    {
251
        return new Page(
252
            $title,
253
            $body,
254
            $source,
255
            $order,
256
            $cover,
257
            $lead
258
        );
259
    }
260
261
    /**
262
     * Create Gallery object
263
     * @param  array $values
264
     * @return Gallery
265
     */
266
    private function createGallery($body, $order, $photo, $source, $lead)
267
    {
268
        return new Gallery(
269
            $body,
270
            $order,
271
            $photo,
272
            $source,
273
            $lead
274
        );
275
    }
276
277
    /**
278
     * Create Video object
279
     * @param  array $values
280
     * @return Video
281
     */
282
    private function createVideo($body, $source, $order, $cover, $lead)
283
    {
284
        return new Video(
285
286
            $body,
287
            $source,
288
            $order,
289
            $cover,
290
            $lead
291
        );
292
    }
293
294
    /**
295
     * Map ratio to photo ratio constants
296
     * @param   string $ratio
297
     * @return   string
298
     * @throws Exception
299
     */
300
    private function photoRatio($ratio)
301
    {
302
        if ($ratio == "1:1") {
303
            return Photo::RATIO_SQUARE;
304
        } elseif ($ratio == "2:1") {
305
            return Photo::RATIO_RECTANGLE;
306
        } elseif ($ratio == "3:2") {
307
            return Photo::RATIO_HEADLINE;
308
        } elseif ($ratio == "9:16") {
309
            return Photo::RATIO_VERTICAL;
310
        } elseif ($ratio == 'cover') {
311
            return Photo::RATIO_COVER;
312
        } else {
313
            throw new \Exception("Unknown ratio", 1);
314
        }
315
    }
316
317
    /**
318
     * Make sure value is integer
319
     * @param  mixed $int
320
     * @return int
321
     * @throws Exception
322
     */
323
    private function filterInteger($int)
324
    {
325
        if (is_int($int)) {
326
            return $int;
327
        }
328
        throw new \Exception("Invalid Integer", 1);
329
    }
330
331
    /**
332
     * Make sure string is not null or empty
333
     * @param   mixed $str
334
     * @return string if it is valid or exception
335
     * @throws Exception
336
     */
337
    private function filterString($str)
338
    {
339
        if (is_string($str) && strlen($str) > 0 && !is_null($str)) {
340
            return $str;
341
        }
342
        throw new \Exception("String required", 1);
343
    }
344
345
    /**
346
     * Make sure variable is type of array
347
     * @param  mixed $array
348
     * @return array
349
     * @throws Exception
350
     */
351
    private function filterArray($array)
352
    {
353
        if (is_array($array)) {
354
            return $array;
355
        }
356
        throw new \Exception("Array required", 1);
357
    }
358
359
    /**
360
     * Make sure attachment object not null
361
     * @param  mixed $object
362
     * @return object
363
     * @throws Exception
364
     */
365
    private function filterAttachmentObject($object)
366
    {
367
        if (!is_null($object)) {
368
            return $object;
369
        }
370
        throw new \Exception("Attachment object required", 1);
371
    }
372
373
    /**
374
     * Get value of array based on attributes(keys)
375
     * @param  mixed $attribute
376
     * @param  array $data
377
     * @return mixed
378
     */
379
    private function getValue($attribute, $data)
380
    {
381
        return isset($data[$attribute]) ? $data[$attribute] : null;
382
    }
383
}
384