1<?php
2/*
3 * vim:set softtabstop=4 shiftwidth=4 expandtab:
4 *
5 * LICENSE: GNU Affero General Public License, version 3 (AGPL-3.0-or-later)
6 * Copyright 2001 - 2020 Ampache.org
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 *
21 */
22
23declare(strict_types=0);
24
25namespace Ampache\Repository\Model;
26
27use Ampache\Module\System\Dba;
28use Ampache\Config\AmpConfig;
29use Ampache\Repository\ShoutRepositoryInterface;
30use Ampache\Repository\UserActivityRepositoryInterface;
31use PDOStatement;
32
33class TVShow_Season extends database_object implements library_item, GarbageCollectibleInterface
34{
35    protected const DB_TABLENAME = 'tvshow_season';
36
37    /* Variables from DB */
38    public $id;
39    public $season_number;
40    public $tvshow;
41
42    public $catalog_id;
43    public $episodes;
44    public $f_name;
45    public $f_tvshow;
46    public $f_tvshow_link;
47    public $link;
48    public $f_link;
49
50    // Constructed vars
51    private static $_mapcache = array();
52
53    /**
54     * TV Show
55     * Takes the ID of the tv show season and pulls the info from the db
56     * @param $show_id
57     */
58    public function __construct($show_id)
59    {
60        /* Get the information from the db */
61        $info = $this->get_info($show_id);
62
63        foreach ($info as $key => $value) {
64            $this->$key = $value;
65        } // foreach info
66
67        return true;
68    } // constructor
69
70    public function getId(): int
71    {
72        return (int) $this->id;
73    }
74
75    /**
76     * garbage_collection
77     *
78     * This cleans out unused tv shows seasons
79     */
80    public static function garbage_collection()
81    {
82        $sql = "DELETE FROM `tvshow_season` USING `tvshow_season` LEFT JOIN `tvshow_episode` ON `tvshow_episode`.`season` = `tvshow_season`.`id` WHERE `tvshow_episode`.`id` IS NULL";
83        Dba::write($sql);
84    }
85
86    /**
87     * get_songs
88     * gets all episodes for this tv show season
89     * @return array
90     */
91    public function get_episodes()
92    {
93        $sql = (AmpConfig::get('catalog_disable'))
94            ? "SELECT `tvshow_episode`.`id` FROM `tvshow_episode` LEFT JOIN `video` ON `video`.`id` = `tvshow_episode`.`id` LEFT JOIN `catalog` ON `catalog`.`id` = `video`.`catalog` WHERE `tvshow_episode`.`season`='" . Dba::escape($this->id) . "' AND `catalog`.`enabled` = '1' "
95            : "SELECT `tvshow_episode`.`id` FROM `tvshow_episode` WHERE `tvshow_episode`.`season`='" . Dba::escape($this->id) . "' ";
96        $sql .= "ORDER BY `tvshow_episode`.`episode_number`";
97
98        $db_results = Dba::read($sql);
99        $results    = array();
100        while ($row = Dba::fetch_assoc($db_results)) {
101            $results[] = $row['id'];
102        }
103
104        return $results;
105    } // get_episodes
106
107    /**
108     * _get_extra info
109     * This returns the extra information for the tv show season, this means totals etc
110     * @return array
111     */
112    private function _get_extra_info()
113    {
114        // Try to find it in the cache and save ourselves the trouble
115        if (parent::is_cached('tvshow_extra', $this->id)) {
116            $row = parent::get_from_cache('tvshow_extra', $this->id);
117        } else {
118            $sql = "SELECT COUNT(`tvshow_episode`.`id`) AS `episode_count`, `video`.`catalog` as `catalog_id` FROM `tvshow_episode` LEFT JOIN `video` ON `video`.`id` = `tvshow_episode`.`id` WHERE `tvshow_episode`.`season` = ?GROUP BY `catalog_id`";
119
120            $db_results = Dba::read($sql, array($this->id));
121            $row        = Dba::fetch_assoc($db_results);
122            parent::add_to_cache('tvshow_extra', $this->id, $row);
123        }
124
125        /* Set Object Vars */
126        $this->episodes   = $row['episode_count'];
127        $this->catalog_id = $row['catalog_id'];
128
129        return $row;
130    } // _get_extra_info
131
132    /**
133     * format
134     * this function takes the object and formats some values
135     * @param boolean $details
136     * @return boolean
137     */
138    public function format($details = true)
139    {
140        $this->f_name = T_('Season') . ' ' . $this->season_number;
141
142        $tvshow = new TvShow($this->tvshow);
143        $tvshow->format($details);
144        $this->f_tvshow      = $tvshow->f_name;
145        $this->f_tvshow_link = $tvshow->f_link;
146
147        $this->link   = AmpConfig::get('web_path') . '/tvshow_seasons.php?action=show&season=' . $this->id;
148        $this->f_link = '<a href="' . $this->link . '" title="' . $tvshow->f_name . ' - ' . scrub_out($this->f_name) . '">' . scrub_out($this->f_name) . '</a>';
149
150        if ($details) {
151            $this->_get_extra_info();
152        }
153
154        return true;
155    }
156
157    /**
158     * get_keywords
159     * @return array|mixed
160     */
161    public function get_keywords()
162    {
163        $keywords           = array();
164        $keywords['tvshow'] = array(
165            'important' => true,
166            'label' => T_('TV Show'),
167            'value' => $this->f_tvshow
168        );
169        $keywords['tvshow_season'] = array(
170            'important' => false,
171            'label' => T_('Season'),
172            'value' => $this->season_number
173        );
174        $keywords['type'] = array(
175            'important' => false,
176            'label' => null,
177            'value' => 'tvshow'
178        );
179
180        return $keywords;
181    }
182
183    /**
184     * @return string
185     */
186    public function get_fullname()
187    {
188        return $this->f_name;
189    }
190
191    /**
192     * @return array
193     */
194    public function get_parent()
195    {
196        return array('object_type' => 'tvshow', 'object_id' => $this->tvshow);
197    }
198
199    /**
200     * @return array
201     */
202    public function get_childrens()
203    {
204        return array('tvshow_episode' => $this->get_episodes());
205    }
206
207    /**
208     * @param string $name
209     * @return array
210     */
211    public function search_childrens($name)
212    {
213        debug_event(self::class, 'search_childrens ' . $name, 5);
214
215        return array();
216    }
217
218    /**
219     * get_medias
220     * @param string $filter_type
221     * @return array
222     */
223    public function get_medias($filter_type = null)
224    {
225        $medias = array();
226        if ($filter_type === null || $filter_type == 'video') {
227            $episodes = $this->get_episodes();
228            foreach ($episodes as $episode_id) {
229                $medias[] = array(
230                    'object_type' => 'video',
231                    'object_id' => $episode_id
232                );
233            }
234        }
235
236        return $medias;
237    }
238
239    /**
240     * get_catalogs
241     *
242     * Get all catalog ids related to this item.
243     * @return integer[]
244     */
245    public function get_catalogs()
246    {
247        return array($this->catalog_id);
248    }
249
250    /**
251     * @return mixed|null
252     */
253    public function get_user_owner()
254    {
255        return null;
256    }
257
258    /**
259     * @return string
260     */
261    public function get_default_art_kind()
262    {
263        return 'default';
264    }
265
266    /**
267     * @return mixed
268     */
269    public function get_description()
270    {
271        // No season description for now, always return tvshow description
272        $tvshow = new TvShow($this->tvshow);
273
274        return $tvshow->get_description();
275    }
276
277    /**
278     * display_art
279     * @param integer $thumb
280     * @param boolean $force
281     */
282    public function display_art($thumb = 2, $force = false)
283    {
284        $tvshow_id = null;
285        $type      = null;
286
287        if (Art::has_db($this->id, 'tvshow_season')) {
288            $tvshow_id = $this->id;
289            $type      = 'tvshow_season';
290        } else {
291            if (Art::has_db($this->tvshow, 'tvshow') || $force) {
292                $tvshow_id = $this->tvshow;
293                $type      = 'tvshow';
294            }
295        }
296
297        if ($tvshow_id !== null && $type !== null) {
298            Art::display($type, $tvshow_id, $this->get_fullname(), $thumb, $this->link);
299        }
300    }
301
302    /**
303     * check
304     *
305     * Checks for an existing tv show season; if none exists, insert one.
306     * @param $tvshow
307     * @param $season_number
308     * @param boolean $readonly
309     * @return string|null
310     */
311    public static function check($tvshow, $season_number, $readonly = false)
312    {
313        $name = $tvshow . '_' . $season_number;
314        // null because we don't have any unique id like mbid for now
315        if (isset(self::$_mapcache[$name]['null'])) {
316            return self::$_mapcache[$name]['null'];
317        }
318
319        $object_id  = 0;
320        $exists     = false;
321        $sql        = 'SELECT `id` FROM `tvshow_season` WHERE `tvshow` = ? AND `season_number` = ?';
322        $db_results = Dba::read($sql, array($tvshow, $season_number));
323        $id_array   = array();
324        while ($row = Dba::fetch_assoc($db_results)) {
325            $key            = 'null';
326            $id_array[$key] = $row['id'];
327        }
328
329        if (count($id_array)) {
330            $object_id = array_shift($id_array);
331            $exists    = true;
332        }
333
334        if ($exists && (int)$object_id > 0) {
335            self::$_mapcache[$name]['null'] = $object_id;
336
337            return $object_id;
338        }
339
340        if ($readonly) {
341            return null;
342        }
343
344        $sql = 'INSERT INTO `tvshow_season` (`tvshow`, `season_number`) ' . 'VALUES(?, ?)';
345
346        $db_results = Dba::write($sql, array($tvshow, $season_number));
347        if (!$db_results) {
348            return null;
349        }
350        $object_id = Dba::insert_id();
351
352        self::$_mapcache[$name]['null'] = $object_id;
353
354        return $object_id;
355    }
356
357    /**
358     * update
359     * This takes a key'd array of data and updates the current tv show
360     * @param array $data
361     * @return mixed
362     */
363    public function update(array $data)
364    {
365        $sql = 'UPDATE `tvshow_season` SET `season_number` = ?, `tvshow` = ? WHERE `id` = ?';
366        Dba::write($sql, array($data['season_number'], $data['tvshow'], $this->id));
367
368        return $this->id;
369    } // update
370
371    /**
372     * @return PDOStatement|boolean
373     */
374    public function remove()
375    {
376        $deleted = true;
377        $videos  = $this->get_episodes();
378        foreach ($videos as $video_id) {
379            $video   = Video::create_from_id($video_id);
380            $deleted = $video->remove();
381            if (!$deleted) {
382                debug_event(self::class, 'Error when deleting the video `' . $video_id . '`.', 1);
383                break;
384            }
385        }
386
387        if ($deleted) {
388            $sql     = "DELETE FROM `tvshow_season` WHERE `id` = ?";
389            $deleted = Dba::write($sql, array($this->id));
390            if ($deleted) {
391                Art::garbage_collection('tvshow_season', $this->id);
392                Userflag::garbage_collection('tvshow_season', $this->id);
393                Rating::garbage_collection('tvshow_season', $this->id);
394                $this->getShoutRepository()->collectGarbage('tvshow_season', $this->getId());
395                $this->getUseractivityRepository()->collectGarbage('tvshow_season', $this->getId());
396            }
397        }
398
399        return $deleted;
400    }
401
402    /**
403     * @param $tvshow_id
404     * @param $season_id
405     * @return PDOStatement|boolean
406     */
407    public static function update_tvshow($tvshow_id, $season_id)
408    {
409        $sql = "UPDATE `tvshow_season` SET `tvshow` = ? WHERE `id` = ?";
410
411        return Dba::write($sql, array($tvshow_id, $season_id));
412    }
413
414    /**
415     * @deprecated
416     */
417    private function getShoutRepository(): ShoutRepositoryInterface
418    {
419        global $dic;
420
421        return $dic->get(ShoutRepositoryInterface::class);
422    }
423
424    /**
425     * @deprecated
426     */
427    private function getUseractivityRepository(): UserActivityRepositoryInterface
428    {
429        global $dic;
430
431        return $dic->get(UserActivityRepositoryInterface::class);
432    }
433}
434