2015-01-02 08:16:54 +00:00
|
|
|
<?php
|
|
|
|
namespace Entity;
|
|
|
|
|
|
|
|
use \Doctrine\Common\Collections\ArrayCollection;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Table(name="station")
|
|
|
|
* @Entity
|
2015-02-26 05:01:02 +00:00
|
|
|
* @HasLifecycleCallbacks
|
2015-01-02 08:16:54 +00:00
|
|
|
*/
|
2016-05-02 08:18:32 +00:00
|
|
|
class Station extends \App\Doctrine\Entity
|
2015-01-02 08:16:54 +00:00
|
|
|
{
|
2015-02-16 16:35:49 +00:00
|
|
|
use Traits\FileUploads;
|
|
|
|
|
2015-01-02 08:16:54 +00:00
|
|
|
public function __construct()
|
|
|
|
{
|
2016-08-30 06:28:56 +00:00
|
|
|
$this->automation_timestamp = 0;
|
|
|
|
|
2015-01-02 08:16:54 +00:00
|
|
|
$this->history = new ArrayCollection;
|
|
|
|
$this->managers = new ArrayCollection;
|
2016-05-04 00:03:28 +00:00
|
|
|
|
2015-01-02 08:16:54 +00:00
|
|
|
$this->media = new ArrayCollection;
|
2016-05-04 00:03:28 +00:00
|
|
|
$this->playlists = new ArrayCollection;
|
2015-01-02 08:16:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Column(name="id", type="integer")
|
|
|
|
* @Id
|
|
|
|
* @GeneratedValue(strategy="IDENTITY")
|
|
|
|
*/
|
|
|
|
protected $id;
|
|
|
|
|
|
|
|
/** @Column(name="name", type="string", length=100, nullable=true) */
|
|
|
|
protected $name;
|
|
|
|
|
|
|
|
public function getShortName()
|
|
|
|
{
|
|
|
|
return self::getStationShortName($this->name);
|
|
|
|
}
|
|
|
|
|
2016-05-06 08:57:34 +00:00
|
|
|
/** @Column(name="frontend_type", type="string", length=100, nullable=true) */
|
|
|
|
protected $frontend_type;
|
2015-02-16 07:46:37 +00:00
|
|
|
|
2016-05-19 14:56:21 +00:00
|
|
|
/** @Column(name="frontend_config", type="json", nullable=true) */
|
|
|
|
protected $frontend_config;
|
|
|
|
|
2016-05-06 08:57:34 +00:00
|
|
|
/**
|
|
|
|
* @return \App\RadioFrontend\AdapterAbstract
|
2016-05-14 07:27:52 +00:00
|
|
|
* @throws \Exception
|
2016-05-06 08:57:34 +00:00
|
|
|
*/
|
|
|
|
public function getFrontendAdapter()
|
2015-01-02 08:16:54 +00:00
|
|
|
{
|
2016-05-06 08:57:34 +00:00
|
|
|
$adapters = self::getFrontendAdapters();
|
|
|
|
|
|
|
|
if (!isset($adapters['adapters'][$this->frontend_type]))
|
|
|
|
throw new \Exception('Adapter not found: '.$this->frontend_type);
|
|
|
|
|
|
|
|
$class_name = $adapters['adapters'][$this->frontend_type]['class'];
|
|
|
|
return new $class_name($this);
|
2015-01-02 08:16:54 +00:00
|
|
|
}
|
|
|
|
|
2016-05-06 08:57:34 +00:00
|
|
|
/** @Column(name="backend_type", type="string", length=100, nullable=true) */
|
|
|
|
protected $backend_type;
|
2015-02-17 12:23:21 +00:00
|
|
|
|
2016-05-19 14:56:21 +00:00
|
|
|
/** @Column(name="backend_config", type="json", nullable=true) */
|
|
|
|
protected $backend_config;
|
|
|
|
|
2016-05-06 08:57:34 +00:00
|
|
|
/**
|
|
|
|
* @return \App\RadioBackend\AdapterAbstract
|
2016-05-14 07:27:52 +00:00
|
|
|
* @throws \Exception
|
2016-05-06 08:57:34 +00:00
|
|
|
*/
|
|
|
|
public function getBackendAdapter()
|
2015-02-17 12:23:21 +00:00
|
|
|
{
|
2016-05-06 08:57:34 +00:00
|
|
|
$adapters = self::getBackendAdapters();
|
|
|
|
|
|
|
|
if (!isset($adapters['adapters'][$this->backend_type]))
|
|
|
|
throw new \Exception('Adapter not found: '.$this->backend_type);
|
|
|
|
|
|
|
|
$class_name = $adapters['adapters'][$this->backend_type]['class'];
|
|
|
|
return new $class_name($this);
|
2015-02-17 12:23:21 +00:00
|
|
|
}
|
|
|
|
|
2016-05-06 08:57:34 +00:00
|
|
|
/** @Column(name="description", type="text", nullable=true) */
|
|
|
|
protected $description;
|
|
|
|
|
|
|
|
/** @Column(name="radio_port", type="smallint", nullable=true) */
|
|
|
|
protected $radio_port;
|
|
|
|
|
2016-05-17 08:40:44 +00:00
|
|
|
public function getRadioStreamUrl()
|
|
|
|
{
|
2016-05-19 14:56:21 +00:00
|
|
|
$frontend_adapter = $this->getFrontendAdapter();
|
|
|
|
return $frontend_adapter->getStreamUrl();
|
2016-05-17 08:40:44 +00:00
|
|
|
}
|
|
|
|
|
2016-05-06 08:57:34 +00:00
|
|
|
/** @Column(name="radio_base_dir", type="string", length=255, nullable=true) */
|
|
|
|
protected $radio_base_dir;
|
2015-01-02 08:16:54 +00:00
|
|
|
|
2016-05-07 09:13:17 +00:00
|
|
|
public function setRadioBaseDir($new_dir)
|
|
|
|
{
|
|
|
|
if ($new_dir != $this->radio_base_dir)
|
|
|
|
{
|
2016-05-14 07:27:52 +00:00
|
|
|
$this->radio_base_dir = $new_dir;
|
2016-05-07 09:13:17 +00:00
|
|
|
|
2016-05-15 09:31:21 +00:00
|
|
|
@mkdir($this->getRadioMediaDir(), 0777, TRUE);
|
|
|
|
@mkdir($this->getRadioPlaylistsDir(), 0777, TRUE);
|
2016-05-19 14:56:21 +00:00
|
|
|
@mkdir($this->getRadioConfigDir(), 0777, TRUE);
|
2016-05-07 09:13:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-15 09:31:21 +00:00
|
|
|
public function getRadioMediaDir()
|
|
|
|
{
|
|
|
|
return $this->radio_base_dir.'/media';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getRadioPlaylistsDir()
|
|
|
|
{
|
|
|
|
return $this->radio_base_dir.'/playlists';
|
|
|
|
}
|
|
|
|
|
2016-05-19 14:56:21 +00:00
|
|
|
public function getRadioConfigDir()
|
|
|
|
{
|
|
|
|
return $this->radio_base_dir.'/config';
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @Column(name="nowplaying_data", type="json", nullable=true) */
|
|
|
|
protected $nowplaying_data;
|
|
|
|
|
2016-08-30 06:28:56 +00:00
|
|
|
/** @Column(name="automation_settings", type="json", nullable=true) */
|
|
|
|
protected $automation_settings;
|
|
|
|
|
|
|
|
/** @Column(name="automation_timestamp", type="integer", nullable=true) */
|
|
|
|
protected $automation_timestamp;
|
|
|
|
|
2015-01-02 08:16:54 +00:00
|
|
|
/**
|
|
|
|
* @OneToMany(targetEntity="SongHistory", mappedBy="station")
|
|
|
|
* @OrderBy({"timestamp" = "DESC"})
|
|
|
|
*/
|
|
|
|
protected $history;
|
|
|
|
|
|
|
|
/**
|
2015-05-22 07:26:49 +00:00
|
|
|
* @ManyToMany(targetEntity="User", mappedBy="stations")
|
2015-01-02 08:16:54 +00:00
|
|
|
*/
|
|
|
|
protected $managers;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @OneToMany(targetEntity="StationMedia", mappedBy="station")
|
|
|
|
*/
|
|
|
|
protected $media;
|
|
|
|
|
2016-05-04 00:03:28 +00:00
|
|
|
/**
|
|
|
|
* @OneToMany(targetEntity="StationPlaylist", mappedBy="station")
|
2016-05-16 13:21:51 +00:00
|
|
|
* @OrderBy({"weight" = "DESC"})
|
2016-05-04 00:03:28 +00:00
|
|
|
*/
|
|
|
|
protected $playlists;
|
2015-01-02 08:16:54 +00:00
|
|
|
|
2016-05-10 10:34:10 +00:00
|
|
|
public function getRecentHistory($num_entries = 5)
|
2015-01-02 08:16:54 +00:00
|
|
|
{
|
|
|
|
$em = self::getEntityManager();
|
2016-05-10 10:34:10 +00:00
|
|
|
$history = $em->createQuery('SELECT sh, s FROM Entity\SongHistory sh JOIN sh.song s WHERE sh.station_id = :station_id ORDER BY sh.id DESC')
|
2015-01-02 08:16:54 +00:00
|
|
|
->setParameter('station_id', $this->id)
|
|
|
|
->setMaxResults($num_entries)
|
|
|
|
->getArrayResult();
|
|
|
|
|
|
|
|
$return = array();
|
|
|
|
foreach($history as $sh)
|
|
|
|
{
|
|
|
|
$history = array(
|
2016-05-15 13:40:25 +00:00
|
|
|
'played_at' => $sh['timestamp_start'],
|
2015-01-02 08:16:54 +00:00
|
|
|
'song' => Song::api($sh['song']),
|
|
|
|
);
|
|
|
|
$return[] = $history;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $return;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function canManage(User $user = null)
|
|
|
|
{
|
2016-05-10 10:34:10 +00:00
|
|
|
$di = \Phalcon\Di::getDefault();
|
|
|
|
|
2015-01-02 08:16:54 +00:00
|
|
|
if ($user === null)
|
2016-05-10 10:34:10 +00:00
|
|
|
{
|
|
|
|
$auth = $di->get('auth');
|
|
|
|
$user = $auth->getLoggedInUser();
|
|
|
|
}
|
2015-01-02 08:16:54 +00:00
|
|
|
|
2015-01-07 10:29:52 +00:00
|
|
|
$acl = $di->get('acl');
|
2015-01-02 08:16:54 +00:00
|
|
|
if ($acl->userAllowed('manage stations', $user))
|
|
|
|
return true;
|
|
|
|
|
2015-05-22 07:26:49 +00:00
|
|
|
return ($this->managers->contains($user));
|
2015-01-02 08:16:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Static Functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
public static function getStationShortName($name)
|
|
|
|
{
|
2016-05-14 07:27:52 +00:00
|
|
|
return strtolower(preg_replace("/[^A-Za-z0-9_]/", '', str_replace(' ', '_', trim($name))));
|
2015-01-02 08:16:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static function getStationClassName($name)
|
|
|
|
{
|
|
|
|
$name = preg_replace("/[^A-Za-z0-9_ ]/", '', $name);
|
|
|
|
$name = str_replace('_', ' ', $name);
|
|
|
|
$name = str_replace(' ', '', $name);
|
|
|
|
return $name;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function fetchAll()
|
|
|
|
{
|
|
|
|
$em = self::getEntityManager();
|
2016-05-12 11:07:27 +00:00
|
|
|
return $em->createQuery('SELECT s FROM '.__CLASS__.' s ORDER BY s.name ASC')->execute();
|
2015-01-02 08:16:54 +00:00
|
|
|
}
|
2015-02-07 13:13:20 +00:00
|
|
|
|
2015-01-02 08:16:54 +00:00
|
|
|
public static function fetchArray($cached = true)
|
|
|
|
{
|
2016-05-06 08:57:34 +00:00
|
|
|
$em = self::getEntityManager();
|
|
|
|
$stations = $em->createQuery('SELECT s FROM '.__CLASS__.' s ORDER BY s.name ASC')
|
|
|
|
->getArrayResult();
|
2015-01-02 08:16:54 +00:00
|
|
|
|
2016-05-06 08:57:34 +00:00
|
|
|
foreach($stations as &$station)
|
2015-01-02 08:16:54 +00:00
|
|
|
{
|
2016-05-06 08:57:34 +00:00
|
|
|
$station['short_name'] = self::getStationShortName($station['name']);
|
2015-01-02 08:16:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return $stations;
|
|
|
|
}
|
|
|
|
|
2015-09-11 03:30:29 +00:00
|
|
|
public static function fetchSelect($add_blank = FALSE, \Closure $display = NULL, $pk = 'id', $order_by = 'name')
|
|
|
|
{
|
|
|
|
$select = array();
|
|
|
|
|
|
|
|
// Specify custom text in the $add_blank parameter to override.
|
|
|
|
if ($add_blank !== FALSE)
|
|
|
|
$select[''] = ($add_blank === TRUE) ? 'Select...' : $add_blank;
|
|
|
|
|
|
|
|
// Build query for records.
|
|
|
|
$results = self::fetchArray();
|
|
|
|
|
|
|
|
// Assemble select values and, if necessary, call $display callback.
|
|
|
|
foreach((array)$results as $result)
|
|
|
|
{
|
|
|
|
$key = $result[$pk];
|
|
|
|
$value = ($display === NULL) ? $result['name'] : $display($result);
|
|
|
|
$select[$key] = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $select;
|
|
|
|
}
|
|
|
|
|
2015-01-02 08:16:54 +00:00
|
|
|
public static function getShortNameLookup($cached = true)
|
|
|
|
{
|
|
|
|
$stations = self::fetchArray($cached);
|
|
|
|
|
|
|
|
$lookup = array();
|
|
|
|
foreach ($stations as $station)
|
|
|
|
{
|
|
|
|
$lookup[$station['short_name']] = $station;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $lookup;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function findByShortCode($short_code)
|
|
|
|
{
|
|
|
|
$short_names = self::getShortNameLookup();
|
|
|
|
|
|
|
|
if (isset($short_names[$short_code]))
|
|
|
|
{
|
|
|
|
$id = $short_names[$short_code]['id'];
|
|
|
|
return self::find($id);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve the API version of the object/array.
|
|
|
|
public static function api($row)
|
|
|
|
{
|
|
|
|
if ($row instanceof self)
|
|
|
|
$row = $row->toArray();
|
|
|
|
|
|
|
|
$api = array(
|
|
|
|
'id' => (int)$row['id'],
|
|
|
|
'name' => $row['name'],
|
|
|
|
'shortcode' => self::getStationShortName($row['name']),
|
|
|
|
);
|
|
|
|
|
2016-05-04 00:03:28 +00:00
|
|
|
/*
|
2015-01-02 08:16:54 +00:00
|
|
|
if (isset($row['streams']))
|
|
|
|
{
|
|
|
|
$api['streams'] = array();
|
|
|
|
|
|
|
|
foreach ((array)$row['streams'] as $stream)
|
|
|
|
{
|
|
|
|
$api['streams'][] = StationStream::api($stream);
|
|
|
|
|
2015-07-11 11:05:00 +00:00
|
|
|
// Set first stream as default, override if a later stream is explicitly default.
|
|
|
|
if ($stream['is_default'] || !isset($api['default_stream_id']))
|
2015-01-02 08:16:54 +00:00
|
|
|
{
|
2015-05-22 07:26:49 +00:00
|
|
|
$api['default_stream_id'] = (int)$stream['id'];
|
2015-01-02 08:16:54 +00:00
|
|
|
$api['stream_url'] = $stream['stream_url'];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-04 00:03:28 +00:00
|
|
|
*/
|
2015-01-02 08:16:54 +00:00
|
|
|
|
2016-05-04 00:03:28 +00:00
|
|
|
// $api['player_url'] = ShortUrl::stationUrl($api['shortcode']);
|
2015-01-02 08:16:54 +00:00
|
|
|
|
|
|
|
return $api;
|
|
|
|
}
|
2016-05-06 08:57:34 +00:00
|
|
|
|
|
|
|
public static function getFrontendAdapters()
|
|
|
|
{
|
|
|
|
return array(
|
|
|
|
'default' => 'icecast',
|
|
|
|
'adapters' => array(
|
|
|
|
'icecast' => array(
|
|
|
|
'name' => 'IceCast v2.4 or Above',
|
|
|
|
'class' => '\App\RadioFrontend\IceCast',
|
|
|
|
),
|
|
|
|
/*
|
|
|
|
'shoutcast1' => array(
|
|
|
|
'name' => 'ShoutCast 1',
|
|
|
|
'class' => '\App\RadioFrontend\ShoutCast1',
|
|
|
|
),
|
|
|
|
'shoutcast2' => array(
|
|
|
|
'name' => 'ShoutCast 2',
|
|
|
|
'class' => '\App\RadioFrontend\ShoutCast2',
|
|
|
|
),
|
|
|
|
*/
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function getBackendAdapters()
|
|
|
|
{
|
|
|
|
return array(
|
|
|
|
'default' => 'liquidsoap',
|
|
|
|
'adapters' => array(
|
|
|
|
'liquidsoap' => array(
|
|
|
|
'name' => 'LiquidSoap',
|
|
|
|
'class' => '\App\RadioBackend\LiquidSoap',
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2014-02-21 09:25:10 +00:00
|
|
|
}
|