Passed
Pull Request — master (#21)
by kenny
01:49
created

FormatMapping::lookUp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 12
rs 9.8666
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
                $this->filterString(
66
                    $this->getValue('title', $dataArticle)
67
                ),
68
69
                $this->filterString(
70
                    $this->getValue('body', $dataArticle)
71
                ),
72
73
                $this->filterString(
74
                    $this->getValue('source', $dataArticle)
75
                ),
76
77
                $this->getValue('unique_id', $dataArticle),
78
79
                $this->filterInteger(
80
                    $this->getValue('type_id', $dataArticle['type'])
81
                ),
82
83
                $this->filterInteger(
84
                    $this->getValue(
85
                        'category_id',
86
                        $dataArticle['category']
87
                    )
88
                ),
89
90
                $this->getValue('reporter', $dataArticle),
91
92
                $this->filterString(
93
                    $this->getValue('lead', $dataArticle)
94
                ),
95
96
                $this->getValue('tag_name', $dataArticle['tags']),
97
98
                $this->filterString(
99
                    $this->getValue('published_at', $dataArticle)
100
                ),
101
102
                $this->filterInteger(
103
                    $this->getValue('id', $dataArticle)
104
                )
105
106
            );
107
108
            $attachmentConstants = array(
109
                Article::ATTACHMENT_FIELD_PHOTO, Article::ATTACHMENT_FIELD_PAGE,
110
                Article::ATTACHMENT_FIELD_GALLERY, Article::ATTACHMENT_FIELD_VIDEO,
111
            );
112
113
            $attachmentTypes = array(
114
                self::JSON_PHOTO_FIELD, self::JSON_PAGE_FIELD,
115
                self::JSON_GALLERY_FIELD, self::JSON_VIDEO_FIELD,
116
            );
117
118
            $attachmentAttributes = $this->lookUp($attachmentConstants);
119
120
            $article = $this->generalAttachment($article, $attachmentConstants, $attachmentTypes, $attachmentAttributes, $dataArticle);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $article is correct as $this->generalAttachment...tributes, $dataArticle) targeting one\FormatMapping::generalAttachment() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

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