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