EpisodeComponent::loadShow()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 10
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 10
loc 10
rs 9.4286
cc 2
eloc 6
nc 2
nop 0
1
<?php namespace CosmicRadioTV\Podcast\Components;
2
3
use CosmicRadioTV\Podcast\Classes\ComponentBase;
4
use CosmicRadioTV\Podcast\Classes\TitlePlaceholdersTrait;
5
use CosmicRadioTV\Podcast\Models\Release;
6
use CosmicRadioTV\Podcast\Models\Show;
7
use CosmicRadioTV\Podcast\Models;
8
use CosmicRadioTV\Podcast\Models\Episode;
9
use CosmicRadioTV\Podcast\Models\Tag;
10
use Illuminate\Database\Eloquent\Collection;
11
use Illuminate\Database\Eloquent\ModelNotFoundException;
12
use October\Rain\Database\Builder;
13
use URL;
14
15
class EpisodeComponent extends ComponentBase
16
{
17
18
    use TitlePlaceholdersTrait;
19
20
    /**
21
     * @var Episode The show being displayed
22
     */
23
    public $episode;
24
25
    /**
26
     * @var string[]
27
     */
28
    public $meta_tags = [];
29
30
    /**
31
     * @var Collection|Release[]
32
     */
33
    public $releases;
34
35
    /**
36
     * @var Show The show being displayed
37
     */
38
    public $show;
39
40
    /**
41
     * @var Tag The tag being used
42
     */
43
    public $tag;
44
45
    /**
46
     * Component Details
47
     *
48
     * @return array
49
     */
50
    public function componentDetails()
51
    {
52
        return [
53
            'name'        => 'cosmicradiotv.podcast::components.episode.name',
54
            'description' => 'cosmicradiotv.podcast::components.episode.description'
55
        ];
56
    }
57
58
    /**
59
     * User editable properties
60
     *
61
     * @return array
62
     */
63
    public function defineProperties()
64
    {
65
        return [
66
            'showSlug'    => [
67
                'title'       => 'cosmicradiotv.podcast::components.common.properties.show_slug.title',
68
                'description' => 'cosmicradiotv.podcast::components.common.properties.show_slug.description',
69
                'default'     => '{{ :show_slug }}',
70
                'type'        => 'string',
71
                'group'       => trans('cosmicradiotv.podcast::components.episode.groups.filters'),
72
            ],
73
            'episodeSlug' => [
74
                'title'       => 'cosmicradiotv.podcast::components.common.properties.episode_slug.title',
75
                'description' => 'cosmicradiotv.podcast::components.common.properties.episode_slug.description',
76
                'default'     => '{{ :episode_slug }}',
77
                'type'        => 'string',
78
                'group'       => trans('cosmicradiotv.podcast::components.episode.groups.filters'),
79
            ],
80
            'tagSlug'     => [
81
                'title'       => 'cosmicradiotv.podcast::components.common.properties.tag_slug.title',
82
                'description' => 'cosmicradiotv.podcast::components.episodes.properties.tag_slug.description',
83
                'default'     => '',
84
                'type'        => 'string',
85
                'group'       => trans('cosmicradiotv.podcast::components.episode.groups.filters'),
86
            ],
87
            'updateTitle' => [
88
                'title'       => 'cosmicradiotv.podcast::components.common.properties.update_title.title',
89
                'description' => 'cosmicradiotv.podcast::components.common.properties.update_title.description',
90
                'default'     => true,
91
                'type'        => 'checkbox',
92
            ],
93
            'metaTags'    => [
94
                'title'       => 'cosmicradiotv.podcast::components.common.properties.meta_tags.title',
95
                'description' => 'cosmicradiotv.podcast::components.common.properties.meta_tags.description',
96
                'default'     => false,
97
                'type'        => 'checkbox',
98
            ],
99
        ];
100
    }
101
102
    /**
103
     * Runs when the page or layout loads (sets up properties available to the component partial)
104
     *
105
     * @returns null|string
106
     */
107
    public function onRun()
108
    {
109
        try {
110
            $this->setState();
111
        } catch (ModelNotFoundException $e) {
112
            // Show/Episode not found, return 404
113
            $this->controller->setStatusCode(404);
114
115
            return $this->controller->run('404');
116
        }
117
118
        if ($this->property('updateTitle')) {
119
            $this->updateTitle();
120
        }
121
122
        $this->addCss('/plugins/cosmicradiotv/podcast/assets/stylesheet/player.css');
123
        $this->addJs('/plugins/cosmicradiotv/podcast/assets/javascript/player.js');
124
125
        if ($this->property('metaTags')) {
126
            $this->setMetaTags();
127
        }
128
129
        return null;
130
    }
131
132
    /**
133
     * Set components state based on parameters
134
     *
135
     * @throws ModelNotFoundException
136
     */
137
    public function setState()
138
    {
139
        $this->show = $this->loadShow();
140
        if ($this->property('tagSlug')) {
141
            $this->tag = Tag::query()->where('slug', $this->property('tagSlug'))->firstOrFail();
142
        }
143
        $this->episode = $this->loadEpisode();
144
145
        $this->releases = Collection::make($this->episode->releases); // Creates a copy
146 View Code Duplication
        $this->releases->sort(function (Release $a, Release $b) {
147
            // Order by the sort_order column
148
            $aRating = $a->release_type->sort_order;
149
            $bRating = $b->release_type->sort_order;
150
151
            return $aRating - $bRating;
152
        });
153
    }
154
155
    /**
156
     * If a show is requested by slug loads it, or null if all shows (left blank)
157
     *
158
     * @throws ModelNotFoundException
159
     * @return Show|null
160
     */
161 View Code Duplication
    protected function loadShow()
162
    {
163
        $slug = $this->property('showSlug');
164
165
        if ($slug) {
166
            return Show::query()->where('slug', $this->property('showSlug'))->firstOrFail();
167
        } else {
168
            return null;
169
        }
170
    }
171
172
    /**
173
     * Load the episode as requested
174
     *
175
     * @throws ModelNotFoundException
176
     * @return Episode
177
     */
178
    protected function loadEpisode()
179
    {
180
        // Show filter / Query base
181
        if ($this->show) {
182
            // Show's episodes
183
            $query = $this->show->episodes();
184
            $setShow = true; // Skips loading from database
185
            $latest = false; // In case of Show & Episode no need to find latest
186
        } else {
187
            // All shows' episodes
188
            $query = Episode::query();
189
            $query->with('show');
190
            $setShow = false;
191
            $latest = true;
192
        }
193
194
        // Episode slug filter
195
        if($this->property('episodeSlug')) {
196
            // Load specific episode, unless show isn't set
197
            $latest = $latest || false;
198
199
            $query->where('slug', $this->property('episodeSlug'));
200
        } else {
201
            // Load latest episode
202
            $latest = true;
203
        }
204
205
        // Tag filter
206
        if ($this->tag) {
207
            $query->whereHas('tags', function (Builder $q) {
208
                $q->where('cosmicradiotv_podcast_tags.id', $this->tag->id);
209
            });
210
        }
211
212
        // Generic rules
213
        $query->with(['releases', 'releases.release_type', 'image', 'tags'])
214
              ->where('published', true);
215
216
        // If latest also order by
217
        if($latest) {
218
            $query->orderBy('release', 'desc');
219
        }
220
221
        $episode = $query->firstOrFail();
222
223
        if($setShow) {
224
            // Set show on episode
225
            $episode->setRelation('show', $this->show);
226
        } else {
227
            // Set component's show to episode's show
228
            $this->show = $episode->show;
229
        }
230
231
        return $episode;
232
    }
233
234
    /**
235
     * Things to replace placeholders with
236
     *
237
     * @return object
238
     */
239
    protected function getTitlePlaceholderReplaces()
240
    {
241
        return (object) [
242
            'show'    => $this->show,
243
            'episode' => $this->episode,
244
        ];
245
    }
246
247
    /**
248
     * Injects meta tags into the header
249
     */
250 View Code Duplication
    protected function setMetaTags()
251
    {
252
        if ($this->episode) {
253
            $this->page->meta_title = $this->episode->title;
254
            $this->page->meta_description = $this->episode->summary;
255
256
            // Extra meta tags, available via {% placeholder head %}
257
            $this->meta_tags = [
258
                'twitter:card'   => 'summary',
259
                'og:title'       => $this->episode->title,
260
                'og:description' => $this->episode->summary,
261
                'og:type'        => 'video.episode',
262
                'og:url'         => $this->controller->currentPageUrl(),
263
            ];
264
265
            if ($this->episode->image) {
266
                // Full path
267
                $this->meta_tags['og:image'] = URL::to($this->episode->image->getPath());
268
            }
269
270
        }
271
    }
272
273
}