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\Module\System\AmpError;
30use PDOStatement;
31
32/**
33 * Radio Class
34 *
35 * This handles the internet radio stuff, that is inserted into live_stream
36 * this can include podcasts or what-have-you
37 *
38 */
39class Live_Stream extends database_object implements Media, library_item
40{
41    protected const DB_TABLENAME = 'live_stream';
42
43    /* DB based variables */
44
45    /**
46     * @var integer $id
47     */
48    public $id;
49    /**
50     * @var string $name
51     */
52    public $name;
53    /**
54     * @var string $site_url
55     */
56    public $site_url;
57    /**
58     * @var string $url
59     */
60    public $url;
61    /**
62     * @var string $f_link
63     */
64    public $link;
65
66    /**
67     * @var string $codec
68     */
69    public $codec;
70    /**
71     * @var integer $catalog
72     */
73    public $catalog;
74
75    /**
76     * @var string $f_name
77     */
78    public $f_name;
79
80    /**
81     * @var string $f_link
82     */
83    public $f_link;
84    /**
85     * @var string $f_name_link
86     */
87    public $f_name_link;
88    /**
89     * @var string $f_url_link
90     */
91    public $f_url_link;
92    /**
93     * @var string $f_site_url_link
94     */
95    public $f_site_url_link;
96
97    /**
98     * Constructor
99     * This takes a flagged.id and then pulls in the information for said flag entry
100     * @param integer $stream_id
101     */
102    public function __construct($stream_id)
103    {
104        $info = $this->get_info($stream_id, 'live_stream');
105
106        // Set the vars
107        foreach ($info as $key => $value) {
108            $this->$key = $value;
109        }
110    } // constructor
111
112    public function getId(): int
113    {
114        return (int) $this->id;
115    }
116
117    /**
118     * format
119     * This takes the normal data from the database and makes it pretty
120     * for the users, the new variables are put in f_??? and f_???_link
121     * @param boolean $details
122     * @return true
123     */
124    public function format($details = true)
125    {
126        unset($details); // dead code but called from other format calls
127        // Default link used on the rightbar
128        $this->f_name          = filter_var($this->name, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
129        $this->link            = AmpConfig::get('web_path') . '/radio.php?action=show&radio=' . scrub_out($this->id);
130        $this->f_link          = "<a href=\"" . $this->link . "\">" . scrub_out($this->f_name) . "</a>";
131        $this->f_name_link     = "<a target=\"_blank\" href=\"" . $this->site_url . "\">" . $this->f_name . "</a>";
132        $this->f_url_link      = "<a target=\"_blank\" href=\"" . $this->url . "\">" . $this->url . "</a>";
133        $this->f_site_url_link = "<a target=\"_blank\" href=\"" . $this->site_url . "\">" . $this->site_url . "</a>";
134
135        return true;
136    } // format
137
138    /**
139     * @return array
140     */
141    public function get_keywords()
142    {
143        return array();
144    }
145
146    /**
147     * @return string
148     */
149    public function get_fullname()
150    {
151        return $this->name;
152    }
153
154    /**
155     * @return null
156     */
157    public function get_parent()
158    {
159        return null;
160    }
161
162    /**
163     * @return array
164     */
165    public function get_childrens()
166    {
167        return array();
168    }
169
170    /**
171     * @param string $name
172     * @return array
173     */
174    public function search_childrens($name)
175    {
176        debug_event(self::class, 'search_childrens ' . $name, 5);
177
178        return array();
179    }
180
181    /**
182     * @param string $filter_type
183     * @return array
184     */
185    public function get_medias($filter_type = null)
186    {
187        $medias = array();
188        if ($filter_type === null || $filter_type == 'live_stream') {
189            $medias[] = array(
190                'object_type' => 'live_stream',
191                'object_id' => $this->id
192            );
193        }
194
195        return $medias;
196    }
197
198    /**
199     * get_catalogs
200     *
201     * Get all catalog ids related to this item.
202     * @return integer[]
203     */
204    public function get_catalogs()
205    {
206        return array($this->catalog);
207    }
208
209    /**
210     * @return null
211     */
212    public function get_user_owner()
213    {
214        return null;
215    }
216
217    /**
218     * @return string
219     */
220    public function get_default_art_kind()
221    {
222        return 'default';
223    }
224
225    /**
226     * @return null
227     */
228    public function get_description()
229    {
230        return null;
231    }
232
233    /**
234     * display_art
235     * @param integer $thumb
236     * @param boolean $force
237     */
238    public function display_art($thumb = 2, $force = false)
239    {
240        if (Art::has_db($this->id, 'live_stream') || $force) {
241            Art::display('live_stream', $this->id, $this->get_fullname(), $thumb, $this->link);
242        }
243    }
244
245    /**
246     * update
247     * This is a static function that takes a key'd array for input
248     * it depends on a ID element to determine which radio element it
249     * should be updating
250     * @param array $data
251     * @return boolean|integer
252     */
253    public function update(array $data)
254    {
255        if (!$data['name']) {
256            AmpError::add('general', T_('Name is required'));
257        }
258
259        $allowed_array = array('https', 'http', 'mms', 'mmsh', 'mmsu', 'mmst', 'rtsp', 'rtmp');
260
261        $elements = explode(":", (string)$data['url']);
262
263        if (!in_array($elements['0'], $allowed_array)) {
264            AmpError::add('general', T_('URL is invalid, must be mms://, https:// or http://'));
265        }
266
267        if (!empty($data['site_url'])) {
268            $elements = explode(":", (string)$data['site_url']);
269            if (!in_array($elements['0'], $allowed_array)) {
270                AmpError::add('site_url', T_('URL is invalid, must be http:// or https://'));
271            }
272        }
273
274        if (AmpError::occurred()) {
275            return false;
276        }
277
278        $sql = "UPDATE `live_stream` SET `name` = ?,`site_url` = ?,`url` = ?, codec = ? WHERE `id` = ?";
279        Dba::write($sql,
280            array($data['name'], $data['site_url'], $data['url'], strtolower((string)$data['codec']), $this->id));
281
282        return $this->id;
283    } // update
284
285    /**
286     * create
287     * This is a static function that takes a key'd array for input
288     * and if everything is good creates the object.
289     * @param array $data
290     * @return PDOStatement|boolean
291     */
292    public static function create(array $data)
293    {
294        // Make sure we've got a name and codec
295        if (!strlen((string)$data['name'])) {
296            AmpError::add('name', T_('Name is required'));
297        }
298        if (!strlen((string)$data['codec'])) {
299            AmpError::add('codec', T_('Codec is required (e.g. MP3, OGG...)'));
300        }
301
302        $allowed_array = array('https', 'http', 'mms', 'mmsh', 'mmsu', 'mmst', 'rtsp', 'rtmp');
303
304        $elements = explode(":", (string)$data['url']);
305
306        if (!in_array($elements['0'], $allowed_array)) {
307            AmpError::add('url', T_('URL is invalid, must be http:// or https://'));
308        }
309
310        if (!empty($data['site_url'])) {
311            $elements = explode(":", (string)$data['site_url']);
312            if (!in_array($elements['0'], $allowed_array)) {
313                AmpError::add('site_url', T_('URL is invalid, must be http:// or https://'));
314            }
315        }
316
317        // Make sure it's a real catalog
318        $catalog = Catalog::create_from_id($data['catalog']);
319        if (!$catalog->name) {
320            AmpError::add('catalog', T_('Catalog is invalid'));
321        }
322
323        if (AmpError::occurred()) {
324            return false;
325        }
326
327        // If we've made it this far everything must be ok... I hope
328        $sql = "INSERT INTO `live_stream` (`name`, `site_url`, `url`, `catalog`, `codec`) VALUES (?, ?, ?, ?, ?)";
329
330        return Dba::write($sql,
331            array($data['name'], $data['site_url'], $data['url'], $catalog->id, strtolower((string)$data['codec'])));
332    } // create
333
334    /**
335     * get_stream_types
336     * This is needed by the media interface
337     * @param string $player
338     * @return array
339     */
340    public function get_stream_types($player = null)
341    {
342        return array('foreign');
343    } // native_stream
344
345    /**
346     * play_url
347     * This is needed by the media interface
348     * @param string $additional_params
349     * @param string $player
350     * @param boolean $local
351     * @param string $sid
352     * @param string $force_http
353     * @return string
354     */
355    public function play_url($additional_params = '', $player = null, $local = false, $sid = '', $force_http = '')
356    {
357        return $this->url . $additional_params;
358    } // play_url
359
360    /**
361     * @return string
362     */
363    public function get_stream_name()
364    {
365        return $this->get_fullname();
366    }
367
368    /**
369     * get_transcode_settings
370     *
371     * This will probably never be implemented
372     * @param string $target
373     * @param string $player
374     * @param array $options
375     * @return false
376     */
377    public function get_transcode_settings($target = null, $player = null, $options = array())
378    {
379        return false;
380    }
381
382    /**
383     * @param integer $user
384     * @param string $agent
385     * @param array $location
386     * @param integer $date
387     * @return boolean
388     */
389    public function set_played($user, $agent, $location, $date = null)
390    {
391        // Do nothing
392        unset($user, $agent, $location, $date);
393
394        return false;
395    }
396
397    /**
398     * @param integer $user
399     * @param string $agent
400     * @param integer $date
401     * @return boolean
402     */
403    public function check_play_history($user, $agent, $date)
404    {
405        // Do nothing
406        unset($user, $agent, $date);
407
408        return false;
409    }
410
411    public function remove()
412    {
413    }
414}
415