FormatMapping::handleString()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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