Completed
Push — dev ( c609b9...13aaf0 )
by Darko
09:26
created

XML_Response::buildCdata()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 18
ccs 0
cts 9
cp 0
rs 9.9
c 0
b 0
f 0
cc 4
nc 4
nop 1
crap 20
1
<?php
2
/**
3
 * This program is free software: you can redistribute it and/or modify
4
 * it under the terms of the GNU General Public License as published by
5
 * the Free Software Foundation, either version 3 of the License, or
6
 * (at your option) any later version.
7
 *
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 * GNU General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU General Public License
14
 * along with this program (see LICENSE.txt in the base directory.  If
15
 * not, see:
16
 *
17
 * @link      <http://www.gnu.org/licenses/>.
18
 * @author    ruhllatio
19
 * @copyright 2016 nZEDb
20
 */
21
22
namespace Blacklight\http;
23
24
use App\Models\Release;
25
use App\Models\Category;
26
use Illuminate\Support\Carbon;
27
28
/**
29
 * Class XMLReturn.
30
 */
31
class XML_Response
32
{
33
    /**
34
     * @var string The buffered cData before final write
35
     */
36
    protected $cdata;
37
38
    /**
39
     * The RSS namespace used for the output.
40
     *
41
     * @var string
42
     */
43
    protected $namespace;
44
45
    /**
46
     * The trailing URL parameters on the request.
47
     *
48
     * @var mixed
49
     */
50
    protected $parameters;
51
52
    /**
53
     * The release we are adding to the stream.
54
     *
55
     * @var mixed
56
     */
57
    protected $release;
58
59
    /**
60
     * The retrieved releases we are returning from the API call.
61
     *
62
     * @var mixed
63
     */
64
    protected $releases;
65
66
    /**
67
     * The various server variables and active categories.
68
     *
69
     * @var mixed
70
     */
71
    protected $server;
72
73
    /**
74
     * The XML formatting operation we are returning.
75
     *
76
     * @var mixed
77
     */
78
    protected $type;
79
80
    /**
81
     * The XMLWriter Class.
82
     *
83
     * @var \XMLWriter
84
     */
85
    protected $xml;
86
87
    /**
88
     * @var mixed
89
     */
90
    protected $offset;
91
92
    /**
93
     * XMLReturn constructor.
94
     *
95
     * @param array $options
96
     */
97
    public function __construct(array $options = [])
98
    {
99
        $defaults = [
100
            'Parameters' => null,
101
            'Data'       => null,
102
            'Server'     => null,
103
            'Offset'     => null,
104
            'Type'       => null,
105
        ];
106
        $options += $defaults;
107
108
        $this->parameters = $options['Parameters'];
109
        $this->releases = $options['Data'];
110
        $this->server = $options['Server'];
111
        $this->offset = $options['Offset'];
112
        $this->type = $options['Type'];
113
114
        $this->xml = new \XMLWriter();
115
        $this->xml->openMemory();
116
        $this->xml->setIndent(true);
117
    }
118
119
    /**
120
     * @return bool|string
121
     */
122
    public function returnXML()
123
    {
124
        if ($this->xml) {
125
            switch ($this->type) {
126
                case 'caps':
127
                    return $this->returnCaps();
128
                    break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
129
                case 'api':
130
                    $this->namespace = 'newznab';
131
132
                    return $this->returnApiRss();
133
                    break;
134
                case 'rss':
135
                    $this->namespace = 'nntmux';
136
137
                    return $this->returnApiRss();
138
                    break;
139
                case 'reg':
140
                    return $this->returnReg();
141
                    break;
142
            }
143
        }
144
145
        return false;
146
    }
147
148
    /**
149
     * XML writes and returns the API capabilities.
150
     *
151
     * @return string The XML Formatted string data
152
     */
153
    protected function returnCaps(): string
154
    {
155
        $this->xml->startDocument('1.0', 'UTF-8');
156
        $this->xml->startElement('caps');
157
        $this->addNode(['name' => 'server', 'data' => $this->server['server']]);
158
        $this->addNode(['name' => 'limits', 'data' => $this->server['limits']]);
159
        $this->addNode(['name' => 'registration', 'data' => $this->server['registration']]);
160
        $this->addNodes(['name' => 'searching', 'data' => $this->server['searching']]);
161
        $this->writeCategoryListing();
162
        $this->xml->endElement();
163
        $this->xml->endDocument();
164
165
        return $this->xml->outputMemory();
166
    }
167
168
    /**
169
     * XML writes and returns the API data.
170
     *
171
     * @return string The XML Formatted string data
172
     */
173
    protected function returnApiRss(): string
174
    {
175
        $this->xml->startDocument('1.0', 'UTF-8');
176
        $this->includeRssAtom(); // Open RSS
177
        $this->xml->startElement('channel'); // Open channel
178
        $this->includeRssAtomLink();
179
        $this->includeMetaInfo();
180
        $this->includeImage();
181
        $this->includeTotalRows();
182
        $this->includeReleases();
183
        $this->xml->endElement(); // End channel
184
        $this->xml->endElement(); // End RSS
185
        $this->xml->endDocument();
186
187
        return $this->xml->outputMemory();
188
    }
189
190
    /**
191
     * @return string The XML formatted registration information
192
     */
193
    protected function returnReg(): string
194
    {
195
        $this->xml->startDocument('1.0', 'UTF-8');
196
        $this->xml->startElement('register');
197
        $this->xml->writeAttribute('username', $this->parameters['username']);
198
        $this->xml->writeAttribute('password', $this->parameters['password']);
199
        $this->xml->writeAttribute('apikey', $this->parameters['token']);
200
        $this->xml->endElement();
201
        $this->xml->endDocument();
202
203
        return $this->xml->outputMemory();
204
    }
205
206
    /**
207
     * Starts a new element, loops through the attribute data and ends the element.
208
     *
209
     * @param array $element An array with the name of the element and the attribute data
210
     */
211
    protected function addNode($element): void
212
    {
213
        $this->xml->startElement($element['name']);
214
        foreach ($element['data'] as $attr => $val) {
215
            $this->xml->writeAttribute($attr, $val);
216
        }
217
        $this->xml->endElement();
218
    }
219
220
    /**
221
     * Starts a new element, loops through the attribute data and ends the element.
222
     *
223
     * @param array $element An array with the name of the element and the attribute data
224
     */
225
    protected function addNodes($element): void
226
    {
227
        $this->xml->startElement($element['name']);
228
        foreach ($element['data'] as $elem => $value) {
229
            $subelement['name'] = $elem;
230
            $subelement['data'] = $value;
231
            $this->addNode($subelement);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $subelement seems to be defined later in this foreach loop on line 229. Are you sure it is defined here?
Loading history...
232
        }
233
        $this->xml->endElement();
234
    }
235
236
    /**
237
     * Adds the site category listing to the XML feed.
238
     */
239
    protected function writeCategoryListing(): void
240
    {
241
        $this->xml->startElement('categories');
242
        foreach ($this->server['categories'] as $this->parameters) {
243
            $this->xml->startElement('category');
244
            $this->xml->writeAttribute('id', $this->parameters['id']);
245
            $this->xml->writeAttribute('name', html_entity_decode($this->parameters['title']));
246
            if (! empty($this->parameters['description'])) {
247
                $this->xml->writeAttribute('description', html_entity_decode($this->parameters['description']));
248
            }
249
            foreach ($this->parameters['categories'] as $c) {
250
                $this->xml->startElement('subcat');
251
                $this->xml->writeAttribute('id', $c['id']);
252
                $this->xml->writeAttribute('name', html_entity_decode($c['title']));
253
                if (! empty($c['description'])) {
254
                    $this->xml->writeAttribute('description', html_entity_decode($c['description']));
255
                }
256
                $this->xml->endElement();
257
            }
258
            $this->xml->endElement();
259
        }
260
    }
261
262
    /**
263
     * Adds RSS Atom information to the XML.
264
     */
265
    protected function includeRssAtom(): void
266
    {
267
        switch ($this->namespace) {
268
            case 'newznab':
269
                $url = 'http://www.newznab.com/DTD/2010/feeds/attributes/';
270
                break;
271
            case 'nntmux':
272
            default:
273
                $url = $this->server['server']['url'].'/rss-info/';
274
        }
275
276
        $this->xml->startElement('rss');
277
        $this->xml->writeAttribute('version', '2.0');
278
        $this->xml->writeAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom');
279
        $this->xml->writeAttribute("xmlns:{$this->namespace}", $url);
280
        $this->xml->writeAttribute('encoding', 'utf-8');
281
    }
282
283
    protected function includeRssAtomLink(): void
284
    {
285
        $this->xml->startElement('atom:link');
286
        $this->xml->startAttribute('href');
287
        $this->xml->text($this->server['server']['url'].($this->namespace === 'newznab' ? '/api/v1/api' : '/rss'));
288
        $this->xml->endAttribute();
289
        $this->xml->startAttribute('rel');
290
        $this->xml->text('self');
291
        $this->xml->endAttribute();
292
        $this->xml->startAttribute('type');
293
        $this->xml->text('application/rss+xml');
294
        $this->xml->endAttribute();
295
        $this->xml->endElement();
296
    }
297
298
    /**
299
     * Writes the channel information for the feed.
300
     */
301
    protected function includeMetaInfo(): void
302
    {
303
        $server = $this->server['server'];
304
305
        switch ($this->namespace) {
306
            case 'newznab':
307
                $path = '/apihelp/';
308
                $tag = 'API';
309
                break;
310
            case 'nntmux':
311
            default:
312
                $path = '/rss-info/';
313
                $tag = 'RSS';
314
        }
315
316
        $this->xml->writeElement('title', $server['title']);
317
        $this->xml->writeElement('description', $server['title']." {$tag} Details");
318
        $this->xml->writeElement('link', $server['url']);
319
        $this->xml->writeElement('language', 'en-gb');
320
        $this->xml->writeElement('webMaster', $server['email'].' '.$server['title']);
321
        $this->xml->writeElement('category', $server['meta']);
322
        $this->xml->writeElement('generator', 'nntmux');
323
        $this->xml->writeElement('ttl', '10');
324
        $this->xml->writeElement('docs', $this->server['server']['url'].$path);
325
    }
326
327
    /**
328
     * Adds nntmux logo data to the XML.
329
     */
330
    protected function includeImage(): void
331
    {
332
        $this->xml->startElement('image');
333
        $this->xml->writeAttribute('url', $this->server['server']['url'].'/assets/images/tmux_logo.png');
334
        $this->xml->writeAttribute('title', $this->server['server']['title']);
335
        $this->xml->writeAttribute('link', $this->server['server']['url']);
336
        $this->xml->writeAttribute(
337
            'description',
338
            'Visit '.$this->server['server']['title'].' - '.$this->server['server']['strapline']
339
        );
340
        $this->xml->endElement();
341
    }
342
343
    public function includeTotalRows(): void
344
    {
345
        $this->xml->startElement($this->namespace.':response');
346
        $this->xml->writeAttribute('offset', $this->offset);
347
        $this->xml->writeAttribute('total', $this->releases[0]->_totalrows ?? 0);
348
        $this->xml->endElement();
349
    }
350
351
    /**
352
     * Loop through the releases and add their info to the XML stream.
353
     */
354
    public function includeReleases(): void
355
    {
356
        if (! empty($this->releases)) {
357
            if (! $this->releases instanceof Release) {
358
                foreach ($this->releases as $this->release) {
359
                    $this->xml->startElement('item');
360
                    $this->includeReleaseMain();
361
                    $this->setZedAttributes();
362
                    $this->xml->endElement();
363
                }
364
            } elseif ($this->releases instanceof Release) {
0 ignored issues
show
introduced by
$this->releases is always a sub-type of App\Models\Release.
Loading history...
365
                $this->release = $this->releases;
366
                $this->xml->startElement('item');
367
                $this->includeReleaseMain();
368
                $this->setZedAttributes();
369
                $this->xml->endElement();
370
            }
371
        }
372
    }
373
374
    /**
375
     * Writes the primary release information.
376
     */
377
    public function includeReleaseMain(): void
378
    {
379
        $this->xml->writeElement('title', $this->release->searchname);
380
        $this->xml->startElement('guid');
381
        $this->xml->writeAttribute('isPermaLink', 'true');
382
        $this->xml->text("{$this->server['server']['url']}/details/{$this->release->guid}");
383
        $this->xml->endElement();
384
        $this->xml->writeElement(
385
            'link',
386
            "{$this->server['server']['url']}/getnzb?id={$this->release->guid}.nzb".
387
            "&r={$this->parameters['token']}".
388
            ((int) $this->parameters['del'] === 1 ? '&del=1' : '')
389
        );
390
        $this->xml->writeElement('comments', "{$this->server['server']['url']}/details/{$this->release->guid}#comments");
391
        $this->xml->writeElement('pubDate', date(DATE_RSS, strtotime($this->release->adddate)));
392
        $this->xml->writeElement('category', $this->release->category_name);
393
        if ($this->namespace === 'newznab') {
394
            $this->xml->writeElement('description', $this->release->searchname);
395
        } else {
396
            $this->writeRssCdata();
397
        }
398
        if (! isset($this->parameters['dl']) || (isset($this->parameters['dl']) && (int) $this->parameters['dl'] === 1)) {
399
            $this->xml->startElement('enclosure');
400
            $this->xml->writeAttribute(
401
                'url',
402
                "{$this->server['server']['url']}/getnzb?id={$this->release->guid}.nzb".
403
                "&r={$this->parameters['token']}".
404
                ((int) $this->parameters['del'] === 1 ? '&del=1' : '')
405
            );
406
            $this->xml->writeAttribute('length', $this->release->size);
407
            $this->xml->writeAttribute('type', 'application/x-nzb');
408
            $this->xml->endElement();
409
        }
410
    }
411
412
    /**
413
     * Writes the Zed (newznab) specific attributes.
414
     */
415
    protected function setZedAttributes(): void
416
    {
417
        $this->writeZedAttr('category', $this->release->categories_id);
418
        $this->writeZedAttr('size', $this->release->size);
419
        if (isset($this->release->coverurl) && ! empty($this->release->coverurl)) {
420
            $this->writeZedAttr(
421
                'coverurl',
422
                $this->server['server']['url']."/covers/{$this->release->coverurl}"
423
            );
424
        }
425
426
        if ((int) $this->parameters['extended'] === 1) {
427
            $this->writeZedAttr('files', $this->release->totalpart);
428
            $this->writeZedAttr('poster', $this->release->fromname);
429
            if (($this->release->videos_id > 0 || $this->release->tv_episodes_id > 0) && $this->namespace === 'newznab') {
430
                $this->setTvAttr();
431
            }
432
433
            if (isset($this->release->imdbid) && $this->release->imdbid > 0) {
434
                $this->writeZedAttr('imdb', $this->release->imdbid);
435
            }
436
            if (isset($this->release->anidbid) && $this->release->anidbid > 0) {
437
                $this->writeZedAttr('anidbid', $this->release->anidbid);
438
            }
439
            if (isset($this->release->predb_id) && $this->release->predb_id > 0) {
440
                $this->writeZedAttr('prematch', 1);
441
            }
442
            if (isset($this->release->nfostatus) && (int) $this->release->nfostatus === 1) {
443
                $this->writeZedAttr(
444
                    'info',
445
                    $this->server['server']['url'].
446
                    "api?t=info&id={$this->release->guid}&r={$this->parameters['token']}"
447
                );
448
            }
449
450
            $this->writeZedAttr('grabs', $this->release->grabs);
451
            $this->writeZedAttr('comments', $this->release->comments);
452
            $this->writeZedAttr('password', $this->release->passwordstatus);
453
            $this->writeZedAttr('usenetdate', Carbon::parse($this->release->postdate)->toRssString());
454
            if (! empty($this->release->group_name)) {
455
                $this->writeZedAttr('group', $this->release->group_name);
456
            }
457
        }
458
    }
459
460
    /**
461
     * Writes the TV Specific attributes.
462
     */
463
    protected function setTvAttr(): void
464
    {
465
        if (! empty($this->release->title)) {
466
            $this->writeZedAttr('title', $this->release->title);
467
        }
468
        if (isset($this->release->series) && $this->release->series > 0) {
469
            $this->writeZedAttr('season', $this->release->series);
470
        }
471
        if (isset($this->release->episode->episode) && $this->release->episode->episode > 0) {
472
            $this->writeZedAttr('episode', $this->release->episode->episode);
473
        }
474
        if (! empty($this->release->firstaired)) {
475
            $this->writeZedAttr('tvairdate', $this->release->firstaired);
476
        }
477
        if (isset($this->release->tvdb) && $this->release->tvdb > 0) {
478
            $this->writeZedAttr('tvdbid', $this->release->tvdb);
479
        }
480
        if (isset($this->release->trakt) && $this->release->trakt > 0) {
481
            $this->writeZedAttr('traktid', $this->release->trakt);
482
        }
483
        if (isset($this->release->tvrage) && $this->release->tvrage > 0) {
484
            $this->writeZedAttr('tvrageid', $this->release->tvrage);
485
            $this->writeZedAttr('rageid', $this->release->tvrage);
486
        }
487
        if (isset($this->release->tvmaze) && $this->release->tvmaze > 0) {
488
            $this->writeZedAttr('tvmazeid', $this->release->tvmaze);
489
        }
490
        if (isset($this->release->imdb) && $this->release->imdb > 0) {
491
            $this->writeZedAttr('imdbid', $this->release->imdb);
492
        }
493
        if (isset($this->release->tmdb) && $this->release->tmdb > 0) {
494
            $this->writeZedAttr('tmdbid', $this->release->tmdb);
495
        }
496
    }
497
498
    /**
499
     * Writes individual zed (newznab) type attributes.
500
     *
501
     * @param string $name  The namespaced attribute name tag
502
     * @param string $value The namespaced attribute value
503
     */
504
    protected function writeZedAttr($name, $value): void
505
    {
506
        $this->xml->startElement($this->namespace.':attr');
507
        $this->xml->writeAttribute('name', $name);
508
        $this->xml->writeAttribute('value', $value);
509
        $this->xml->endElement();
510
    }
511
512
    /**
513
     * Writes the cData (HTML format) for the RSS feed
514
     * Also calls supplementary cData writes depending upon post process.
515
     */
516
    protected function writeRssCdata(): void
517
    {
518
        $this->cdata = "\n\t<div>\n";
519
        switch (1) {
520
            case ! empty($this->release->cover):
521
                $dir = 'movies';
522
                $column = 'imdbid';
523
                break;
524
            case ! empty($this->release->mu_cover):
525
                $dir = 'music';
526
                $column = 'musicinfo_id';
527
                break;
528
            case ! empty($this->release->co_cover):
529
                $dir = 'console';
530
                $column = 'consoleinfo_id';
531
                break;
532
            case ! empty($this->release->bo_cover):
533
                $dir = 'books';
534
                $column = 'bookinfo_id';
535
                break;
536
        }
537
        if (isset($dir, $column)) {
538
            $dcov = ($dir === 'movies' ? '-cover' : '');
539
            $this->cdata .=
540
                "\t<img style=\"margin-left:10px;margin-bottom:10px;float:right;\" ".
541
                "src=\"{$this->server['server']['url']}/covers/{$dir}/{$this->release->$column}{$dcov}.jpg\" ".
542
                "width=\"120\" alt=\"{$this->release->searchname}\" />\n";
543
        }
544
        $size = human_filesize($this->release->size);
545
        $this->cdata .=
546
            "\t<li>ID: <a href=\"{$this->server['server']['url']}/details/{$this->release->guid}\">{$this->release->guid}</a></li>\n".
547
            "\t<li>Name: {$this->release->searchname}</li>\n".
548
            "\t<li>Size: {$size}</li>\n".
549
            "\t<li>Category: <a href=\"{$this->server['server']['url']}/browse/{$this->release->category_name}\">{$this->release->category_name}</a></li>\n".
550
            "\t<li>Group: <a href=\"{$this->server['server']['url']}/browse/group?g={$this->release->group_name}\">{$this->release->group_name}</a></li>\n".
551
            "\t<li>Poster: {$this->release->fromname}</li>\n".
552
            "\t<li>Posted: {$this->release->postdate}</li>\n";
553
554
        switch ($this->release->passwordstatus) {
555
            case 0:
556
                $pstatus = 'None';
557
                break;
558
            case 1:
559
                $pstatus = 'Possibly Passworded';
560
                break;
561
            case 2:
562
                $pstatus = 'Probably not viable';
563
                break;
564
            case 10:
565
                $pstatus = 'Passworded';
566
                break;
567
            default:
568
                $pstatus = 'Unknown';
569
        }
570
        $this->cdata .= "\t<li>Password: {$pstatus}</li>\n";
571
        if ($this->release->nfostatus === 1) {
572
            $this->cdata .=
573
                "\t<li>Nfo: ".
574
                "<a href=\"{$this->server['server']['url']}/api?t=nfo&id={$this->release->guid}&raw=1&i={$this->parameters['uid']}&r={$this->parameters['token']}\">".
575
                "{$this->release->searchname}.nfo</a></li>\n";
576
        }
577
578
        if ($this->release->parentid === Category::MOVIE_ROOT && $this->release->imdbid !== '') {
579
            $this->writeRssMovieInfo();
580
        } elseif ($this->release->parentid === Category::MUSIC_ROOT && $this->release->musicinfo_id > 0) {
581
            $this->writeRssMusicInfo();
582
        } elseif ($this->release->parentid === Category::GAME_ROOT && $this->release->consoleinfo_id > 0) {
583
            $this->writeRssConsoleInfo();
584
        }
585
        $this->xml->startElement('description');
586
        $this->xml->writeCdata($this->cdata."\t</div>");
587
        $this->xml->endElement();
588
    }
589
590
    /**
591
     * Writes the Movie Info for the RSS feed cData.
592
     */
593
    protected function writeRssMovieInfo(): void
594
    {
595
        $movieCol = ['rating', 'plot', 'year', 'genre', 'director', 'actors'];
596
597
        $cData = $this->buildCdata($movieCol);
598
599
        $this->cdata .=
600
            "\t<li>Imdb Info:
601
				\t<ul>
602
					\t<li>IMDB Link: <a href=\"http://www.imdb.com/title/tt{$this->release->imdbid}/\">{$this->release->searchname}</a></li>\n
603
					\t{$cData}
604
				\t</ul>
605
			\t</li>
606
			\n";
607
    }
608
609
    /**
610
     * Writes the Music Info for the RSS feed cData.
611
     */
612
    protected function writeRssMusicInfo(): void
613
    {
614
        $tData = $cDataUrl = '';
615
616
        $musicCol = ['mu_artist', 'mu_genre', 'mu_publisher', 'mu_releasedate', 'mu_review'];
617
618
        $cData = $this->buildCdata($musicCol);
619
620
        if ($this->release->mu_url !== '') {
621
            $cDataUrl = "<li>Amazon: <a href=\"{$this->release->mu_url}\">{$this->release->mu_title}</a></li>";
622
        }
623
624
        $this->cdata .=
625
            "\t<li>Music Info:
626
			<ul>
627
			{$cDataUrl}
628
			{$cData}
629
			</ul>
630
			</li>\n";
631
        if ($this->release->mu_tracks !== '') {
632
            $tracks = explode('|', $this->release->mu_tracks);
633
            if (\count($tracks) > 0) {
634
                foreach ($tracks as $track) {
635
                    $track = trim($track);
636
                    $tData .= "<li>{$track}</li>";
637
                }
638
            }
639
            $this->cdata .= "
640
			<li>Track Listing:
641
				<ol>
642
				{$tData}
643
				</ol>
644
			</li>\n";
645
        }
646
    }
647
648
    /**
649
     * Writes the Console Info for the RSS feed cData.
650
     */
651
    protected function writeRssConsoleInfo(): void
652
    {
653
        $gamesCol = ['co_genre', 'co_publisher', 'year', 'co_review'];
654
655
        $cData = $this->buildCdata($gamesCol);
656
657
        $this->cdata .= "
658
		<li>Console Info:
659
			<ul>
660
				<li>Amazon: <a href=\"{$this->release->co_url}\">{$this->release->co_title}</a></li>\n
661
				{$cData}
662
			</ul>
663
		</li>\n";
664
    }
665
666
    /**
667
     * Accepts an array of values to loop through to build cData from the release info.
668
     *
669
     * @param array $columns The columns in the release we need to insert
670
     *
671
     * @return string The HTML format cData
672
     */
673
    protected function buildCdata($columns): string
674
    {
675
        $cData = '';
676
677
        foreach ($columns as $info) {
678
            if (! empty($this->release->$info)) {
679
                if ($info === 'mu_releasedate') {
680
                    $ucInfo = 'Released';
681
                    $rDate = date('Y-m-d', strtotime($this->release->$info));
682
                    $cData .= "<li>{$ucInfo}: {$rDate}</li>\n";
683
                } else {
684
                    $ucInfo = ucfirst(preg_replace('/^[a-z]{2}_/i', '', $info));
685
                    $cData .= "<li>{$ucInfo}: {$this->release->$info}</li>\n";
686
                }
687
            }
688
        }
689
690
        return $cData;
691
    }
692
}
693