Rename airtime_mvc/ to legacy/
This commit is contained in:
parent
f0879322c2
commit
3e18d42c8b
1316 changed files with 0 additions and 0 deletions
70
legacy/application/Bootstrap.php
Normal file
70
legacy/application/Bootstrap.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
require_once CONFIG_PATH . "conf.php";
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
require_once CONFIG_PATH . "ACL.php";
|
||||
|
||||
// Since we initialize the database during the configuration check,
|
||||
// check the $configRun global to avoid reinitializing unnecessarily
|
||||
if (!isset($configRun) || !$configRun) {
|
||||
Propel::init(CONFIG_PATH . 'airtime-conf-production.php');
|
||||
}
|
||||
|
||||
require_once CONFIG_PATH . "constants.php";
|
||||
|
||||
Logging::setLogPath(LIBRETIME_LOG_DIR . '/zendphp.log');
|
||||
|
||||
Zend_Session::setOptions(array('strict' => true));
|
||||
Config::setAirtimeVersion();
|
||||
require_once (CONFIG_PATH . 'navigation.php');
|
||||
|
||||
Zend_Validate::setDefaultNamespaces("Zend");
|
||||
|
||||
$front = Zend_Controller_Front::getInstance();
|
||||
$front->registerPlugin(new RabbitMqPlugin());
|
||||
$front->throwExceptions(false);
|
||||
|
||||
/* The bootstrap class should only be used to initialize actions that return a view.
|
||||
Actions that return JSON will not use the bootstrap class! */
|
||||
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
|
||||
{
|
||||
protected function _initDoctype()
|
||||
{
|
||||
$this->bootstrap('view');
|
||||
$view = $this->getResource('view');
|
||||
$view->doctype('XHTML1_STRICT');
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize front controller
|
||||
*
|
||||
* This is call ZFrontController to ensure it is executed last in the bootstrap process.
|
||||
*/
|
||||
protected function _initZFrontController()
|
||||
{
|
||||
Zend_Controller_Front::getInstance()->throwExceptions(false);
|
||||
}
|
||||
|
||||
protected function _initRouter()
|
||||
{
|
||||
$front = Zend_Controller_Front::getInstance();
|
||||
$router = $front->getRouter();
|
||||
$front->setBaseUrl(Application_Common_OsPath::getBaseDir());
|
||||
|
||||
$router->addRoute(
|
||||
'password-change',
|
||||
new Zend_Controller_Router_Route('password-change/:user_id/:token', array(
|
||||
'module' => 'default',
|
||||
'controller' => 'login',
|
||||
'action' => 'password-change',
|
||||
)));
|
||||
}
|
||||
|
||||
public function _initPlugins()
|
||||
{
|
||||
$front = Zend_Controller_Front::getInstance();
|
||||
$front->registerPlugin(new Zend_Controller_Plugin_Maintenance());
|
||||
$front->registerPlugin(new PageLayoutInitPlugin($this));
|
||||
}
|
||||
}
|
||||
|
108
legacy/application/airtime-boot.php
Normal file
108
legacy/application/airtime-boot.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
// Only enable cookie secure if we are supporting https.
|
||||
// Ideally, this would always be on and we would force https,
|
||||
// but the default installation configs are likely to be installed by
|
||||
// amature users on the setup that does not have https. Forcing
|
||||
// cookie_secure on non https would result in confusing login problems.
|
||||
if(!empty($_SERVER['HTTPS'])) {
|
||||
ini_set('session.cookie_secure', '1');
|
||||
}
|
||||
ini_set('session.cookie_httponly', '1');
|
||||
|
||||
error_reporting(E_ALL|E_STRICT);
|
||||
|
||||
function exception_error_handler($errno, $errstr, $errfile, $errline) {
|
||||
//Check if the statement that threw this error wanted its errors to be
|
||||
//suppressed. If so then return without with throwing exception.
|
||||
if (0 === error_reporting()) return;
|
||||
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
|
||||
return false;
|
||||
}
|
||||
|
||||
set_error_handler("exception_error_handler");
|
||||
|
||||
// Define application environment
|
||||
defined('APPLICATION_ENV')
|
||||
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
|
||||
|
||||
defined('VERBOSE_STACK_TRACE')
|
||||
|| define('VERBOSE_STACK_TRACE', (getenv('VERBOSE_STACK_TRACE') ? getenv('VERBOSE_STACK_TRACE') : true));
|
||||
|
||||
// Ensure library/ is on include_path
|
||||
set_include_path(implode(PATH_SEPARATOR, array(
|
||||
get_include_path(),
|
||||
realpath(LIB_PATH)
|
||||
)));
|
||||
|
||||
set_include_path(APPLICATION_PATH . 'common' . PATH_SEPARATOR . get_include_path());
|
||||
set_include_path(APPLICATION_PATH . 'common/enum' . PATH_SEPARATOR . get_include_path());
|
||||
set_include_path(APPLICATION_PATH . 'common/interface' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
//Propel classes.
|
||||
set_include_path(APPLICATION_PATH . 'models' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
//Controller plugins.
|
||||
set_include_path(APPLICATION_PATH . 'controllers' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
//Controller plugins.
|
||||
set_include_path(APPLICATION_PATH . 'controllers/plugins' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
//Services.
|
||||
set_include_path(APPLICATION_PATH . '/services/' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
//cloud storage directory
|
||||
set_include_path(APPLICATION_PATH . '/cloud_storage' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
//Upgrade directory
|
||||
set_include_path(APPLICATION_PATH . '/upgrade/' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
//Common directory
|
||||
set_include_path(APPLICATION_PATH . '/common/' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
//Composer's autoloader
|
||||
require_once 'autoload.php';
|
||||
|
||||
/** Zend_Application */
|
||||
$application = new Zend_Application(
|
||||
APPLICATION_ENV,
|
||||
CONFIG_PATH . 'application.ini',
|
||||
true
|
||||
);
|
||||
|
||||
require_once(APPLICATION_PATH . "logging/Logging.php");
|
||||
Logging::setLogPath(LIBRETIME_LOG_DIR . '/zendphp.log');
|
||||
Logging::setupParseErrorLogging();
|
||||
|
||||
// Create application, bootstrap, and run
|
||||
try {
|
||||
$sapi_type = php_sapi_name();
|
||||
if (substr($sapi_type, 0, 3) == 'cli') {
|
||||
set_include_path(APPLICATION_PATH . PATH_SEPARATOR . get_include_path());
|
||||
require_once("Bootstrap.php");
|
||||
} else {
|
||||
$application->bootstrap()->run();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
if ($e->getCode() == 401)
|
||||
{
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 401 Unauthorized', true, 401);
|
||||
return;
|
||||
}
|
||||
|
||||
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
|
||||
Logging::error($e->getMessage());
|
||||
|
||||
if (VERBOSE_STACK_TRACE) {
|
||||
echo $e->getMessage();
|
||||
echo "<pre>";
|
||||
echo $e->getTraceAsString();
|
||||
echo "</pre>";
|
||||
Logging::error($e->getMessage());
|
||||
Logging::error($e->getTraceAsString());
|
||||
} else {
|
||||
Logging::error($e->getTrace());
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
117
legacy/application/auth/adapters/FreeIpa.php
Normal file
117
legacy/application/auth/adapters/FreeIpa.php
Normal file
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
/**
|
||||
* Auth adaptor for FreeIPA
|
||||
*/
|
||||
|
||||
class LibreTime_Auth_Adaptor_FreeIpa implements Zend_Auth_Adapter_Interface {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $username;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $password;
|
||||
/**
|
||||
* @var Application_Model_User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* username from form
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
function setIdentity($username) {
|
||||
$this->username = $username;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* password from form
|
||||
*
|
||||
* This is ignored by FreeIPA but needs to get passed for completeness
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
function setCredential($password) {
|
||||
$this->password = $password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if apache logged the user and get data from ldap
|
||||
*
|
||||
* @return Zend_Auth_Result
|
||||
*/
|
||||
function authenticate()
|
||||
{
|
||||
if (array_key_exists('EXTERNAL_AUTH_ERROR', $_SERVER)) {
|
||||
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null, array($_SERVER['EXTERNAL_AUTH_ERROR']));
|
||||
}
|
||||
if (!array_key_exists('REMOTE_USER', $_SERVER)) {
|
||||
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null);
|
||||
}
|
||||
// success, the user is good since the service populated the REMOTE_USER
|
||||
$remoteUser = $_SERVER['REMOTE_USER'];
|
||||
|
||||
$subj = CcSubjsQuery::create()->findOneByDbLogin($remoteUser);
|
||||
$subjId =null;
|
||||
if ($subj) {
|
||||
$subjId = $subj->getDBId();
|
||||
}
|
||||
|
||||
if ($subjId) {
|
||||
$user = new Application_Model_User($subjId);
|
||||
} else {
|
||||
// upsert the user on login for first time users
|
||||
$user = new Application_Model_User('');
|
||||
}
|
||||
|
||||
// Always zap any local info with new info from ipa
|
||||
$user->setLogin($remoteUser);
|
||||
|
||||
// Use a random password for IPA users, reset on each login... I may change this to get set to the IPA pass but hate that it is being stored as md5 behind the scenes
|
||||
// gets rescrambled on each succeful login for security purposes
|
||||
$ipaDummyPass = bin2hex(openssl_random_pseudo_bytes(10));
|
||||
$user->setPassword($ipaDummyPass);
|
||||
|
||||
// grab user info from LDAP
|
||||
$userParts = explode('@', $remoteUser);
|
||||
$userInfo = LibreTime_Model_FreeIpa::GetUserInfo($userParts[0]);
|
||||
|
||||
$user->setType($userInfo['type']);
|
||||
$user->setFirstName($userInfo['first_name']);
|
||||
$user->setLastName($userInfo['last_name']);
|
||||
$user->setEmail($userInfo['email']);
|
||||
$user->setCellPhone($userInfo['cell_phone']);
|
||||
$user->setSkype($userInfo['skype']);
|
||||
$user->setJabber($userInfo['jabber']);
|
||||
$user->save();
|
||||
$this->user = $user;
|
||||
try {
|
||||
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $user);
|
||||
} catch (Exception $e) {
|
||||
// exception occured
|
||||
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return dummy object for internal auth handling
|
||||
*
|
||||
* we need to build a dummpy object since the auth layer knows nothing about the db
|
||||
*
|
||||
* @return stdClass
|
||||
*/
|
||||
public function getResultRowObject() {
|
||||
$o = new \stdClass;
|
||||
$o->id = $this->user->getId();
|
||||
$o->username = $this->user->getLogin();
|
||||
$o->password = $this->user->getPassword();
|
||||
$o->real_name = implode(' ', array($this->user->getFirstName(), $this->user->getLastName()));
|
||||
$o->type = $this->user->getType();
|
||||
$o->login = $this->user->getLogin();
|
||||
return $o;
|
||||
}
|
||||
}
|
30
legacy/application/cloud_storage/FileStorageBackend.php
Normal file
30
legacy/application/cloud_storage/FileStorageBackend.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
class FileStorageBackend extends StorageBackend
|
||||
{
|
||||
public function getAbsoluteFilePath($resourceId)
|
||||
{
|
||||
//TODO
|
||||
return $resourceId;
|
||||
}
|
||||
|
||||
public function getDownloadURLs($resourceId, $contentDispositionFilename)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public function deletePhysicalFile($resourceId)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
public function deleteAllCloudFileObjects()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public function getFilePrefix()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
55
legacy/application/cloud_storage/ProxyStorageBackend.php
Normal file
55
legacy/application/cloud_storage/ProxyStorageBackend.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Controls access to the storage backend class where a file is stored.
|
||||
*
|
||||
*/
|
||||
class ProxyStorageBackend extends StorageBackend
|
||||
{
|
||||
private $storageBackend;
|
||||
|
||||
/**
|
||||
* Receives the file's storage backend and instantiates the appropriate
|
||||
* object.
|
||||
*/
|
||||
public function __construct($storageBackend)
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
// The storage backend in the airtime.conf directly corresponds to
|
||||
// the name of the class that implements it, so we can create the
|
||||
// right backend object dynamically:
|
||||
if ($storageBackend == "file") {
|
||||
$this->storageBackend = new FileStorageBackend();
|
||||
} else {
|
||||
$this->storageBackend = new $storageBackend($CC_CONFIG[$storageBackend]);
|
||||
}
|
||||
}
|
||||
|
||||
public function getAbsoluteFilePath($resourceId)
|
||||
{
|
||||
return $this->storageBackend->getAbsoluteFilePath($resourceId);
|
||||
}
|
||||
|
||||
public function getDownloadURLs($resourceId, $contentDispositionFilename)
|
||||
{
|
||||
return $this->storageBackend->getDownloadURLs($resourceId, $contentDispositionFilename);
|
||||
}
|
||||
|
||||
public function deletePhysicalFile($resourceId)
|
||||
{
|
||||
$this->storageBackend->deletePhysicalFile($resourceId);
|
||||
}
|
||||
|
||||
public function deleteAllCloudFileObjects()
|
||||
{
|
||||
$this->storageBackend->deleteAllCloudFileObjects();
|
||||
}
|
||||
|
||||
public function getFilePrefix()
|
||||
{
|
||||
return $this->storageBackend->getFilePrefix();
|
||||
}
|
||||
}
|
59
legacy/application/cloud_storage/StorageBackend.php
Normal file
59
legacy/application/cloud_storage/StorageBackend.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides access to file objects stored on a specific storage backend.
|
||||
*/
|
||||
abstract class StorageBackend
|
||||
{
|
||||
private $bucket;
|
||||
private $accessKey;
|
||||
private $secretKey;
|
||||
|
||||
/** Returns the file object's URL to the storage backend it is located on. */
|
||||
abstract public function getAbsoluteFilePath($resourceId);
|
||||
|
||||
/** Returns the file object's signed URL. The URL must be signed since they
|
||||
* privately stored on the storage backend. */
|
||||
abstract public function getDownloadURLs($resourceId, $contentDispositionFilename);
|
||||
|
||||
/** Deletes the file from the storage backend. */
|
||||
abstract public function deletePhysicalFile($resourceId);
|
||||
|
||||
/** Deletes all objects (files) stored on the cloud service. To be used
|
||||
* for station termination */
|
||||
abstract public function deleteAllCloudFileObjects();
|
||||
|
||||
/** Get a prefix for the file (which is usually treated like a directory in the cloud) */
|
||||
abstract public function getFilePrefix();
|
||||
|
||||
protected function getBucket()
|
||||
{
|
||||
return $this->bucket;
|
||||
}
|
||||
|
||||
protected function setBucket($bucket)
|
||||
{
|
||||
$this->bucket = $bucket;
|
||||
}
|
||||
|
||||
protected function getAccessKey()
|
||||
{
|
||||
return $this->accessKey;
|
||||
}
|
||||
|
||||
protected function setAccessKey($accessKey)
|
||||
{
|
||||
$this->accessKey = $accessKey;
|
||||
}
|
||||
|
||||
protected function getSecretKey()
|
||||
{
|
||||
return $this->secretKey;
|
||||
}
|
||||
|
||||
protected function setSecretKey($secretKey)
|
||||
{
|
||||
$this->secretKey = $secretKey;
|
||||
}
|
||||
}
|
109
legacy/application/common/AutoPlaylistManager.php
Normal file
109
legacy/application/common/AutoPlaylistManager.php
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
class AutoPlaylistManager {
|
||||
/**
|
||||
* @var int how often, in seconds, to check for and ingest new podcast episodes
|
||||
*/
|
||||
private static $_AUTOPLAYLIST_POLL_INTERVAL_SECONDS = 60; // 10 minutes
|
||||
|
||||
/**
|
||||
* Check whether $_AUTOPLAYLIST_POLL_INTERVAL_SECONDS have passed since the last call to
|
||||
* buildAutoPlaylist
|
||||
*
|
||||
* @return bool true if $_AUTOPLAYLIST_POLL_INTERVAL_SECONDS has passed since the last check
|
||||
*/
|
||||
public static function hasAutoPlaylistPollIntervalPassed() {
|
||||
$lastPolled = Application_Model_Preference::getAutoPlaylistPollLock();
|
||||
return empty($lastPolled) || (microtime(true) > $lastPolled + self::$_AUTOPLAYLIST_POLL_INTERVAL_SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all shows with autoplaylists who have yet to have their playlists built and added to the schedule
|
||||
*
|
||||
*/
|
||||
public static function buildAutoPlaylist() {
|
||||
$autoPlaylists = static::_upcomingAutoPlaylistShows();
|
||||
foreach ($autoPlaylists as $autoplaylist) {
|
||||
// creates a ShowInstance object to build the playlist in from the ShowInstancesQuery Object
|
||||
$si = new Application_Model_ShowInstance($autoplaylist->getDbId());
|
||||
$playlistid = $si->GetAutoPlaylistId();
|
||||
// call the addPlaylist to show function and don't check for user permission to avoid call to non-existant user object
|
||||
$sid = $si->getShowId();
|
||||
$playlistrepeat = new Application_Model_Show($sid);
|
||||
$introplaylistid = Application_Model_Preference::GetIntroPlaylist();
|
||||
$outroplaylistid = Application_Model_Preference::GetOutroPlaylist();
|
||||
|
||||
// we want to check and see if we need to repeat this process until the show is 100% scheduled
|
||||
// so we create a while loop and break it immediately if repeat until full isn't enabled
|
||||
// otherwise we continue to go through adding playlists, including the intro and outro if enabled
|
||||
$full = false;
|
||||
$repeatuntilfull = $playlistrepeat->getAutoPlaylistRepeat();
|
||||
$tempPercentScheduled = 0;
|
||||
$si = new Application_Model_ShowInstance($autoplaylist->getDbId());
|
||||
// the intro playlist should be added exactly once
|
||||
if ($introplaylistid != null) {
|
||||
//Logging::info('adding intro');
|
||||
$si->addPlaylistToShowStart($introplaylistid, false);
|
||||
}
|
||||
while(!$full) {
|
||||
// we do not want to try to schedule an empty playlist
|
||||
if ($playlistid != null) {
|
||||
$si->addPlaylistToShow($playlistid, false);
|
||||
}
|
||||
$ps = $si->getPercentScheduled();
|
||||
if ($ps > 100) {
|
||||
$full = true;
|
||||
}
|
||||
elseif (!$repeatuntilfull) {
|
||||
break;
|
||||
}
|
||||
// we want to avoid an infinite loop if all of the playlists are null
|
||||
if ($playlistid == null) {
|
||||
break;
|
||||
}
|
||||
// another possible issue would be if the show isn't increasing in length each loop
|
||||
// ie if all of the playlists being added are zero lengths this could cause an infinite loop
|
||||
if ($tempPercentScheduled == $ps) {
|
||||
break;
|
||||
}
|
||||
//now reset it to the current percent scheduled
|
||||
$tempPercentScheduled = $ps;
|
||||
}
|
||||
// the outroplaylist is added at the end, it will always overbook
|
||||
// shows that have repeat until full enabled because they will
|
||||
// never have time remaining for the outroplaylist to be added
|
||||
// this is done outside the content loop to avoid a scenario
|
||||
// where a time remaining smartblock in a outro playlist
|
||||
// prevents the repeat until full from functioning by filling up the show
|
||||
if ($outroplaylistid != null) {
|
||||
$si->addPlaylistToShow($outroplaylistid, false);
|
||||
}
|
||||
$si->setAutoPlaylistBuilt(true);
|
||||
}
|
||||
Application_Model_Preference::setAutoPlaylistPollLock(microtime(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all show instances starting in the next hour with autoplaylists not yet added to the schedule
|
||||
*
|
||||
* @return PropelObjectCollection collection of ShowInstance objects
|
||||
* that have unbuilt autoplaylists
|
||||
*/
|
||||
protected static function _upcomingAutoPlaylistShows() {
|
||||
//setting now so that past shows aren't referenced
|
||||
$now = new DateTime("now", new DateTimeZone("UTC"));
|
||||
// only build playlists for shows that start up to an hour from now
|
||||
$future = clone $now;
|
||||
$future->add(new DateInterval('PT1H'));
|
||||
|
||||
return CcShowInstancesQuery::create()
|
||||
->filterByDbModifiedInstance(false)
|
||||
->filterByDbStarts($now,Criteria::GREATER_THAN)
|
||||
->filterByDbStarts($future,Criteria::LESS_THAN)
|
||||
->useCcShowQuery('a', 'left join')
|
||||
->filterByDbHasAutoPlaylist(true)
|
||||
->endUse()
|
||||
->filterByDbAutoPlaylistBuilt(false)
|
||||
->find();
|
||||
}
|
||||
}
|
59
legacy/application/common/CORSHelper.php
Normal file
59
legacy/application/common/CORSHelper.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
|
||||
class CORSHelper
|
||||
{
|
||||
public static function enableCrossOriginRequests(&$request, &$response)
|
||||
{
|
||||
//Chrome sends the Origin header for all requests, so we whitelist the webserver's hostname as well.
|
||||
$origin = $request->getHeader('Origin');
|
||||
$allowedOrigins = self::getAllowedOrigins($request);
|
||||
|
||||
if ((!(preg_match("/https?:\/\/localhost/", $origin) === 1)) && ($origin != "") &&
|
||||
(!in_array($origin, $allowedOrigins))
|
||||
) {
|
||||
//Don't allow CORS from other domains to prevent XSS.
|
||||
Logging::error("request origin '{$origin}' is not in allowed '" . implode(', ', $allowedOrigins) . "'!");
|
||||
throw new Zend_Controller_Action_Exception('Forbidden', 403);
|
||||
}
|
||||
//Allow AJAX requests from configured websites. We use this to allow other pages to use LibreTimes API.
|
||||
if ($origin) {
|
||||
$response = $response->setHeader('Access-Control-Allow-Origin', $origin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all allowed origins
|
||||
*
|
||||
* @param Request $request request object
|
||||
*/
|
||||
public static function getAllowedOrigins($request)
|
||||
{
|
||||
$allowedCorsUrls = array_map(
|
||||
function($v) { return trim($v); },
|
||||
explode(PHP_EOL, Application_Model_Preference::GetAllowedCorsUrls())
|
||||
);
|
||||
|
||||
// always allow the configured server in (as reported by the server and not what is i baseUrl)
|
||||
$scheme = $request->getServer('REQUEST_SCHEME');
|
||||
$host = $request->getServer('SERVER_NAME');
|
||||
$port = $request->getServer('SERVER_PORT');
|
||||
|
||||
$portString = '';
|
||||
if (
|
||||
$scheme == 'https' && $port != 443 ||
|
||||
$scheme == 'http' && $port != 80
|
||||
) {
|
||||
$portString = sprintf(':%s', $port);
|
||||
}
|
||||
$requestedUrl = sprintf(
|
||||
'%s://%s%s',
|
||||
$scheme,
|
||||
$host,
|
||||
$portString
|
||||
);
|
||||
return array_merge($allowedCorsUrls, array(
|
||||
$requestedUrl
|
||||
));
|
||||
}
|
||||
}
|
211
legacy/application/common/CeleryManager.php
Normal file
211
legacy/application/common/CeleryManager.php
Normal file
|
@ -0,0 +1,211 @@
|
|||
<?php
|
||||
|
||||
class CeleryManager {
|
||||
|
||||
/**
|
||||
* @var int milliseconds (for compatibility with celery) until we consider a message to have timed out
|
||||
*/
|
||||
private static $_CELERY_MESSAGE_TIMEOUT = 900000; // 15 minutes
|
||||
|
||||
/**
|
||||
* We have to use celeryresults (the default results exchange) because php-celery
|
||||
* doesn't support named results exchanges.
|
||||
*
|
||||
* @var string exchange for celery task results
|
||||
*/
|
||||
private static $_CELERY_RESULTS_EXCHANGE = 'celeryresults';
|
||||
|
||||
/**
|
||||
* @var PropelCollection cache of any pending CeleryTasks results for a service or task
|
||||
*/
|
||||
private static $_pendingTasks;
|
||||
|
||||
/**
|
||||
* Connect to the Celery daemon via amqp
|
||||
*
|
||||
* @param $config array the airtime configuration array
|
||||
* @param $exchange string the amqp exchange name
|
||||
* @param $queue string the amqp queue name
|
||||
*
|
||||
* @return Celery the Celery connection object
|
||||
*
|
||||
* @throws Exception when a connection error occurs
|
||||
*/
|
||||
private static function _setupCeleryExchange($config, $exchange, $queue) {
|
||||
return new Celery($config["rabbitmq"]["host"],
|
||||
$config["rabbitmq"]["user"],
|
||||
$config["rabbitmq"]["password"],
|
||||
$config["rabbitmq"]["vhost"],
|
||||
$exchange, // Exchange name
|
||||
$queue, // Binding/queue
|
||||
$config["rabbitmq"]["port"],
|
||||
false,
|
||||
true, // Persistent messages
|
||||
self::$_CELERY_MESSAGE_TIMEOUT); // Result expiration
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an amqp message to Celery the airtime-celery daemon to perform a task
|
||||
*
|
||||
* @param $task string the Celery task name
|
||||
* @param $exchange string the amqp exchange name
|
||||
* @param $data array an associative array containing arguments for the Celery task
|
||||
*
|
||||
* @return string the task identifier for the started Celery task so we can fetch the
|
||||
* results asynchronously later
|
||||
*/
|
||||
public static function sendCeleryMessage($task, $exchange, $data) {
|
||||
$config = Config::getConfig();
|
||||
$queue = $routingKey = $exchange;
|
||||
$c = self::_setupCeleryExchange($config, $exchange, $queue); // Use the exchange name for the queue
|
||||
$result = $c->PostTask($task, $data, true, $routingKey); // and routing key
|
||||
return $result->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a task name and identifier, check the Celery results queue for any
|
||||
* corresponding messages
|
||||
*
|
||||
* @param $task CeleryTasks the Celery task object
|
||||
*
|
||||
* @return array the message response array
|
||||
*
|
||||
* @throws CeleryException when no message is found
|
||||
* @throws CeleryTimeoutException when no message is found and more than
|
||||
* $_CELERY_MESSAGE_TIMEOUT milliseconds have passed
|
||||
*/
|
||||
private static function getAsyncResultMessage($task) {
|
||||
$config = Config::getConfig();
|
||||
$queue = self::$_CELERY_RESULTS_EXCHANGE . "." . $task;
|
||||
$c = self::_setupCeleryExchange($config, self::$_CELERY_RESULTS_EXCHANGE, $queue);
|
||||
$message = $c->getAsyncResultMessage($task->getDbName(), $task->getDbTaskId());
|
||||
|
||||
// If the message isn't ready yet (Celery hasn't finished the task), throw an exception.
|
||||
if ($message == FALSE) {
|
||||
if (static::_checkMessageTimeout($task)) {
|
||||
// If the task times out, mark it as failed. We don't want to remove the
|
||||
// track reference here in case it was a deletion that failed, for example.
|
||||
$task->setDbStatus(CELERY_FAILED_STATUS)->save();
|
||||
throw new CeleryTimeoutException("Celery task " . $task->getDbName()
|
||||
. " with ID " . $task->getDbTaskId() . " timed out");
|
||||
} else {
|
||||
// The message hasn't timed out, but it's still false, which means it hasn't been
|
||||
// sent back from Celery yet.
|
||||
throw new CeleryException("Waiting on Celery task " . $task->getDbName()
|
||||
. " with ID " . $task->getDbTaskId());
|
||||
}
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if there are any pending tasks for this service
|
||||
*
|
||||
* @param string $taskName the name of the task to poll for
|
||||
* @param string $serviceName the name of the service to poll for
|
||||
*
|
||||
* @return bool true if there are any pending tasks, otherwise false
|
||||
*/
|
||||
public static function isBrokerTaskQueueEmpty($taskName = "", $serviceName = "") {
|
||||
self::$_pendingTasks = static::_getPendingTasks($taskName, $serviceName);
|
||||
return empty(self::$_pendingTasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll the message queue for this service to see if any tasks with the given name have completed
|
||||
*
|
||||
* If we find any completed tasks, adjust the ThirdPartyTrackReferences table accordingly
|
||||
*
|
||||
* If no task name is passed, we poll all tasks for this service
|
||||
*
|
||||
* @param string $taskName the name of the task to poll for
|
||||
* @param string $serviceName the name of the service to poll for
|
||||
*/
|
||||
public static function pollBrokerTaskQueue($taskName = "", $serviceName = "") {
|
||||
$pendingTasks = empty(self::$_pendingTasks) ? static::_getPendingTasks($taskName, $serviceName)
|
||||
: self::$_pendingTasks;
|
||||
foreach ($pendingTasks as $task) {
|
||||
try {
|
||||
$message = static::_getTaskMessage($task);
|
||||
static::_processTaskMessage($task, $message);
|
||||
} catch (CeleryTimeoutException $e) {
|
||||
Logging::warn($e->getMessage());
|
||||
} catch (CeleryException $e) {
|
||||
// Don't log these - they end up clogging up the logs
|
||||
} catch (Exception $e) {
|
||||
// Because $message->result can be either an object or a string, sometimes
|
||||
// we get a json_decode error and end up here
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a collection of all pending CeleryTasks for this service or task
|
||||
*
|
||||
* @param string $taskName the name of the task to find
|
||||
* @param string $serviceName the name of the service to find
|
||||
*
|
||||
* @return PropelCollection any pending CeleryTasks results for this service
|
||||
* or task if taskName is provided
|
||||
*/
|
||||
protected static function _getPendingTasks($taskName, $serviceName) {
|
||||
$query = CeleryTasksQuery::create()
|
||||
->filterByDbStatus(CELERY_PENDING_STATUS)
|
||||
->filterByDbTaskId('', Criteria::NOT_EQUAL);
|
||||
if (!empty($taskName)) {
|
||||
$query->filterByDbName($taskName);
|
||||
}
|
||||
if (!empty($serviceName)) {
|
||||
$query->useThirdPartyTrackReferencesQuery()
|
||||
->filterByDbService($serviceName)->endUse();
|
||||
}
|
||||
return $query->joinThirdPartyTrackReferences()
|
||||
->with('ThirdPartyTrackReferences')->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Celery task message from the results queue
|
||||
*
|
||||
* @param $task CeleryTasks the Celery task object
|
||||
*
|
||||
* @return object the task message object
|
||||
*
|
||||
* @throws CeleryException when the result message for this task is still pending
|
||||
* @throws CeleryTimeoutException when the result message for this task no longer exists
|
||||
*/
|
||||
protected static function _getTaskMessage($task) {
|
||||
$message = self::getAsyncResultMessage($task);
|
||||
return json_decode($message['body']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a message from the results queue
|
||||
*
|
||||
* @param $task CeleryTasks Celery task object
|
||||
* @param $message mixed async message object from php-celery
|
||||
*/
|
||||
protected static function _processTaskMessage($task, $message) {
|
||||
$ref = $task->getThirdPartyTrackReferences(); // ThirdPartyTrackReferences join
|
||||
$service = CeleryServiceFactory::getService($ref->getDbService());
|
||||
$service->updateTrackReference($task, $ref->getDbId(), json_decode($message->result), $message->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a task message has been unreachable for more our timeout time
|
||||
*
|
||||
* @param $task CeleryTasks the Celery task object
|
||||
*
|
||||
* @return bool true if the dispatch time is empty or it's been more than our timeout time
|
||||
* since the message was dispatched, otherwise false
|
||||
*/
|
||||
protected static function _checkMessageTimeout($task) {
|
||||
$utc = new DateTimeZone("UTC");
|
||||
$dispatchTime = new DateTime($task->getDbDispatchTime(), $utc);
|
||||
$now = new DateTime("now", $utc);
|
||||
$timeoutSeconds = self::$_CELERY_MESSAGE_TIMEOUT / 1000; // Convert from milliseconds
|
||||
$timeoutInterval = new DateInterval("PT" . $timeoutSeconds . "S");
|
||||
return (empty($dispatchTime) || $dispatchTime->add($timeoutInterval) <= $now);
|
||||
}
|
||||
|
||||
}
|
70
legacy/application/common/Database.php
Normal file
70
legacy/application/common/Database.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
class Application_Common_Database
|
||||
{
|
||||
const SINGLE = 'single';
|
||||
const COLUMN = 'column';
|
||||
const ALL = 'all';
|
||||
const EXECUTE = 'execute';
|
||||
const ROW_COUNT = 'row_count';
|
||||
|
||||
public static function prepareAndExecute($sql,
|
||||
array $paramValueMap = array(),
|
||||
$type=self::ALL,
|
||||
$fetchType=PDO::FETCH_ASSOC,
|
||||
$con=null)
|
||||
{
|
||||
if (is_null($con)) {
|
||||
$con = Propel::getConnection();
|
||||
}
|
||||
$stmt = $con->prepare($sql);
|
||||
foreach ($paramValueMap as $param => $v) {
|
||||
$stmt->bindValue($param, $v);
|
||||
}
|
||||
$rows = array();
|
||||
if ($stmt->execute()) {
|
||||
if ($type == self::SINGLE) {
|
||||
$rows = $stmt->fetch($fetchType);
|
||||
} else if ($type == self::COLUMN){
|
||||
$rows = $stmt->fetchColumn();
|
||||
} else if ($type == self::ALL) {
|
||||
$rows = $stmt->fetchAll($fetchType);
|
||||
} else if ($type == self::EXECUTE) {
|
||||
$rows = null;
|
||||
} else if ($type == self::ROW_COUNT) {
|
||||
$rows = $stmt->rowCount();
|
||||
} else {
|
||||
$msg = "bad type passed: type($type)";
|
||||
throw new Exception("Error: $msg");
|
||||
}
|
||||
} else {
|
||||
$msg = implode(',', $stmt->errorInfo());
|
||||
throw new Exception("Error: $msg");
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
/*
|
||||
Wrapper around prepareAndExecute that allows you to use multipe :xx's
|
||||
in one query. Transforms $sql to :xx1, :xx2, ....
|
||||
*/
|
||||
public static function smartPrepareAndExecute($sql, array $params,
|
||||
$type='all', $fetchType=PDO::FETCH_ASSOC)
|
||||
{
|
||||
$new_params = array();
|
||||
$new_sql = $sql;
|
||||
foreach ($params as $k => $v) {
|
||||
$matches_count = substr_count($sql, $k);
|
||||
if ($matches_count == 0) {
|
||||
throw new Exception("Argument $k is not inside $sql");
|
||||
} elseif ($matches_count == 1) {
|
||||
$new_params[$k] = $new_params[$v];
|
||||
} else {
|
||||
foreach ( range(1,$matches_count) as $i ) {
|
||||
preg_replace( "/$k(\D)/", "$k$i${1}", $sql, 1);
|
||||
$new_params[ $k.$i ] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Application_Common_Database::prepareAndExecute( $new_sql,
|
||||
$new_params, $type, $fetchType);
|
||||
}
|
||||
}
|
501
legacy/application/common/DateHelper.php
Normal file
501
legacy/application/common/DateHelper.php
Normal file
|
@ -0,0 +1,501 @@
|
|||
<?php
|
||||
|
||||
class Application_Common_DateHelper
|
||||
{
|
||||
private $_dateTime;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->_dateTime = date("U");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time of object construction in the format
|
||||
* YYYY-MM-DD HH:mm:ss
|
||||
*/
|
||||
function getTimestamp()
|
||||
{
|
||||
return date(DEFAULT_TIMESTAMP_FORMAT, $this->_dateTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time of object construction in the format
|
||||
* YYYY-MM-DD HH:mm:ss
|
||||
*/
|
||||
function getUtcTimestamp()
|
||||
{
|
||||
return gmdate(DEFAULT_TIMESTAMP_FORMAT, $this->_dateTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date of object construction in the format
|
||||
* YYYY-MM-DD
|
||||
*/
|
||||
function getDate()
|
||||
{
|
||||
return gmdate("Y-m-d", $this->_dateTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time of object construction in the format
|
||||
* HH:mm:ss
|
||||
*/
|
||||
function getTime()
|
||||
{
|
||||
return gmdate("H:i:s", $this->_dateTime);
|
||||
}
|
||||
|
||||
/** Get the abbreviated timezone for the currently logged in user.
|
||||
* @return A string containing the short form of the timezone set in the preferences for the current user (eg. EST, CEST, etc.)
|
||||
*/
|
||||
public static function getUserTimezoneAbbreviation()
|
||||
{
|
||||
return self::getTimezoneAbbreviation(Application_Model_Preference::GetUserTimezone());
|
||||
}
|
||||
|
||||
/** Get the abbreviated timezone string of the timezone the station is set to.
|
||||
* @return A string containing the short form of the station's timezone (eg. EST, CEST, etc.)
|
||||
*/
|
||||
public static function getStationTimezoneAbbreviation()
|
||||
{
|
||||
return self::getTimezoneAbbreviation(Application_Model_Preference::GetDefaultTimezone());
|
||||
}
|
||||
|
||||
private static function getTimezoneAbbreviation($fullTimeZoneName)
|
||||
{
|
||||
$timeZone = new DateTimeZone($fullTimeZoneName);
|
||||
$now = new DateTime("now", $timeZone);
|
||||
return $now->format("T");
|
||||
}
|
||||
|
||||
public static function getUserTimezoneOffset()
|
||||
{
|
||||
$userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
|
||||
$now = new DateTime("now", $userTimezone);
|
||||
|
||||
return $now->format("Z");
|
||||
}
|
||||
|
||||
public static function getStationTimezoneOffset()
|
||||
{
|
||||
$stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone());
|
||||
$now = new DateTime("now", $stationTimezone);
|
||||
|
||||
return $now->format("Z");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return DateTime - YYYY-MM-DD 00:00 in station timezone of today
|
||||
*/
|
||||
public static function getTodayStationStartDateTime()
|
||||
{
|
||||
$stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone());
|
||||
$now = new DateTime("now", $stationTimezone);
|
||||
|
||||
$now->setTime(0, 0, 0);
|
||||
|
||||
return $now;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return DateTime - YYYY-MM-DD 00:00 in station timezone of tomorrow
|
||||
*/
|
||||
public static function getTodayStationEndDateTime()
|
||||
{
|
||||
$stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone());
|
||||
$now = new DateTime("now", $stationTimezone);
|
||||
|
||||
$now->add(new DateInterval("P1D"));
|
||||
$now->setTime(0, 0, 0);
|
||||
|
||||
return $now;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return DateTime - YYYY-MM-DD 00:00 in station timezone
|
||||
*/
|
||||
public static function getWeekStartDateTime()
|
||||
{
|
||||
$now = self::getTodayStationStartDateTime();
|
||||
|
||||
// our week starts on monday, but php week starts on sunday.
|
||||
$day = $now->format('w');
|
||||
if ($day == 0) {
|
||||
$day = 7;
|
||||
}
|
||||
|
||||
$dayDiff = $day - 1;
|
||||
if ($dayDiff > 0) {
|
||||
$now->sub(new DateInterval("P{$dayDiff}D"));
|
||||
}
|
||||
|
||||
return $now;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function formats a time by removing seconds
|
||||
*
|
||||
* When we receive a time from the database we get the
|
||||
* format "hh:mm:ss". But when dealing with show times, we
|
||||
* do not care about the seconds.
|
||||
*
|
||||
* @param int $p_dateTime
|
||||
* The value which to format.
|
||||
* @return int
|
||||
* The timestamp with the new format "hh:mm", or
|
||||
* the original input parameter, if it does not have
|
||||
* the correct format.
|
||||
*/
|
||||
public static function removeSecondsFromTime($p_dateTime)
|
||||
{
|
||||
//Format is in hh:mm:ss. We want hh:mm
|
||||
$timeExplode = explode(":", $p_dateTime);
|
||||
|
||||
if (count($timeExplode) == 3)
|
||||
return $timeExplode[0].":".$timeExplode[1];
|
||||
else
|
||||
return $p_dateTime;
|
||||
}
|
||||
|
||||
/* Given a track length in the format HH:MM:SS.mm, we want to
|
||||
* convert this to seconds. This is useful for Liquidsoap which
|
||||
* likes input parameters give in seconds.
|
||||
* For example, 00:06:31.444, should be converted to 391.444 seconds
|
||||
* @param int $p_time
|
||||
* The time interval in format HH:MM:SS.mm we wish to
|
||||
* convert to seconds.
|
||||
* @return float
|
||||
* The input parameter converted to seconds.
|
||||
*/
|
||||
public static function calculateLengthInSeconds($p_time){
|
||||
|
||||
if (2 !== substr_count($p_time, ":")){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (1 === substr_count($p_time, ".")){
|
||||
list($hhmmss, $ms) = explode(".", $p_time);
|
||||
} else {
|
||||
$hhmmss = $p_time;
|
||||
$ms = 0;
|
||||
}
|
||||
|
||||
list($hours, $minutes, $seconds) = explode(":", $hhmmss);
|
||||
|
||||
$totalSeconds = ($hours*3600 + $minutes*60 + $seconds).".$ms";
|
||||
return round($totalSeconds, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true or false depending on input is wether in
|
||||
* valid range of SQL date/time
|
||||
* @param string $p_datetime
|
||||
* should be in format of '0000-00-00 00:00:00'
|
||||
*/
|
||||
public static function checkDateTimeRangeForSQL($p_datetime){
|
||||
$info = explode(' ', $p_datetime);
|
||||
$dateInfo = explode('-', $info[0]);
|
||||
if (isset($info[1])) {
|
||||
$timeInfo = explode(':', $info[1]);
|
||||
}
|
||||
$retVal = array();
|
||||
$retVal["success"] = true;
|
||||
|
||||
$year = $dateInfo[0];
|
||||
$month = $dateInfo[1];
|
||||
$day = $dateInfo[2];
|
||||
// if year is < 1753 or > 9999 it's out of range
|
||||
if ($year < 1753) {
|
||||
$retVal['success'] = false;
|
||||
$retVal['errMsg'] = sprintf(_("The year %s must be within the range of 1753 - 9999"), $year);
|
||||
} else if (!checkdate($month, $day, $year)) {
|
||||
$retVal['success'] = false;
|
||||
$retVal['errMsg'] = sprintf(_("%s-%s-%s is not a valid date"), $year, $month, $day);
|
||||
} else {
|
||||
// check time
|
||||
if (isset($timeInfo)) {
|
||||
if (isset($timeInfo[0]) && $timeInfo[0] != "") {
|
||||
$hour = intval($timeInfo[0]);
|
||||
} else {
|
||||
$hour = -1;
|
||||
}
|
||||
|
||||
if (isset($timeInfo[1]) && $timeInfo[1] != "") {
|
||||
$min = intval($timeInfo[1]);
|
||||
} else {
|
||||
$min = -1;
|
||||
}
|
||||
|
||||
if (isset($timeInfo[2]) && $timeInfo[2] != "") {
|
||||
$sec = intval($timeInfo[2]);
|
||||
} else {
|
||||
$sec = -1;
|
||||
}
|
||||
|
||||
if ( ($hour < 0 || $hour > 23) || ($min < 0 || $min > 59) || ($sec < 0 || $sec > 59) ) {
|
||||
$retVal['success'] = false;
|
||||
$retVal['errMsg'] = sprintf(_("%s:%s:%s is not a valid time"), $timeInfo[0], $timeInfo[1] ,$timeInfo[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param $datetime string Y-m-d H:i:s in UTC timezone
|
||||
*
|
||||
* @return string in $format default Y-m-d H:i:s in station timezone
|
||||
*/
|
||||
public static function UTCStringToStationTimezoneString($datetime, $format=DEFAULT_TIMESTAMP_FORMAT) {
|
||||
$stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone());
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
|
||||
$d = new DateTime($datetime, $utcTimezone);
|
||||
$d->setTimezone($stationTimezone);
|
||||
|
||||
return $d->format($format);
|
||||
}
|
||||
|
||||
/*
|
||||
* @param $datetime string Y-m-d H:i:s in UTC timezone
|
||||
*
|
||||
* @return string Y-m-d H:i:s in user's timezone
|
||||
*/
|
||||
public static function UTCStringToUserTimezoneString($datetime, $format=DEFAULT_TIMESTAMP_FORMAT) {
|
||||
$userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
|
||||
$d = new DateTime($datetime, $utcTimezone);
|
||||
$d->setTimezone($userTimezone);
|
||||
|
||||
return $d->format($format);
|
||||
}
|
||||
|
||||
/*
|
||||
* @param $datetime string Y-m-d H:i:s in user timezone
|
||||
*
|
||||
* @return string Y-m-d H:i:s in UTC timezone
|
||||
*/
|
||||
public static function UserTimezoneStringToUTCString($datetime, $format=DEFAULT_TIMESTAMP_FORMAT) {
|
||||
$userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
|
||||
$d = new DateTime($datetime, $userTimezone);
|
||||
$d->setTimezone($utcTimezone);
|
||||
|
||||
return $d->format($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the columns given in the array $columnsToConvert in the
|
||||
* database result $rows to local timezone.
|
||||
*
|
||||
* @param array $rows arrays of arrays containing database query result
|
||||
* @param array $columnsToConvert array of column names to convert
|
||||
* @param string (station|user) convert to either station or user timezone.
|
||||
*/
|
||||
public static function convertTimestamps(&$rows, $columnsToConvert, $domain="station")
|
||||
{
|
||||
if (!is_array($rows)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$converter = "UTCStringTo".ucfirst($domain)."TimezoneString";
|
||||
|
||||
foreach ($rows as &$row) {
|
||||
foreach ($columnsToConvert as $column) {
|
||||
$row[$column] = self::$converter($row[$column]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the columns given in the array $columnsToConvert in the
|
||||
* database result $rows to local timezone.
|
||||
*
|
||||
* @param array $rows arrays of arrays containing database query result
|
||||
* @param array $columnsToConvert array of column names to convert
|
||||
* @param string $timezone convert to the given timezone.
|
||||
* @param string $format time format to convert to
|
||||
*/
|
||||
public static function convertTimestampsToTimezone(&$rows, $columnsToConvert, $timezone, $format=DEFAULT_TIMESTAMP_FORMAT)
|
||||
{
|
||||
$timezone = strtolower($timezone);
|
||||
// Check that the timezone is valid and rows is an array
|
||||
if (!is_array($rows)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($rows as &$row) {
|
||||
if (is_array($row)) {
|
||||
foreach ($columnsToConvert as $column) {
|
||||
if (array_key_exists($column, $row)) {
|
||||
$newTimezone = new DateTimeZone($timezone);
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
|
||||
$d = new DateTime($row[$column], $utcTimezone);
|
||||
$d->setTimezone($newTimezone);
|
||||
$row[$column] = $d->format($format);
|
||||
}
|
||||
}
|
||||
self::convertTimestampsToTimezone($row, $columnsToConvert, $timezone, $format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the end date time in the given timezone
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public static function getEndDateTime($timezoneString, $days)
|
||||
{
|
||||
$timezone = new DateTimeZone($timezoneString);
|
||||
$now = new DateTime("now", $timezone);
|
||||
|
||||
$now->add(new DateInterval("P".$days."D"));
|
||||
$now->setTime(0, 0, 0);
|
||||
|
||||
return $now;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a formatted string representing the
|
||||
* given datetime in the given timezone
|
||||
*
|
||||
* @param unknown $datetime the time to convert
|
||||
* @param unknown $timezone the timezone to convert to
|
||||
* @param string $format the formatted string
|
||||
*/
|
||||
public static function UTCStringToTimezoneString($datetime, $timezone, $format=DEFAULT_TIMESTAMP_FORMAT) {
|
||||
$d = new DateTime($datetime, new DateTimeZone("UTC"));
|
||||
$timezone = strtolower($timezone);
|
||||
$newTimezone = new DateTimeZone($timezone);
|
||||
$d->setTimezone($newTimezone);
|
||||
|
||||
return $d->format($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timezone offset in seconds for the given timezone
|
||||
*
|
||||
* @param unknown $userDefinedTimezone the timezone used to determine the offset
|
||||
*/
|
||||
public static function getTimezoneOffset($userDefinedTimezone) {
|
||||
$now = new DateTimeZone($userDefinedTimezone);
|
||||
|
||||
$d = new DateTime("now", $now);
|
||||
return $d->format("Z");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function is used for calculations! Don't modify for display purposes!
|
||||
*
|
||||
* Convert playlist time value to float seconds
|
||||
*
|
||||
* @param string $plt
|
||||
* playlist interval value (HH:mm:ss.dddddd)
|
||||
* @return int
|
||||
* seconds
|
||||
*/
|
||||
public static function playlistTimeToSeconds($plt)
|
||||
{
|
||||
$arr = preg_split('/:/', $plt);
|
||||
if (isset($arr[2])) {
|
||||
return (intval($arr[0])*60 + intval($arr[1]))*60 + floatval($arr[2]);
|
||||
}
|
||||
if (isset($arr[1])) {
|
||||
return intval($arr[0])*60 + floatval($arr[1]);
|
||||
}
|
||||
|
||||
return floatval($arr[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function is used for calculations! Don't modify for display purposes!
|
||||
*
|
||||
* Convert float seconds value to playlist time format
|
||||
*
|
||||
* @param float $seconds
|
||||
* @return string
|
||||
* interval in playlist time format (HH:mm:ss.d)
|
||||
*/
|
||||
public static function secondsToPlaylistTime($p_seconds)
|
||||
{
|
||||
$info = explode('.', $p_seconds);
|
||||
$seconds = $info[0];
|
||||
if (!isset($info[1])) {
|
||||
$milliStr = 0;
|
||||
} else {
|
||||
$milliStr = $info[1];
|
||||
}
|
||||
$hours = floor($seconds / 3600);
|
||||
$seconds -= $hours * 3600;
|
||||
$minutes = floor($seconds / 60);
|
||||
$seconds -= $minutes * 60;
|
||||
|
||||
$res = sprintf("%02d:%02d:%02d.%s", $hours, $minutes, $seconds, $milliStr);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns date fields from give start and end teimstamp strings
|
||||
* if no start or end parameter is passed start will be set to 1
|
||||
* in the past and end to now
|
||||
*
|
||||
* @param string startTimestamp Y-m-d H:i:s
|
||||
* @param string endTImestamp Y-m-d H:i:s
|
||||
* @param string timezone (ex UTC) of the start and end parameters
|
||||
* @return array (start DateTime, end DateTime) in UTC timezone
|
||||
*/
|
||||
public static function getStartEnd($startTimestamp, $endTimestamp, $timezone)
|
||||
{
|
||||
$prefTimezone = Application_Model_Preference::GetTimezone();
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
$utcNow = new DateTime("now", $utcTimezone);
|
||||
|
||||
if (empty($timezone)) {
|
||||
$userTimezone = new DateTimeZone($prefTimezone);
|
||||
} else {
|
||||
$userTimezone = new DateTimeZone($timezone);
|
||||
}
|
||||
|
||||
// default to 1 day
|
||||
if (empty($startTimestamp) || empty($endTimestamp)) {
|
||||
$startsDT = clone $utcNow;
|
||||
$startsDT->sub(new DateInterval("P1D"));
|
||||
$endsDT = clone $utcNow;
|
||||
} else {
|
||||
|
||||
try {
|
||||
$startsDT = new DateTime($startTimestamp, $userTimezone);
|
||||
$startsDT->setTimezone($utcTimezone);
|
||||
|
||||
$endsDT = new DateTime($endTimestamp, $userTimezone);
|
||||
$endsDT->setTimezone($utcTimezone);
|
||||
|
||||
if ($startsDT > $endsDT) {
|
||||
throw new Exception("start greater than end");
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
|
||||
$startsDT = clone $utcNow;
|
||||
$startsDT->sub(new DateInterval("P1D"));
|
||||
$endsDT = clone $utcNow;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return array($startsDT, $endsDT);
|
||||
}
|
||||
}
|
||||
|
452
legacy/application/common/FileDataHelper.php
Normal file
452
legacy/application/common/FileDataHelper.php
Normal file
|
@ -0,0 +1,452 @@
|
|||
<?php
|
||||
|
||||
class FileDataHelper {
|
||||
|
||||
public static function getAudioMimeTypeArray() {
|
||||
return array(
|
||||
"audio/ogg" => "ogg",
|
||||
"application/ogg" => "ogg",
|
||||
"audio/vorbis" => "ogg",
|
||||
"audio/mp3" => "mp3",
|
||||
"audio/mpeg" => "mp3",
|
||||
"audio/mpeg3" => "mp3",
|
||||
"audio/x-aac" => "aac",
|
||||
"audio/aac" => "aac",
|
||||
"audio/aacp" => "aac",
|
||||
"audio/mp4" => "m4a",
|
||||
"video/mp4" => "mp4",
|
||||
"audio/x-flac" => "flac",
|
||||
"audio/flac" => "flac",
|
||||
"audio/wav" => "wav",
|
||||
"audio/x-wav" => "wav",
|
||||
"audio/mp2" => "mp2",
|
||||
"audio/mp1" => "mp1",
|
||||
"audio/x-ms-wma" => "wma",
|
||||
"audio/basic" => "au",
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to throw out invalid data and process the upload successfully
|
||||
* at all costs, so check the data and sanitize it if necessary
|
||||
* @param array $data array containing new file metadata
|
||||
*/
|
||||
public static function sanitizeData(&$data)
|
||||
{
|
||||
if (array_key_exists("track_number", $data)) {
|
||||
// If the track number isn't numeric, this will return 0
|
||||
$data["track_number"] = intval($data["track_number"]);
|
||||
}
|
||||
if (array_key_exists("year", $data)) {
|
||||
// If the track number isn't numeric, this will return 0
|
||||
$data["year"] = intval($data["year"]);
|
||||
}
|
||||
if (array_key_exists("bpm", $data)) {
|
||||
//Some BPM tags are silly and include the word "BPM". Let's strip that...
|
||||
$data["bpm"] = str_ireplace("BPM", "", $data["bpm"]);
|
||||
// This will convert floats to ints too.
|
||||
$data["bpm"] = intval($data["bpm"]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a suitable extension for the given file
|
||||
*
|
||||
* @param string $mime
|
||||
*
|
||||
* @return string file extension with(!) a dot (for convenience)
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getFileExtensionFromMime($mime)
|
||||
{
|
||||
$mime = trim(strtolower($mime));
|
||||
try {
|
||||
return ('.' . static::getAudioMimeTypeArray()[$mime]);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Unknown file type: $mime");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data URI from artwork file
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $size
|
||||
* @param string $filepath
|
||||
*
|
||||
* @return string Data URI for artwork
|
||||
*/
|
||||
public static function getArtworkData($file, $size, $filepath = false)
|
||||
{
|
||||
$baseUrl = Application_Common_HTTPHelper::getStationUrl();
|
||||
$default = $baseUrl . "css/images/no-cover.jpg";
|
||||
|
||||
if ($filepath != false) {
|
||||
$path = $filepath . $file . "-" . $size;
|
||||
if (!file_exists($path)) {
|
||||
$get_file_content = $default;
|
||||
} else {
|
||||
$get_file_content = file_get_contents($path);
|
||||
}
|
||||
} else {
|
||||
$storDir = Application_Model_MusicDir::getStorDir();
|
||||
$path = $storDir->getDirectory() . $file . "-" . $size;
|
||||
if (!file_exists($path)) {
|
||||
$get_file_content = $default;
|
||||
} else {
|
||||
$get_file_content = file_get_contents($path);
|
||||
}
|
||||
}
|
||||
return $get_file_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add artwork file
|
||||
*
|
||||
* @param string $analyzeFile
|
||||
* @param string $filename
|
||||
* @param string $importDir
|
||||
* @param string $DbPath
|
||||
*
|
||||
* @return string Path to artwork
|
||||
*/
|
||||
public static function saveArtworkData($analyzeFile, $filename, $importDir = null, $DbPath = null)
|
||||
{
|
||||
if (class_exists('getID3')) {
|
||||
$getID3 = new \getID3();
|
||||
$getFileInfo = $getID3->analyze($analyzeFile);
|
||||
} else {
|
||||
$getFileInfo = [];
|
||||
Logging::error("Failed to load getid3 library. Please upgrade Libretime.");
|
||||
}
|
||||
|
||||
if(isset($getFileInfo['comments']['picture'][0])) {
|
||||
|
||||
$get_img = "";
|
||||
$timestamp = time();
|
||||
$mime = $getFileInfo['comments']['picture'][0]['image_mime'];
|
||||
$Image = 'data:'.$mime.';charset=utf-8;base64,'.base64_encode($getFileInfo['comments']['picture'][0]['data']);
|
||||
$base64 = @$Image;
|
||||
|
||||
if (!file_exists($importDir . "/" . "artwork/")) {
|
||||
if (!mkdir($importDir . "/" . "artwork/", 0777, true)) {
|
||||
Logging::error("Failed to create artwork directory.");
|
||||
throw new Exception("Failed to create artwork directory.");
|
||||
}
|
||||
}
|
||||
|
||||
$path_parts = pathinfo($filename);
|
||||
$file = $importDir . "artwork/" . $path_parts['filename'];
|
||||
|
||||
//Save Data URI
|
||||
if (file_put_contents($file, $base64)) {
|
||||
$get_img = $DbPath . "artwork/". $path_parts['filename'];
|
||||
} else {
|
||||
Logging::error("Could not save Data URI");
|
||||
}
|
||||
|
||||
if ($mime == "image/png") {
|
||||
$ext = 'png';
|
||||
} elseif ($mime == "image/gif") {
|
||||
$ext = 'gif';
|
||||
} elseif ($mime == "image/bmp") {
|
||||
$ext = 'bmp';
|
||||
} else {
|
||||
$ext = 'jpg';
|
||||
}
|
||||
self::resizeGroup($file, $ext);
|
||||
|
||||
} else {
|
||||
$get_img = '';
|
||||
}
|
||||
return $get_img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset artwork
|
||||
*
|
||||
* @param string $trackid
|
||||
*
|
||||
* @return string $get_img Path to artwork
|
||||
*/
|
||||
public static function resetArtwork($trackid)
|
||||
{
|
||||
$file = Application_Model_StoredFile::RecallById($trackid);
|
||||
$md = $file->getMetadata();
|
||||
|
||||
$storDir = Application_Model_MusicDir::getStorDir();
|
||||
$fp = $storDir->getDirectory();
|
||||
|
||||
$dbAudioPath = $md["MDATA_KEY_FILEPATH"];
|
||||
$fullpath = $fp . $dbAudioPath;
|
||||
|
||||
if (class_exists('getID3')) {
|
||||
$getID3 = new \getID3();
|
||||
$getFileInfo = $getID3->analyze($fullpath);
|
||||
} else {
|
||||
$getFileInfo = [];
|
||||
Logging::error("Failed to load getid3 library. Please upgrade Libretime.");
|
||||
}
|
||||
|
||||
if(isset($getFileInfo['comments']['picture'][0])) {
|
||||
|
||||
$get_img = "";
|
||||
$mime = $getFileInfo['comments']['picture'][0]['image_mime'];
|
||||
$Image = 'data:'.$getFileInfo['comments']['picture'][0]['image_mime'].';charset=utf-8;base64,'.base64_encode($getFileInfo['comments']['picture'][0]['data']);
|
||||
$base64 = @$Image;
|
||||
|
||||
$audioPath = dirname($fullpath);
|
||||
$dbPath = dirname($dbAudioPath);
|
||||
$path_parts = pathinfo($fullpath);
|
||||
$file = $path_parts['filename'];
|
||||
|
||||
//Save Data URI
|
||||
if (file_put_contents($audioPath . "/" . $file, $base64)) {
|
||||
$get_img = $dbPath . "/" . $file;
|
||||
} else {
|
||||
Logging::error("Could not save Data URI");
|
||||
}
|
||||
|
||||
$rfile = $audioPath . "/" . $file;
|
||||
|
||||
if ($mime == "image/png") {
|
||||
$ext = 'png';
|
||||
} elseif ($mime == "image/gif") {
|
||||
$ext = 'gif';
|
||||
} elseif ($mime == "image/bmp") {
|
||||
$ext = 'bmp';
|
||||
} else {
|
||||
$ext = 'jpg';
|
||||
}
|
||||
self::resizeGroup($rfile, $ext);
|
||||
|
||||
} else {
|
||||
$get_img = "";
|
||||
}
|
||||
return $get_img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload artwork
|
||||
*
|
||||
* @param string $trackid
|
||||
* @param string $data
|
||||
*
|
||||
* @return string Path to artwork
|
||||
*/
|
||||
public static function setArtwork($trackid, $data)
|
||||
{
|
||||
$file = Application_Model_StoredFile::RecallById($trackid);
|
||||
$md = $file->getMetadata();
|
||||
|
||||
$storDir = Application_Model_MusicDir::getStorDir();
|
||||
$fp = $storDir->getDirectory();
|
||||
|
||||
$dbAudioPath = $md["MDATA_KEY_FILEPATH"];
|
||||
$fullpath = $fp . $dbAudioPath;
|
||||
|
||||
if ($data == "0") {
|
||||
|
||||
$get_img = "";
|
||||
self::removeArtwork($trackid, $data);
|
||||
|
||||
} else {
|
||||
|
||||
$base64 = @$data;
|
||||
$mime = explode(';', $base64)[0];
|
||||
|
||||
$audioPath = dirname($fullpath);
|
||||
$dbPath = dirname($dbAudioPath);
|
||||
$path_parts = pathinfo($fullpath);
|
||||
$file = $path_parts['filename'];
|
||||
|
||||
//Save Data URI
|
||||
if (file_put_contents($audioPath . "/" . $file, $base64)) {
|
||||
$get_img = $dbPath . "/" . $file;
|
||||
} else {
|
||||
Logging::error("Could not save Data URI");
|
||||
}
|
||||
|
||||
$rfile = $audioPath . "/" . $file;
|
||||
|
||||
if ($mime == "data:image/png") {
|
||||
$ext = 'png';
|
||||
} elseif ($mime == "data:image/gif") {
|
||||
$ext = 'gif';
|
||||
} elseif ($mime == "data:image/bmp") {
|
||||
$ext = 'bmp';
|
||||
} else {
|
||||
$ext = 'jpg';
|
||||
}
|
||||
self::resizeGroup($rfile, $ext);
|
||||
|
||||
}
|
||||
return $get_img;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Deletes just the artwork
|
||||
*/
|
||||
public static function removeArtwork($trackid)
|
||||
{
|
||||
$file = Application_Model_StoredFile::RecallById($trackid);
|
||||
$md = $file->getMetadata();
|
||||
|
||||
$storDir = Application_Model_MusicDir::getStorDir();
|
||||
$fp = $storDir->getDirectory();
|
||||
|
||||
$dbAudioPath = $md["MDATA_KEY_ARTWORK"];
|
||||
$fullpath = $fp . $dbAudioPath;
|
||||
|
||||
if (file_exists($fullpath)) {
|
||||
foreach (glob("$fullpath*", GLOB_NOSORT) as $filename) {
|
||||
unlink($filename);
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Could not locate file ".$filepath);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize artwork group
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $ext
|
||||
*/
|
||||
public static function resizeGroup($file, $ext)
|
||||
{
|
||||
if (file_exists($file)) {
|
||||
self::resizeImage($file, $file . '-32.jpg', $ext, 32, 100);
|
||||
self::resizeImage($file, $file . '-64.jpg', $ext, 64, 100);
|
||||
self::resizeImage($file, $file . '-128.jpg', $ext, 128, 100);
|
||||
self::resizeImage($file, $file . '-256.jpg', $ext, 256, 100);
|
||||
self::resizeImage($file, $file . '-512.jpg', $ext, 512, 100);
|
||||
self::imgToDataURI($file . '-32.jpg', $file . '-32');
|
||||
self::imgToDataURI($file . '-64.jpg', $file . '-64');
|
||||
self::imgToDataURI($file . '-128.jpg', $file . '-128');
|
||||
self::imgToDataURI($file . '-256.jpg', $file . '-256');
|
||||
} else {
|
||||
Logging::error("The file $file does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render image
|
||||
* Used in API to render JPEG
|
||||
*
|
||||
* @param string $file
|
||||
*/
|
||||
public static function renderImage($file)
|
||||
{
|
||||
$im = @imagecreatefromjpeg($file);
|
||||
header('Content-Type: image/jpeg');
|
||||
$img = $im;
|
||||
imagejpeg($img);
|
||||
imagedestroy($img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Data URI
|
||||
* Used in API to render Data URI
|
||||
*
|
||||
* @param string $dataFile
|
||||
*/
|
||||
public static function renderDataURI($dataFile)
|
||||
{
|
||||
if($filecontent = file_get_contents($dataFile) !== false){
|
||||
$image = @file_get_contents($dataFile);
|
||||
$image = base64_encode($image);
|
||||
if (!$image || $image === '') {
|
||||
return;
|
||||
}
|
||||
$blob = base64_decode($image);
|
||||
$f = finfo_open();
|
||||
$mime_type = finfo_buffer($f, $blob, FILEINFO_MIME_TYPE);
|
||||
finfo_close($f);
|
||||
header("Content-Type: " . $mime_type);
|
||||
echo $blob;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize Image
|
||||
*
|
||||
* @param string $orig_filename
|
||||
* @param string $converted_filename
|
||||
* @param string $ext
|
||||
* @param string $size Default: 500
|
||||
* @param string $quality Default: 75
|
||||
*
|
||||
*/
|
||||
public static function resizeImage($orig_filename, $converted_filename, $ext, $size=500, $quality=75)
|
||||
{
|
||||
$get_cont = file_get_contents($orig_filename);
|
||||
if ($ext == "png") {
|
||||
$im = @imagecreatefrompng($get_cont);
|
||||
} elseif ($ext == "gif") {
|
||||
$im = @imagecreatefromgif($get_cont);
|
||||
} else {
|
||||
$im = @imagecreatefromjpeg($get_cont);
|
||||
}
|
||||
|
||||
// if one of those bombs, create an error image instead
|
||||
if (!$im) {
|
||||
$im = imagecreatetruecolor(150, 30);
|
||||
$bgc = imagecolorallocate($im, 255, 255, 255);
|
||||
$tc = imagecolorallocate($im, 0, 0, 0);
|
||||
imagefilledrectangle($im, 0, 0, 150, 30, $bgc);
|
||||
imagestring($im, 1, 5, 5, 'Error loading ' . $converted_filename, $tc);
|
||||
}
|
||||
|
||||
// scale if appropriate
|
||||
if ($size){
|
||||
$im = imagescale($im , $size);
|
||||
}
|
||||
|
||||
$img = $im;
|
||||
imagejpeg($img, $converted_filename, $quality);
|
||||
imagedestroy($img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert image to Data URI
|
||||
*
|
||||
* @param string $orig_filename
|
||||
* @param string $conv_filename
|
||||
*/
|
||||
public static function imgToDataURI($orig_filename, $conv_filename)
|
||||
{
|
||||
$file = file_get_contents($orig_filename);
|
||||
$Image = 'data:image/jpeg;charset=utf-8;base64,'.base64_encode($file);
|
||||
$base64 = @$Image;
|
||||
|
||||
//Save Data URI
|
||||
if (file_put_contents($conv_filename, $base64)) {
|
||||
|
||||
} else {
|
||||
Logging::error("Could not save Data URI");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Track Type
|
||||
*
|
||||
* @return string Track type key value
|
||||
*/
|
||||
public static function saveTrackType()
|
||||
{
|
||||
if (isset($_COOKIE['tt_upload'])) {
|
||||
$tt = $_COOKIE['tt_upload'];
|
||||
} else {
|
||||
// Use default track type
|
||||
$tt = Application_Model_Preference::GetTrackTypeDefault();
|
||||
}
|
||||
return $tt;
|
||||
}
|
||||
|
||||
}
|
92
legacy/application/common/FileIO.php
Normal file
92
legacy/application/common/FileIO.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class Application_Common_FileIO contains helper functions for reading and writing files, and sending them over HTTP.
|
||||
*/
|
||||
class Application_Common_FileIO
|
||||
{
|
||||
/**
|
||||
* Reads the requested portion of a file and sends its contents to the client with the appropriate headers.
|
||||
*
|
||||
* This HTTP_RANGE compatible read file function is necessary for allowing streaming media to be skipped around in.
|
||||
*
|
||||
* @param string $filePath - the full filepath or URL pointing to the location of the file
|
||||
* @param string $mimeType - the file's mime type. Defaults to 'audio/mp3'
|
||||
* @param integer $size - the file size, in bytes
|
||||
* @return void
|
||||
*
|
||||
* @link https://groups.google.com/d/msg/jplayer/nSM2UmnSKKA/Hu76jDZS4xcJ
|
||||
* @link http://php.net/manual/en/function.readfile.php#86244
|
||||
*/
|
||||
public static function smartReadFile($filePath, $size, $mimeType)
|
||||
{
|
||||
$fm = @fopen($filePath, 'rb');
|
||||
if (!$fm) {
|
||||
throw new LibreTimeFileNotFoundException($filePath);
|
||||
}
|
||||
|
||||
//Note that $size is allowed to be zero. If that's the case, it means we don't
|
||||
//know the filesize, and we need to figure one out so modern browsers don't get
|
||||
//confused. This should only affect files imported by legacy upstream since
|
||||
//media monitor did not always set the proper size in the database but analyzer
|
||||
//seems to always have a value for this.
|
||||
if ($size === 0) {
|
||||
$fstats = fstat($fm);
|
||||
$size = $fstats['size'];
|
||||
}
|
||||
|
||||
if ($size <= 0) {
|
||||
throw new Exception("Invalid file size returned for file at $filePath");
|
||||
}
|
||||
|
||||
|
||||
$begin = 0;
|
||||
$end = $size - 1;
|
||||
|
||||
ob_start(); //Must start a buffer here for these header() functions
|
||||
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
if (preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) {
|
||||
$begin = intval($matches[1]);
|
||||
if (!empty($matches[2])) {
|
||||
$end = intval($matches[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
} else {
|
||||
header('HTTP/1.1 200 OK');
|
||||
}
|
||||
header("Content-Type: $mimeType");
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header('Cache-Control: public, must-revalidate, max-age=0');
|
||||
header('Pragma: no-cache');
|
||||
header('Accept-Ranges: bytes');
|
||||
header('Content-Length:' . (($end - $begin) + 1));
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
header("Content-Range: bytes $begin-$end/$size");
|
||||
}
|
||||
|
||||
//We can have multiple levels of output buffering. Need to
|
||||
//keep looping until all have been disabled!!!
|
||||
//http://www.php.net/manual/en/function.ob-end-flush.php
|
||||
while (ob_get_level() > 0) {
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
|
||||
//These two lines were removed from Airtime 2.5.x at some point after Libretime forked from Airtime.
|
||||
//These lines allow seek to work for files.
|
||||
//Issue #349
|
||||
$cur = $begin;
|
||||
fseek($fm,$begin,0);
|
||||
|
||||
|
||||
while(!feof($fm) && (connection_status() == 0) && ($cur <= $end)) {
|
||||
echo fread($fm, 1024 * 8);
|
||||
}
|
||||
fclose($fm);
|
||||
}
|
||||
}
|
117
legacy/application/common/HTTPHelper.php
Normal file
117
legacy/application/common/HTTPHelper.php
Normal file
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
class Application_Common_HTTPHelper
|
||||
{
|
||||
/**
|
||||
* Returns start and end DateTime vars from given
|
||||
* HTTP Request object
|
||||
*
|
||||
* @param Request
|
||||
* @return array(start DateTime, end DateTime)
|
||||
*/
|
||||
public static function getStartEndFromRequest($request)
|
||||
{
|
||||
return Application_Common_DateHelper::getStartEnd(
|
||||
$request->getParam("start", null),
|
||||
$request->getParam("end", null),
|
||||
$request->getParam("timezone", null)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the base station URL
|
||||
*
|
||||
* @param boolean $secured whether or not to use HTTPS
|
||||
*
|
||||
* @return string the station URL
|
||||
*/
|
||||
public static function getStationUrl($secured = true)
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = $CC_CONFIG['baseUrl'];
|
||||
$baseDir = $CC_CONFIG['baseDir'];
|
||||
$basePort = $CC_CONFIG['basePort'];
|
||||
$forceSSL = $CC_CONFIG['forceSSL'];
|
||||
$configProtocol = $CC_CONFIG['protocol'];
|
||||
if (empty($baseDir)) {
|
||||
$baseDir = "/";
|
||||
}
|
||||
if ($baseDir[0] != "/") {
|
||||
$baseDir = "/" . $baseDir;
|
||||
}
|
||||
if (substr($baseDir, -1) != "/") {
|
||||
$baseDir = $baseDir . "/";
|
||||
}
|
||||
|
||||
# Set in reverse order of preference. ForceSSL configuration takes absolute preference, then
|
||||
# the protocol set in config. If neither are set, the port is used to determine the scheme
|
||||
$scheme = "http";
|
||||
if ($secured && $basePort == "443") {
|
||||
$scheme = "https";
|
||||
}
|
||||
if (!empty($configProtocol)) {
|
||||
$scheme = $configProtocol;
|
||||
}
|
||||
if ($forceSSL) {
|
||||
$scheme = "https";
|
||||
}
|
||||
|
||||
$portStr = "";
|
||||
if (($scheme == "http" && $basePort !== "80")
|
||||
|| ($scheme == "https" && $basePort !== "443")) {
|
||||
$portStr = ":${basePort}";
|
||||
}
|
||||
$stationUrl = "$scheme://${baseUrl}${portStr}${baseDir}";
|
||||
|
||||
return $stationUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a cURL POST
|
||||
*
|
||||
* @param string $url the URL to POST to
|
||||
* @param string[] $userPwd array of user args of the form ['user', 'pwd']
|
||||
* @param array $formData array of form data kwargs
|
||||
*
|
||||
* @return mixed the cURL result
|
||||
*/
|
||||
public static function doPost($url, $userPwd, $formData) {
|
||||
$params = "";
|
||||
foreach($formData as $key=>$value) {
|
||||
$params .= $key.'='.$value.'&';
|
||||
}
|
||||
rtrim($params, '&');
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, TRUE);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
|
||||
curl_setopt($ch, CURLOPT_USERPWD, implode(':', $userPwd));
|
||||
$result = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
class ZendActionHttpException extends Exception {
|
||||
|
||||
/**
|
||||
* @param Zend_Controller_Action $action
|
||||
* @param int $statusCode
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Exception $previous
|
||||
*
|
||||
* @throws Zend_Controller_Response_Exception
|
||||
*/
|
||||
public function __construct(Zend_Controller_Action $action, $statusCode, $message,
|
||||
$code = 0, Exception $previous = null) {
|
||||
Logging::error("Error in action " . $action->getRequest()->getActionName()
|
||||
. " with status code $statusCode: $message");
|
||||
$action->getResponse()
|
||||
->setHttpResponseCode($statusCode)
|
||||
->appendBody($message);
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
}
|
160
legacy/application/common/LocaleHelper.php
Normal file
160
legacy/application/common/LocaleHelper.php
Normal file
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
// Global functions for translating domain-specific strings
|
||||
|
||||
class Application_Common_LocaleHelper {
|
||||
|
||||
/**
|
||||
* Return an array of all ISO 639-1 language codes and their corresponding translated language names
|
||||
*
|
||||
* @return array the array of language codes to names
|
||||
*/
|
||||
public static function getISO6391LanguageCodes() {
|
||||
/**
|
||||
* From: http://www.binarytides.com/php-array-of-iso-639-1-language-codes-and-names/
|
||||
*
|
||||
* ISO 639-1 Language Codes
|
||||
* References :
|
||||
* 1. http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
||||
* 2. http://blog.xoundboy.com/?p=235
|
||||
*/
|
||||
return array(
|
||||
'en' => _('English'),
|
||||
'aa' => _('Afar'),
|
||||
'ab' => _('Abkhazian'),
|
||||
'af' => _('Afrikaans'),
|
||||
'am' => _('Amharic'),
|
||||
'ar' => _('Arabic'),
|
||||
'as' => _('Assamese'),
|
||||
'ay' => _('Aymara'),
|
||||
'az' => _('Azerbaijani'),
|
||||
'ba' => _('Bashkir'),
|
||||
'be' => _('Belarusian'),
|
||||
'bg' => _('Bulgarian'),
|
||||
'bh' => _('Bihari'),
|
||||
'bi' => _('Bislama'),
|
||||
'bn' => _('Bengali/Bangla'),
|
||||
'bo' => _('Tibetan'),
|
||||
'br' => _('Breton'),
|
||||
'ca' => _('Catalan'),
|
||||
'co' => _('Corsican'),
|
||||
'cs' => _('Czech'),
|
||||
'cy' => _('Welsh'),
|
||||
'da' => _('Danish'),
|
||||
'de' => _('German'),
|
||||
'dz' => _('Bhutani'),
|
||||
'el' => _('Greek'),
|
||||
'eo' => _('Esperanto'),
|
||||
'es' => _('Spanish'),
|
||||
'et' => _('Estonian'),
|
||||
'eu' => _('Basque'),
|
||||
'fa' => _('Persian'),
|
||||
'fi' => _('Finnish'),
|
||||
'fj' => _('Fiji'),
|
||||
'fo' => _('Faeroese'),
|
||||
'fr' => _('French'),
|
||||
'fy' => _('Frisian'),
|
||||
'ga' => _('Irish'),
|
||||
'gd' => _('Scots/Gaelic'),
|
||||
'gl' => _('Galician'),
|
||||
'gn' => _('Guarani'),
|
||||
'gu' => _('Gujarati'),
|
||||
'ha' => _('Hausa'),
|
||||
'hi' => _('Hindi'),
|
||||
'hr' => _('Croatian'),
|
||||
'hu' => _('Hungarian'),
|
||||
'hy' => _('Armenian'),
|
||||
'ia' => _('Interlingua'),
|
||||
'ie' => _('Interlingue'),
|
||||
'ik' => _('Inupiak'),
|
||||
'in' => _('Indonesian'),
|
||||
'is' => _('Icelandic'),
|
||||
'it' => _('Italian'),
|
||||
'iw' => _('Hebrew'),
|
||||
'ja' => _('Japanese'),
|
||||
'ji' => _('Yiddish'),
|
||||
'jw' => _('Javanese'),
|
||||
'ka' => _('Georgian'),
|
||||
'kk' => _('Kazakh'),
|
||||
'kl' => _('Greenlandic'),
|
||||
'km' => _('Cambodian'),
|
||||
'kn' => _('Kannada'),
|
||||
'ko' => _('Korean'),
|
||||
'ks' => _('Kashmiri'),
|
||||
'ku' => _('Kurdish'),
|
||||
'ky' => _('Kirghiz'),
|
||||
'la' => _('Latin'),
|
||||
'ln' => _('Lingala'),
|
||||
'lo' => _('Laothian'),
|
||||
'lt' => _('Lithuanian'),
|
||||
'lv' => _('Latvian/Lettish'),
|
||||
'mg' => _('Malagasy'),
|
||||
'mi' => _('Maori'),
|
||||
'mk' => _('Macedonian'),
|
||||
'ml' => _('Malayalam'),
|
||||
'mn' => _('Mongolian'),
|
||||
'mo' => _('Moldavian'),
|
||||
'mr' => _('Marathi'),
|
||||
'ms' => _('Malay'),
|
||||
'mt' => _('Maltese'),
|
||||
'my' => _('Burmese'),
|
||||
'na' => _('Nauru'),
|
||||
'ne' => _('Nepali'),
|
||||
'nl' => _('Dutch'),
|
||||
'no' => _('Norwegian'),
|
||||
'oc' => _('Occitan'),
|
||||
'om' => _('(Afan)/Oromoor/Oriya'),
|
||||
'pa' => _('Punjabi'),
|
||||
'pl' => _('Polish'),
|
||||
'ps' => _('Pashto/Pushto'),
|
||||
'pt' => _('Portuguese'),
|
||||
'qu' => _('Quechua'),
|
||||
'rm' => _('Rhaeto-Romance'),
|
||||
'rn' => _('Kirundi'),
|
||||
'ro' => _('Romanian'),
|
||||
'ru' => _('Russian'),
|
||||
'rw' => _('Kinyarwanda'),
|
||||
'sa' => _('Sanskrit'),
|
||||
'sd' => _('Sindhi'),
|
||||
'sg' => _('Sangro'),
|
||||
'sh' => _('Serbo-Croatian'),
|
||||
'si' => _('Singhalese'),
|
||||
'sk' => _('Slovak'),
|
||||
'sl' => _('Slovenian'),
|
||||
'sm' => _('Samoan'),
|
||||
'sn' => _('Shona'),
|
||||
'so' => _('Somali'),
|
||||
'sq' => _('Albanian'),
|
||||
'sr' => _('Serbian'),
|
||||
'ss' => _('Siswati'),
|
||||
'st' => _('Sesotho'),
|
||||
'su' => _('Sundanese'),
|
||||
'sv' => _('Swedish'),
|
||||
'sw' => _('Swahili'),
|
||||
'ta' => _('Tamil'),
|
||||
'te' => _('Tegulu'),
|
||||
'tg' => _('Tajik'),
|
||||
'th' => _('Thai'),
|
||||
'ti' => _('Tigrinya'),
|
||||
'tk' => _('Turkmen'),
|
||||
'tl' => _('Tagalog'),
|
||||
'tn' => _('Setswana'),
|
||||
'to' => _('Tonga'),
|
||||
'tr' => _('Turkish'),
|
||||
'ts' => _('Tsonga'),
|
||||
'tt' => _('Tatar'),
|
||||
'tw' => _('Twi'),
|
||||
'uk' => _('Ukrainian'),
|
||||
'ur' => _('Urdu'),
|
||||
'uz' => _('Uzbek'),
|
||||
'vi' => _('Vietnamese'),
|
||||
'vo' => _('Volapuk'),
|
||||
'wo' => _('Wolof'),
|
||||
'xh' => _('Xhosa'),
|
||||
'yo' => _('Yoruba'),
|
||||
'zh' => _('Chinese'),
|
||||
'zu' => _('Zulu'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
96
legacy/application/common/OsPath.php
Normal file
96
legacy/application/common/OsPath.php
Normal file
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
class Application_Common_OsPath{
|
||||
// this function is from http://stackoverflow.com/questions/2670299/is-there-a-php-equivalent-function-to-the-python-os-path-normpath
|
||||
public static function normpath($path)
|
||||
{
|
||||
if (empty($path))
|
||||
return '.';
|
||||
|
||||
if (strpos($path, '/') === 0)
|
||||
$initial_slashes = true;
|
||||
else
|
||||
$initial_slashes = false;
|
||||
if (
|
||||
($initial_slashes) &&
|
||||
(strpos($path, '//') === 0) &&
|
||||
(strpos($path, '///') === false)
|
||||
)
|
||||
$initial_slashes = 2;
|
||||
$initial_slashes = (int) $initial_slashes;
|
||||
|
||||
$comps = explode('/', $path);
|
||||
$new_comps = array();
|
||||
foreach ($comps as $comp)
|
||||
{
|
||||
if (in_array($comp, array('', '.')))
|
||||
continue;
|
||||
if (
|
||||
($comp != '..') ||
|
||||
(!$initial_slashes && !$new_comps) ||
|
||||
($new_comps && (end($new_comps) == '..'))
|
||||
)
|
||||
array_push($new_comps, $comp);
|
||||
elseif ($new_comps)
|
||||
array_pop($new_comps);
|
||||
}
|
||||
$comps = $new_comps;
|
||||
$path = implode('/', $comps);
|
||||
if ($initial_slashes)
|
||||
$path = str_repeat('/', $initial_slashes) . $path;
|
||||
if ($path)
|
||||
return $path;
|
||||
else
|
||||
return '.';
|
||||
}
|
||||
|
||||
/* Similar to the os.path.join python method
|
||||
* http://stackoverflow.com/a/1782990/276949 */
|
||||
public static function join() {
|
||||
$args = func_get_args();
|
||||
$paths = array();
|
||||
|
||||
foreach($args as $arg) {
|
||||
$paths = array_merge($paths, (array)$arg);
|
||||
}
|
||||
|
||||
foreach($paths as &$path) {
|
||||
$path = trim($path, DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
if (substr($args[0], 0, 1) == DIRECTORY_SEPARATOR) {
|
||||
$paths[0] = DIRECTORY_SEPARATOR . $paths[0];
|
||||
}
|
||||
|
||||
return join(DIRECTORY_SEPARATOR, $paths);
|
||||
}
|
||||
|
||||
public static function getBaseDir() {
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = $CC_CONFIG['baseDir'];
|
||||
|
||||
if ($baseUrl[0] != "/") {
|
||||
$baseUrl = "/".$baseUrl;
|
||||
}
|
||||
|
||||
if ($baseUrl[strlen($baseUrl) -1] != "/") {
|
||||
$baseUrl = $baseUrl."/";
|
||||
}
|
||||
|
||||
|
||||
return $baseUrl;
|
||||
}
|
||||
|
||||
public static function formatDirectoryWithDirectorySeparators($dir)
|
||||
{
|
||||
if ($dir[0] != "/") {
|
||||
$dir = "/".$dir;
|
||||
}
|
||||
|
||||
if ($dir[strlen($dir) -1] != "/") {
|
||||
$dir = $dir."/";
|
||||
}
|
||||
|
||||
return $dir;
|
||||
}
|
||||
}
|
104
legacy/application/common/PodcastManager.php
Normal file
104
legacy/application/common/PodcastManager.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
class PodcastManager {
|
||||
|
||||
/**
|
||||
* @var int how often, in seconds, to check for and ingest new podcast episodes
|
||||
*/
|
||||
private static $_PODCAST_POLL_INTERVAL_SECONDS = 3600; // 1 hour
|
||||
|
||||
/**
|
||||
* Check whether $_PODCAST_POLL_INTERVAL_SECONDS have passed since the last call to
|
||||
* downloadNewestEpisodes
|
||||
*
|
||||
* @return bool true if $_PODCAST_POLL_INTERVAL_SECONDS has passed since the last check
|
||||
*/
|
||||
public static function hasPodcastPollIntervalPassed() {
|
||||
$lastPolled = Application_Model_Preference::getPodcastPollLock();
|
||||
return empty($lastPolled) || (microtime(true) > $lastPolled + self::$_PODCAST_POLL_INTERVAL_SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all podcasts flagged for automatic ingest whose most recent episode has
|
||||
* yet to be downloaded and download it with Celery
|
||||
*
|
||||
* @throws InvalidPodcastException
|
||||
* @throws PodcastNotFoundException
|
||||
*/
|
||||
public static function downloadNewestEpisodes() {
|
||||
$autoIngestPodcasts = static::_getAutoIngestPodcasts();
|
||||
$service = new Application_Service_PodcastEpisodeService();
|
||||
foreach ($autoIngestPodcasts as $podcast) {
|
||||
$episodes = static::_findUningestedEpisodes($podcast, $service);
|
||||
// Since episodes don't have to be uploaded with a time (H:i:s) component,
|
||||
// store the timestamp of the most recent (first pushed to the array) episode
|
||||
// that we're ingesting.
|
||||
// Note that this folds to the failure case (Celery task timeout/download failure)
|
||||
// but will at least continue to ingest new episodes.
|
||||
if (!empty($episodes)) {
|
||||
$podcast->setDbAutoIngestTimestamp(gmdate('r', strtotime($episodes[0]->getDbPublicationDate())))->save();
|
||||
$service->downloadEpisodes($episodes);
|
||||
}
|
||||
}
|
||||
|
||||
Application_Model_Preference::setPodcastPollLock(microtime(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an ImportedPodcast, find all uningested episodes since the last automatic ingest,
|
||||
* and add them to a given episodes array
|
||||
*
|
||||
* @param ImportedPodcast $podcast the podcast to search
|
||||
* @param Application_Service_PodcastEpisodeService $service podcast episode service object
|
||||
*
|
||||
* @return array array of episodes to append be downloaded
|
||||
*/
|
||||
protected static function _findUningestedEpisodes($podcast, $service) {
|
||||
$episodeList = $service->getPodcastEpisodes($podcast->getDbPodcastId());
|
||||
$episodes = array();
|
||||
usort($episodeList, array(__CLASS__, "_sortByEpisodePubDate"));
|
||||
for ($i = 0; $i < sizeof($episodeList); $i++) {
|
||||
$episodeData = $episodeList[$i];
|
||||
$ts = $podcast->getDbAutoIngestTimestamp();
|
||||
// If the timestamp for this podcast is empty (no previous episodes have been ingested) and there are no
|
||||
// episodes in the list of episodes to ingest, don't skip this episode - we should try to ingest the
|
||||
// most recent episode when the user first sets the podcast to automatic ingest.
|
||||
// If the publication date of this episode is before the ingest timestamp, we don't need to ingest it
|
||||
if ((empty($ts) && ($i > 0)) || strtotime($episodeData["pub_date"]) < strtotime($ts)) {
|
||||
continue;
|
||||
}
|
||||
$episode = PodcastEpisodesQuery::create()->findOneByDbEpisodeGuid($episodeData["guid"]);
|
||||
// Make sure there's no existing episode placeholder or import, and that the data is non-empty
|
||||
if (empty($episode) && !empty($episodeData)) {
|
||||
$placeholder = $service->addPlaceholder($podcast->getDbPodcastId(), $episodeData);
|
||||
array_push($episodes, $placeholder);
|
||||
}
|
||||
}
|
||||
return $episodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all podcasts flagged for automatic ingest
|
||||
*
|
||||
* @return PropelObjectCollection collection of ImportedPodcast objects
|
||||
* flagged for automatic ingest
|
||||
*/
|
||||
protected static function _getAutoIngestPodcasts() {
|
||||
return ImportedPodcastQuery::create()
|
||||
->filterByDbAutoIngest(true)
|
||||
->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom sort function for podcast episodes
|
||||
*
|
||||
* @param array $a first episode array to compare
|
||||
* @param array $b second episode array to compare
|
||||
* @return bool boolean for ordering
|
||||
*/
|
||||
protected static function _sortByEpisodePubDate($a, $b) {
|
||||
if ($a["pub_date"] == $b["pub_date"]) return 0;
|
||||
return (strtotime($a["pub_date"]) < strtotime($b["pub_date"])) ? 1 : -1; // Descending order
|
||||
}
|
||||
|
||||
}
|
23
legacy/application/common/SecurityHelper.php
Normal file
23
legacy/application/common/SecurityHelper.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
class SecurityHelper {
|
||||
|
||||
public static function htmlescape_recursive(&$arr) {
|
||||
foreach ($arr as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
self::htmlescape_recursive($arr[$key]);
|
||||
} else if (is_string($val)) {
|
||||
$arr[$key] = htmlspecialchars($val, ENT_QUOTES);
|
||||
}
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
public static function verifyCSRFToken($observedToken) {
|
||||
$current_namespace = new Zend_Session_Namespace('csrf_namespace');
|
||||
$observed_csrf_token = $observedToken;
|
||||
$expected_csrf_token = $current_namespace->authtoken;
|
||||
|
||||
return ($observed_csrf_token == $expected_csrf_token);
|
||||
}
|
||||
}
|
13
legacy/application/common/SessionHelper.php
Normal file
13
legacy/application/common/SessionHelper.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
class SessionHelper
|
||||
{
|
||||
public static function reopenSessionForWriting() {
|
||||
//PHP will send double Set-Cookie headers if we reopen the
|
||||
//session for writing, and this breaks IE8 and some other browsers.
|
||||
//This hacky workaround prevents double headers. Background here:
|
||||
// https://bugs.php.net/bug.php?id=38104
|
||||
ini_set('session.cache_limiter', null);
|
||||
session_start(); // Reopen the session for writing (without resending the Set-Cookie header)
|
||||
}
|
||||
}
|
372
legacy/application/common/TaskManager.php
Normal file
372
legacy/application/common/TaskManager.php
Normal file
|
@ -0,0 +1,372 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class TaskManager
|
||||
*
|
||||
* Background class for 'asynchronous' task management for Airtime stations
|
||||
*/
|
||||
final class TaskManager {
|
||||
|
||||
/**
|
||||
* @var array tasks to be run. Maps task names to a boolean value denoting
|
||||
* whether the task has been checked/run
|
||||
*/
|
||||
protected $_taskList;
|
||||
|
||||
/**
|
||||
* @var TaskManager singleton instance object
|
||||
*/
|
||||
protected static $_instance;
|
||||
|
||||
/**
|
||||
* @var int TASK_INTERVAL_SECONDS how often, in seconds, to run the TaskManager tasks
|
||||
*/
|
||||
const TASK_INTERVAL_SECONDS = 30;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var $con PDO Propel connection object
|
||||
*/
|
||||
private $_con;
|
||||
|
||||
/**
|
||||
* Private constructor so class is uninstantiable
|
||||
*/
|
||||
private function __construct() {
|
||||
foreach (TaskFactory::getTasks() as $k => $task) {
|
||||
$this->_taskList[$task] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton instance of this class
|
||||
*
|
||||
* @return TaskManager the TaskManager instance
|
||||
*/
|
||||
public static function getInstance() {
|
||||
if (!self::$_instance) {
|
||||
self::$_instance = new TaskManager();
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a single task.
|
||||
*
|
||||
* @param string $taskName the ENUM name of the task to be run
|
||||
*/
|
||||
public function runTask($taskName) {
|
||||
$task = TaskFactory::getTask($taskName);
|
||||
if ($task && $task->shouldBeRun()) {
|
||||
$task->run();
|
||||
}
|
||||
$this->_taskList[$taskName] = true; // Mark that the task has been checked/run.
|
||||
// This is important for prioritized tasks that
|
||||
// we need to run on every request (such as the
|
||||
// schema check/upgrade)
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all tasks that need to be run.
|
||||
*
|
||||
* To prevent blocking and making too many requests to the database,
|
||||
* we implement a row-level, non-blocking, read-protected lock on a
|
||||
* timestamp that we check each time the application is bootstrapped,
|
||||
* which, assuming enough time has passed, is updated before running
|
||||
* the tasks.
|
||||
*/
|
||||
public function runTasks() {
|
||||
// If there is data in auth storage, this could be a user request
|
||||
// so we should just return to avoid blocking
|
||||
if ($this->_isUserSessionRequest()) {
|
||||
return;
|
||||
}
|
||||
$this->_con = Propel::getConnection(CcPrefPeer::DATABASE_NAME);
|
||||
$this->_con->beginTransaction();
|
||||
try {
|
||||
$lock = $this->_getLock();
|
||||
if ($lock && (microtime(true) < ($lock['valstr'] + self::TASK_INTERVAL_SECONDS))) {
|
||||
// Propel caches the database connection and uses it persistently, so if we don't
|
||||
// use commit() here, we end up blocking other queries made within this request
|
||||
$this->_con->commit();
|
||||
return;
|
||||
}
|
||||
$this->_updateLock($lock);
|
||||
$this->_con->commit();
|
||||
} catch (Exception $e) {
|
||||
// We get here if there are simultaneous requests trying to fetch the lock row
|
||||
$this->_con->rollBack();
|
||||
Logging::warn($e->getMessage());
|
||||
return;
|
||||
}
|
||||
foreach ($this->_taskList as $task => $hasTaskRun) {
|
||||
if (!$hasTaskRun) {
|
||||
$this->runTask($task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current session is a user request
|
||||
*
|
||||
* @return bool true if there is a Zend_Auth object in the current session,
|
||||
* otherwise false
|
||||
*/
|
||||
private function _isUserSessionRequest() {
|
||||
if (!Zend_Session::isStarted()) {
|
||||
return false;
|
||||
}
|
||||
$auth = Zend_Auth::getInstance();
|
||||
$data = $auth->getStorage()->read();
|
||||
return !empty($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the task_manager_lock from cc_pref with a row-level lock for atomicity
|
||||
*
|
||||
* The lock is exclusive (prevent reads) and will only last for the duration
|
||||
* of the transaction. We add NOWAIT so reads on the row during the transaction
|
||||
* won't block
|
||||
*
|
||||
* @return array|bool an array containing the row values, or false on failure
|
||||
*/
|
||||
private function _getLock() {
|
||||
$sql = "SELECT * FROM cc_pref WHERE keystr='task_manager_lock' LIMIT 1 FOR UPDATE NOWAIT";
|
||||
$st = $this->_con->prepare($sql);
|
||||
$st->execute();
|
||||
return $st->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update and commit the new lock value, or insert it if it doesn't exist
|
||||
*
|
||||
* @param $lock array cc_pref lock row values
|
||||
*/
|
||||
private function _updateLock($lock) {
|
||||
$sql = empty($lock) ? "INSERT INTO cc_pref (keystr, valstr) VALUES ('task_manager_lock', :value)"
|
||||
: "UPDATE cc_pref SET valstr=:value WHERE keystr='task_manager_lock'";
|
||||
$st = $this->_con->prepare($sql);
|
||||
$st->execute(array(":value" => microtime(true)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface AirtimeTask Interface for task operations
|
||||
*/
|
||||
interface AirtimeTask {
|
||||
|
||||
/**
|
||||
* Check whether the task should be run
|
||||
*
|
||||
* @return bool true if the task needs to be run, otherwise false
|
||||
*/
|
||||
public function shouldBeRun();
|
||||
|
||||
/**
|
||||
* Run the task
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class UpgradeTask
|
||||
*
|
||||
* Checks the current Airtime version and runs any outstanding upgrades
|
||||
*/
|
||||
class UpgradeTask implements AirtimeTask {
|
||||
|
||||
/**
|
||||
* Check the current Airtime schema version to see if an upgrade should be run
|
||||
*
|
||||
* @return bool true if an upgrade is needed
|
||||
*/
|
||||
public function shouldBeRun() {
|
||||
return UpgradeManager::checkIfUpgradeIsNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all upgrades above the current schema version
|
||||
*/
|
||||
public function run() {
|
||||
UpgradeManager::doUpgrade();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class CeleryTask
|
||||
*
|
||||
* Checks the Celery broker task queue and runs callbacks for completed tasks
|
||||
*/
|
||||
class CeleryTask implements AirtimeTask {
|
||||
|
||||
/**
|
||||
* Check the ThirdPartyTrackReferences table to see if there are any pending tasks
|
||||
*
|
||||
* @return bool true if there are pending tasks in ThirdPartyTrackReferences
|
||||
*/
|
||||
public function shouldBeRun() {
|
||||
return !CeleryManager::isBrokerTaskQueueEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll the task queue for any completed Celery tasks
|
||||
*/
|
||||
public function run() {
|
||||
CeleryManager::pollBrokerTaskQueue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class AutoPlaylistTask
|
||||
*
|
||||
* Checks for shows with an autoplaylist that needs to be filled in
|
||||
*
|
||||
*/
|
||||
class AutoPlaylistTask implements AirtimeTask
|
||||
{
|
||||
/**
|
||||
* Checks whether or not the autoplaylist polling interval has passed
|
||||
*
|
||||
* @return bool true if the autoplaylist polling interval has passed
|
||||
*/
|
||||
public function shouldBeRun()
|
||||
{
|
||||
return AutoPlaylistManager::hasAutoPlaylistPollIntervalPassed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the autoplaylist for the shows
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
AutoPlaylistManager::buildAutoPlaylist();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class PodcastTask
|
||||
*
|
||||
* Checks podcasts marked for automatic ingest and downloads any new episodes
|
||||
* since the task was last run
|
||||
*/
|
||||
class PodcastTask implements AirtimeTask {
|
||||
|
||||
/**
|
||||
* Check whether or not the podcast polling interval has passed
|
||||
*
|
||||
* @return bool true if the podcast polling interval has passed
|
||||
*/
|
||||
public function shouldBeRun() {
|
||||
$overQuota = Application_Model_Systemstatus::isDiskOverQuota();
|
||||
return !$overQuota && PodcastManager::hasPodcastPollIntervalPassed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the latest episode for all podcasts flagged for automatic ingest
|
||||
*/
|
||||
public function run() {
|
||||
PodcastManager::downloadNewestEpisodes();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ImportTask
|
||||
*/
|
||||
class ImportCleanupTask implements AirtimeTask {
|
||||
|
||||
/**
|
||||
* Check if there are any files that have been stuck
|
||||
* in Pending status for over an hour
|
||||
*
|
||||
* @return bool true if there are any files stuck pending,
|
||||
* otherwise false
|
||||
*/
|
||||
public function shouldBeRun() {
|
||||
return Application_Service_MediaService::areFilesStuckInPending();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up stuck imports by changing their import status to Failed
|
||||
*/
|
||||
public function run() {
|
||||
Application_Service_MediaService::clearStuckPendingImports();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class StationPodcastTask
|
||||
*
|
||||
* Checks the Station podcast rollover timer and resets allotted
|
||||
* downloads if enough time has passed (default: 1 month)
|
||||
*/
|
||||
class StationPodcastTask implements AirtimeTask {
|
||||
|
||||
const STATION_PODCAST_RESET_TIMER_SECONDS = 2.628e+6; // 1 month
|
||||
|
||||
/**
|
||||
* Check whether or not the download counter for the station podcast should be reset
|
||||
*
|
||||
* @return bool true if enough time has passed
|
||||
*/
|
||||
public function shouldBeRun() {
|
||||
$lastReset = Application_Model_Preference::getStationPodcastDownloadResetTimer();
|
||||
return empty($lastReset) || (microtime(true) > ($lastReset + self::STATION_PODCAST_RESET_TIMER_SECONDS));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the station podcast download counter
|
||||
*/
|
||||
public function run() {
|
||||
Application_Model_Preference::resetStationPodcastDownloadCounter();
|
||||
Application_Model_Preference::setStationPodcastDownloadResetTimer(microtime(true));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class TaskFactory Factory class to abstract task instantiation
|
||||
*/
|
||||
class TaskFactory {
|
||||
|
||||
/**
|
||||
* Check if the class with the given name implements AirtimeTask
|
||||
*
|
||||
* @param $c string class name
|
||||
*
|
||||
* @return bool true if the class $c implements AirtimeTask
|
||||
*/
|
||||
private static function _isTask($c) {
|
||||
return array_key_exists('AirtimeTask', class_implements($c));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter all declared classes to get all classes implementing the AirtimeTask interface
|
||||
*
|
||||
* @return array all classes implementing the AirtimeTask interface
|
||||
*/
|
||||
public static function getTasks() {
|
||||
return array_filter(get_declared_classes(), array(__CLASS__, "_isTask"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an AirtimeTask based on class name
|
||||
*
|
||||
* @param $task string name of the class implementing AirtimeTask to construct
|
||||
*
|
||||
* @return AirtimeTask|null return a task of the given type or null if no corresponding task exists
|
||||
*/
|
||||
public static function getTask($task) {
|
||||
// Try to get a valid class name from the given string
|
||||
if (!class_exists($task)) $task = str_replace(' ', '', ucwords($task)) . "Task";
|
||||
return class_exists($task) ? new $task() : null;
|
||||
}
|
||||
|
||||
}
|
32
legacy/application/common/Timezone.php
Normal file
32
legacy/application/common/Timezone.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
class Application_Common_Timezone
|
||||
{
|
||||
public static function getTimezones()
|
||||
{
|
||||
$regions = array(
|
||||
'Africa' => DateTimeZone::AFRICA,
|
||||
'America' => DateTimeZone::AMERICA,
|
||||
'Antarctica' => DateTimeZone::ANTARCTICA,
|
||||
'Arctic' => DateTimeZone::ARCTIC,
|
||||
'Asia' => DateTimeZone::ASIA,
|
||||
'Atlantic' => DateTimeZone::ATLANTIC,
|
||||
'Australia' => DateTimeZone::AUSTRALIA,
|
||||
'Europe' => DateTimeZone::EUROPE,
|
||||
'Indian' => DateTimeZone::INDIAN,
|
||||
'Pacific' => DateTimeZone::PACIFIC,
|
||||
'UTC' => DateTimeZone::UTC
|
||||
);
|
||||
|
||||
$tzlist = array(NULL => _("Use station default"));
|
||||
|
||||
foreach ($regions as $name => $mask) {
|
||||
$ids = DateTimeZone::listIdentifiers($mask);
|
||||
foreach ($ids as $id) {
|
||||
$tzlist[$id] = str_replace("_", " ", $id);
|
||||
}
|
||||
}
|
||||
|
||||
return $tzlist;
|
||||
}
|
||||
}
|
44
legacy/application/common/TuneIn.php
Normal file
44
legacy/application/common/TuneIn.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
class Application_Common_TuneIn
|
||||
{
|
||||
/**
|
||||
* @param $title url encoded string
|
||||
* @param $artist url encoded string
|
||||
*/
|
||||
public static function sendMetadataToTunein($title, $artist)
|
||||
{
|
||||
$credQryStr = self::getCredentialsQueryString();
|
||||
$metadataQryStr = "&title=".$title."&artist=".$artist."&commercial=false";
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, TUNEIN_API_URL . $credQryStr . $metadataQryStr);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||
|
||||
$xmlResponse = curl_exec($ch);
|
||||
if (curl_error($ch)) {
|
||||
Logging::error("Failed to reach TuneIn: ". curl_errno($ch)." - ". curl_error($ch) . " - " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$xmlObj = new SimpleXMLElement($xmlResponse);
|
||||
if (!$xmlObj || $xmlObj->head->status != "200") {
|
||||
Logging::info("Error occurred pushing metadata to TuneIn:");
|
||||
Logging::info($xmlResponse);
|
||||
} else if ($xmlObj->head->status == "200") {
|
||||
Application_Model_Preference::setLastTuneinMetadataUpdate(time());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static function getCredentialsQueryString() {
|
||||
$tuneInStationID = Application_Model_Preference::getTuneinStationId();
|
||||
$tuneInPartnerID = Application_Model_Preference::getTuneinPartnerId();
|
||||
$tuneInPartnerKey = Application_Model_Preference::getTuneinPartnerKey();
|
||||
|
||||
return "?partnerId=".$tuneInPartnerID."&partnerKey=".$tuneInPartnerKey."&id=".$tuneInStationID;
|
||||
}
|
||||
|
||||
}
|
221
legacy/application/common/UsabilityHints.php
Normal file
221
legacy/application/common/UsabilityHints.php
Normal file
|
@ -0,0 +1,221 @@
|
|||
<?php
|
||||
|
||||
class Application_Common_UsabilityHints
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $userPath User's current location in Airtime (i.e. /Plupload)
|
||||
* @return string
|
||||
*/
|
||||
public static function getUsabilityHint($userPath=null)
|
||||
{
|
||||
// We want to display hints in this order:
|
||||
// 1. Check if files are uploaded
|
||||
// 2. Check if a show is scheduled
|
||||
// 3. Check if current or next show needs content
|
||||
|
||||
// Once the user is on the page linked to from the hint we want to
|
||||
// display a new message further describing what to do. Once this
|
||||
// action has been done we can hide the message and get the next
|
||||
// usability hint, if there is one.
|
||||
|
||||
$userIsOnCalendarPage = false;
|
||||
$userIsOnAddMediaPage = false;
|
||||
$userIsOnShowbuilderPage = false;
|
||||
$userIsSuperAdmin = Application_Model_User::getCurrentUser()->isSuperAdmin();
|
||||
|
||||
// If $userPath is set the request came from AJAX so the user's
|
||||
// current location inside Airtime gets passed in to this function.
|
||||
if (!is_null($userPath)) {
|
||||
// We check if the controller names are in the user's current location
|
||||
// so we can ignore leading or trailing slashes, special characters like '#',
|
||||
// and additional controller action names like '/user/add-user'
|
||||
|
||||
if (strpos(strtolower($userPath), 'plupload') !== false) {
|
||||
$userIsOnAddMediaPage = true;
|
||||
}
|
||||
|
||||
if (strpos(strtolower($userPath), 'schedule') !== false) {
|
||||
$userIsOnCalendarPage = true;
|
||||
}
|
||||
|
||||
if (strpos(strtolower($userPath), 'showbuilder') !== false) {
|
||||
$userIsOnShowbuilderPage = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
// If $userPath is not set the request came from inside Airtime so
|
||||
// we can use Zend's Front Controller to get the user's current location.
|
||||
$currentController = strtolower(Zend_Controller_Front::getInstance()->getRequest()->getControllerName());
|
||||
|
||||
if ($currentController == "schedule") {
|
||||
$userIsOnCalendarPage = true;
|
||||
}
|
||||
|
||||
if ($currentController == "plupload") {
|
||||
$userIsOnAddMediaPage = true;
|
||||
}
|
||||
|
||||
if ($currentController == 'showbuilder') {
|
||||
$userIsOnShowbuilderPage = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (self::zeroFilesUploaded()) {
|
||||
if ($userIsOnAddMediaPage) {
|
||||
return _("Upload some tracks below to add them to your library!");
|
||||
} else {
|
||||
return sprintf(_("It looks like you haven't uploaded any audio files yet. %sUpload a file now%s."),
|
||||
"<a href=\"/plupload\">",
|
||||
"</a>");
|
||||
}
|
||||
} else if (!self::isFutureOrCurrentShowScheduled()) {
|
||||
if ($userIsOnCalendarPage) {
|
||||
return _("Click the 'New Show' button and fill out the required fields.");
|
||||
} else {
|
||||
return sprintf(_("It looks like you don't have any shows scheduled. %sCreate a show now%s."),
|
||||
"<a href=\"/schedule\">",
|
||||
"</a>");
|
||||
}
|
||||
} else if (self::isCurrentShowEmpty()) {
|
||||
// If the current show is linked users cannot add content to it so we have to provide a different message.
|
||||
if (self::isCurrentShowLinked()) {
|
||||
if ($userIsOnCalendarPage) {
|
||||
return _("To start broadcasting, cancel the current linked show by clicking on it and selecting 'Cancel Show'.");
|
||||
} else {
|
||||
return sprintf(_("Linked shows need to be filled with tracks before it starts. To start broadcasting cancel the current linked show and schedule an unlinked show.
|
||||
%sCreate an unlinked show now%s."), "<a href=\"/schedule\">", "</a>");
|
||||
}
|
||||
} else {
|
||||
if ($userIsOnCalendarPage) {
|
||||
return _("To start broadcasting, click on the current show and select 'Schedule Tracks'");
|
||||
} else {
|
||||
return sprintf(_("It looks like the current show needs more tracks. %sAdd tracks to your show now%s."),
|
||||
"<a href=\"/schedule\">",
|
||||
"</a>");
|
||||
}
|
||||
}
|
||||
} else if (!self::getCurrentShow() && self::isNextShowEmpty()) {
|
||||
if ($userIsOnCalendarPage) {
|
||||
return _("Click on the show starting next and select 'Schedule Tracks'");
|
||||
} else {
|
||||
return sprintf(_("It looks like the next show is empty. %sAdd tracks to your show now%s."),
|
||||
"<a href=\"/schedule\">",
|
||||
"</a>");
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if no files have been uploaded.
|
||||
*/
|
||||
private static function zeroFilesUploaded()
|
||||
{
|
||||
$fileCount = CcFilesQuery::create()
|
||||
->filterByDbFileExists(true)
|
||||
->filterByDbHidden(false)
|
||||
->count();
|
||||
|
||||
if ($fileCount == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is at least one show currently scheduled
|
||||
* or in the future.
|
||||
*/
|
||||
private static function isFutureOrCurrentShowScheduled()
|
||||
{
|
||||
$futureShow = self::getNextFutureShow();
|
||||
$currentShow = self::getCurrentShow();
|
||||
|
||||
if (is_null($futureShow) && is_null($currentShow)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static function isCurrentShowEmpty()
|
||||
{
|
||||
$currentShow = self::getCurrentShow();
|
||||
|
||||
if (is_null($currentShow)) {
|
||||
return false;
|
||||
} else {
|
||||
$now = new DateTime("now", new DateTimeZone("UTC"));
|
||||
$scheduledTracks = CcScheduleQuery::create()
|
||||
->filterByDbInstanceId($currentShow->getDbId())
|
||||
->filterByDbEnds($now, Criteria::GREATER_EQUAL)
|
||||
->find();
|
||||
if ($scheduledTracks->count() == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function isNextShowEmpty()
|
||||
{
|
||||
$futureShow = self::getNextFutureShow();
|
||||
|
||||
if (is_null($futureShow)) {
|
||||
return false;
|
||||
} else {
|
||||
$now = new DateTime("now", new DateTimeZone("UTC"));
|
||||
$scheduledTracks = CcScheduleQuery::create()
|
||||
->filterByDbInstanceId($futureShow->getDbId())
|
||||
->filterByDbStarts($now, Criteria::GREATER_EQUAL)
|
||||
->find();
|
||||
if ($scheduledTracks->count() == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function getCurrentShow()
|
||||
{
|
||||
$now = new DateTime("now", new DateTimeZone("UTC"));
|
||||
|
||||
return CcShowInstancesQuery::create()
|
||||
->filterByDbStarts($now, Criteria::LESS_THAN)
|
||||
->filterByDbEnds($now, Criteria::GREATER_THAN)
|
||||
->filterByDbModifiedInstance(false)
|
||||
->findOne();
|
||||
}
|
||||
|
||||
private static function getNextFutureShow()
|
||||
{
|
||||
$now = new DateTime("now", new DateTimeZone("UTC"));
|
||||
|
||||
return CcShowInstancesQuery::create()
|
||||
->filterByDbStarts($now, Criteria::GREATER_THAN)
|
||||
->filterByDbModifiedInstance(false)
|
||||
->orderByDbStarts()
|
||||
->findOne();
|
||||
}
|
||||
|
||||
private static function isCurrentShowLinked()
|
||||
{
|
||||
$currentShow = self::getCurrentShow();
|
||||
if (!is_null($currentShow)) {
|
||||
$show = CcShowQuery::create()
|
||||
->filterByDbId($currentShow->getDbShowId())
|
||||
->findOne();
|
||||
if ($show->isLinked()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
175
legacy/application/common/WidgetHelper.php
Normal file
175
legacy/application/common/WidgetHelper.php
Normal file
|
@ -0,0 +1,175 @@
|
|||
<?php
|
||||
|
||||
define("DAYS_PER_WEEK", 7);
|
||||
|
||||
class WidgetHelper
|
||||
{
|
||||
public static function getWeekInfo($userDefinedTimezone)
|
||||
{
|
||||
//weekStart is in station time.
|
||||
$weekStartDateTime = Application_Common_DateHelper::getWeekStartDateTime();
|
||||
|
||||
$dow = array("monday", "tuesday", "wednesday", "thursday", "friday",
|
||||
"saturday", "sunday", "nextmonday", "nexttuesday", "nextwednesday",
|
||||
"nextthursday", "nextfriday", "nextsaturday", "nextsunday");
|
||||
|
||||
$result = array();
|
||||
|
||||
// default to the station timezone
|
||||
$timezone = Application_Model_Preference::GetDefaultTimezone();
|
||||
if ($userDefinedTimezone) {
|
||||
$userDefinedTimezone = strtolower($userDefinedTimezone);
|
||||
// if the timezone defined by the user exists, use that
|
||||
if (array_key_exists($userDefinedTimezone, timezone_abbreviations_list())) {
|
||||
$timezone = $userDefinedTimezone;
|
||||
}
|
||||
}
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
|
||||
$weekStartDateTime->setTimezone($utcTimezone);
|
||||
$utcDayStart = $weekStartDateTime->format(DEFAULT_TIMESTAMP_FORMAT);
|
||||
for ($i = 0; $i < 14; $i++) {
|
||||
//have to be in station timezone when adding 1 day for daylight savings.
|
||||
$weekStartDateTime->setTimezone(new DateTimeZone($timezone));
|
||||
$weekStartDateTime->add(new DateInterval('P1D'));
|
||||
|
||||
//convert back to UTC to get the actual timestamp used for search.
|
||||
$weekStartDateTime->setTimezone($utcTimezone);
|
||||
|
||||
$utcDayEnd = $weekStartDateTime->format(DEFAULT_TIMESTAMP_FORMAT);
|
||||
$shows = Application_Model_Show::getNextShows($utcDayStart, "ALL", $utcDayEnd);
|
||||
$utcDayStart = $utcDayEnd;
|
||||
|
||||
// convert to user-defined timezone, or default to station
|
||||
Application_Common_DateHelper::convertTimestampsToTimezone(
|
||||
$shows,
|
||||
array("starts", "ends", "start_timestamp","end_timestamp"),
|
||||
$timezone
|
||||
);
|
||||
|
||||
$result[$dow[$i]] = $shows;
|
||||
}
|
||||
|
||||
// XSS exploit prevention
|
||||
SecurityHelper::htmlescape_recursive($result);
|
||||
|
||||
// convert image paths to point to api endpoints
|
||||
self::findAndConvertPaths($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a weeks worth of shows in UTC, and an info array of the current week's days.
|
||||
* Returns an array of two arrays:
|
||||
*
|
||||
* The first array is 7 consecutive week days, starting with the current day.
|
||||
*
|
||||
* The second array contains shows scheduled during the 7 week days in the first array.
|
||||
* The shows returned in this array are not in any order and are in UTC.
|
||||
*
|
||||
* We don't do any timezone conversion in this function on purpose. All timezone conversion
|
||||
* and show time ordering should be done on the frontend.
|
||||
*
|
||||
* *** This function does no HTML encoding. It is up to the caller to escape or encode the data appropriately.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getWeekInfoV2()
|
||||
{
|
||||
$weekStartDateTime = new DateTime("now", new DateTimeZone(Application_Model_Preference::GetTimezone()));
|
||||
|
||||
$result = array();
|
||||
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
|
||||
$weekStartDateTime->setTimezone($utcTimezone);
|
||||
|
||||
// Use this variable as the start date/time range when querying
|
||||
// for shows. We set it to 1 day prior to the beginning of the
|
||||
// schedule widget data to account for show date changes when
|
||||
// converting their start day/time to the client's local timezone.
|
||||
$showQueryDateRangeStart = clone $weekStartDateTime;
|
||||
$showQueryDateRangeStart->sub(new DateInterval("P1D"));
|
||||
$showQueryDateRangeStart->setTime(0, 0, 0);
|
||||
|
||||
for ($dayOfWeekCounter = 0; $dayOfWeekCounter < DAYS_PER_WEEK; $dayOfWeekCounter++) {
|
||||
$dateParse = date_parse($weekStartDateTime->format("Y-m-d H:i:s"));
|
||||
|
||||
// Associate data to its date so that when we convert this array
|
||||
// to json the order remains the same - in chronological order.
|
||||
// We also format the key to be for example: "2015-6-1" to match
|
||||
// javascript date formats so it's easier to sort the shows by day.
|
||||
$result["weekDays"][$weekStartDateTime->format("Y-n-j")] = array();
|
||||
$result["weekDays"][$weekStartDateTime->format("Y-n-j")]["dayOfMonth"] = $dateParse["day"];
|
||||
$result["weekDays"][$weekStartDateTime->format("Y-n-j")]["dayOfWeek"] = strtoupper(_(date("D", $weekStartDateTime->getTimestamp())));
|
||||
|
||||
// Shows scheduled for this day will get added to this array when
|
||||
// we convert the show times to the client's local timezone in weekly-program.phtml
|
||||
$result["weekDays"][$weekStartDateTime->format("Y-n-j")]["shows"] = array();
|
||||
|
||||
// $weekStartDateTime has to be in station timezone when adding 1 day for daylight savings.
|
||||
// TODO: is this necessary since we set the time to "00:00" ?
|
||||
$stationTimezone = Application_Model_Preference::GetDefaultTimezone();
|
||||
$weekStartDateTime->setTimezone(new DateTimeZone($stationTimezone));
|
||||
|
||||
$weekStartDateTime->add(new DateInterval('P1D'));
|
||||
|
||||
//convert back to UTC to get the actual timestamp used for search.
|
||||
$weekStartDateTime->setTimezone($utcTimezone);
|
||||
}
|
||||
|
||||
// Use this variable as the end date/time range when querying
|
||||
// for shows. We set it to 1 day after the end of the schedule
|
||||
// widget data to account for show date changes when converting
|
||||
// their start day/time to the client's local timezone.
|
||||
$showQueryDateRangeEnd = clone $weekStartDateTime;
|
||||
$showQueryDateRangeEnd->setTime(23, 59, 0);
|
||||
|
||||
$shows = Application_Model_Show::getNextShows(
|
||||
$showQueryDateRangeStart->format("Y-m-d H:i:s"),
|
||||
"ALL",
|
||||
$showQueryDateRangeEnd->format("Y-m-d H:i:s"));
|
||||
|
||||
// Convert each start and end time string to DateTime objects
|
||||
// so we can get a real timestamp. The timestamps will be used
|
||||
// to convert into javascript Date objects.
|
||||
foreach($shows as &$show) {
|
||||
$dtStarts = new DateTime($show["starts"], new DateTimeZone("UTC"));
|
||||
$show["starts_timestamp"] = $dtStarts->getTimestamp();
|
||||
|
||||
$dtEnds = new DateTime($show["ends"], new DateTimeZone("UTC"));
|
||||
$show["ends_timestamp"] = $dtEnds->getTimestamp();
|
||||
}
|
||||
$result["shows"] = $shows;
|
||||
|
||||
// convert image paths to point to api endpoints
|
||||
//TODO: do we need this here?
|
||||
self::findAndConvertPaths($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively find image_path keys in the various $result subarrays,
|
||||
* and convert them to point to the show-logo endpoint
|
||||
*
|
||||
* @param unknown $arr the array to search
|
||||
*/
|
||||
public static function findAndConvertPaths(&$arr)
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseDir = Application_Common_OsPath::formatDirectoryWithDirectorySeparators($CC_CONFIG['baseDir']);
|
||||
|
||||
foreach ($arr as &$a) {
|
||||
if (is_array($a)) {
|
||||
if (array_key_exists("image_path", $a)) {
|
||||
$a["image_path"] = $a["image_path"] && $a["image_path"] !== '' ?
|
||||
Application_Common_HTTPHelper::getStationUrl()."api/show-logo?id=".$a["id"] : '';
|
||||
} else {
|
||||
self::findAndConvertPaths($a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
legacy/application/common/enum/HttpRequestType.php
Normal file
12
legacy/application/common/enum/HttpRequestType.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class HttpRequestType {
|
||||
|
||||
const GET = "GET";
|
||||
const POST = "POST";
|
||||
const PUT = "PUT";
|
||||
const DELETE = "DELETE";
|
||||
const PATCH = "PATCH";
|
||||
const OPTIONS = "OPTIONS";
|
||||
|
||||
}
|
17
legacy/application/common/enum/MediaType.php
Normal file
17
legacy/application/common/enum/MediaType.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
final class MediaType {
|
||||
|
||||
const __default = self::FILE;
|
||||
|
||||
const FILE = 1;
|
||||
const PLAYLIST = 2;
|
||||
const BLOCK = 3;
|
||||
const WEBSTREAM = 4;
|
||||
const PODCAST = 5;
|
||||
|
||||
public static function getDefault() {
|
||||
return static::__default;
|
||||
}
|
||||
|
||||
}
|
31
legacy/application/common/interface/OAuth2.php
Normal file
31
legacy/application/common/interface/OAuth2.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
interface OAuth2 {
|
||||
|
||||
/**
|
||||
* Check whether an OAuth access token exists
|
||||
*
|
||||
* @return bool true if an access token exists, otherwise false
|
||||
*/
|
||||
public function hasAccessToken();
|
||||
|
||||
/**
|
||||
* Get the OAuth authorization URL
|
||||
*
|
||||
* @return string the authorization URL
|
||||
*/
|
||||
public function getAuthorizeUrl();
|
||||
|
||||
/**
|
||||
* Request a new OAuth access token and store it in CcPref
|
||||
*
|
||||
* @param $code string exchange authorization code for access token
|
||||
*/
|
||||
public function requestNewAccessToken($code);
|
||||
|
||||
/**
|
||||
* Regenerate the OAuth access token
|
||||
*/
|
||||
public function accessTokenRefresh();
|
||||
|
||||
}
|
27
legacy/application/common/interface/OAuth2Controller.php
Normal file
27
legacy/application/common/interface/OAuth2Controller.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
interface OAuth2Controller {
|
||||
|
||||
/**
|
||||
* Send user to a third-party service to authorize before being redirected
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function authorizeAction();
|
||||
|
||||
/**
|
||||
* Clear the previously saved request token from the preferences
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deauthorizeAction();
|
||||
|
||||
/**
|
||||
* Called when user successfully completes third-party authorization
|
||||
* Store the returned request token for future requests
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function redirectAction();
|
||||
|
||||
}
|
36
legacy/application/common/interface/Publish.php
Normal file
36
legacy/application/common/interface/Publish.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
interface Publish {
|
||||
|
||||
/**
|
||||
* Publish the file with the given file ID
|
||||
*
|
||||
* @param int $fileId ID of the file to be published
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function publish($fileId);
|
||||
|
||||
/**
|
||||
* Unpublish the file with the given file ID
|
||||
*
|
||||
* @param int $fileId ID of the file to be unpublished
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unpublish($fileId);
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the publication status for the file with the given ID
|
||||
*
|
||||
* @param int $fileId the ID of the file to check
|
||||
*
|
||||
* @return int 1 if the file has been published,
|
||||
* 0 if the file has yet to be published,
|
||||
* -1 if the file is in a pending state,
|
||||
* 2 if the source is unreachable (disconnected)
|
||||
*/
|
||||
public function getPublishStatus($fileId);
|
||||
|
||||
}
|
30
legacy/application/common/widgets/Table.php
Normal file
30
legacy/application/common/widgets/Table.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: asantoni
|
||||
* Date: 11/09/15
|
||||
* Time: 2:47 PM
|
||||
*/
|
||||
|
||||
class AirtimeTableView {
|
||||
|
||||
private static function _getTableJavaScriptDependencies() {
|
||||
return ['js/airtime/widgets/table.js',
|
||||
'js/datatables/js/jquery.dataTables.js',
|
||||
'js/datatables/plugin/dataTables.pluginAPI.js',
|
||||
'js/datatables/plugin/dataTables.fnSetFilteringDelay.js',
|
||||
'js/datatables/plugin/dataTables.ColVis.js',
|
||||
'js/datatables/plugin/dataTables.colReorder.min.js?',
|
||||
'js/datatables/plugin/dataTables.FixedColumns.js',
|
||||
'js/datatables/plugin/dataTables.FixedHeader.js',
|
||||
'js/datatables/plugin/dataTables.columnFilter.js?'];
|
||||
}
|
||||
|
||||
public static function injectTableJavaScriptDependencies(&$headScript, $baseUrl, $airtimeVersion)
|
||||
{
|
||||
$deps = self::_getTableJavaScriptDependencies();
|
||||
for ($i = 0; $i < count($deps); $i++) {
|
||||
$headScript->appendFile($baseUrl . $deps[$i] .'?'. $airtimeVersion, 'text/javascript');
|
||||
}
|
||||
}
|
||||
}
|
94
legacy/application/configs/ACL.php
Normal file
94
legacy/application/configs/ACL.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
|
||||
$ccAcl = new Zend_Acl();
|
||||
|
||||
$ccAcl->addRole(new Zend_Acl_Role('G'))
|
||||
->addRole(new Zend_Acl_Role('H'), 'G')
|
||||
->addRole(new Zend_Acl_Role('P'), 'H')
|
||||
->addRole(new Zend_Acl_Role('A'), 'P')
|
||||
->addRole(new Zend_Acl_Role('S'), 'A');
|
||||
|
||||
$ccAcl->add(new Zend_Acl_Resource('library'))
|
||||
->add(new Zend_Acl_Resource('index'))
|
||||
->add(new Zend_Acl_Resource('user'))
|
||||
->add(new Zend_Acl_Resource('tracktype'))
|
||||
->add(new Zend_Acl_Resource('error'))
|
||||
->add(new Zend_Acl_Resource('login'))
|
||||
->add(new Zend_Acl_Resource('playlist'))
|
||||
->add(new Zend_Acl_Resource('plupload'))
|
||||
->add(new Zend_Acl_Resource('schedule'))
|
||||
->add(new Zend_Acl_Resource('api'))
|
||||
->add(new Zend_Acl_Resource('systemstatus'))
|
||||
->add(new Zend_Acl_Resource('dashboard'))
|
||||
->add(new Zend_Acl_Resource('preference'))
|
||||
->add(new Zend_Acl_Resource('showbuilder'))
|
||||
->add(new Zend_Acl_Resource('playouthistory'))
|
||||
->add(new Zend_Acl_Resource('playouthistorytemplate'))
|
||||
->add(new Zend_Acl_Resource('listenerstat'))
|
||||
->add(new Zend_Acl_Resource('showlistenerstat'))
|
||||
->add(new Zend_Acl_Resource('usersettings'))
|
||||
->add(new Zend_Acl_Resource('audiopreview'))
|
||||
->add(new Zend_Acl_Resource('webstream'))
|
||||
->add(new Zend_Acl_Resource('locale'))
|
||||
->add(new Zend_Acl_Resource('upgrade'))
|
||||
->add(new Zend_Acl_Resource('downgrade'))
|
||||
->add(new Zend_Acl_Resource('rest:media'))
|
||||
->add(new Zend_Acl_Resource('rest:show-image'))
|
||||
->add(new Zend_Acl_Resource('rest:podcast'))
|
||||
->add(new Zend_Acl_Resource('rest:podcast-episodes'))
|
||||
->add(new Zend_Acl_Resource('podcast'))
|
||||
->add(new Zend_Acl_Resource('player'))
|
||||
->add(new Zend_Acl_Resource('render'))
|
||||
->add(new Zend_Acl_Resource('embeddablewidgets'))
|
||||
->add(new Zend_Acl_Resource('setup'))
|
||||
->add(new Zend_Acl_Resource('feeds'));
|
||||
|
||||
/** Creating permissions */
|
||||
$ccAcl->allow('G', 'index')
|
||||
->allow('G', 'login')
|
||||
->allow('G', 'error')
|
||||
->allow('G', 'user', 'edit-user')
|
||||
->allow('G', 'showbuilder')
|
||||
->allow('G', 'render')
|
||||
->allow('G', 'api')
|
||||
->allow('G', 'schedule')
|
||||
->allow('G', 'dashboard')
|
||||
->allow('G', 'audiopreview')
|
||||
->allow('G', 'webstream')
|
||||
->allow('G', 'locale')
|
||||
->allow('G', 'upgrade')
|
||||
->allow('G', 'downgrade')
|
||||
->allow('G', 'rest:show-image', 'get')
|
||||
->allow('G', 'rest:media', 'get')
|
||||
->allow('G', 'rest:podcast', 'get')
|
||||
->allow('G', 'rest:podcast-episodes', 'get')
|
||||
->allow('G', 'setup')
|
||||
->allow('G', 'embeddablewidgets')
|
||||
->allow('G', 'feeds')
|
||||
->allow('H', 'rest:show-image')
|
||||
->allow('H', 'rest:media')
|
||||
->allow('H', 'rest:podcast')
|
||||
->allow('H', 'rest:podcast-episodes')
|
||||
->allow('H', 'podcast')
|
||||
->allow('H', 'preference', 'is-import-in-progress')
|
||||
->allow('H', 'usersettings')
|
||||
->allow('H', 'plupload')
|
||||
->allow('H', 'library')
|
||||
->allow('H', 'playlist')
|
||||
->allow('H', 'playouthistory')
|
||||
->allow('H', 'listenerstat')
|
||||
->allow('H', 'showlistenerstat')
|
||||
->allow('A', 'playouthistorytemplate')
|
||||
->allow('A', 'user')
|
||||
->allow('A', 'tracktype')
|
||||
->allow('A', 'systemstatus')
|
||||
->allow('A', 'preference');
|
||||
|
||||
|
||||
$aclPlugin = new Zend_Controller_Plugin_Acl($ccAcl);
|
||||
|
||||
Zend_View_Helper_Navigation_HelperAbstract::setDefaultAcl($ccAcl);
|
||||
|
||||
$front = Zend_Controller_Front::getInstance();
|
||||
$front->registerPlugin($aclPlugin);
|
34
legacy/application/configs/airtime-conf-production.php
Normal file
34
legacy/application/configs/airtime-conf-production.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
// This file generated by Propel 1.5.2 convert-conf target
|
||||
// from XML runtime conf file /home/james/src/airtime/airtime_mvc/build/runtime-conf.xml
|
||||
|
||||
/* The original name of this file is airtime-conf.php but since we need to make custom changes
|
||||
* to it I've renamed it so that our changes aren't removed everytime we regenerate a database schema.
|
||||
* our custom changes requires the database parameters to be loaded from /etc/airtime/airtime.conf so
|
||||
* that the user can customize these.
|
||||
*/
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$dbhost = $CC_CONFIG['dsn']['hostspec'];
|
||||
$dbname = $CC_CONFIG['dsn']['database'];
|
||||
$dbuser = $CC_CONFIG['dsn']['username'];
|
||||
$dbpass = $CC_CONFIG['dsn']['password'];
|
||||
|
||||
$conf = array (
|
||||
'datasources' =>
|
||||
array (
|
||||
'airtime' =>
|
||||
array (
|
||||
'adapter' => 'pgsql',
|
||||
'connection' =>
|
||||
array (
|
||||
'dsn' => "pgsql:host=$dbhost;port=5432;dbname=$dbname;user=$dbuser;password=$dbpass",
|
||||
),
|
||||
),
|
||||
'default' => 'airtime',
|
||||
),
|
||||
'generator_version' => '1.7.0',
|
||||
);
|
||||
$conf['classmap'] = include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'classmap-airtime-conf.php');
|
||||
return $conf;
|
28
legacy/application/configs/airtime-conf.php
Normal file
28
legacy/application/configs/airtime-conf.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
// This file generated by Propel 1.7.0 convert-conf target
|
||||
// from XML runtime conf file /vagrant/airtime_mvc/build/runtime-conf.xml
|
||||
$conf = array (
|
||||
'datasources' =>
|
||||
array (
|
||||
'airtime' =>
|
||||
array (
|
||||
'adapter' => 'pgsql',
|
||||
'connection' =>
|
||||
array (
|
||||
'dsn' => 'pgsql:host=localhost;port=5432;dbname=airtime;user=airtime;password=airtime',
|
||||
),
|
||||
),
|
||||
'airtime_test' =>
|
||||
array (
|
||||
'adapter' => 'pgsql',
|
||||
'connection' =>
|
||||
array (
|
||||
'dsn' => 'pgsql:host=localhost;port=5432;dbname=airtime_test;user=airtime;password=airtime',
|
||||
),
|
||||
),
|
||||
'default' => 'airtime',
|
||||
),
|
||||
'generator_version' => '1.7.0',
|
||||
);
|
||||
$conf['classmap'] = include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'classmap-airtime-conf.php');
|
||||
return $conf;
|
33
legacy/application/configs/application.ini
Normal file
33
legacy/application/configs/application.ini
Normal file
|
@ -0,0 +1,33 @@
|
|||
[production]
|
||||
phpSettings.display_startup_errors = 0
|
||||
phpSettings.display_errors = 0
|
||||
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
|
||||
bootstrap.class = "Bootstrap"
|
||||
appnamespace = "Application"
|
||||
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
|
||||
resources.frontController.params.displayExceptions = 0
|
||||
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
|
||||
resources.frontController.plugins.putHandler = "Zend_Controller_Plugin_PutHandler"
|
||||
resources.modules[] = ""
|
||||
;load everything in the modules directory including models
|
||||
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
|
||||
resources.modules[] = ""
|
||||
resources.view[] =
|
||||
; These are no longer needed. They are specified in /etc/airtime/airtime.conf:
|
||||
;resources.db.adapter = "Pdo_Pgsql"
|
||||
;resources.db.params.charset = "utf8"
|
||||
;resources.db.params.host = "localhost"
|
||||
;resources.db.params.username = "airtime"
|
||||
;resources.db.params.password = "airtime"
|
||||
;resources.db.params.dbname = "airtime"
|
||||
|
||||
[staging : production]
|
||||
|
||||
[testing : production]
|
||||
phpSettings.display_startup_errors = 1
|
||||
phpSettings.display_errors = 1
|
||||
|
||||
[development : production]
|
||||
phpSettings.display_startup_errors = 1
|
||||
phpSettings.display_errors = 1
|
||||
resources.frontController.params.displayExceptions = 1
|
284
legacy/application/configs/classmap-airtime-conf.php
Normal file
284
legacy/application/configs/classmap-airtime-conf.php
Normal file
|
@ -0,0 +1,284 @@
|
|||
<?php
|
||||
// This file generated by Propel 1.7.0 convert-conf target
|
||||
return array (
|
||||
'BaseCcBlock' => 'airtime/om/BaseCcBlock.php',
|
||||
'BaseCcBlockPeer' => 'airtime/om/BaseCcBlockPeer.php',
|
||||
'BaseCcBlockQuery' => 'airtime/om/BaseCcBlockQuery.php',
|
||||
'BaseCcBlockcontents' => 'airtime/om/BaseCcBlockcontents.php',
|
||||
'BaseCcBlockcontentsPeer' => 'airtime/om/BaseCcBlockcontentsPeer.php',
|
||||
'BaseCcBlockcontentsQuery' => 'airtime/om/BaseCcBlockcontentsQuery.php',
|
||||
'BaseCcBlockcriteria' => 'airtime/om/BaseCcBlockcriteria.php',
|
||||
'BaseCcBlockcriteriaPeer' => 'airtime/om/BaseCcBlockcriteriaPeer.php',
|
||||
'BaseCcBlockcriteriaQuery' => 'airtime/om/BaseCcBlockcriteriaQuery.php',
|
||||
'BaseCcCountry' => 'airtime/om/BaseCcCountry.php',
|
||||
'BaseCcCountryPeer' => 'airtime/om/BaseCcCountryPeer.php',
|
||||
'BaseCcCountryQuery' => 'airtime/om/BaseCcCountryQuery.php',
|
||||
'BaseCcFiles' => 'airtime/om/BaseCcFiles.php',
|
||||
'BaseCcFilesPeer' => 'airtime/om/BaseCcFilesPeer.php',
|
||||
'BaseCcFilesQuery' => 'airtime/om/BaseCcFilesQuery.php',
|
||||
'BaseCcListenerCount' => 'airtime/om/BaseCcListenerCount.php',
|
||||
'BaseCcListenerCountPeer' => 'airtime/om/BaseCcListenerCountPeer.php',
|
||||
'BaseCcListenerCountQuery' => 'airtime/om/BaseCcListenerCountQuery.php',
|
||||
'BaseCcLiveLog' => 'airtime/om/BaseCcLiveLog.php',
|
||||
'BaseCcLiveLogPeer' => 'airtime/om/BaseCcLiveLogPeer.php',
|
||||
'BaseCcLiveLogQuery' => 'airtime/om/BaseCcLiveLogQuery.php',
|
||||
'BaseCcLoginAttempts' => 'airtime/om/BaseCcLoginAttempts.php',
|
||||
'BaseCcLoginAttemptsPeer' => 'airtime/om/BaseCcLoginAttemptsPeer.php',
|
||||
'BaseCcLoginAttemptsQuery' => 'airtime/om/BaseCcLoginAttemptsQuery.php',
|
||||
'BaseCcMountName' => 'airtime/om/BaseCcMountName.php',
|
||||
'BaseCcMountNamePeer' => 'airtime/om/BaseCcMountNamePeer.php',
|
||||
'BaseCcMountNameQuery' => 'airtime/om/BaseCcMountNameQuery.php',
|
||||
'BaseCcMusicDirs' => 'airtime/om/BaseCcMusicDirs.php',
|
||||
'BaseCcMusicDirsPeer' => 'airtime/om/BaseCcMusicDirsPeer.php',
|
||||
'BaseCcMusicDirsQuery' => 'airtime/om/BaseCcMusicDirsQuery.php',
|
||||
'BaseCcPerms' => 'airtime/om/BaseCcPerms.php',
|
||||
'BaseCcPermsPeer' => 'airtime/om/BaseCcPermsPeer.php',
|
||||
'BaseCcPermsQuery' => 'airtime/om/BaseCcPermsQuery.php',
|
||||
'BaseCcPlaylist' => 'airtime/om/BaseCcPlaylist.php',
|
||||
'BaseCcPlaylistPeer' => 'airtime/om/BaseCcPlaylistPeer.php',
|
||||
'BaseCcPlaylistQuery' => 'airtime/om/BaseCcPlaylistQuery.php',
|
||||
'BaseCcPlaylistcontents' => 'airtime/om/BaseCcPlaylistcontents.php',
|
||||
'BaseCcPlaylistcontentsPeer' => 'airtime/om/BaseCcPlaylistcontentsPeer.php',
|
||||
'BaseCcPlaylistcontentsQuery' => 'airtime/om/BaseCcPlaylistcontentsQuery.php',
|
||||
'BaseCcPlayoutHistory' => 'airtime/om/BaseCcPlayoutHistory.php',
|
||||
'BaseCcPlayoutHistoryMetaData' => 'airtime/om/BaseCcPlayoutHistoryMetaData.php',
|
||||
'BaseCcPlayoutHistoryMetaDataPeer' => 'airtime/om/BaseCcPlayoutHistoryMetaDataPeer.php',
|
||||
'BaseCcPlayoutHistoryMetaDataQuery' => 'airtime/om/BaseCcPlayoutHistoryMetaDataQuery.php',
|
||||
'BaseCcPlayoutHistoryPeer' => 'airtime/om/BaseCcPlayoutHistoryPeer.php',
|
||||
'BaseCcPlayoutHistoryQuery' => 'airtime/om/BaseCcPlayoutHistoryQuery.php',
|
||||
'BaseCcPlayoutHistoryTemplate' => 'airtime/om/BaseCcPlayoutHistoryTemplate.php',
|
||||
'BaseCcPlayoutHistoryTemplateField' => 'airtime/om/BaseCcPlayoutHistoryTemplateField.php',
|
||||
'BaseCcPlayoutHistoryTemplateFieldPeer' => 'airtime/om/BaseCcPlayoutHistoryTemplateFieldPeer.php',
|
||||
'BaseCcPlayoutHistoryTemplateFieldQuery' => 'airtime/om/BaseCcPlayoutHistoryTemplateFieldQuery.php',
|
||||
'BaseCcPlayoutHistoryTemplatePeer' => 'airtime/om/BaseCcPlayoutHistoryTemplatePeer.php',
|
||||
'BaseCcPlayoutHistoryTemplateQuery' => 'airtime/om/BaseCcPlayoutHistoryTemplateQuery.php',
|
||||
'BaseCcPref' => 'airtime/om/BaseCcPref.php',
|
||||
'BaseCcPrefPeer' => 'airtime/om/BaseCcPrefPeer.php',
|
||||
'BaseCcPrefQuery' => 'airtime/om/BaseCcPrefQuery.php',
|
||||
'BaseCcSchedule' => 'airtime/om/BaseCcSchedule.php',
|
||||
'BaseCcSchedulePeer' => 'airtime/om/BaseCcSchedulePeer.php',
|
||||
'BaseCcScheduleQuery' => 'airtime/om/BaseCcScheduleQuery.php',
|
||||
'BaseCcServiceRegister' => 'airtime/om/BaseCcServiceRegister.php',
|
||||
'BaseCcServiceRegisterPeer' => 'airtime/om/BaseCcServiceRegisterPeer.php',
|
||||
'BaseCcServiceRegisterQuery' => 'airtime/om/BaseCcServiceRegisterQuery.php',
|
||||
'BaseCcSess' => 'airtime/om/BaseCcSess.php',
|
||||
'BaseCcSessPeer' => 'airtime/om/BaseCcSessPeer.php',
|
||||
'BaseCcSessQuery' => 'airtime/om/BaseCcSessQuery.php',
|
||||
'BaseCcShow' => 'airtime/om/BaseCcShow.php',
|
||||
'BaseCcShowDays' => 'airtime/om/BaseCcShowDays.php',
|
||||
'BaseCcShowDaysPeer' => 'airtime/om/BaseCcShowDaysPeer.php',
|
||||
'BaseCcShowDaysQuery' => 'airtime/om/BaseCcShowDaysQuery.php',
|
||||
'BaseCcShowHosts' => 'airtime/om/BaseCcShowHosts.php',
|
||||
'BaseCcShowHostsPeer' => 'airtime/om/BaseCcShowHostsPeer.php',
|
||||
'BaseCcShowHostsQuery' => 'airtime/om/BaseCcShowHostsQuery.php',
|
||||
'BaseCcShowInstances' => 'airtime/om/BaseCcShowInstances.php',
|
||||
'BaseCcShowInstancesPeer' => 'airtime/om/BaseCcShowInstancesPeer.php',
|
||||
'BaseCcShowInstancesQuery' => 'airtime/om/BaseCcShowInstancesQuery.php',
|
||||
'BaseCcShowPeer' => 'airtime/om/BaseCcShowPeer.php',
|
||||
'BaseCcShowQuery' => 'airtime/om/BaseCcShowQuery.php',
|
||||
'BaseCcShowRebroadcast' => 'airtime/om/BaseCcShowRebroadcast.php',
|
||||
'BaseCcShowRebroadcastPeer' => 'airtime/om/BaseCcShowRebroadcastPeer.php',
|
||||
'BaseCcShowRebroadcastQuery' => 'airtime/om/BaseCcShowRebroadcastQuery.php',
|
||||
'BaseCcStreamSetting' => 'airtime/om/BaseCcStreamSetting.php',
|
||||
'BaseCcStreamSettingPeer' => 'airtime/om/BaseCcStreamSettingPeer.php',
|
||||
'BaseCcStreamSettingQuery' => 'airtime/om/BaseCcStreamSettingQuery.php',
|
||||
'BaseCcTracktypes' => 'airtime/om/BaseCcTracktypes.php',
|
||||
'BaseCcTracktypesPeer' => 'airtime/om/BaseCcTracktypesPeer.php',
|
||||
'BaseCcTracktypesQuery' => 'airtime/om/BaseCcTracktypesQuery.php',
|
||||
'BaseCcSubjs' => 'airtime/om/BaseCcSubjs.php',
|
||||
'BaseCcSubjsPeer' => 'airtime/om/BaseCcSubjsPeer.php',
|
||||
'BaseCcSubjsQuery' => 'airtime/om/BaseCcSubjsQuery.php',
|
||||
'BaseCcSubjsToken' => 'airtime/om/BaseCcSubjsToken.php',
|
||||
'BaseCcSubjsTokenPeer' => 'airtime/om/BaseCcSubjsTokenPeer.php',
|
||||
'BaseCcSubjsTokenQuery' => 'airtime/om/BaseCcSubjsTokenQuery.php',
|
||||
'BaseCcTimestamp' => 'airtime/om/BaseCcTimestamp.php',
|
||||
'BaseCcTimestampPeer' => 'airtime/om/BaseCcTimestampPeer.php',
|
||||
'BaseCcTimestampQuery' => 'airtime/om/BaseCcTimestampQuery.php',
|
||||
'BaseCcWebstream' => 'airtime/om/BaseCcWebstream.php',
|
||||
'BaseCcWebstreamMetadata' => 'airtime/om/BaseCcWebstreamMetadata.php',
|
||||
'BaseCcWebstreamMetadataPeer' => 'airtime/om/BaseCcWebstreamMetadataPeer.php',
|
||||
'BaseCcWebstreamMetadataQuery' => 'airtime/om/BaseCcWebstreamMetadataQuery.php',
|
||||
'BaseCcWebstreamPeer' => 'airtime/om/BaseCcWebstreamPeer.php',
|
||||
'BaseCcWebstreamQuery' => 'airtime/om/BaseCcWebstreamQuery.php',
|
||||
'BaseCeleryTasks' => 'airtime/om/BaseCeleryTasks.php',
|
||||
'BaseCeleryTasksPeer' => 'airtime/om/BaseCeleryTasksPeer.php',
|
||||
'BaseCeleryTasksQuery' => 'airtime/om/BaseCeleryTasksQuery.php',
|
||||
'BaseCloudFile' => 'airtime/om/BaseCloudFile.php',
|
||||
'BaseCloudFilePeer' => 'airtime/om/BaseCloudFilePeer.php',
|
||||
'BaseCloudFileQuery' => 'airtime/om/BaseCloudFileQuery.php',
|
||||
'BaseImportedPodcast' => 'airtime/om/BaseImportedPodcast.php',
|
||||
'BaseImportedPodcastPeer' => 'airtime/om/BaseImportedPodcastPeer.php',
|
||||
'BaseImportedPodcastQuery' => 'airtime/om/BaseImportedPodcastQuery.php',
|
||||
'BasePodcast' => 'airtime/om/BasePodcast.php',
|
||||
'BasePodcastEpisodes' => 'airtime/om/BasePodcastEpisodes.php',
|
||||
'BasePodcastEpisodesPeer' => 'airtime/om/BasePodcastEpisodesPeer.php',
|
||||
'BasePodcastEpisodesQuery' => 'airtime/om/BasePodcastEpisodesQuery.php',
|
||||
'BasePodcastPeer' => 'airtime/om/BasePodcastPeer.php',
|
||||
'BasePodcastQuery' => 'airtime/om/BasePodcastQuery.php',
|
||||
'BaseStationPodcast' => 'airtime/om/BaseStationPodcast.php',
|
||||
'BaseStationPodcastPeer' => 'airtime/om/BaseStationPodcastPeer.php',
|
||||
'BaseStationPodcastQuery' => 'airtime/om/BaseStationPodcastQuery.php',
|
||||
'BaseThirdPartyTrackReferences' => 'airtime/om/BaseThirdPartyTrackReferences.php',
|
||||
'BaseThirdPartyTrackReferencesPeer' => 'airtime/om/BaseThirdPartyTrackReferencesPeer.php',
|
||||
'BaseThirdPartyTrackReferencesQuery' => 'airtime/om/BaseThirdPartyTrackReferencesQuery.php',
|
||||
'CcBlock' => 'airtime/CcBlock.php',
|
||||
'CcBlockPeer' => 'airtime/CcBlockPeer.php',
|
||||
'CcBlockQuery' => 'airtime/CcBlockQuery.php',
|
||||
'CcBlockTableMap' => 'airtime/map/CcBlockTableMap.php',
|
||||
'CcBlockcontents' => 'airtime/CcBlockcontents.php',
|
||||
'CcBlockcontentsPeer' => 'airtime/CcBlockcontentsPeer.php',
|
||||
'CcBlockcontentsQuery' => 'airtime/CcBlockcontentsQuery.php',
|
||||
'CcBlockcontentsTableMap' => 'airtime/map/CcBlockcontentsTableMap.php',
|
||||
'CcBlockcriteria' => 'airtime/CcBlockcriteria.php',
|
||||
'CcBlockcriteriaPeer' => 'airtime/CcBlockcriteriaPeer.php',
|
||||
'CcBlockcriteriaQuery' => 'airtime/CcBlockcriteriaQuery.php',
|
||||
'CcBlockcriteriaTableMap' => 'airtime/map/CcBlockcriteriaTableMap.php',
|
||||
'CcCountry' => 'airtime/CcCountry.php',
|
||||
'CcCountryPeer' => 'airtime/CcCountryPeer.php',
|
||||
'CcCountryQuery' => 'airtime/CcCountryQuery.php',
|
||||
'CcCountryTableMap' => 'airtime/map/CcCountryTableMap.php',
|
||||
'CcFiles' => 'airtime/CcFiles.php',
|
||||
'CcFilesPeer' => 'airtime/CcFilesPeer.php',
|
||||
'CcFilesQuery' => 'airtime/CcFilesQuery.php',
|
||||
'CcFilesTableMap' => 'airtime/map/CcFilesTableMap.php',
|
||||
'CcListenerCount' => 'airtime/CcListenerCount.php',
|
||||
'CcListenerCountPeer' => 'airtime/CcListenerCountPeer.php',
|
||||
'CcListenerCountQuery' => 'airtime/CcListenerCountQuery.php',
|
||||
'CcListenerCountTableMap' => 'airtime/map/CcListenerCountTableMap.php',
|
||||
'CcLiveLog' => 'airtime/CcLiveLog.php',
|
||||
'CcLiveLogPeer' => 'airtime/CcLiveLogPeer.php',
|
||||
'CcLiveLogQuery' => 'airtime/CcLiveLogQuery.php',
|
||||
'CcLiveLogTableMap' => 'airtime/map/CcLiveLogTableMap.php',
|
||||
'CcLoginAttempts' => 'airtime/CcLoginAttempts.php',
|
||||
'CcLoginAttemptsPeer' => 'airtime/CcLoginAttemptsPeer.php',
|
||||
'CcLoginAttemptsQuery' => 'airtime/CcLoginAttemptsQuery.php',
|
||||
'CcLoginAttemptsTableMap' => 'airtime/map/CcLoginAttemptsTableMap.php',
|
||||
'CcMountName' => 'airtime/CcMountName.php',
|
||||
'CcMountNamePeer' => 'airtime/CcMountNamePeer.php',
|
||||
'CcMountNameQuery' => 'airtime/CcMountNameQuery.php',
|
||||
'CcMountNameTableMap' => 'airtime/map/CcMountNameTableMap.php',
|
||||
'CcMusicDirs' => 'airtime/CcMusicDirs.php',
|
||||
'CcMusicDirsPeer' => 'airtime/CcMusicDirsPeer.php',
|
||||
'CcMusicDirsQuery' => 'airtime/CcMusicDirsQuery.php',
|
||||
'CcMusicDirsTableMap' => 'airtime/map/CcMusicDirsTableMap.php',
|
||||
'CcPerms' => 'airtime/CcPerms.php',
|
||||
'CcPermsPeer' => 'airtime/CcPermsPeer.php',
|
||||
'CcPermsQuery' => 'airtime/CcPermsQuery.php',
|
||||
'CcPermsTableMap' => 'airtime/map/CcPermsTableMap.php',
|
||||
'CcPlaylist' => 'airtime/CcPlaylist.php',
|
||||
'CcPlaylistPeer' => 'airtime/CcPlaylistPeer.php',
|
||||
'CcPlaylistQuery' => 'airtime/CcPlaylistQuery.php',
|
||||
'CcPlaylistTableMap' => 'airtime/map/CcPlaylistTableMap.php',
|
||||
'CcPlaylistcontents' => 'airtime/CcPlaylistcontents.php',
|
||||
'CcPlaylistcontentsPeer' => 'airtime/CcPlaylistcontentsPeer.php',
|
||||
'CcPlaylistcontentsQuery' => 'airtime/CcPlaylistcontentsQuery.php',
|
||||
'CcPlaylistcontentsTableMap' => 'airtime/map/CcPlaylistcontentsTableMap.php',
|
||||
'CcPlayoutHistory' => 'airtime/CcPlayoutHistory.php',
|
||||
'CcPlayoutHistoryMetaData' => 'airtime/CcPlayoutHistoryMetaData.php',
|
||||
'CcPlayoutHistoryMetaDataPeer' => 'airtime/CcPlayoutHistoryMetaDataPeer.php',
|
||||
'CcPlayoutHistoryMetaDataQuery' => 'airtime/CcPlayoutHistoryMetaDataQuery.php',
|
||||
'CcPlayoutHistoryMetaDataTableMap' => 'airtime/map/CcPlayoutHistoryMetaDataTableMap.php',
|
||||
'CcPlayoutHistoryPeer' => 'airtime/CcPlayoutHistoryPeer.php',
|
||||
'CcPlayoutHistoryQuery' => 'airtime/CcPlayoutHistoryQuery.php',
|
||||
'CcPlayoutHistoryTableMap' => 'airtime/map/CcPlayoutHistoryTableMap.php',
|
||||
'CcPlayoutHistoryTemplate' => 'airtime/CcPlayoutHistoryTemplate.php',
|
||||
'CcPlayoutHistoryTemplateField' => 'airtime/CcPlayoutHistoryTemplateField.php',
|
||||
'CcPlayoutHistoryTemplateFieldPeer' => 'airtime/CcPlayoutHistoryTemplateFieldPeer.php',
|
||||
'CcPlayoutHistoryTemplateFieldQuery' => 'airtime/CcPlayoutHistoryTemplateFieldQuery.php',
|
||||
'CcPlayoutHistoryTemplateFieldTableMap' => 'airtime/map/CcPlayoutHistoryTemplateFieldTableMap.php',
|
||||
'CcPlayoutHistoryTemplatePeer' => 'airtime/CcPlayoutHistoryTemplatePeer.php',
|
||||
'CcPlayoutHistoryTemplateQuery' => 'airtime/CcPlayoutHistoryTemplateQuery.php',
|
||||
'CcPlayoutHistoryTemplateTableMap' => 'airtime/map/CcPlayoutHistoryTemplateTableMap.php',
|
||||
'CcPref' => 'airtime/CcPref.php',
|
||||
'CcPrefPeer' => 'airtime/CcPrefPeer.php',
|
||||
'CcPrefQuery' => 'airtime/CcPrefQuery.php',
|
||||
'CcPrefTableMap' => 'airtime/map/CcPrefTableMap.php',
|
||||
'CcSchedule' => 'airtime/CcSchedule.php',
|
||||
'CcSchedulePeer' => 'airtime/CcSchedulePeer.php',
|
||||
'CcScheduleQuery' => 'airtime/CcScheduleQuery.php',
|
||||
'CcScheduleTableMap' => 'airtime/map/CcScheduleTableMap.php',
|
||||
'CcServiceRegister' => 'airtime/CcServiceRegister.php',
|
||||
'CcServiceRegisterPeer' => 'airtime/CcServiceRegisterPeer.php',
|
||||
'CcServiceRegisterQuery' => 'airtime/CcServiceRegisterQuery.php',
|
||||
'CcServiceRegisterTableMap' => 'airtime/map/CcServiceRegisterTableMap.php',
|
||||
'CcSess' => 'airtime/CcSess.php',
|
||||
'CcSessPeer' => 'airtime/CcSessPeer.php',
|
||||
'CcSessQuery' => 'airtime/CcSessQuery.php',
|
||||
'CcSessTableMap' => 'airtime/map/CcSessTableMap.php',
|
||||
'CcShow' => 'airtime/CcShow.php',
|
||||
'CcShowDays' => 'airtime/CcShowDays.php',
|
||||
'CcShowDaysPeer' => 'airtime/CcShowDaysPeer.php',
|
||||
'CcShowDaysQuery' => 'airtime/CcShowDaysQuery.php',
|
||||
'CcShowDaysTableMap' => 'airtime/map/CcShowDaysTableMap.php',
|
||||
'CcShowHosts' => 'airtime/CcShowHosts.php',
|
||||
'CcShowHostsPeer' => 'airtime/CcShowHostsPeer.php',
|
||||
'CcShowHostsQuery' => 'airtime/CcShowHostsQuery.php',
|
||||
'CcShowHostsTableMap' => 'airtime/map/CcShowHostsTableMap.php',
|
||||
'CcShowInstances' => 'airtime/CcShowInstances.php',
|
||||
'CcShowInstancesPeer' => 'airtime/CcShowInstancesPeer.php',
|
||||
'CcShowInstancesQuery' => 'airtime/CcShowInstancesQuery.php',
|
||||
'CcShowInstancesTableMap' => 'airtime/map/CcShowInstancesTableMap.php',
|
||||
'CcShowPeer' => 'airtime/CcShowPeer.php',
|
||||
'CcShowQuery' => 'airtime/CcShowQuery.php',
|
||||
'CcShowRebroadcast' => 'airtime/CcShowRebroadcast.php',
|
||||
'CcShowRebroadcastPeer' => 'airtime/CcShowRebroadcastPeer.php',
|
||||
'CcShowRebroadcastQuery' => 'airtime/CcShowRebroadcastQuery.php',
|
||||
'CcShowRebroadcastTableMap' => 'airtime/map/CcShowRebroadcastTableMap.php',
|
||||
'CcShowTableMap' => 'airtime/map/CcShowTableMap.php',
|
||||
'CcStreamSetting' => 'airtime/CcStreamSetting.php',
|
||||
'CcStreamSettingPeer' => 'airtime/CcStreamSettingPeer.php',
|
||||
'CcStreamSettingQuery' => 'airtime/CcStreamSettingQuery.php',
|
||||
'CcStreamSettingTableMap' => 'airtime/map/CcStreamSettingTableMap.php',
|
||||
'CcTracktypes' => 'airtime/CcTracktypes.php',
|
||||
'CcTracktypesPeer' => 'airtime/CcTracktypesPeer.php',
|
||||
'CcTracktypesQuery' => 'airtime/CcTracktypesQuery.php',
|
||||
'CcTracktypesTableMap' => 'airtime/map/CcTracktypesTableMap.php',
|
||||
'CcSubjs' => 'airtime/CcSubjs.php',
|
||||
'CcSubjsPeer' => 'airtime/CcSubjsPeer.php',
|
||||
'CcSubjsQuery' => 'airtime/CcSubjsQuery.php',
|
||||
'CcSubjsTableMap' => 'airtime/map/CcSubjsTableMap.php',
|
||||
'CcSubjsToken' => 'airtime/CcSubjsToken.php',
|
||||
'CcSubjsTokenPeer' => 'airtime/CcSubjsTokenPeer.php',
|
||||
'CcSubjsTokenQuery' => 'airtime/CcSubjsTokenQuery.php',
|
||||
'CcSubjsTokenTableMap' => 'airtime/map/CcSubjsTokenTableMap.php',
|
||||
'CcTimestamp' => 'airtime/CcTimestamp.php',
|
||||
'CcTimestampPeer' => 'airtime/CcTimestampPeer.php',
|
||||
'CcTimestampQuery' => 'airtime/CcTimestampQuery.php',
|
||||
'CcTimestampTableMap' => 'airtime/map/CcTimestampTableMap.php',
|
||||
'CcWebstream' => 'airtime/CcWebstream.php',
|
||||
'CcWebstreamMetadata' => 'airtime/CcWebstreamMetadata.php',
|
||||
'CcWebstreamMetadataPeer' => 'airtime/CcWebstreamMetadataPeer.php',
|
||||
'CcWebstreamMetadataQuery' => 'airtime/CcWebstreamMetadataQuery.php',
|
||||
'CcWebstreamMetadataTableMap' => 'airtime/map/CcWebstreamMetadataTableMap.php',
|
||||
'CcWebstreamPeer' => 'airtime/CcWebstreamPeer.php',
|
||||
'CcWebstreamQuery' => 'airtime/CcWebstreamQuery.php',
|
||||
'CcWebstreamTableMap' => 'airtime/map/CcWebstreamTableMap.php',
|
||||
'CeleryTasks' => 'airtime/CeleryTasks.php',
|
||||
'CeleryTasksPeer' => 'airtime/CeleryTasksPeer.php',
|
||||
'CeleryTasksQuery' => 'airtime/CeleryTasksQuery.php',
|
||||
'CeleryTasksTableMap' => 'airtime/map/CeleryTasksTableMap.php',
|
||||
'CloudFile' => 'airtime/CloudFile.php',
|
||||
'CloudFilePeer' => 'airtime/CloudFilePeer.php',
|
||||
'CloudFileQuery' => 'airtime/CloudFileQuery.php',
|
||||
'CloudFileTableMap' => 'airtime/map/CloudFileTableMap.php',
|
||||
'ImportedPodcast' => 'airtime/ImportedPodcast.php',
|
||||
'ImportedPodcastPeer' => 'airtime/ImportedPodcastPeer.php',
|
||||
'ImportedPodcastQuery' => 'airtime/ImportedPodcastQuery.php',
|
||||
'ImportedPodcastTableMap' => 'airtime/map/ImportedPodcastTableMap.php',
|
||||
'Podcast' => 'airtime/Podcast.php',
|
||||
'PodcastEpisodes' => 'airtime/PodcastEpisodes.php',
|
||||
'PodcastEpisodesPeer' => 'airtime/PodcastEpisodesPeer.php',
|
||||
'PodcastEpisodesQuery' => 'airtime/PodcastEpisodesQuery.php',
|
||||
'PodcastEpisodesTableMap' => 'airtime/map/PodcastEpisodesTableMap.php',
|
||||
'PodcastPeer' => 'airtime/PodcastPeer.php',
|
||||
'PodcastQuery' => 'airtime/PodcastQuery.php',
|
||||
'PodcastTableMap' => 'airtime/map/PodcastTableMap.php',
|
||||
'StationPodcast' => 'airtime/StationPodcast.php',
|
||||
'StationPodcastPeer' => 'airtime/StationPodcastPeer.php',
|
||||
'StationPodcastQuery' => 'airtime/StationPodcastQuery.php',
|
||||
'StationPodcastTableMap' => 'airtime/map/StationPodcastTableMap.php',
|
||||
'ThirdPartyTrackReferences' => 'airtime/ThirdPartyTrackReferences.php',
|
||||
'ThirdPartyTrackReferencesPeer' => 'airtime/ThirdPartyTrackReferencesPeer.php',
|
||||
'ThirdPartyTrackReferencesQuery' => 'airtime/ThirdPartyTrackReferencesQuery.php',
|
||||
'ThirdPartyTrackReferencesTableMap' => 'airtime/map/ThirdPartyTrackReferencesTableMap.php',
|
||||
);
|
122
legacy/application/configs/conf.php
Normal file
122
legacy/application/configs/conf.php
Normal file
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
/* THIS FILE IS NOT MEANT FOR CUSTOMIZING.
|
||||
* PLEASE EDIT THE FOLLOWING TO CHANGE YOUR CONFIG:
|
||||
* LIBRETIME_CONF_DIR/airtime.conf
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/constants.php';
|
||||
|
||||
class Config {
|
||||
private static $CC_CONFIG = null;
|
||||
private static $rootDir;
|
||||
public static function loadConfig() {
|
||||
|
||||
self::$rootDir = __DIR__."/../..";
|
||||
$CC_CONFIG = array(
|
||||
/* ================================================ storage configuration */
|
||||
"rootDir" => self::$rootDir
|
||||
);
|
||||
|
||||
//In the unit testing environment, LIBRETIME_CONF_DIR will our local airtime.conf in airtime_mvc/application/test/conf:
|
||||
$filename = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : LIBRETIME_CONF_DIR . "/airtime.conf";
|
||||
|
||||
$values = parse_ini_file($filename, true);
|
||||
|
||||
// Name of the web server user
|
||||
$CC_CONFIG['webServerUser'] = $values['general']['web_server_user'];
|
||||
$CC_CONFIG['rabbitmq'] = $values['rabbitmq'];
|
||||
|
||||
$CC_CONFIG['baseDir'] = $values['general']['base_dir'];
|
||||
$CC_CONFIG['baseUrl'] = $values['general']['base_url'];
|
||||
$CC_CONFIG['basePort'] = $values['general']['base_port'];
|
||||
$CC_CONFIG['stationId'] = $values['general']['station_id'];
|
||||
$CC_CONFIG['phpDir'] = $values['general']['airtime_dir'];
|
||||
$CC_CONFIG['forceSSL'] = isset($values['general']['force_ssl']) ? Config::isYesValue($values['general']['force_ssl']) : FALSE;
|
||||
$CC_CONFIG['protocol'] = isset($values['general']['protocol']) ? $values['general']['protocol'] : '';
|
||||
if (isset($values['general']['dev_env'])) {
|
||||
$CC_CONFIG['dev_env'] = $values['general']['dev_env'];
|
||||
} else {
|
||||
$CC_CONFIG['dev_env'] = 'production';
|
||||
}
|
||||
|
||||
$CC_CONFIG['auth'] = 'local';
|
||||
if (isset($values['general']['auth'])) {
|
||||
$CC_CONFIG['auth'] = $values['general']['auth'];
|
||||
}
|
||||
|
||||
//Backported static_base_dir default value into saas for now.
|
||||
if (array_key_exists('static_base_dir', $values['general'])) {
|
||||
$CC_CONFIG['staticBaseDir'] = $values['general']['static_base_dir'];
|
||||
} else {
|
||||
$CC_CONFIG['staticBaseDir'] = '/';
|
||||
}
|
||||
|
||||
// Tells us where file uploads will be uploaded to.
|
||||
// It will either be set to a cloud storage backend or local file storage.
|
||||
$CC_CONFIG["current_backend"] = $values["current_backend"]["storage_backend"];
|
||||
|
||||
$CC_CONFIG['cache_ahead_hours'] = $values['general']['cache_ahead_hours'];
|
||||
|
||||
// Database config
|
||||
$CC_CONFIG['dsn']['username'] = $values['database']['dbuser'];
|
||||
$CC_CONFIG['dsn']['password'] = $values['database']['dbpass'];
|
||||
$CC_CONFIG['dsn']['hostspec'] = $values['database']['host'];
|
||||
$CC_CONFIG['dsn']['phptype'] = 'pgsql';
|
||||
$CC_CONFIG['dsn']['database'] = $values['database']['dbname'];
|
||||
|
||||
$CC_CONFIG['apiKey'] = array($values['general']['api_key']);
|
||||
|
||||
if (isset($values['facebook']['facebook_app_id'])) {
|
||||
$CC_CONFIG['facebook-app-id'] = $values['facebook']['facebook_app_id'];
|
||||
$CC_CONFIG['facebook-app-url'] = $values['facebook']['facebook_app_url'];
|
||||
$CC_CONFIG['facebook-app-api-key'] = $values['facebook']['facebook_app_api_key'];
|
||||
}
|
||||
|
||||
// ldap config
|
||||
if (array_key_exists('ldap', $values)) {
|
||||
$CC_CONFIG['ldap_hostname'] = $values['ldap']['hostname'];
|
||||
$CC_CONFIG['ldap_binddn'] = $values['ldap']['binddn'];
|
||||
$CC_CONFIG['ldap_password'] = $values['ldap']['password'];
|
||||
$CC_CONFIG['ldap_account_domain'] = $values['ldap']['account_domain'];
|
||||
$CC_CONFIG['ldap_basedn'] = $values['ldap']['basedn'];
|
||||
$CC_CONFIG['ldap_groupmap_guest'] = $values['ldap']['groupmap_guest'];
|
||||
$CC_CONFIG['ldap_groupmap_host'] = $values['ldap']['groupmap_host'];
|
||||
$CC_CONFIG['ldap_groupmap_program_manager'] = $values['ldap']['groupmap_program_manager'];
|
||||
$CC_CONFIG['ldap_groupmap_admin'] = $values['ldap']['groupmap_admin'];
|
||||
$CC_CONFIG['ldap_groupmap_superadmin'] = $values['ldap']['groupmap_superadmin'];
|
||||
$CC_CONFIG['ldap_filter_field'] = $values['ldap']['filter_field'];
|
||||
}
|
||||
|
||||
if(isset($values['demo']['demo'])){
|
||||
$CC_CONFIG['demo'] = $values['demo']['demo'];
|
||||
}
|
||||
self::$CC_CONFIG = $CC_CONFIG;
|
||||
}
|
||||
|
||||
public static function setAirtimeVersion() {
|
||||
$version = @file_get_contents(self::$rootDir."/../VERSION");
|
||||
if (!$version) {
|
||||
// fallback to constant from constants.php if no other info is available
|
||||
$version = LIBRETIME_MAJOR_VERSION;
|
||||
}
|
||||
self::$CC_CONFIG['airtime_version'] = trim($version);
|
||||
}
|
||||
|
||||
public static function getConfig() {
|
||||
if (is_null(self::$CC_CONFIG)) {
|
||||
self::loadConfig();
|
||||
}
|
||||
return self::$CC_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string is one of 'yes' or 'true' (case insensitive).
|
||||
*/
|
||||
public static function isYesValue($value)
|
||||
{
|
||||
if (is_bool($value)) return $value;
|
||||
if (!is_string($value)) return false;
|
||||
|
||||
return in_array(strtolower($value), ['yes', 'true']);
|
||||
}
|
||||
}
|
288
legacy/application/configs/config-check.php
Normal file
288
legacy/application/configs/config-check.php
Normal file
|
@ -0,0 +1,288 @@
|
|||
<?php
|
||||
/*
|
||||
* We only get here after setup, or if there's an error in the configuration.
|
||||
*
|
||||
* Display a table to the user showing the necessary dependencies
|
||||
* (both PHP and binary) and the status of any application services,
|
||||
* along with steps to fix them if they're not found or misconfigured.
|
||||
*/
|
||||
|
||||
$phpDependencies = checkPhpDependencies();
|
||||
$externalServices = checkExternalServices();
|
||||
$postgres = $phpDependencies["postgres"];
|
||||
|
||||
$database = $externalServices["database"];
|
||||
$rabbitmq = $externalServices["rabbitmq"];
|
||||
|
||||
$pypo = $externalServices["pypo"];
|
||||
$liquidsoap = $externalServices["liquidsoap"];
|
||||
$analyzer = $externalServices["analyzer"];
|
||||
$celery = $externalServices['celery'];
|
||||
$api = $externalServices['api'];
|
||||
|
||||
$r1 = array_reduce($phpDependencies, "booleanReduce", true);
|
||||
$r2 = array_reduce($externalServices, "booleanReduce", true);
|
||||
$result = $r1 && $r2;
|
||||
?>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="css/bootstrap-3.3.1.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/setup/config-check.css">
|
||||
</head>
|
||||
<style>
|
||||
/*
|
||||
This is here because we're using the config-check css for
|
||||
both this page and the system status page
|
||||
*/
|
||||
html {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 2em;
|
||||
min-width: 600px;
|
||||
text-align: center;
|
||||
margin: 3em ;
|
||||
border: 1px solid lightgray;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<h2>
|
||||
<img class="logo" src="css/images/airtime_logo_jp.png" /><br/>
|
||||
<strong>Configuration Checklist</strong>
|
||||
</h2>
|
||||
|
||||
<?php
|
||||
if (!$result) {
|
||||
?>
|
||||
<br/>
|
||||
<h3 class="error">Looks like something went wrong!</h3>
|
||||
<p>
|
||||
Take a look at the checklist below for possible solutions. If you're tried the suggestions and are
|
||||
still experiencing issues, read the
|
||||
<a href="https://github.com/LibreTime/libretime/releases">release notes</a>,
|
||||
come <a href="https://discourse.libretime.org/">visit our discourse</a>
|
||||
or, check <a href="http://www.libretime.org/">the website and main docs</a>.
|
||||
</p>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<p>
|
||||
Your Airtime station is up and running! Get started by logging in with the default username and password: admin/admin
|
||||
</p>
|
||||
<button onclick="location = location.pathname;">Log in to Airtime!</button>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="component">
|
||||
Component
|
||||
</th>
|
||||
<th class="description">
|
||||
<strong>Description</strong>
|
||||
</th>
|
||||
<th class="solution">
|
||||
<strong>Status or Solution</strong>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
<div class="checklist">
|
||||
<table class="table table-striped">
|
||||
<caption class="caption">
|
||||
PHP Dependencies
|
||||
</caption>
|
||||
<tbody>
|
||||
<tr class="<?=$postgres ? 'success' : 'danger';?>">
|
||||
<td class="component">
|
||||
Postgres
|
||||
</td>
|
||||
<td class="description">
|
||||
PDO and PostgreSQL libraries
|
||||
</td>
|
||||
<td class="solution <?php if ($postgres) {echo 'check';?>">
|
||||
<?php
|
||||
} else {
|
||||
?>">
|
||||
Try running <code>sudo apt-get install php5-pgsql</code>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="table table-striped">
|
||||
<caption class="caption">
|
||||
External Services
|
||||
</caption>
|
||||
<tbody>
|
||||
<tr class="<?=$database ? 'success' : 'danger';?>">
|
||||
<td class="component">
|
||||
Database
|
||||
</td>
|
||||
<td class="description">
|
||||
Database configuration for Airtime
|
||||
</td>
|
||||
<td class="solution <?php if ($database) {echo 'check';?>">
|
||||
<?php
|
||||
} else {
|
||||
?>">
|
||||
Make sure you aren't missing any of the Postgres dependencies in the table above.
|
||||
If your dependencies check out, make sure your database configuration settings in
|
||||
<code>/etc/airtime.conf</code> are correct and the Airtime database was installed correctly.
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="<?=$rabbitmq ? 'success' : 'danger';?>">
|
||||
<td class="component">
|
||||
RabbitMQ
|
||||
</td>
|
||||
<td class="description">
|
||||
RabbitMQ configuration for Airtime
|
||||
</td>
|
||||
<td class="solution <?php if ($rabbitmq) {echo 'check';?>">
|
||||
<?php
|
||||
} else {
|
||||
?>">
|
||||
Make sure RabbitMQ is installed correctly, and that your settings in /etc/airtime/airtime.conf
|
||||
are correct. Try using <code>sudo rabbitmqctl list_users</code> and <code>sudo rabbitmqctl list_vhosts</code>
|
||||
to see if the airtime user (or your custom RabbitMQ user) exists, then checking that
|
||||
<code>sudo rabbitmqctl list_exchanges</code> contains entries for airtime-pypo and airtime-uploads.
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="<?=$analyzer ? 'success' : 'danger';?>">
|
||||
<td class="component">
|
||||
Media Analyzer
|
||||
</td>
|
||||
<td class="description">
|
||||
<?php echo _("LibreTime media analyzer service") ?>
|
||||
</td>
|
||||
<td class="solution <?php if ($analyzer) {echo 'check';?>">
|
||||
<?php
|
||||
} else {
|
||||
?>">
|
||||
<?php echo _("Check that the libretime-analyzer service is installed correctly in ") ?><code>/etc/systemd/system/</code>,
|
||||
<?php echo _(" and ensure that it's running with ") ?>
|
||||
<br/><code>systemctl status libretime-analyzer</code><br/>
|
||||
<?php echo _("If not, try ") ?><br/><code>sudo systemctl restart libretime-analyzer</code>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="<?=$pypo ? 'success' : 'danger';?>">
|
||||
<td class="component">
|
||||
Pypo
|
||||
</td>
|
||||
<td class="description">
|
||||
<?php echo _("LibreTime playout service") ?>
|
||||
</td>
|
||||
<td class="solution <?php if ($pypo) {echo 'check';?>">
|
||||
<?php
|
||||
} else {
|
||||
?>">
|
||||
<?php echo _("Check that the libretime-playout service is installed correctly in ") ?><code>/etc/systemd/system/</code>,
|
||||
<?php echo _(" and ensure that it's running with ") ?>
|
||||
<br/><code>systemctl status libretime-playout</code><br/>
|
||||
<?php echo _("If not, try ") ?><br/><code>sudo systemctl restart libretime-playout</code>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="<?=$liquidsoap ? 'success' : 'danger';?>">
|
||||
<td class="component">
|
||||
Liquidsoap
|
||||
</td>
|
||||
<td class="description">
|
||||
<?php echo _("LibreTime liquidsoap service") ?>
|
||||
</td>
|
||||
<td class="solution <?php if ($liquidsoap) {echo 'check';?>" >
|
||||
<?php
|
||||
} else {
|
||||
?>">
|
||||
<?php echo _("Check that the libretime-liquidsoap service is installed correctly in ") ?><code>/etc/systemd/system/</code>,
|
||||
<?php echo _(" and ensure that it's running with ") ?>
|
||||
<br/><code>systemctl status libretime-liquidsoap</code><br/>
|
||||
<?php echo _("If not, try ") ?><br/><code>sudo systemctl restart libretime-liquidsoap</code>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="<?=$celery ? 'success' : 'danger';?>">
|
||||
<td class="component">
|
||||
Celery
|
||||
</td>
|
||||
<td class="description">
|
||||
<?php echo _("LibreTime Celery Task service") ?>
|
||||
</td>
|
||||
<td class="solution <?php if ($celery) {echo 'check';?>" >
|
||||
<?php
|
||||
} else {
|
||||
?>">
|
||||
<?php echo _("Check that the libretime-celery service is installed correctly in ") ?><code>/etc/systemd/system/</code>,
|
||||
<?php echo _(" and ensure that it's running with ") ?>
|
||||
<br/><code>systemctl status libretime-celery</code><br/>
|
||||
<?php echo _("If not, try ") ?><br/><code>sudo systemctl restart libretime-celery</code>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="<?=$api ? 'success' : 'danger';?>">
|
||||
<td class="component">
|
||||
API
|
||||
</td>
|
||||
<td class="description">
|
||||
<?php echo _("LibreTime API service") ?>
|
||||
</td>
|
||||
<td class="solution <?php if ($api) {echo 'check';?>" >
|
||||
<?php
|
||||
} else {
|
||||
?>">
|
||||
<?php echo _("Check that the libretime-api service is installed correctly in ") ?><code>/etc/init.d/</code>,
|
||||
<?php echo _(" and ensure that it's running with ") ?>
|
||||
<br/><code>systemctl status libretime-api</code><br/>
|
||||
<?php echo _("If not, try ") ?><br/><code>sudo systemctl restart libretime-api</code>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<h3>
|
||||
PHP Extension List
|
||||
</h3>
|
||||
<p>
|
||||
<?php
|
||||
global $extensions;
|
||||
$first = true;
|
||||
foreach ($extensions as $ext) {
|
||||
if (!$first) {
|
||||
echo " | ";
|
||||
} else {
|
||||
$first = false;
|
||||
}
|
||||
echo $ext;
|
||||
}
|
||||
?>
|
||||
</p>
|
||||
</div>
|
130
legacy/application/configs/constants.php
Normal file
130
legacy/application/configs/constants.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
define('PRODUCT_NAME' , 'LibreTime');
|
||||
define('PRODUCT_SITE_URL' , 'http://libretime.org');
|
||||
|
||||
define('SAAS_PRODUCT_BRANDING_NAME', 'LibreTime');
|
||||
define('SAAS_LOGIN_REFERRER', 'http://libretime.org');
|
||||
|
||||
define('COMPANY_NAME' , 'LibreTime Community');
|
||||
define('COMPANY_SUFFIX' , '');
|
||||
define('COMPANY_SITE' , 'libretime.org');
|
||||
define('COMPANY_SITE_URL' , 'http://libretime.org');
|
||||
define('SUPPORT_ADDRESS' , 'https://discourse.libretime.org/');
|
||||
|
||||
define('HELP_URL' , 'https://discourse.libretime.org/');
|
||||
define('WHOS_USING_URL' , 'https://github.com/orgs/LibreTime/people');
|
||||
define('TERMS_AND_CONDITIONS_URL' , 'https://github.com/LibreTime/libretime/blob/master/README.md');
|
||||
define('PRIVACY_POLICY_URL' , 'https://github.com/LibreTime/code-of-conduct/blob/master/CODE_OF_CONDUCT.md');
|
||||
define('USER_MANUAL_URL' , 'http://libretime.org/docs');
|
||||
define('ABOUT_AIRTIME_URL' , 'http://libretime.org');
|
||||
define('LIBRETIME_CONTRIBUTE_URL' , 'https://libretime.org/contribute');
|
||||
define('LIBRETIME_DISCOURSE_URL' , 'https://discourse.libretime.org');
|
||||
define('UI_REVAMP_EMBED_URL' , 'https://www.youtube.com/embed/nqpNnCKGluY');
|
||||
define('LIBRETIME_WHATS_NEW_URL' , 'https://github.com/LibreTime/libretime/releases');
|
||||
define('LIBRETIME_UPDATE_FEED' , 'https://github.com/LibreTime/libretime/releases.atom');
|
||||
define('LIBRETIME_EMAIL_FROM' , 'noreply@libretime.org');
|
||||
|
||||
define('LICENSE_VERSION' , 'GNU AGPL v.3');
|
||||
define('LICENSE_URL' , 'http://www.gnu.org/licenses/agpl-3.0-standalone.html');
|
||||
|
||||
define('AIRTIME_COPYRIGHT_DATE' , '2010-2015');
|
||||
define('AIRTIME_REST_VERSION' , '1.1');
|
||||
define('AIRTIME_API_VERSION' , '1.1');
|
||||
// XXX: it's important that we upgrade this on major version bumps, usually users get more exact info from VERSION in airtime root dir
|
||||
define('LIBRETIME_MAJOR_VERSION', '3');
|
||||
|
||||
// grab values from env (i'll do this everywhere with a small function if we like it)
|
||||
define('LIBRETIME_CONF_DIR', getenv('LIBRETIME_CONF_DIR') ? getenv('LIBRETIME_CONF_DIR') : '/etc/airtime');
|
||||
define('LIBRETIME_LOG_DIR', getenv('LIBRETIME_LOG_DIR') ? getenv('LIBRETIME_LOG_DIR') : '/var/log/airtime');
|
||||
|
||||
// Defaults
|
||||
define('DEFAULT_LOGO_PLACEHOLDER', 1);
|
||||
define('DEFAULT_LOGO_FILE', 'images/airtime_logo.png');
|
||||
define('DEFAULT_TIMESTAMP_FORMAT', 'Y-m-d H:i:s');
|
||||
define('DEFAULT_MICROTIME_FORMAT', 'Y-m-d H:i:s.u');
|
||||
define('DEFAULT_ICECAST_PORT', 8000);
|
||||
define('DEFAULT_ICECAST_PASS', 'hackme');
|
||||
define('DEFAULT_SHOW_COLOR', '76aca5');
|
||||
define('DEFAULT_INTERVAL_FORMAT', 'H:i:s.u');
|
||||
|
||||
// Metadata Keys for files
|
||||
define('MDATA_KEY_FILEPATH' , 'filepath');
|
||||
define('MDATA_KEY_DIRECTORY' , 'directory');
|
||||
define('MDATA_KEY_MD5' , 'md5');
|
||||
define('MDATA_KEY_TITLE' , 'track_title');
|
||||
define('MDATA_KEY_CREATOR' , 'artist_name');
|
||||
define('MDATA_KEY_SOURCE' , 'album_title');
|
||||
define('MDATA_KEY_DURATION' , 'length');
|
||||
define('MDATA_KEY_MIME' , 'mime');
|
||||
define('MDATA_KEY_FTYPE' , 'ftype');
|
||||
define('MDATA_KEY_URL' , 'info_url');
|
||||
define('MDATA_KEY_GENRE' , 'genre');
|
||||
define('MDATA_KEY_MOOD' , 'mood');
|
||||
define('MDATA_KEY_LABEL' , 'label');
|
||||
define('MDATA_KEY_COMPOSER' , 'composer');
|
||||
define('MDATA_KEY_DESCRIPTION' , 'description');
|
||||
define('MDATA_KEY_SAMPLERATE' , 'sample_rate');
|
||||
define('MDATA_KEY_BITRATE' , 'bit_rate');
|
||||
define('MDATA_KEY_ENCODER' , 'encoded_by');
|
||||
define('MDATA_KEY_ISRC' , 'isrc_number');
|
||||
define('MDATA_KEY_COPYRIGHT' , 'copyright');
|
||||
define('MDATA_KEY_YEAR' , 'year');
|
||||
define('MDATA_KEY_BPM' , 'bpm');
|
||||
define('MDATA_KEY_TRACKNUMBER' , 'track_number');
|
||||
define('MDATA_KEY_CONDUCTOR' , 'conductor');
|
||||
define('MDATA_KEY_LANGUAGE' , 'language');
|
||||
define('MDATA_KEY_REPLAYGAIN' , 'replay_gain');
|
||||
define('MDATA_KEY_OWNER_ID' , 'owner_id');
|
||||
define('MDATA_KEY_CUE_IN' , 'cuein');
|
||||
define('MDATA_KEY_CUE_OUT' , 'cueout');
|
||||
define('MDATA_KEY_ARTWORK' , 'artwork');
|
||||
define('MDATA_KEY_ARTWORK_DATA', 'artwork_data');
|
||||
define('MDATA_KEY_TRACK_TYPE' , 'track_type');
|
||||
|
||||
define('UI_MDATA_VALUE_FORMAT_FILE' , 'File');
|
||||
define('UI_MDATA_VALUE_FORMAT_STREAM' , 'live stream');
|
||||
|
||||
//User types
|
||||
define('UTYPE_HOST' , 'H');
|
||||
define('UTYPE_ADMIN' , 'A');
|
||||
define('UTYPE_SUPERADMIN' , 'S');
|
||||
define('UTYPE_GUEST' , 'G');
|
||||
define('UTYPE_PROGRAM_MANAGER' , 'P');
|
||||
|
||||
//Constants for playout history template fields
|
||||
define('TEMPLATE_DATE', 'date');
|
||||
define('TEMPLATE_TIME', 'time');
|
||||
define('TEMPLATE_DATETIME', 'datetime');
|
||||
define('TEMPLATE_STRING', 'string');
|
||||
define('TEMPLATE_BOOLEAN', 'boolean');
|
||||
define('TEMPLATE_INT', 'integer');
|
||||
define('TEMPLATE_FLOAT', 'float');
|
||||
|
||||
// Session Keys
|
||||
define('UI_PLAYLISTCONTROLLER_OBJ_SESSNAME', 'PLAYLISTCONTROLLER_OBJ');
|
||||
/*define('UI_PLAYLIST_SESSNAME', 'PLAYLIST');
|
||||
define('UI_BLOCK_SESSNAME', 'BLOCK');*/
|
||||
|
||||
//Sentry error logging
|
||||
define('SENTRY_CONFIG_PATH', LIBRETIME_CONF_DIR . '/sentry.airtime_web.ini');
|
||||
|
||||
//TuneIn integration
|
||||
define("TUNEIN_API_URL", "http://air.radiotime.com/Playing.ashx");
|
||||
|
||||
// Celery
|
||||
define('CELERY_PENDING_STATUS', 'PENDING');
|
||||
define('CELERY_SUCCESS_STATUS', 'SUCCESS');
|
||||
define('CELERY_FAILED_STATUS', 'FAILED');
|
||||
|
||||
// Celery Services
|
||||
define('PODCAST_SERVICE_NAME', 'podcast');
|
||||
|
||||
// Publish Services
|
||||
define('STATION_PODCAST_SERVICE_NAME', 'station_podcast');
|
||||
|
||||
// Podcast Types
|
||||
//define('STATION_PODCAST', 0);
|
||||
//define('IMPORTED_PODCAST', 1);
|
||||
|
||||
define('ITUNES_XML_NAMESPACE_URL', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
|
10
legacy/application/configs/db-conf.php
Normal file
10
legacy/application/configs/db-conf.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
/* This file is only needed during upgrades when we need the database parameters from /etc/airtime/airtime.conf.
|
||||
* The reason we don't just use conf.php is because conf.php may try to load configuration parameters that aren't
|
||||
* yet available because airtime.conf hasn't been updated yet. This situation ends up throwing a lot of errors to stdout.
|
||||
* airtime*/
|
||||
|
||||
require_once("conf.php");
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
197
legacy/application/configs/navigation.php
Normal file
197
legacy/application/configs/navigation.php
Normal file
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
/**
|
||||
* Navigation container (config/array)
|
||||
*
|
||||
* Each element in the array will be passed to
|
||||
* Zend_Navigation_Page::factory() when constructing
|
||||
* the navigation container below.
|
||||
*
|
||||
* The class field is used to contain the icon rendered
|
||||
* before the nav entry for i18n purposes. When this
|
||||
* gets parsed the language is not yet set and the
|
||||
* strings stay plain en for now. They get retranslated
|
||||
* in the menu.phtml script when they are output.
|
||||
*/
|
||||
$pages = array();
|
||||
// Disable My podcasts
|
||||
// See https://github.com/LibreTime/libretime/issues/1320
|
||||
// $pages[] = array(
|
||||
// 'label' => _('My Podcast'),
|
||||
// 'module' => 'default',
|
||||
// 'controller' => 'podcast',
|
||||
// 'action' => 'station',
|
||||
// 'resource' => 'podcast',
|
||||
// 'class' => '<i class="icon-music icon-white"></i>'
|
||||
// );
|
||||
$pages[] = array(
|
||||
'label' => _('Radio Page'),
|
||||
'uri' => '/',
|
||||
'resource' => '',
|
||||
'class' => '<i class="icon-globe icon-white"></i>',
|
||||
'pages' => array(),
|
||||
'visible' => false
|
||||
);
|
||||
$pages[] = array(
|
||||
'label' => _('Calendar'),
|
||||
'module' => 'default',
|
||||
'controller' => 'schedule',
|
||||
'action' => 'index',
|
||||
'resource' => 'schedule',
|
||||
'class' => '<i class="icon-calendar icon-white"></i>'
|
||||
);
|
||||
$pages[] = array(
|
||||
'label' => _('Widgets'),
|
||||
'module' => 'default',
|
||||
'controller' => 'embeddablewidgets',
|
||||
'action' => 'player',
|
||||
'resource' => 'embeddablewidgets',
|
||||
'class' => '<i class="icon-wrench icon-white"></i>',
|
||||
'title' => 'Widgets',
|
||||
'pages' => array(
|
||||
array(
|
||||
'label' => _('Player'),
|
||||
'module' => 'default',
|
||||
'controller' => 'embeddablewidgets',
|
||||
'action' => 'player',
|
||||
),
|
||||
array(
|
||||
'label' => _('Weekly Schedule'),
|
||||
'module' => 'default',
|
||||
'controller' => 'embeddablewidgets',
|
||||
'action' => 'schedule',
|
||||
)
|
||||
)
|
||||
);
|
||||
$pages[] = array(
|
||||
'label' => _("Settings"),
|
||||
'action' => 'edit-user',
|
||||
'module' => 'default',
|
||||
'controller' => 'user',
|
||||
'class' => '<i class="icon-cog icon-white"></i>',
|
||||
'title' => 'Settings',
|
||||
'pages' => array(
|
||||
array(
|
||||
'label' => _('General'),
|
||||
'module' => 'default',
|
||||
'controller' => 'preference',
|
||||
'resource' => 'preference'
|
||||
),
|
||||
array(
|
||||
'label' => _('My Profile'),
|
||||
'controller' => 'user',
|
||||
'action' => 'edit-user'
|
||||
),
|
||||
array(
|
||||
'label' => _('Users'),
|
||||
'module' => 'default',
|
||||
'controller' => 'user',
|
||||
'action' => 'add-user',
|
||||
'resource' => 'user'
|
||||
),array(
|
||||
'label' => _('Track Types'),
|
||||
'module' => 'default',
|
||||
'controller' => 'tracktype',
|
||||
'action' => 'add-tracktype',
|
||||
'resource' => 'tracktype'
|
||||
),
|
||||
array(
|
||||
'label' => _('Streams'),
|
||||
'module' => 'default',
|
||||
'controller' => 'preference',
|
||||
'action' => 'stream-setting',
|
||||
'resource' => 'preference'
|
||||
),
|
||||
array(
|
||||
'label' => _('Status'),
|
||||
'module' => 'default',
|
||||
'controller' => 'systemstatus',
|
||||
'action' => 'index',
|
||||
'resource' => 'systemstatus'
|
||||
),
|
||||
)
|
||||
);
|
||||
$pages[] = array(
|
||||
'label' => _("Analytics"),
|
||||
'module' => 'default',
|
||||
'controller' => 'playouthistory',
|
||||
'action' => 'index',
|
||||
'resource' => 'playouthistory',
|
||||
'class' => '<i class="icon-signal icon-white"></i>',
|
||||
'title' => 'Analytics',
|
||||
'pages' => array(
|
||||
array(
|
||||
'label' => _('Playout History'),
|
||||
'module' => 'default',
|
||||
'controller' => 'playouthistory',
|
||||
'action' => 'index',
|
||||
'resource' => 'playouthistory'
|
||||
),
|
||||
array(
|
||||
'label' => _('History Templates'),
|
||||
'module' => 'default',
|
||||
'controller' => 'playouthistorytemplate',
|
||||
'action' => 'index',
|
||||
'resource' => 'playouthistorytemplate'
|
||||
),
|
||||
array(
|
||||
'label' => _('Listener Stats'),
|
||||
'module' => 'default',
|
||||
'controller' => 'listenerstat',
|
||||
'action' => 'index',
|
||||
'resource' => 'listenerstat'
|
||||
),
|
||||
array(
|
||||
'label' => _('Show Listener Stats'),
|
||||
'module' => 'default',
|
||||
'controller' => 'listenerstat',
|
||||
'action' => 'show',
|
||||
'resource' => 'showlistenerstat'
|
||||
),
|
||||
|
||||
)
|
||||
);
|
||||
$pages[] = array(
|
||||
'label' => _('Help'),
|
||||
'controller' => 'dashboard',
|
||||
'action' => 'help',
|
||||
'resource' => 'dashboard',
|
||||
'class' => '<i class="icon-question-sign icon-white"></i>',
|
||||
'title' => 'Help',
|
||||
'pages' => array(
|
||||
array(
|
||||
'label' => _('Getting Started'),
|
||||
'module' => 'default',
|
||||
'controller' => 'dashboard',
|
||||
'action' => 'help',
|
||||
'resource' => 'dashboard'
|
||||
),
|
||||
array(
|
||||
'label' => _('User Manual'),
|
||||
'uri' => USER_MANUAL_URL,
|
||||
'target' => "_blank"
|
||||
),
|
||||
array(
|
||||
'label' => _('Get Help Online'),
|
||||
'uri' => LIBRETIME_DISCOURSE_URL,
|
||||
'target' => "_blank"
|
||||
),
|
||||
array(
|
||||
'label' => _('Contribute to LibreTime'),
|
||||
'uri' => LIBRETIME_CONTRIBUTE_URL,
|
||||
'target' => "_blank"
|
||||
),
|
||||
array(
|
||||
'label' => _('What\'s New?'),
|
||||
'uri' => LIBRETIME_WHATS_NEW_URL,
|
||||
'target' => "_blank"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Create container from array
|
||||
$container = new Zend_Navigation($pages);
|
||||
$container->id = "nav";
|
||||
|
||||
//store it in the registry:
|
||||
Zend_Registry::set('Zend_Navigation', $container);
|
1756
legacy/application/controllers/ApiController.php
Normal file
1756
legacy/application/controllers/ApiController.php
Normal file
File diff suppressed because it is too large
Load diff
295
legacy/application/controllers/AudiopreviewController.php
Normal file
295
legacy/application/controllers/AudiopreviewController.php
Normal file
|
@ -0,0 +1,295 @@
|
|||
<?php
|
||||
|
||||
class AudiopreviewController extends Zend_Controller_Action
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('show-preview', 'json')
|
||||
->addActionContext('audio-preview', 'json')
|
||||
->addActionContext('get-show', 'json')
|
||||
->addActionContext('playlist-preview', 'json')
|
||||
->addActionContext('get-playlist', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply sets up the view to play the required audio track.
|
||||
* Gets the parameters from the request and sets them to the view.
|
||||
*/
|
||||
public function audioPreviewAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$audioFileID = $this->_getParam('audioFileID');
|
||||
$type = $this->_getParam('type');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$this->view->headScript()->appendFile(
|
||||
$baseUrl.'js/airtime/audiopreview/preview_jplayer.js?'.$CC_CONFIG['airtime_version'],
|
||||
'text/javascript');
|
||||
$this->view->headScript()->appendFile(
|
||||
$baseUrl.'js/jplayer/jplayer.playlist.min.js?'.$CC_CONFIG['airtime_version'],
|
||||
'text/javascript');
|
||||
$this->view->headLink()->appendStylesheet(
|
||||
$baseUrl.'js/jplayer/skin/jplayer.airtime.audio.preview.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->_helper->layout->setLayout('audioPlayer');
|
||||
|
||||
$logo = Application_Model_Preference::GetStationLogo();
|
||||
if ($logo) {
|
||||
$this->view->logo = "data:image/png;base64,$logo";
|
||||
} else {
|
||||
$this->view->logo = $baseUrl."css/images/airtime_logo_jp.png";
|
||||
}
|
||||
|
||||
if ($type == "audioclip") {
|
||||
$media = Application_Model_StoredFile::RecallById($audioFileID);
|
||||
$uri = $baseUrl."api/get-media/file/".$audioFileID;
|
||||
$mime = $media->getPropelOrm()->getDbMime();
|
||||
$this->view->audioFileArtist = htmlspecialchars($media->getPropelOrm()->getDbArtistName());
|
||||
$this->view->audioFileTitle = htmlspecialchars($media->getPropelOrm()->getDbTrackTitle());
|
||||
|
||||
} elseif ($type == "stream") {
|
||||
$webstream = CcWebstreamQuery::create()->findPk($audioFileID);
|
||||
$uri = $webstream->getDbUrl();
|
||||
$mime = $webstream->getDbMime();
|
||||
$this->view->audioFileTitle = htmlspecialchars($webstream->getDbName());
|
||||
|
||||
} else {
|
||||
throw new Exception("Unknown type for audio preview!.Type=$type");
|
||||
}
|
||||
|
||||
$this->view->uri = $uri;
|
||||
$this->view->mime = $mime;
|
||||
$this->view->audioFileID = $audioFileID;
|
||||
|
||||
$this->view->type = $type;
|
||||
|
||||
$this->_helper->viewRenderer->setRender('audio-preview');
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply sets up the view to play the required playlist track.
|
||||
* Gets the parameters from the request and sets them to the view.
|
||||
*/
|
||||
public function playlistPreviewAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$playlistIndex = $this->_getParam('playlistIndex');
|
||||
$playlistID = $this->_getParam('playlistID');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/audiopreview/preview_jplayer.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/jplayer/jplayer.playlist.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'js/jplayer/skin/jplayer.airtime.audio.preview.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->_helper->layout->setLayout('audioPlayer');
|
||||
|
||||
$logo = Application_Model_Preference::GetStationLogo();
|
||||
if ($logo) {
|
||||
$this->view->logo = "data:image/png;base64,$logo";
|
||||
} else {
|
||||
$this->view->logo = $baseUrl."css/images/airtime_logo_jp.png";
|
||||
}
|
||||
$this->view->playlistIndex= $playlistIndex;
|
||||
$this->view->playlistID = $playlistID;
|
||||
|
||||
$this->_helper->viewRenderer->setRender('audio-preview');
|
||||
}
|
||||
|
||||
public function blockPreviewAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$blockIndex = $this->_getParam('blockIndex');
|
||||
$blockId = $this->_getParam('blockId');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/audiopreview/preview_jplayer.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/jplayer/jplayer.playlist.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'js/jplayer/skin/jplayer.airtime.audio.preview.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->_helper->layout->setLayout('audioPlayer');
|
||||
|
||||
$logo = Application_Model_Preference::GetStationLogo();
|
||||
if ($logo) {
|
||||
$this->view->logo = "data:image/png;base64,$logo";
|
||||
} else {
|
||||
$this->view->logo = $baseUrl."css/images/airtime_logo_jp.png";
|
||||
}
|
||||
$this->view->blockIndex= $blockIndex;
|
||||
$this->view->blockId = $blockId;
|
||||
|
||||
$this->_helper->viewRenderer->setRender('audio-preview');
|
||||
}
|
||||
public function getBlockAction()
|
||||
{
|
||||
// disable the view and the layout
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$blockId = $this->_getParam('blockId');
|
||||
|
||||
if (!isset($blockId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bl = new Application_Model_Block($blockId);
|
||||
$result = array();
|
||||
foreach ($bl->getContents(true) as $ele) {
|
||||
$result[] = $this->createElementMap($ele);
|
||||
}
|
||||
$this->_helper->json($result);
|
||||
}
|
||||
/**
|
||||
*Function will load and return the contents of the requested playlist.
|
||||
*/
|
||||
public function getPlaylistAction()
|
||||
{
|
||||
// disable the view and the layout
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$playlistID = $this->_getParam('playlistID');
|
||||
|
||||
if (!isset($playlistID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pl = new Application_Model_Playlist($playlistID);
|
||||
$result = Array();
|
||||
|
||||
foreach ($pl->getContents(true) as $ele) {
|
||||
if ($ele['type'] == 2) {
|
||||
// if element is a block expand and add
|
||||
$bl = new Application_Model_Block($ele['item_id']);
|
||||
if ($bl->isStatic()) {
|
||||
foreach ($bl->getContents(true) as $track) {
|
||||
$result[] = $this->createElementMap($track);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result[] = $this->createElementMap($ele);
|
||||
}
|
||||
}
|
||||
$this->_helper->json($result);
|
||||
}
|
||||
|
||||
private function createElementMap($track)
|
||||
{
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$elementMap = array( 'element_title' => isset($track['track_title'])?$track['track_title']:"",
|
||||
'element_artist' => isset($track['artist_name'])?$track['artist_name']:"",
|
||||
'element_id' => isset($track['id'])?$track['id']:"",
|
||||
'element_position' => isset($track['position'])?$track['position']:"",
|
||||
'mime' => isset($track['mime'])?$track['mime']:""
|
||||
);
|
||||
|
||||
/* If the track type is static we know it must be
|
||||
* a track because static blocks can only contain
|
||||
* tracks
|
||||
*/
|
||||
if ($track['type'] == 'static') {
|
||||
$track['type'] = 0;
|
||||
}
|
||||
$elementMap['type'] = $track['type'];
|
||||
|
||||
if ($track['type'] == 0) {
|
||||
$mime = trim(strtolower($track['mime']));
|
||||
try {
|
||||
$elementMap['element_' . FileDataHelper::getAudioMimeTypeArray()[$mime]] = $track['item_id'];
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Unknown file type: $mime");
|
||||
}
|
||||
|
||||
$elementMap['uri'] = $baseUrl."api/get-media/file/".$track['item_id'];
|
||||
} else {
|
||||
$elementMap['uri'] = $track['path'];
|
||||
}
|
||||
|
||||
return $elementMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply sets up the view to play the required show track.
|
||||
* Gets the parameters from the request and sets them to the view.
|
||||
*/
|
||||
public function showPreviewAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$showID = $this->_getParam('showID');
|
||||
$showIndex = $this->_getParam('showIndex');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/audiopreview/preview_jplayer.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/jplayer/jplayer.playlist.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'js/jplayer/skin/jplayer.airtime.audio.preview.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->_helper->layout->setLayout('audioPlayer');
|
||||
|
||||
$logo = Application_Model_Preference::GetStationLogo();
|
||||
if ($logo) {
|
||||
$this->view->logo = "data:image/png;base64,$logo";
|
||||
} else {
|
||||
$this->view->logo = $baseUrl."css/images/airtime_logo_jp.png";
|
||||
}
|
||||
|
||||
$this->view->showID = $showID;
|
||||
$this->view->showIndex = $showIndex;
|
||||
|
||||
$this->_helper->viewRenderer->setRender('audio-preview');
|
||||
}
|
||||
|
||||
/**
|
||||
*Function will load and return the contents of the requested show.
|
||||
*/
|
||||
public function getShowAction()
|
||||
{
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
// disable the view and the layout
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$showID = $this->_getParam('showID');
|
||||
|
||||
if (!isset($showID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$showInstance = new Application_Model_ShowInstance($showID);
|
||||
$result = array();
|
||||
$position = 0;
|
||||
foreach ($showInstance->getShowListContent() as $track) {
|
||||
|
||||
$elementMap = array(
|
||||
'element_title' => isset($track['track_title']) ? $track['track_title'] : "",
|
||||
'element_artist' => isset($track['creator']) ? $track['creator'] : "",
|
||||
'element_position' => $position,
|
||||
'element_id' => ++$position,
|
||||
'mime' => isset($track['mime'])?$track['mime']:""
|
||||
);
|
||||
|
||||
$elementMap['type'] = $track['type'];
|
||||
if ($track['type'] == 0) {
|
||||
$mime = trim(strtolower($track['mime']));
|
||||
try {
|
||||
$elementMap['element_' . FileDataHelper::getAudioMimeTypeArray()[$mime]] = $track['item_id'];
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Unknown file type: $mime");
|
||||
}
|
||||
|
||||
$elementMap['uri'] = $baseUrl."api/get-media/file/".$track['item_id'];
|
||||
} else {
|
||||
$elementMap['uri'] = $track['filepath'];
|
||||
}
|
||||
$result[] = $elementMap;
|
||||
}
|
||||
|
||||
$this->_helper->json($result);
|
||||
|
||||
}
|
||||
}
|
130
legacy/application/controllers/DashboardController.php
Normal file
130
legacy/application/controllers/DashboardController.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
class DashboardController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('switch-source', 'json')
|
||||
->addActionContext('disconnect-source', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
}
|
||||
|
||||
public function disconnectSourceAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$sourcename = $request->getParam('sourcename');
|
||||
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
|
||||
$show = Application_Model_Show::getCurrentShow();
|
||||
$show_id = isset($show[0]['id'])?$show[0]['id']:0;
|
||||
$source_connected = Application_Model_Preference::GetSourceStatus($sourcename);
|
||||
|
||||
if ($user->canSchedule($show_id) && $source_connected) {
|
||||
$data = array("sourcename"=>$sourcename);
|
||||
Application_Model_RabbitMq::SendMessageToPypo("disconnect_source", $data);
|
||||
} else {
|
||||
if ($source_connected) {
|
||||
$this->view->error = _("You don't have permission to disconnect source.");
|
||||
} else {
|
||||
$this->view->error = _("There is no source connected to this input.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function switchSourceAction()
|
||||
{
|
||||
$sourcename = $this->_getParam('sourcename');
|
||||
$current_status = $this->_getParam('status');
|
||||
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
|
||||
$show = Application_Model_Show::getCurrentShow();
|
||||
$show_id = isset($show[0]['id'])?$show[0]['id']:0;
|
||||
|
||||
$source_connected = Application_Model_Preference::GetSourceStatus($sourcename);
|
||||
if ($user->canSchedule($show_id) && ($source_connected || $sourcename == 'scheduled_play' || $current_status == "on")) {
|
||||
|
||||
$change_status_to = "on";
|
||||
|
||||
if (strtolower($current_status) == "on") {
|
||||
$change_status_to = "off";
|
||||
}
|
||||
|
||||
$data = array("sourcename"=>$sourcename, "status"=>$change_status_to);
|
||||
Application_Model_RabbitMq::SendMessageToPypo("switch_source", $data);
|
||||
if (strtolower($current_status) == "on") {
|
||||
Application_Model_Preference::SetSourceSwitchStatus($sourcename, "off");
|
||||
$this->view->status = "OFF";
|
||||
|
||||
//Log table updates
|
||||
Application_Model_LiveLog::SetEndTime($sourcename == 'scheduled_play'?'S':'L',
|
||||
new DateTime("now", new DateTimeZone('UTC')));
|
||||
} else {
|
||||
Application_Model_Preference::SetSourceSwitchStatus($sourcename, "on");
|
||||
$this->view->status = "ON";
|
||||
|
||||
//Log table updates
|
||||
Application_Model_LiveLog::SetNewLogTime($sourcename == 'scheduled_play'?'S':'L',
|
||||
new DateTime("now", new DateTimeZone('UTC')));
|
||||
}
|
||||
} else {
|
||||
if ($source_connected) {
|
||||
$this->view->error = _("You don't have permission to switch source.");
|
||||
} else {
|
||||
if ($sourcename == 'scheduled_play') {
|
||||
$this->view->error = _("You don't have permission to disconnect source.");
|
||||
} else {
|
||||
$this->view->error = _("There is no source connected to this input.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function streamPlayerAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'js/jplayer/skin/jplayer.blue.monday.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->_helper->layout->setLayout('livestream');
|
||||
|
||||
$logo = Application_Model_Preference::GetStationLogo();
|
||||
$this->view->logo = "data:image/png;base64,".$logo;
|
||||
}
|
||||
|
||||
public function helpAction()
|
||||
{
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Help');
|
||||
}
|
||||
|
||||
public function aboutAction()
|
||||
{
|
||||
$config = Config::getConfig();
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Help');
|
||||
$this->view->airtime_version = $config['airtime_version'];
|
||||
}
|
||||
|
||||
public function tableTestAction()
|
||||
{
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Help');
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$headScript = $this->view->headScript();
|
||||
AirtimeTableView::injectTableJavaScriptDependencies($headScript, $baseUrl, $CC_CONFIG['airtime_version']);
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/widgets/table-example.js?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
}
|
||||
}
|
99
legacy/application/controllers/EmbedController.php
Normal file
99
legacy/application/controllers/EmbedController.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
class EmbedController extends Zend_Controller_Action
|
||||
{
|
||||
public function init() {
|
||||
// translate widgets to station default language
|
||||
$locale = Application_Model_Preference::GetDefaultLocale();
|
||||
if ($locale) {
|
||||
Application_Model_Locale::configureLocalization($locale);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This is the action that is called to insert the player onto a web page.
|
||||
* It passes all the js and css files to the view, as well as all the
|
||||
* stream customization information.
|
||||
*
|
||||
* The view for this action contains all the inline javascript needed to
|
||||
* create the player.
|
||||
*/
|
||||
public function playerAction()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
$this->view->playerhtml5_js = "/js/airtime/player/playerhtml5.js?".$CC_CONFIG['airtime_version'];
|
||||
$this->view->jquery = "/js/libs/jquery-1.10.2.min.js";
|
||||
$this->view->metadata_api_url = "/api/live-info";
|
||||
$this->view->player_title = json_encode($this->view->escape($request->getParam('title')));
|
||||
$this->view->jquery_i18n = "/js/i18n/jquery.i18n.js?";
|
||||
|
||||
$styleParam = $request->getParam('style');
|
||||
$player_style = isset($styleParam) ? $styleParam : "basic";
|
||||
if ($player_style == "premium") {
|
||||
$this->view->css = "/css/radio-page/premium_player.css?".$CC_CONFIG['airtime_version'];
|
||||
} else {
|
||||
$this->view->css = "/css/player.css?".$CC_CONFIG['airtime_version'];
|
||||
}
|
||||
$this->view->player_style = $player_style;
|
||||
|
||||
$stream = $request->getParam('stream');
|
||||
$streamData = Application_Model_StreamSetting::getEnabledStreamData();
|
||||
$availableMobileStreams = array();
|
||||
$availableDesktopStreams = array();
|
||||
|
||||
if ($stream == "auto") {
|
||||
$this->view->playerMode = "auto";
|
||||
$this->view->streamURL = json_encode("");
|
||||
foreach ($streamData as $s) {
|
||||
if ($s["mobile"]) {
|
||||
array_push($availableMobileStreams, $s);
|
||||
} else if (!$s["mobile"]) {
|
||||
array_push($availableDesktopStreams, $s);
|
||||
}
|
||||
}
|
||||
} else if ($stream == "file") {
|
||||
$this->view->playerMode = "file";
|
||||
$this->view->streamURL = json_encode($request->getParam("file_url"));
|
||||
$this->view->codec = $request->getParam("file_codec");
|
||||
} elseif (!empty($stream)) {
|
||||
$this->view->playerMode = "manual";
|
||||
$selectedStreamData = $streamData[$stream];
|
||||
$this->view->streamURL = json_encode($selectedStreamData["url"]);
|
||||
$this->view->codec = $selectedStreamData["codec"];
|
||||
}
|
||||
$this->view->availableMobileStreams = json_encode($availableMobileStreams);
|
||||
$this->view->availableDesktopStreams = json_encode($availableDesktopStreams);
|
||||
}
|
||||
|
||||
public function weeklyProgramAction()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
$this->view->angular = Application_Common_HTTPHelper::getStationUrl() . 'js/libs/angular.min.js?'.$CC_CONFIG['airtime_version'];
|
||||
$widgetStyle = $request->getParam('style');
|
||||
if ($widgetStyle == "premium") {
|
||||
$this->view->widgetStyle = "premium";
|
||||
$this->view->css = "/css/embed/weekly-schedule-widget.css?" . $CC_CONFIG['airtime_version'];
|
||||
} else {
|
||||
$this->view->widgetStyle = "basic";
|
||||
$this->view->css = "/css/embed/weekly-schedule-widget-basic.css?" . $CC_CONFIG['airtime_version'];
|
||||
}
|
||||
$this->view->jquery = "/js/libs/jquery-1.8.3.min.js?".$CC_CONFIG['airtime_version'];
|
||||
|
||||
$weeklyScheduleData = WidgetHelper::getWeekInfoV2();
|
||||
|
||||
$this->view->schedule_data = json_encode($weeklyScheduleData);
|
||||
|
||||
$currentDay = new DateTime("now", new DateTimeZone(Application_Model_Preference::GetTimezone()));
|
||||
//day of the month without leading zeros (1 to 31)
|
||||
$this->view->currentDayOfMonth = $currentDay->format("j");
|
||||
}
|
||||
}
|
122
legacy/application/controllers/EmbeddablewidgetsController.php
Normal file
122
legacy/application/controllers/EmbeddablewidgetsController.php
Normal file
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
|
||||
class EmbeddableWidgetsController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function playerAction()
|
||||
{
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Widgets');
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/player-form.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/player/player.js?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$form = new Application_Form_Player();
|
||||
|
||||
$apiEnabled = Application_Model_Preference::GetAllow3rdPartyApi();
|
||||
$numEnabledStreams = $form->getElement('player_stream_url')->getAttrib('numberOfEnabledStreams');
|
||||
|
||||
if ($numEnabledStreams > 0 && $apiEnabled) {
|
||||
$this->view->player_form = $form;
|
||||
} else {
|
||||
$this->view->player_error_msg = _("To configure and use the embeddable player you must:<br><br>
|
||||
1. Enable at least one MP3, AAC, or OGG stream under Settings -> Streams<br>
|
||||
2. Enable the Public LibreTime API under Settings -> Preferences");
|
||||
}
|
||||
}
|
||||
|
||||
public function scheduleAction()
|
||||
{
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Widgets');
|
||||
|
||||
$apiEnabled = Application_Model_Preference::GetAllow3rdPartyApi();
|
||||
|
||||
if (!$apiEnabled) {
|
||||
$this->view->weekly_schedule_error_msg = _("To use the embeddable weekly schedule widget you must:<br><br>
|
||||
Enable the Public LibreTime API under Settings -> Preferences");
|
||||
}
|
||||
}
|
||||
|
||||
// The Facebook widget is untested & unsupported, the widget has been removed from the navigation in navigation.php
|
||||
public function facebookAction()
|
||||
{
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Widgets');
|
||||
|
||||
$apiEnabled = Application_Model_Preference::GetAllow3rdPartyApi();
|
||||
|
||||
if (!$apiEnabled) {
|
||||
$this->view->facebook_error_msg = _("To add the Radio Tab to your Facebook Page, you must first:<br><br>
|
||||
Enable the Public LibreTime API under Settings -> Preferences");
|
||||
}
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$facebookAppId = $CC_CONFIG['facebook-app-id'];
|
||||
$this->view->headScript()->appendScript("var FACEBOOK_APP_ID = " . json_encode($facebookAppId) . ";");
|
||||
$this->view->headScript()->appendFile($baseUrl . 'js/airtime/common/facebook.js?' . $CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
}
|
||||
|
||||
/** Airtime makes an AJAX POST here after it successfully adds a tab to your Facebook page. */
|
||||
public function facebookTabSuccessAction()
|
||||
{
|
||||
// disable the view and the layout
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
//TODO: Get list of page IDs (deserialize)
|
||||
|
||||
$request = $this->getRequest();
|
||||
if (!$request->isPost()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$values = $request->getPost();
|
||||
$facebookPageIds = json_decode($values["pages"]);
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$facebookMicroserviceUrl = $CC_CONFIG['facebook-app-url'];
|
||||
$facebookMicroserviceApiKey = $CC_CONFIG['facebook-app-api-key'];
|
||||
|
||||
//Post the page tab ID and station subdomain to the social microservice so that mapping can be saved
|
||||
//in a database.
|
||||
foreach ($facebookPageIds as $facebookPageId)
|
||||
{
|
||||
$postfields = array();
|
||||
$postfields["facebookPageId"] = $facebookPageId;
|
||||
$postfields["stationId"] = $CC_CONFIG['stationId'];
|
||||
|
||||
$query_string = "";
|
||||
foreach ($postfields as $k => $v) $query_string .= "$k=".urlencode($v)."&";
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $facebookMicroserviceUrl);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
|
||||
curl_setopt($ch, CURLOPT_USERPWD, ":$facebookMicroserviceApiKey");
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
|
||||
$jsondata = curl_exec($ch);
|
||||
if (curl_error($ch)) {
|
||||
throw new Exception("Failed to reach server in " . __FUNCTION__ . ": "
|
||||
. curl_errno($ch) . ' - ' . curl_error($ch) . ' - ' . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
}
|
||||
|
||||
//$arr = json_decode($jsondata, true); # Decode JSON String
|
||||
|
||||
}
|
||||
}
|
||||
|
120
legacy/application/controllers/ErrorController.php
Normal file
120
legacy/application/controllers/ErrorController.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
class ErrorController extends Zend_Controller_Action {
|
||||
|
||||
public function init()
|
||||
{
|
||||
//The default layout includes the Dashboard header, which may contain private information.
|
||||
//We cannot show that.
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->setupCSS();
|
||||
|
||||
// TODO: set Help button URL based on whether or not user is logged in
|
||||
try {
|
||||
$service_user = new Application_Service_UserService();
|
||||
$service_user->getCurrentUser();
|
||||
$this->view->helpUrl = Application_Common_OsPath::getBaseDir() . 'dashboard/help';
|
||||
} catch (Exception $e) {
|
||||
$this->view->helpUrl = HELP_URL;
|
||||
}
|
||||
}
|
||||
|
||||
public function errorAction() {
|
||||
$errors = $this->_getParam('error_handler');
|
||||
|
||||
if ($errors) {
|
||||
// log error message and stack trace
|
||||
Logging::error($errors->exception->getMessage());
|
||||
Logging::error($errors->exception->getTraceAsString());
|
||||
|
||||
switch ($errors->type) {
|
||||
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE :
|
||||
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER :
|
||||
$this->error404Action();
|
||||
break;
|
||||
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION :
|
||||
$this->error400Action();
|
||||
break;
|
||||
default :
|
||||
$this->error500Action();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//$exceptions = $this->_getAllParams();
|
||||
//Logging::error($exceptions);
|
||||
$this->error404Action();
|
||||
return;
|
||||
}
|
||||
|
||||
// Log exception, if logger available
|
||||
/* No idea why this doesn't work or why it was implemented like this. Disabling it -- Albert
|
||||
if (($log = $this->getLog())) {
|
||||
$log->crit($this->view->message, $errors->exception);
|
||||
}*/
|
||||
//Logging that actually works: -- Albert
|
||||
Logging::error($this->view->message . ": " . $errors->exception);
|
||||
|
||||
// conditionally display exceptions
|
||||
if ($this->getInvokeArg('displayExceptions') == true) {
|
||||
$this->view->exception = $errors->exception;
|
||||
}
|
||||
|
||||
$this->view->request = $errors->request;
|
||||
}
|
||||
|
||||
private function setupCSS()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$staticBaseDir = Application_Common_OsPath::formatDirectoryWithDirectorySeparators($CC_CONFIG['staticBaseDir']);
|
||||
$this->view->headLink()->appendStylesheet($staticBaseDir . 'css/styles.css?' . $CC_CONFIG['airtime_version']);
|
||||
}
|
||||
|
||||
public function getLog() {
|
||||
$bootstrap = $this->getInvokeArg('bootstrap');
|
||||
if (!$bootstrap->hasPluginResource('Log')) {
|
||||
return false;
|
||||
}
|
||||
$log = $bootstrap->getResource('Log');
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* 404 error - route or controller
|
||||
*/
|
||||
public function error404Action() {
|
||||
$this->_helper->viewRenderer('error');
|
||||
$this->getResponse()->setHttpResponseCode(404);
|
||||
$this->view->message = _('Page not found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 400 error - no such action
|
||||
*/
|
||||
public function error400Action() {
|
||||
$this->_helper->viewRenderer('error-400');
|
||||
$this->getResponse()->setHttpResponseCode(400);
|
||||
$this->view->message = _('The requested action is not supported.');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 403 error - permission denied
|
||||
*/
|
||||
public function error403Action() {
|
||||
|
||||
$this->_helper->viewRenderer('error-403');
|
||||
$this->getResponse()->setHttpResponseCode(403);
|
||||
$this->view->message = _('You do not have permission to access this resource.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 500 error - internal server error
|
||||
*/
|
||||
public function error500Action() {
|
||||
|
||||
$this->_helper->viewRenderer('error-500');
|
||||
|
||||
$this->getResponse()->setHttpResponseCode(500);
|
||||
$this->view->message = _('An internal application error has occurred.');
|
||||
}
|
||||
}
|
62
legacy/application/controllers/FeedsController.php
Normal file
62
legacy/application/controllers/FeedsController.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
class FeedsController extends Zend_Controller_Action
|
||||
{
|
||||
public function stationRssAction()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$request = $this->getRequest();
|
||||
$response = $this->getResponse();
|
||||
|
||||
if ((Application_Model_Preference::getStationPodcastPrivacy()
|
||||
&& $request->getParam("sharing_token") != Application_Model_Preference::getStationPodcastDownloadKey())
|
||||
&& !RestAuth::verifyAuth(true, false, $this)) {
|
||||
$response->setHttpResponseCode(401);
|
||||
return;
|
||||
}
|
||||
|
||||
CORSHelper::enableCrossOriginRequests($request, $response);
|
||||
|
||||
$rssData = Application_Service_PodcastService::createStationRssFeed();
|
||||
|
||||
$mimeType = "text/xml";
|
||||
header("Content-Type: $mimeType; charset=UTF-8");
|
||||
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
} else {
|
||||
header('HTTP/1.1 200 OK');
|
||||
}
|
||||
header("Content-Type: $mimeType");
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header('Cache-Control: public, must-revalidate, max-age=0');
|
||||
header('Pragma: no-cache');
|
||||
header('Accept-Ranges: bytes');
|
||||
$size = strlen($rssData);
|
||||
|
||||
$begin = 0;
|
||||
$end = $size - 1;
|
||||
|
||||
//ob_start(); //Must start a buffer here for these header() functions
|
||||
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
if (preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) {
|
||||
$begin = intval($matches[1]);
|
||||
if (!empty($matches[2])) {
|
||||
$end = intval($matches[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($size > 0) {
|
||||
header('Content-Length:' . (($end - $begin) + 1));
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
header("Content-Range: bytes $begin-$end/$size");
|
||||
}
|
||||
}
|
||||
|
||||
echo $rssData;
|
||||
}
|
||||
}
|
105
legacy/application/controllers/IndexController.php
Normal file
105
legacy/application/controllers/IndexController.php
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
class IndexController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$this->view->headTitle(Application_Model_Preference::GetHeadTitle());
|
||||
$this->view->headScript()->appendFile($baseUrl . 'js/libs/jquery-1.8.3.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl . 'js/i18n/jquery.i18n.js?' . $CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl . 'locale/general-translation-table?' . $CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendScript("$.i18n.setDictionary(general_dict)");
|
||||
$this->view->headScript()->appendScript("var baseUrl='$baseUrl'");
|
||||
|
||||
//jplayer
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/jplayer/jquery.jplayer.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/jplayer/jplayer.playlist.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headLink()->setStylesheet($baseUrl.'css/radio-page/radio-page.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/embed/weekly-schedule-widget.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/radio-page/station-podcast.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/bootstrap.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
//jplayer control buttons
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/redmond/jquery-ui-1.8.8.custom.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$this->_helper->layout->setLayout('radio-page');
|
||||
|
||||
// translate page to station default language
|
||||
$locale = Application_Model_Preference::GetDefaultLocale();
|
||||
if ($locale) {
|
||||
Application_Model_Locale::configureLocalization($locale);
|
||||
}
|
||||
|
||||
$this->view->stationLogo = Application_Model_Preference::GetStationLogo();
|
||||
|
||||
$stationName = Application_Model_Preference::GetStationName();
|
||||
$this->view->stationName = $stationName;
|
||||
|
||||
$stationDescription = Application_Model_Preference::GetStationDescription();
|
||||
$this->view->stationDescription = $stationDescription;
|
||||
|
||||
$this->view->stationUrl = Application_Common_HTTPHelper::getStationUrl();
|
||||
|
||||
$displayRadioPageLoginButtonValue = Application_Model_Preference::getRadioPageDisplayLoginButton();
|
||||
if ($displayRadioPageLoginButtonValue == "") {
|
||||
$displayRadioPageLoginButtonValue = true;
|
||||
}
|
||||
$this->view->displayLoginButton = $displayRadioPageLoginButtonValue;
|
||||
|
||||
//station feed episodes
|
||||
$stationPodcastId = Application_Model_Preference::getStationPodcastId();
|
||||
$podcastEpisodesService = new Application_Service_PodcastEpisodeService();
|
||||
$episodes = $podcastEpisodesService->getPodcastEpisodes($stationPodcastId, 0, 0, PodcastEpisodesPeer::PUBLICATION_DATE, "DESC");
|
||||
foreach ($episodes as $e => $v) {
|
||||
$episodes[$e]["CcFiles"]["track_title"] = htmlspecialchars($v["CcFiles"]["track_title"], ENT_QUOTES);
|
||||
$episodes[$e]["CcFiles"]["artist_name"] = htmlspecialchars($v["CcFiles"]["artist_name"], ENT_QUOTES);
|
||||
|
||||
$pubDate = explode(" ", $v["publication_date"]);
|
||||
$episodes[$e]["publication_date"] = $pubDate[0];
|
||||
|
||||
$length = explode(".", $v["CcFiles"]["length"]);
|
||||
$episodes[$e]["CcFiles"]["length"] = $length[0];
|
||||
|
||||
$episodes[$e]["mime"] = FileDataHelper::getAudioMimeTypeArray()[$v["CcFiles"]["mime"]];
|
||||
|
||||
if (is_null($v["CcFiles"]["description"])) {
|
||||
$episodes[$e]["CcFiles"]["description"] = "";
|
||||
}
|
||||
}
|
||||
|
||||
$episodePages = array_chunk($episodes, 10);
|
||||
|
||||
$this->view->episodes = json_encode($episodePages, JSON_FORCE_OBJECT);
|
||||
$this->view->displayRssTab = (!Application_Model_Preference::getStationPodcastPrivacy());
|
||||
|
||||
$stationPodcast = PodcastQuery::create()->findOneByDbId($stationPodcastId);
|
||||
$url = $stationPodcast->getDbUrl();
|
||||
$this->view->stationPodcastRssUrl = $url;
|
||||
|
||||
$stationName = Application_Model_Preference::GetStationName();
|
||||
$this->view->podcastTitle = sprintf(_("%s Podcast"), !empty($stationName) ? $stationName : $CC_CONFIG["stationId"]);
|
||||
$this->view->emptyPodcastMessage = _("No tracks have been published yet.");
|
||||
|
||||
}
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$this->_helper->layout->setLayout('layout');
|
||||
}
|
||||
|
||||
public function maintenanceAction()
|
||||
{
|
||||
$this->getResponse()->setHttpResponseCode(503);
|
||||
}
|
||||
|
||||
}
|
490
legacy/application/controllers/LibraryController.php
Normal file
490
legacy/application/controllers/LibraryController.php
Normal file
|
@ -0,0 +1,490 @@
|
|||
<?php
|
||||
|
||||
class LibraryController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('contents-feed', 'json')
|
||||
->addActionContext('delete', 'json')
|
||||
->addActionContext('duplicate', 'json')
|
||||
->addActionContext('duplicate-block', 'json')
|
||||
->addActionContext('delete-group', 'json')
|
||||
->addActionContext('context-menu', 'json')
|
||||
->addActionContext('get-file-metadata', 'html')
|
||||
->addActionContext('set-num-entries', 'json')
|
||||
->addActionContext('edit-file-md', 'json')
|
||||
->addActionContext('publish-dialog', 'html')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$this->_redirect("showbuilder");
|
||||
}
|
||||
|
||||
protected function playlistNotFound($p_type)
|
||||
{
|
||||
$this->view->error = sprintf(_("%s not found"), $p_type);
|
||||
|
||||
Logging::info("$p_type not found");
|
||||
Application_Model_Library::changePlaylist(null, $p_type);
|
||||
$this->createFullResponse(null);
|
||||
}
|
||||
|
||||
protected function playlistUnknownError($e)
|
||||
{
|
||||
$this->view->error = _("Something went wrong.");
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
|
||||
protected function createFullResponse($obj = null, $isJson = false)
|
||||
{
|
||||
$isBlock = false;
|
||||
$viewPath = 'playlist/playlist.phtml';
|
||||
if ($obj instanceof Application_Model_Block) {
|
||||
$isBlock = true;
|
||||
$viewPath = 'playlist/smart-block.phtml';
|
||||
}
|
||||
|
||||
if (isset($obj)) {
|
||||
$formatter = new LengthFormatter($obj->getLength());
|
||||
$this->view->length = $formatter->format();
|
||||
|
||||
if ($isBlock) {
|
||||
$form = new Application_Form_SmartBlockCriteria();
|
||||
$form->removeDecorator('DtDdWrapper');
|
||||
$form->startForm($obj->getId());
|
||||
|
||||
$this->view->form = $form;
|
||||
$this->view->obj = $obj;
|
||||
$this->view->id = $obj->getId();
|
||||
if ($isJson) {
|
||||
return $this->view->render($viewPath);
|
||||
} else {
|
||||
$this->view->html = $this->view->render($viewPath);
|
||||
}
|
||||
} else {
|
||||
$this->view->obj = $obj;
|
||||
$this->view->id = $obj->getId();
|
||||
$this->view->html = $this->view->render($viewPath);
|
||||
unset($this->view->obj);
|
||||
}
|
||||
} else {
|
||||
$this->view->html = $this->view->render($viewPath);
|
||||
}
|
||||
}
|
||||
|
||||
public function contextMenuAction()
|
||||
{
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$id = $this->_getParam('id');
|
||||
$type = $this->_getParam('type');
|
||||
//playlist||timeline
|
||||
$screen = $this->_getParam('screen');
|
||||
|
||||
$menu = array();
|
||||
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
|
||||
//Open a jPlayer window and play the audio clip.
|
||||
$menu["play"] = array("name"=> _("Preview"), "icon" => "play", "disabled" => false);
|
||||
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
$obj_sess = new Zend_Session_Namespace(UI_PLAYLISTCONTROLLER_OBJ_SESSNAME);
|
||||
|
||||
if ($type === "audioclip") {
|
||||
$file = Application_Model_StoredFile::RecallById($id);
|
||||
|
||||
$menu["play"]["mime"] = $file->getPropelOrm()->getDbMime();
|
||||
|
||||
if (isset($obj_sess->id) && $screen == "playlist") {
|
||||
// if the user is not admin or pm, check the creator and see if this person owns the playlist or Block
|
||||
if ($obj_sess->type == 'playlist') {
|
||||
$obj = new Application_Model_Playlist($obj_sess->id);
|
||||
} elseif ($obj_sess->type == 'block') {
|
||||
$obj = new Application_Model_Block($obj_sess->id);
|
||||
}
|
||||
if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
|
||||
if ($obj_sess->type === "playlist") {
|
||||
$menu["pl_add"] = array("name"=> _("Add to Playlist"), "icon" => "add-playlist", "icon" => "copy");
|
||||
} elseif ($obj_sess->type === "block" && $obj->isStatic()) {
|
||||
$menu["pl_add"] = array("name"=> _("Add to Smart Block"), "icon" => "add-playlist", "icon" => "copy");
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($isAdminOrPM || $file->getFileOwnerId() == $user->getId()) {
|
||||
$menu["del"] = array("name"=> _("Delete"), "icon" => "delete", "url" => $baseUrl."library/delete");
|
||||
$menu["edit"] = array("name"=> _("Edit..."), "icon" => "edit", "url" => $baseUrl."library/edit-file-md/id/{$id}");
|
||||
// Disable My podcasts
|
||||
// See https://github.com/LibreTime/libretime/issues/1320
|
||||
// $menu["publish"] = array("name"=> _("Publish..."), "url" => $baseUrl."library/publish/id/{$id}");
|
||||
}
|
||||
|
||||
// It's important that we always return the parent id (cc_files id)
|
||||
// and not the cloud_file id (if applicable) for track download.
|
||||
// Our application logic (StoredFile.php) will determine if the track
|
||||
// is a cloud_file and handle it appropriately.
|
||||
$url = $baseUrl."api/get-media/file/$id/download/true";
|
||||
$menu["download"] = array("name" => _("Download"), "icon" => "download", "url" => $url);
|
||||
|
||||
} elseif ($type === "playlist" || $type === "block") {
|
||||
if ($type === 'playlist') {
|
||||
$obj = new Application_Model_Playlist($id);
|
||||
$menu["duplicate"] = array("name" => _("Duplicate Playlist"), "icon" => "edit", "url" => $baseUrl."library/duplicate");
|
||||
} elseif ($type === 'block') {
|
||||
$obj = new Application_Model_Block($id);
|
||||
$menu["duplicate"] = array("name" => _("Duplicate Smartblock"), "icon" => "edit", "url" => $baseUrl."library/duplicate-block");
|
||||
if (!$obj->isStatic()) {
|
||||
unset($menu["play"]);
|
||||
}
|
||||
if (($isAdminOrPM || $obj->getCreatorId() == $user->getId()) && $screen == "playlist") {
|
||||
if ($obj_sess->type === "playlist") {
|
||||
$menu["pl_add"] = array("name"=> _("Add to Playlist"), "icon" => "add-playlist", "icon" => "copy");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($obj_sess->id !== $id && $screen == "playlist") {
|
||||
if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
|
||||
$menu["edit"] = array("name"=> _("Edit..."), "icon" => "edit");
|
||||
}
|
||||
}
|
||||
|
||||
if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
|
||||
$menu["del"] = array("name"=> _("Delete"), "icon" => "delete", "url" => $baseUrl."library/delete");
|
||||
}
|
||||
} elseif ($type == "stream") {
|
||||
$webstream = CcWebstreamQuery::create()->findPK($id);
|
||||
$obj = new Application_Model_Webstream($webstream);
|
||||
|
||||
$menu["play"]["mime"] = $webstream->getDbMime();
|
||||
|
||||
if (isset($obj_sess->id) && $screen == "playlist") {
|
||||
if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
|
||||
if ($obj_sess->type === "playlist") {
|
||||
$menu["pl_add"] = array("name"=> _("Add to Playlist"), "icon" => "add-playlist", "icon" => "copy");
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
|
||||
if ($screen == "playlist") {
|
||||
$menu["edit"] = array("name"=> _("Edit..."), "icon" => "edit", "url" => $baseUrl."library/edit-file-md/id/{$id}");
|
||||
}
|
||||
$menu["del"] = array("name"=> _("Delete"), "icon" => "delete", "url" => $baseUrl."library/delete");
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($menu)) {
|
||||
$menu["noaction"] = array("name"=>_("No action available"));
|
||||
}
|
||||
|
||||
$this->view->items = $menu;
|
||||
}
|
||||
|
||||
public function deleteAction()
|
||||
{
|
||||
//array containing id and type of media to delete.
|
||||
$mediaItems = $this->_getParam('media', null);
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
//$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
$files = array();
|
||||
$playlists = array();
|
||||
$blocks = array();
|
||||
$streams = array();
|
||||
|
||||
$message = null;
|
||||
$noPermissionMsg = _("You don't have permission to delete selected items.");
|
||||
|
||||
foreach ($mediaItems as $media) {
|
||||
|
||||
if ($media["type"] === "audioclip") {
|
||||
$files[] = intval($media["id"]);
|
||||
} elseif ($media["type"] === "playlist") {
|
||||
$playlists[] = intval($media["id"]);
|
||||
} elseif ($media["type"] === "block") {
|
||||
$blocks[] = intval($media["id"]);
|
||||
} elseif ($media["type"] === "stream") {
|
||||
$streams[] = intval($media["id"]);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Application_Model_Playlist::deletePlaylists($playlists, $user->getId());
|
||||
} catch (PlaylistNoPermissionException $e) {
|
||||
$message = $noPermissionMsg;
|
||||
}
|
||||
|
||||
try {
|
||||
Application_Model_Block::deleteBlocks($blocks, $user->getId());
|
||||
} catch (BlockNoPermissionException $e) {
|
||||
$message = $noPermissionMsg;
|
||||
} catch (Exception $e) {
|
||||
//TODO: warn user that not all blocks could be deleted.
|
||||
}
|
||||
|
||||
try {
|
||||
Application_Model_Webstream::deleteStreams($streams, $user->getId());
|
||||
} catch (WebstreamNoPermissionException $e) {
|
||||
$message = $noPermissionMsg;
|
||||
} catch (Exception $e) {
|
||||
//TODO: warn user that not all streams could be deleted.
|
||||
Logging::info($e);
|
||||
}
|
||||
|
||||
foreach ($files as $id) {
|
||||
$file = Application_Model_StoredFile::RecallById($id);
|
||||
if (isset($file)) {
|
||||
try {
|
||||
$res = $file->delete();
|
||||
} catch (FileNoPermissionException $e) {
|
||||
$message = $noPermissionMsg;
|
||||
} catch (DeleteScheduledFileException $e) {
|
||||
$message = _("Could not delete file because it is scheduled in the future.");
|
||||
} catch (Exception $e) {
|
||||
//could throw a scheduled in future exception.
|
||||
$message = _("Could not delete file(s).");
|
||||
Logging::info($message.": ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($message)) {
|
||||
$this->view->message = $message;
|
||||
}
|
||||
}
|
||||
|
||||
// duplicate playlist
|
||||
public function duplicateAction(){
|
||||
$params = $this->getRequest()->getParams();
|
||||
$id = $params['id'];
|
||||
Logging::info($params);
|
||||
|
||||
$originalPl = new Application_Model_Playlist($id);
|
||||
$newPl = new Application_Model_Playlist();
|
||||
|
||||
$contents = $originalPl->getContents();
|
||||
foreach ($contents as &$c) {
|
||||
if ($c['type'] == '0') {
|
||||
$c[1] = 'audioclip';
|
||||
} else if ($c['type'] == '2') {
|
||||
$c[1] = 'block';
|
||||
} else if ($c['type'] == '1') {
|
||||
$c[1] = 'stream';
|
||||
}
|
||||
$c[0] = $c['item_id'];
|
||||
}
|
||||
|
||||
$newPl->addAudioClips($contents, null, 'before');
|
||||
|
||||
$newPl->setCreator(Application_Model_User::getCurrentUser()->getId());
|
||||
$newPl->setDescription($originalPl->getDescription());
|
||||
|
||||
list($plFadeIn, ) = $originalPl->getFadeInfo(0);
|
||||
list(, $plFadeOut) = $originalPl->getFadeInfo($originalPl->getSize()-1);
|
||||
|
||||
$newPl->setfades($plFadeIn, $plFadeOut);
|
||||
$newPl->setName(sprintf(_("Copy of %s"), $originalPl->getName()));
|
||||
}
|
||||
|
||||
// duplicate smartblock
|
||||
public function duplicateBlockAction(){
|
||||
Logging::info("duplicate smartblock functionality not yet implemented");
|
||||
$params = $this->getRequest()->getParams();
|
||||
$id = $params['id'];
|
||||
Logging::info($params);
|
||||
|
||||
$originalBl = new Application_Model_Block($id);
|
||||
$newBl = new Application_Model_Block();
|
||||
$newBl->setCreator(Application_Model_User::getCurrentUser()->getId());
|
||||
$newBl->setDescription($originalBl->getDescription());
|
||||
if ($originalBl->isStatic()) {
|
||||
$newBl->saveType('static');
|
||||
}
|
||||
else {
|
||||
$newBl->saveType('dynamic');
|
||||
}
|
||||
// the issue here is that the format that getCriteria provides is different from the format the saveCriteria
|
||||
// expects due to the useage of startForm. So we either need to write new code that simply copies the database
|
||||
// or figure out a way to instantiate a form inside of here and save it without modifying it.
|
||||
//$newBlForm = new Application_Form_SmartBlockCriteria;
|
||||
//$newBlForm->startForm($id);
|
||||
$criteria = CcBlockcriteriaQuery::create()->orderByDbCriteria()->findByDbBlockId($id);
|
||||
foreach ($criteria as &$c) {
|
||||
$row = new CcBlockcriteria();
|
||||
$row->setDbCriteria($c->getDbCriteria());
|
||||
$row->setDbModifier($c->getDbModifier());
|
||||
$row->setDbValue($c->getDbValue());
|
||||
$row->setDbExtra($c->getDbExtra());
|
||||
$row->setDbBlockId($newBl->getId());
|
||||
$row->save();
|
||||
}
|
||||
$newBl->setName(sprintf(_("Copy of %s"), $originalBl->getName()));
|
||||
}
|
||||
|
||||
|
||||
public function contentsFeedAction()
|
||||
{
|
||||
$params = $this->getRequest()->getParams();
|
||||
|
||||
# terrible name for the method below. it does not only search files.
|
||||
$r = Application_Model_StoredFile::searchLibraryFiles($params);
|
||||
|
||||
$this->view->sEcho = $r["sEcho"];
|
||||
$this->view->iTotalDisplayRecords = $r["iTotalDisplayRecords"];
|
||||
$this->view->iTotalRecords = $r["iTotalRecords"];
|
||||
$this->view->files = SecurityHelper::htmlescape_recursive($r["aaData"]);
|
||||
}
|
||||
|
||||
public function editFileMdAction()
|
||||
{
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
$isAdmin = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN));
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
$file_id = $this->_getParam('id', null);
|
||||
$file = Application_Model_StoredFile::RecallById($file_id);
|
||||
|
||||
$form = new Application_Form_EditAudioMD();
|
||||
$form->startForm($file_id);
|
||||
$form->populate($file->getDbColMetadata());
|
||||
|
||||
$this->view->permissionDenied = false;
|
||||
if (!$isAdminOrPM && $file->getFileOwnerId() != $user->getId()) {
|
||||
$form->makeReadOnly();
|
||||
$form->removeActionButtons();
|
||||
$this->view->permissionDenied = true;
|
||||
}
|
||||
// only admins should be able to edit the owner of a file
|
||||
if (!$isAdmin) {
|
||||
$form->removeOwnerEdit();
|
||||
}
|
||||
|
||||
if ($request->isPost()) {
|
||||
|
||||
$js = $this->_getParam('data');
|
||||
$serialized = array();
|
||||
//need to convert from serialized jQuery array.
|
||||
foreach ($js as $j) {
|
||||
//on edit, if no artwork is set and audiofile has image, automatically add it
|
||||
if ($j["name"] == "artwork") {
|
||||
if ($j["value"] == null || $j["value"] == ''){
|
||||
$serialized["artwork"] = FileDataHelper::resetArtwork($file_id);
|
||||
}
|
||||
} elseif ($j["name"] == "set_artwork") {
|
||||
if ($j["value"] != null || $j["value"] != ''){
|
||||
$serialized["artwork"] = FileDataHelper::setArtwork($file_id, $j["value"] );
|
||||
}
|
||||
} elseif ($j["name"] == "remove_artwork") {
|
||||
if ($j["value"] == 1){
|
||||
$remove_artwork = true;
|
||||
$serialized["artwork"] = FileDataHelper::removeArtwork($file_id);
|
||||
}
|
||||
} else {
|
||||
$serialized[$j["name"]] = $j["value"];
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize any wildly incorrect metadata before it goes to be validated.
|
||||
FileDataHelper::sanitizeData($serialized);
|
||||
|
||||
if ($form->isValid($serialized)) {
|
||||
$file->setDbColMetadata($serialized);
|
||||
$this->view->status = true;
|
||||
} else {
|
||||
$this->view->status = false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->form = $form;
|
||||
$this->view->id = $file_id;
|
||||
$this->view->title = $file->getPropelOrm()->getDbTrackTitle();
|
||||
$this->view->artist_name = $file->getPropelOrm()->getDbArtistName();
|
||||
$this->view->filePath = $file->getPropelOrm()->getDbFilepath();
|
||||
$this->view->artwork = $file->getPropelOrm()->getDbArtwork();
|
||||
$this->view->html = $this->view->render('library/edit-file-md.phtml');
|
||||
}
|
||||
|
||||
public function getFileMetadataAction()
|
||||
{
|
||||
$id = $this->_getParam('id');
|
||||
$type = $this->_getParam('type');
|
||||
|
||||
try {
|
||||
if ($type == "audioclip") {
|
||||
$file = Application_Model_StoredFile::RecallById($id);
|
||||
$this->view->type = $type;
|
||||
$md = $file->getMetadata();
|
||||
|
||||
foreach ($md as $key => $value) {
|
||||
if ($key == 'MDATA_KEY_DIRECTORY' && !is_null($value)) {
|
||||
$musicDir = Application_Model_MusicDir::getDirByPK($value);
|
||||
$md['MDATA_KEY_FILEPATH'] = Application_Common_OsPath::join($musicDir->getDirectory(), $md['MDATA_KEY_FILEPATH']);
|
||||
}
|
||||
}
|
||||
|
||||
$formatter = new SamplerateFormatter($md["MDATA_KEY_SAMPLERATE"]);
|
||||
$md["MDATA_KEY_SAMPLERATE"] = $formatter->format();
|
||||
|
||||
$formatter = new BitrateFormatter($md["MDATA_KEY_BITRATE"]);
|
||||
$md["MDATA_KEY_BITRATE"] = $formatter->format();
|
||||
|
||||
$formatter = new LengthFormatter($md["MDATA_KEY_DURATION"]);
|
||||
$md["MDATA_KEY_DURATION"] = $formatter->format();
|
||||
|
||||
$this->view->md = $md;
|
||||
|
||||
} elseif ($type == "playlist") {
|
||||
|
||||
$file = new Application_Model_Playlist($id);
|
||||
$this->view->type = $type;
|
||||
$md = $file->getAllPLMetaData();
|
||||
|
||||
$formatter = new LengthFormatter($md["dcterms:extent"]);
|
||||
$md["dcterms:extent"] = $formatter->format();
|
||||
|
||||
$this->view->md = $md;
|
||||
$this->view->contents = $file->getContents();
|
||||
} elseif ($type == "block") {
|
||||
$block = new Application_Model_Block($id);
|
||||
$this->view->type = $type;
|
||||
$md = $block->getAllPLMetaData();
|
||||
|
||||
$formatter = new LengthFormatter($md["dcterms:extent"]);
|
||||
$md["dcterms:extent"] = $formatter->format();
|
||||
|
||||
$this->view->md = $md;
|
||||
if ($block->isStatic()) {
|
||||
$this->view->blType = 'Static';
|
||||
$this->view->contents = $block->getContents();
|
||||
} else {
|
||||
$this->view->blType = 'Dynamic';
|
||||
$this->view->contents = $block->getCriteria();
|
||||
}
|
||||
$this->view->block = $block;
|
||||
} elseif ($type == "stream") {
|
||||
$webstream = CcWebstreamQuery::create()->findPK($id);
|
||||
$ws = new Application_Model_Webstream($webstream);
|
||||
|
||||
$md = $ws->getMetadata();
|
||||
|
||||
$this->view->md = $md;
|
||||
$this->view->type = $type;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function publishDialogAction() {
|
||||
$this->_helper->layout->disableLayout();
|
||||
//This just spits out publish-dialog.phtml!
|
||||
}
|
||||
}
|
129
legacy/application/controllers/ListenerstatController.php
Normal file
129
legacy/application/controllers/ListenerstatController.php
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
|
||||
class ListenerstatController extends Zend_Controller_Action
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext
|
||||
->addActionContext('get-data', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$request = $this->getRequest();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Analytics');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/flot/jquery.flot.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/flot/jquery.flot.crosshair.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/flot/jquery.flot.resize.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/listenerstat/listenerstat.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/timepicker/jquery.ui.timepicker.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/buttons/buttons.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/utilities/utilities.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.ui.timepicker.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($request);
|
||||
$userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
|
||||
$startsDT->setTimezone($userTimezone);
|
||||
$endsDT->setTimezone($userTimezone);
|
||||
|
||||
$form = new Application_Form_DateRange();
|
||||
$form->populate(array(
|
||||
'his_date_start' => $startsDT->format("Y-m-d"),
|
||||
'his_time_start' => $startsDT->format("H:i"),
|
||||
'his_date_end' => $endsDT->format("Y-m-d"),
|
||||
'his_time_end' => $endsDT->format("H:i")
|
||||
));
|
||||
|
||||
$errorStatus = Application_Model_StreamSetting::GetAllListenerStatErrors();
|
||||
Logging::info($errorStatus);
|
||||
$out = array();
|
||||
foreach ($errorStatus as $v) {
|
||||
$key = explode('_listener_stat_error', $v['keyname']);
|
||||
if ($v['value'] != 'OK') {
|
||||
$v['value'] = _("Please make sure admin user/password is correct on Settings->Streams page.");
|
||||
}
|
||||
$out[$key[0]] = $v['value'];
|
||||
}
|
||||
|
||||
$this->view->errorStatus = $out;
|
||||
$this->view->date_form = $form;
|
||||
}
|
||||
public function showAction() {
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$request = $this->getRequest();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$headScript = $this->view->headScript();
|
||||
AirtimeTableView::injectTableJavaScriptDependencies($headScript, $baseUrl, $CC_CONFIG['airtime_version']);
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Analytics');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/timepicker/jquery.ui.timepicker.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/buttons/buttons.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/utilities/utilities.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/listenerstat/showlistenerstat.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/ColVis.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/dataTables.colReorder.min.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.ui.timepicker.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/show_analytics.css'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
$this->view->showAllShows = true;
|
||||
}
|
||||
$data = [];
|
||||
$this->view->showData = $data;
|
||||
|
||||
$form = new Application_Form_ShowListenerStat();
|
||||
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($request);
|
||||
$userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
|
||||
$startsDT->setTimezone($userTimezone);
|
||||
$endsDT->setTimezone($userTimezone);
|
||||
$form->populate(array(
|
||||
'his_date_start' => $startsDT->format("Y-m-d"),
|
||||
'his_time_start' => $startsDT->format("H:i"),
|
||||
'his_date_end' => $endsDT->format("Y-m-d"),
|
||||
'his_time_end' => $endsDT->format("H:i")
|
||||
));
|
||||
|
||||
$this->view->date_form = $form;
|
||||
}
|
||||
|
||||
public function getDataAction(){
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($this->getRequest());
|
||||
$data = Application_Model_ListenerStat::getDataPointsWithinRange($startsDT->format(DEFAULT_TIMESTAMP_FORMAT),
|
||||
$endsDT->format(DEFAULT_TIMESTAMP_FORMAT));
|
||||
$this->_helper->json->sendJson($data);
|
||||
}
|
||||
|
||||
public function getShowDataAction(){
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($this->getRequest());
|
||||
$show_id = $this->getRequest()->getParam("show_id", null);
|
||||
$data = Application_Model_ListenerStat::getShowDataPointsWithinRange($startsDT->format(DEFAULT_TIMESTAMP_FORMAT),
|
||||
$endsDT->format(DEFAULT_TIMESTAMP_FORMAT),$show_id);
|
||||
$this->_helper->json->sendJson($data);
|
||||
}
|
||||
public function getAllShowData(){
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($this->getRequest());
|
||||
$data = Application_Model_ListenerStat::getAllShowDataPointsWithinRange($startsDT->format(DEFAULT_TIMESTAMP_FORMAT),
|
||||
$endsDT->format(DEFAULT_TIMESTAMP_FORMAT));
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getAllShowDataAction(){
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($this->getRequest());
|
||||
$show_id = $this->getRequest()->getParam("show_id", null);
|
||||
$data = Application_Model_ListenerStat::getAllShowDataPointsWithinRange($startsDT->format(DEFAULT_TIMESTAMP_FORMAT),
|
||||
$endsDT->format(DEFAULT_TIMESTAMP_FORMAT));
|
||||
$this->_helper->json->sendJson($data);
|
||||
}
|
||||
}
|
504
legacy/application/controllers/LocaleController.php
Normal file
504
legacy/application/controllers/LocaleController.php
Normal file
|
@ -0,0 +1,504 @@
|
|||
<?php
|
||||
|
||||
final class LocaleController extends Zend_Controller_Action
|
||||
{
|
||||
public function datatablesTranslationTableAction()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
header("Content-type: text/javascript");
|
||||
|
||||
$locale = Application_Model_Preference::GetLocale();
|
||||
echo "var datatables_dict =" .
|
||||
file_get_contents(Application_Common_OsPath::join(
|
||||
//$_SERVER["DOCUMENT_ROOT"],
|
||||
dirname(__FILE__) . "/../../public/", // Fixing this... -- Albert
|
||||
"js/datatables/i18n/",
|
||||
$locale.".txt")
|
||||
);
|
||||
}
|
||||
|
||||
public function generalTranslationTableAction()
|
||||
{
|
||||
$translations = array (
|
||||
//common/common.js
|
||||
"Audio Player" => _("Audio Player"),
|
||||
"Something went wrong!" => _("Something went wrong!"),
|
||||
//dashboard/dashboard.js
|
||||
"Recording:" => _("Recording:"),
|
||||
"Master Stream" => _("Master Stream"),
|
||||
"Live Stream" => _("Live Stream"),
|
||||
"Nothing Scheduled" => _("Nothing Scheduled"),
|
||||
"Current Show:" => _("Current Show:"),
|
||||
"Current" => _("Current"),
|
||||
//dashboard/versiontooltip.js
|
||||
"You are running the latest version" => _("You are running the latest version"),
|
||||
"New version available: " => _("New version available: "),
|
||||
"You have a pre-release version of LibreTime intalled." => _("You have a pre-release version of LibreTime intalled."),
|
||||
"A patch update for your LibreTime installation is available." => _("A patch update for your LibreTime installation is available."),
|
||||
"A feature update for your LibreTime installation is available." => _("A feature update for your LibreTime installation is available."),
|
||||
"A major update for your LibreTime installation is available." => _("A major update for your LibreTime installation is available."),
|
||||
"Multiple major updates for LibreTime installation are available. Please upgrade as soon as possible." => _("Multiple major updates for LibreTime installation are available. Please upgrade as soon as possible."),
|
||||
//library/events/library_playlistbuilder.js
|
||||
"Add to current playlist" => _("Add to current playlist"),
|
||||
"Add to current smart block" => _("Add to current smart block"),
|
||||
"Adding 1 Item" => _("Adding 1 Item"),
|
||||
"Adding %s Items" => _("Adding %s Items"),
|
||||
"You can only add tracks to smart blocks." => _("You can only add tracks to smart blocks."),
|
||||
"You can only add tracks, smart blocks, and webstreams to playlists." => _("You can only add tracks, smart blocks, and webstreams to playlists."),
|
||||
//library/events/library_showbuilder.js
|
||||
//already in library/events/library_playlistbuilder.js
|
||||
"Please select a cursor position on timeline." => _("Please select a cursor position on timeline."),
|
||||
"You haven't added any tracks" => _("You haven't added any tracks"),
|
||||
"You haven't added any playlists" => _("You haven't added any playlists"),
|
||||
"You haven't added any podcasts" => _("You haven't added any podcasts"),
|
||||
"You haven't added any smart blocks" => _("You haven't added any smart blocks"),
|
||||
"You haven't added any webstreams" => _("You haven't added any webstreams"),
|
||||
"Learn about tracks" => _("Learn about tracks"),
|
||||
"Learn about playlists" => _("Learn about playlists"),
|
||||
"Learn about podcasts" => _("Learn about podcasts"),
|
||||
"Learn about smart blocks" => _("Learn about smart blocks"),
|
||||
"Learn about webstreams" => _("Learn about webstreams"),
|
||||
"Click 'New' to create one." => _("Click 'New' to create one."),
|
||||
//"Adding 1 Item" => _("Adding 1 Item"),
|
||||
//"Adding %s Items" => _("Adding %s Items"),
|
||||
//library/library.js
|
||||
"Add" => _("Add"),
|
||||
"New" => _("New"),
|
||||
"Edit" => _("Edit"),
|
||||
"Add to Schedule" => _("Add to Schedule"),
|
||||
"Add to next show" => _("Add to next show"),
|
||||
"Add to current show" => _("Add to current show"),
|
||||
"Add after selected items" => _("Add after selected items"),
|
||||
"Delete" => _("Delete"),
|
||||
"Publish" => _("Publish"),
|
||||
"Remove" => _("Remove"),
|
||||
"Edit Metadata" => _("Edit Metadata"),
|
||||
"Add to selected show" => _("Add to selected show"),
|
||||
"Select" => _("Select"),
|
||||
"Select this page" => _("Select this page"),
|
||||
"Deselect this page" => _("Deselect this page"),
|
||||
"Deselect all" => _("Deselect all"),
|
||||
"Are you sure you want to delete the selected item(s)?" => _("Are you sure you want to delete the selected item(s)?"),
|
||||
"Scheduled" => _("Scheduled"),
|
||||
"Tracks" => _("Tracks"),
|
||||
"Playlist" => _("Playlist"),
|
||||
"Title" => _("Title"),
|
||||
"Creator" => _("Creator"),
|
||||
"Album" => _("Album"),
|
||||
"Bit Rate" => _("Bit Rate"),
|
||||
"BPM" => _("BPM"),
|
||||
"Composer" => _("Composer"),
|
||||
"Conductor" => _("Conductor"),
|
||||
"Copyright" => _("Copyright"),
|
||||
"Encoded By" => _("Encoded By"),
|
||||
"Genre" => _("Genre"),
|
||||
"ISRC" => _("ISRC"),
|
||||
"Label" => _("Label"),
|
||||
"Language" => _("Language"),
|
||||
"Last Modified" => _("Last Modified"),
|
||||
"Last Played" => _("Last Played"),
|
||||
"Length" => _("Length"),
|
||||
"Mime" => _("Mime"),
|
||||
"Mood" => _("Mood"),
|
||||
"Owner" => _("Owner"),
|
||||
"Replay Gain" => _("Replay Gain"),
|
||||
"Sample Rate" => _("Sample Rate"),
|
||||
"Track Number" => _("Track Number"),
|
||||
"Uploaded" => _("Uploaded"),
|
||||
"Website" => _("Website"),
|
||||
"Year" => _("Year"),
|
||||
"Loading..." => _("Loading..."),
|
||||
"All" => _("All"),
|
||||
"Files" => _("Files"),
|
||||
"Playlists" => _("Playlists"),
|
||||
"Smart Blocks" => _("Smart Blocks"),
|
||||
"Web Streams" => _("Web Streams"),
|
||||
"Unknown type: " => _("Unknown type: "),
|
||||
"Are you sure you want to delete the selected item?" => _("Are you sure you want to delete the selected item?"),
|
||||
"Uploading in progress..." => _("Uploading in progress..."),
|
||||
"Retrieving data from the server..." => _("Retrieving data from the server..."),
|
||||
//library/podcast.js
|
||||
"Import" => _("Import"),
|
||||
"Imported?" => _("Imported?"),
|
||||
"View" => _("View"),
|
||||
"Error code: " => _("Error code: "),
|
||||
"Error msg: " => _("Error msg: "),
|
||||
"Input must be a positive number" => _("Input must be a positive number"),
|
||||
"Input must be a number" => _("Input must be a number"),
|
||||
"Input must be in the format: yyyy-mm-dd" => _("Input must be in the format: yyyy-mm-dd"),
|
||||
"Input must be in the format: hh:mm:ss.t" => _("Input must be in the format: hh:mm:ss.t"),
|
||||
"My Podcast" => _("My Podcast"),
|
||||
//library/plupload.js
|
||||
"You are currently uploading files. %sGoing to another screen will cancel the upload process. %sAre you sure you want to leave the page?"
|
||||
=> _("You are currently uploading files. %sGoing to another screen will cancel the upload process. %sAre you sure you want to leave the page?"),
|
||||
//library/spl.js
|
||||
"Open Media Builder" => _("Open Media Builder"),
|
||||
"please put in a time '00:00:00 (.0)'" => _("please put in a time '00:00:00 (.0)'"),
|
||||
"Please enter a valid time in seconds. Eg. 0.5'" => _("Please enter a valid time in seconds. Eg. 0.5"),
|
||||
"Your browser does not support playing this file type: " => _("Your browser does not support playing this file type: "),
|
||||
"Dynamic block is not previewable" => _("Dynamic block is not previewable"),
|
||||
"Limit to: " => _("Limit to: "),
|
||||
"Playlist saved" => _("Playlist saved"),
|
||||
"Playlist shuffled" => _("Playlist shuffled"),
|
||||
"Airtime is unsure about the status of this file. This can happen when the file is on a remote drive that is unaccessible or the file is in a directory that isn't 'watched' anymore."
|
||||
=> _("Airtime is unsure about the status of this file. This can happen when the file is on a remote drive that is unaccessible or the file is in a directory that isn't 'watched' anymore."),
|
||||
//listenerstat/listenerstat.js
|
||||
"Listener Count on %s: %s" => _("Listener Count on %s: %s"),
|
||||
//nowplaying/register.js
|
||||
"Remind me in 1 week" => _("Remind me in 1 week"),
|
||||
"Remind me never" => _("Remind me never"),
|
||||
"Yes, help Airtime" => _("Yes, help Airtime"),
|
||||
"Image must be one of jpg, jpeg, png, or gif" => _("Image must be one of jpg, jpeg, png, or gif"),
|
||||
//playlist/smart_blockbuilder.js
|
||||
"A static smart block will save the criteria and generate the block content immediately. This allows you to edit and view it in the Library before adding it to a show."
|
||||
=> _("A static smart block will save the criteria and generate the block content immediately. This allows you to edit and view it in the Library before adding it to a show."),
|
||||
"A dynamic smart block will only save the criteria. The block content will get generated upon adding it to a show. You will not be able to view and edit the content in the Library."
|
||||
=> _("A dynamic smart block will only save the criteria. The block content will get generated upon adding it to a show. You will not be able to view and edit the content in the Library."),
|
||||
"The desired block length will not be reached if %s cannot find enough unique tracks to match your criteria. Enable this option if you wish to allow tracks to be added multiple times to the smart block."
|
||||
=> _("The desired block length will not be reached if %s cannot find enough unique tracks to match your criteria. Enable this option if you wish to allow tracks to be added multiple times to the smart block."),
|
||||
"Smart block shuffled" => _("Smart block shuffled"),
|
||||
"Smart block generated and criteria saved" => _("Smart block generated and criteria saved"),
|
||||
"Smart block saved" => _("Smart block saved"),
|
||||
"Processing..." => _("Processing..."),
|
||||
"Select modifier" => _("Select modifier"),
|
||||
"contains" => _("contains"),
|
||||
"does not contain" => _("does not contain"),
|
||||
"is" => _("is"),
|
||||
"is not" => _("is not"),
|
||||
"starts with" => _("starts with"),
|
||||
"ends with" => _("ends with"),
|
||||
"is greater than" => _("is greater than"),
|
||||
"is less than" => _("is less than"),
|
||||
"is in the range" => _("is in the range"),
|
||||
"Preview" => _("Preview"),
|
||||
"Generate" => _("Generate"),
|
||||
//preferences/musicdirs.js
|
||||
"Choose Storage Folder" => _("Choose Storage Folder"),
|
||||
"Choose Folder to Watch" => _("Choose Folder to Watch"),
|
||||
"Are you sure you want to change the storage folder?\nThis will remove the files from your Airtime library!"
|
||||
=> _("Are you sure you want to change the storage folder?\nThis will remove the files from your Airtime library!"),
|
||||
"Manage Media Folders" => _("Manage Media Folders"),
|
||||
"Are you sure you want to remove the watched folder?" => _("Are you sure you want to remove the watched folder?"),
|
||||
"This path is currently not accessible." => _("This path is currently not accessible."),
|
||||
//preferences/streamsetting.js
|
||||
"Some stream types require extra configuration. Details about enabling %sAAC+ Support%s or %sOpus Support%s are provided." => _("Some stream types require extra configuration. Details about enabling %sAAC+ Support%s or %sOpus Support%s are provided."),
|
||||
"Connected to the streaming server" => _("Connected to the streaming server"),
|
||||
"The stream is disabled" => _("The stream is disabled"),
|
||||
"Getting information from the server..." => _("Getting information from the server..."),
|
||||
"Can not connect to the streaming server" => _("Can not connect to the streaming server"),
|
||||
"If %s is behind a router or firewall, you may need to configure port forwarding and this field information will be incorrect. In this case you will need to manually update this field so it shows the correct host/port/mount that your DJ's need to connect to. The allowed range is between 1024 and 49151."
|
||||
=> _("If %s is behind a router or firewall, you may need to configure port forwarding and this field information will be incorrect. In this case you will need to manually update this field so it shows the correct host/port/mount that your DJ's need to connect to. The allowed range is between 1024 and 49151."),
|
||||
"For more details, please read the %s%s Manual%s" => _("For more details, please read the %s%s Manual%s"),
|
||||
"Check this option to enable metadata for OGG streams (stream metadata is the track title, artist, and show name that is displayed in an audio player). VLC and mplayer have a serious bug when playing an OGG/VORBIS stream that has metadata information enabled: they will disconnect from the stream after every song. If you are using an OGG stream and your listeners do not require support for these audio players, then feel free to enable this option."
|
||||
=> _("Check this option to enable metadata for OGG streams (stream metadata is the track title, artist, and show name that is displayed in an audio player). VLC and mplayer have a serious bug when playing an OGG/VORBIS stream that has metadata information enabled: they will disconnect from the stream after every song. If you are using an OGG stream and your listeners do not require support for these audio players, then feel free to enable this option."),
|
||||
"Check this box to automatically switch off Master/Show source upon source disconnection." => _("Check this box to automatically switch off Master/Show source upon source disconnection."),
|
||||
"Check this box to automatically switch on Master/Show source upon source connection." => _("Check this box to automatically switch on Master/Show source upon source connection."),
|
||||
"If your Icecast server expects a username of 'source', this field can be left blank." => _("If your Icecast server expects a username of 'source', this field can be left blank."),
|
||||
"If your live streaming client does not ask for a username, this field should be 'source'." => _("If your live streaming client does not ask for a username, this field should be 'source'."),
|
||||
"WARNING: This will restart your stream and may cause a short dropout for your listeners!" => _("WARNING: This will restart your stream and may cause a short dropout for your listeners!"),
|
||||
"This is the admin username and password for Icecast/SHOUTcast to get listener statistics." => _("This is the admin username and password for Icecast/SHOUTcast to get listener statistics."),
|
||||
//preferences/support-setting.js
|
||||
"Image must be one of jpg, jpeg, png, or gif" => _("Image must be one of jpg, jpeg, png, or gif"),
|
||||
//schedule/add-show.js
|
||||
"Warning: You cannot change this field while the show is currently playing" => _("Warning: You cannot change this field while the show is currently playing"),
|
||||
"No result found" => _("No result found"),
|
||||
"This follows the same security pattern for the shows: only users assigned to the show can connect." => _("This follows the same security pattern for the shows: only users assigned to the show can connect."),
|
||||
"Specify custom authentication which will work only for this show." => _("Specify custom authentication which will work only for this show."),
|
||||
"If your live streaming client does not ask for a username, this field should be 'source'." => _("If your live streaming client does not ask for a username, this field should be 'source'."),
|
||||
"The show instance doesn't exist anymore!" => _("The show instance doesn't exist anymore!"),
|
||||
"Warning: Shows cannot be re-linked" => _("Warning: Shows cannot be re-linked"),
|
||||
"By linking your repeating shows any media items scheduled in any repeat show will also get scheduled in the other repeat shows" => _("By linking your repeating shows any media items scheduled in any repeat show will also get scheduled in the other repeat shows"),
|
||||
"Timezone is set to the station timezone by default. Shows in the calendar will be displayed in your local time defined by the Interface Timezone in your user settings." => _("Timezone is set to the station timezone by default. Shows in the calendar will be displayed in your local time defined by the Interface Timezone in your user settings."),
|
||||
//schedule/full-calendar-functions
|
||||
//already in schedule/add-show.js
|
||||
//"The show instance doesn't exist anymore!" => _("The show instance doesn't exist anymore!"),
|
||||
"Show" => _("Show"),
|
||||
"Show is empty" => _("Show is empty"),
|
||||
"1m" => _("1m"),
|
||||
"5m" => _("5m"),
|
||||
"10m" => _("10m"),
|
||||
"15m" => _("15m"),
|
||||
"30m" => _("30m"),
|
||||
"60m" => _("60m"),
|
||||
"Uploading in progress..." => _("Uploading in progress..."),
|
||||
"Retreiving data from the server..." => _("Retreiving data from the server..."),
|
||||
"This show has no scheduled content." => _("This show has no scheduled content."),
|
||||
"This show is not completely filled with content." => _("This show is not completely filled with content."),
|
||||
//already in schedule/add-show.js
|
||||
//"The show instance doesn"t exist anymore!" => _("The show instance doesn"t exist anymore!"),
|
||||
//schedule/schedule.js
|
||||
"January" => _("January"),
|
||||
"February" => _("February"),
|
||||
"March" => _("March"),
|
||||
"April" => _("April"),
|
||||
"May" => _("May"),
|
||||
"June" => _("June"),
|
||||
"July" => _("July"),
|
||||
"August" => _("August"),
|
||||
"September" => _("September"),
|
||||
"October" => _("October"),
|
||||
"November" => _("November"),
|
||||
"December" => _("December"),
|
||||
"Jan" => _("Jan"),
|
||||
"Feb" => _("Feb"),
|
||||
"Mar" => _("Mar"),
|
||||
"Apr" => _("Apr"),
|
||||
"May" => _("May"),
|
||||
"Jun" => _("Jun"),
|
||||
"Jul" => _("Jul"),
|
||||
"Aug" => _("Aug"),
|
||||
"Sep" => _("Sep"),
|
||||
"Oct" => _("Oct"),
|
||||
"Nov" => _("Nov"),
|
||||
"Dec" => _("Dec"),
|
||||
"Today" => _("Today"),
|
||||
"Day" => _("Day"),
|
||||
"Week" => _("Week"),
|
||||
"Month" => _("Month"),
|
||||
"Sunday" => _("Sunday"),
|
||||
"Monday" => _("Monday"),
|
||||
"Tuesday" => _("Tuesday"),
|
||||
"Wednesday" => _("Wednesday"),
|
||||
"Thursday" => _("Thursday"),
|
||||
"Friday" => _("Friday"),
|
||||
"Saturday" => _("Saturday"),
|
||||
"Sun" => _("Sun"),
|
||||
"Mon" => _("Mon"),
|
||||
"Tue" => _("Tue"),
|
||||
"Wed" => _("Wed"),
|
||||
"Thu" => _("Thu"),
|
||||
"Fri" => _("Fri"),
|
||||
"Sat" => _("Sat"),
|
||||
"Shows longer than their scheduled time will be cut off by a following show." => _("Shows longer than their scheduled time will be cut off by a following show."),
|
||||
"Cancel Current Show?" => _("Cancel Current Show?"),
|
||||
"Stop recording current show?" => _("Stop recording current show?"),
|
||||
"Ok" => _("Ok"),
|
||||
"Contents of Show" => _("Contents of Show"),
|
||||
//already in schedule/add-show.js
|
||||
//"The show instance doesn"t exist anymore!" => _("The show instance doesn"t exist anymore!"),
|
||||
"Remove all content?" => _("Remove all content?"),
|
||||
//showbuilder/builder.js
|
||||
"Delete selected item(s)?" => _("Delete selected item(s)?"),
|
||||
"Start" => _("Start"),
|
||||
"End" => _("End"),
|
||||
"Duration" => _("Duration"),
|
||||
"Filtering out " => _("Filtering out "),
|
||||
" of " => _(" of "),
|
||||
" records" => _(" records"),
|
||||
"There are no shows scheduled during the specified time period." => _("There are no shows scheduled during the specified time period."),
|
||||
//already in library/library.js
|
||||
//"Title" => _("Title"),
|
||||
//"Creator" => _("Creator"),
|
||||
//"Album" => _("Album"),
|
||||
//"Mime" => _("Mime"),
|
||||
"Cue In" => _("Cue In"),
|
||||
"Cue Out" => _("Cue Out"),
|
||||
"Fade In" => _("Fade In"),
|
||||
"Fade Out" => _("Fade Out"),
|
||||
"Show Empty" => _("Show Empty"),
|
||||
"Recording From Line In" => _("Recording From Line In"),
|
||||
"Track preview" => _("Track preview"),
|
||||
//already in library/spl.js
|
||||
//"Airtime is unsure about the status of this file. This can happen when the file is on a remote drive that is unaccessible or the file is in a directory that isn"t "watched" anymore."
|
||||
//=> _("Airtime is unsure about the status of this file. This can happen when the file is on a remote drive that is unaccessible or the file is in a directory that isn"t "watched" anymore."),
|
||||
"Cannot schedule outside a show." => _("Cannot schedule outside a show."),
|
||||
"Moving 1 Item" => _("Moving 1 Item"),
|
||||
"Moving %s Items" => _("Moving %s Items"),
|
||||
"Save" => _("Save"),
|
||||
"Cancel" => _("Cancel"),
|
||||
"Fade Editor" => _("Fade Editor"),
|
||||
"Cue Editor" => _("Cue Editor"),
|
||||
"Waveform features are available in a browser supporting the Web Audio API" => _("Waveform features are available in a browser supporting the Web Audio API"),
|
||||
//already in library/library.js
|
||||
//"Select" => _("Select"),
|
||||
"Select all" => _("Select all"),
|
||||
"Select none" => _("Select none"),
|
||||
"Trim overbooked shows" => _("Trim overbooked shows"),
|
||||
"Remove selected scheduled items" => _("Remove selected scheduled items"),
|
||||
"Jump to the current playing track" => _("Jump to the current playing track"),
|
||||
"Jump to Current" => _("Jump to Current"),
|
||||
"Cancel current show" => _("Cancel current show"),
|
||||
//already in schedule/schedule.js
|
||||
//"Cancel Current Show?" => _("Cancel Current Show?"),
|
||||
"Stop recording current show?" => _("Stop recording current show?"),
|
||||
//showbuilder/main_builder.js
|
||||
"Open library to add or remove content" => _("Open library to add or remove content"),
|
||||
"Add / Remove Content" => _("Add / Remove Content"),
|
||||
//status/status.js
|
||||
"in use" => _("in use"),
|
||||
"Disk" => _("Disk"),
|
||||
//serverbrowse/serverbrowse.js
|
||||
"Look in" => _("Look in"),
|
||||
"Cancel" => _("Cancel"),
|
||||
"Open" => _("Open"),
|
||||
//user/user.js
|
||||
"Admin" => _("Admin"),
|
||||
"DJ" => _("DJ"),
|
||||
"Program Manager" => _("Program Manager"),
|
||||
"Guest" => _("Guest"),
|
||||
"Guests can do the following:" => _("Guests can do the following:"),
|
||||
"View schedule" => _("View schedule"),
|
||||
"View show content" => _("View show content"),
|
||||
"DJs can do the following:" => _("DJs can do the following:"),
|
||||
"Manage assigned show content" => _("Manage assigned show content"),
|
||||
"Import media files" => _("Import media files"),
|
||||
"Create playlists, smart blocks, and webstreams" => _("Create playlists, smart blocks, and webstreams"),
|
||||
"Manage their own library content" => _("Manage their own library content"),
|
||||
"Program Managers can do the following:" => _("Program Managers can do the following:"),
|
||||
"View and manage show content" => _("View and manage show content"),
|
||||
"Schedule shows" => _("Schedule shows"),
|
||||
"Manage all library content" => _("Manage all library content"),
|
||||
"Admins can do the following:" => _("Admins can do the following:"),
|
||||
"Manage preferences" => _("Manage preferences"),
|
||||
"Manage users" => _("Manage users"),
|
||||
"Manage watched folders" => _("Manage watched folders"),
|
||||
"Send support feedback" => _("Send support feedback"),
|
||||
"View system status" => _("View system status"),
|
||||
"Access playout history" => _("Access playout history"),
|
||||
"View listener stats" => _("View listener stats"),
|
||||
//dataTables/ColVis.js
|
||||
"Show / hide columns" => _("Show / hide columns"),
|
||||
"Columns" => _("Columns"),
|
||||
//datatables.columnFilter.js
|
||||
"From {from} to {to}" => _("From {from} to {to}"),
|
||||
"kbps" => _("kbps"),
|
||||
"yyyy-mm-dd" => _("yyyy-mm-dd"),
|
||||
"hh:mm:ss.t" => _("hh:mm:ss.t"),
|
||||
"kHz" => _("kHz"),
|
||||
//datepicker
|
||||
//months are already in schedule/schedule.js
|
||||
"Su" => _("Su"),
|
||||
"Mo" => _("Mo"),
|
||||
"Tu" => _("Tu"),
|
||||
"We" => _("We"),
|
||||
"Th" => _("Th"),
|
||||
"Fr" => _("Fr"),
|
||||
"Sa" => _("Sa"),
|
||||
"Close" => _("Close"),
|
||||
//timepicker
|
||||
"Hour" => _("Hour"),
|
||||
"Minute" => _("Minute"),
|
||||
"Done" => _("Done"),
|
||||
//plupload ships with translation files but a lot are incomplete
|
||||
//so we will keep them here to prevent incomplete translations
|
||||
"Select files" => _("Select files"),
|
||||
"Add files to the upload queue and click the start button." => _("Add files to the upload queue and click the start button."),
|
||||
"Filename" => _("Add files to the upload queue and click the start button."),
|
||||
"Status" => _("Status"),
|
||||
"Size" => _("Status"),
|
||||
"Add Files" => _("Add Files"),
|
||||
"Stop Upload" => _("Stop Upload"),
|
||||
"Start upload" => _("Start upload"),
|
||||
"Add files" => _("Add files"),
|
||||
"Uploaded %d/%d files"=> _("Uploaded %d/%d files"),
|
||||
"N/A" => _("N/A"),
|
||||
"Drag files here." => _("Drag files here."),
|
||||
"File extension error." => _("File extension error."),
|
||||
"File size error." => _("File size error."),
|
||||
"File count error." => _("File count error."),
|
||||
"Init error." => _("Init error."),
|
||||
"HTTP Error." => _("HTTP Error."),
|
||||
"Security error." => _("Security error."),
|
||||
"Generic error." => _("Generic error."),
|
||||
"IO error." => _("IO error."),
|
||||
"File: %s" => _("File: %s"),
|
||||
"Close" => _("Close"),
|
||||
"%d files queued" => _("%d files queued"),
|
||||
"File: %f, size: %s, max file size: %m" => _("File: %f, size: %s, max file size: %m"),
|
||||
"Upload URL might be wrong or doesn't exist" => _("Upload URL might be wrong or doesn't exist"),
|
||||
"Error: File too large: " => _("Error: File too large: "),
|
||||
"Error: Invalid file extension: " => _("Error: Invalid file extension: "),
|
||||
//history translations
|
||||
"Set Default" => _("Set Default"),
|
||||
"Create Entry" => _("Create Entry"),
|
||||
"Edit History Record" => _("Edit History Record"),
|
||||
"No Show" => _("No Show"),
|
||||
"All" => _("All"),
|
||||
"Copied %s row%s to the clipboard" => _("Copied %s row%s to the clipboard"),
|
||||
"%sPrint view%sPlease use your browser's print function to print this table. Press escape when finished." => _("%sPrint view%sPlease use your browser's print function to print this table. Press escape when finished."),
|
||||
"New Show" => _("New Show"),
|
||||
"New Log Entry" => _("New Log Entry"),
|
||||
//Datatables:
|
||||
"No data available in table" => _("No data available in table"),
|
||||
"(filtered from _MAX_ total entries)" => _("(filtered from _MAX_ total entries)"),
|
||||
": activate to sort column ascending",
|
||||
": activate to sort column descending",
|
||||
//End of datatables
|
||||
|
||||
//New entries from .js "" => _(""),
|
||||
"First" => _("First"),
|
||||
"Last" => _("Last"),
|
||||
"Next" => _("Next"),
|
||||
"Previous" => _("Previous"),
|
||||
"Search:" => _("Search:"),
|
||||
"No matching records found" => _("No matching records found"),
|
||||
"Drag tracks here from the library" => _("Drag tracks here from the library"),
|
||||
"No tracks were played during the selected time period." => _("No tracks were played during the selected time period."),
|
||||
"Unpublish" => _("Unpublish"),
|
||||
"No matching results found." => _("No matching results found."),
|
||||
"Author" => _("Author"),
|
||||
"Description" => _("Description"),
|
||||
"Link" => _("Link"),
|
||||
"Publication Date" => _("Publication Date"),
|
||||
"Import Status" => _("Import Status"),
|
||||
"Actions" => _("Actions"),
|
||||
"Delete from Library" => _("Delete from Library"),
|
||||
"Successfully imported" => _("Successfully imported"),
|
||||
"No matching records found" => _("No matching records found"),
|
||||
"Show _MENU_" => _("Show _MENU_"),
|
||||
"Show _MENU_ entries" => _("Show _MENU_ entries"),
|
||||
"Showing _START_ to _END_ of _TOTAL_ entries" => _("Showing _START_ to _END_ of _TOTAL_ entries"),
|
||||
"Showing _START_ to _END_ of _TOTAL_ tracks" => _("Showing _START_ to _END_ of _TOTAL_ tracks"),
|
||||
"Showing _START_ to _END_ of _TOTAL_ track types" => _("Showing _START_ to _END_ of _TOTAL_ track types"),
|
||||
"Showing _START_ to _END_ of _TOTAL_ users" => _("Showing _START_ to _END_ of _TOTAL_ users"),
|
||||
"Showing 0 to 0 of 0 entries" => _("Showing 0 to 0 of 0 entries"),
|
||||
"Showing 0 to 0 of 0 tracks" => _("Showing 0 to 0 of 0 tracks"),
|
||||
"Showing 0 to 0 of 0 track types" => _("Showing 0 to 0 of 0 track types"),
|
||||
"(filtered from _MAX_ total track types)" => _("(filtered from _MAX_ total track types)"),
|
||||
//"This is used for tracks containing music." => _("This is used for tracks containing music."),
|
||||
"Are you sure you want to delete this tracktype?" => _("Are you sure you want to delete this tracktype?"),
|
||||
"No track types were found." => _("No track types were found."),
|
||||
"No track types found" => _("No track types found"),
|
||||
"No matching track types found" => _("No matching track types found"),
|
||||
"Enabled" => _("Enabled"),
|
||||
"Disabled" => _("Disabled"),
|
||||
"Cancel upload" => _("Cancel upload"),
|
||||
"Type" => _("Type"),
|
||||
"Autoloading playlists' contents are added to shows one hour before the show airs. <a target='_blank' href='http://libretime.org/docs/playlists'>More information</a>" => _("Autoloading playlists' contents are added to shows one hour before the show airs. <a target='_blank' href='http://libretime.org/docs/playlists'>More information</a>"),
|
||||
"Podcast settings saved" => _("Podcast settings saved"),
|
||||
"Are you sure you want to delete this user?" => _("Are you sure you want to delete this user?"),
|
||||
"Can't delete yourself!" => _("Can't delete yourself!"),
|
||||
"You haven't published any episodes!" => _("You haven't published any episodes!"),
|
||||
"You can publish your uploaded content from the 'Tracks' view." => _("You can publish your uploaded content from the 'Tracks' view."),
|
||||
"Try it now" => _("Try it now"),
|
||||
"<p>If this option is unchecked, the smartblock will schedule as many tracks as can be played out <strong>in their entirety</strong> within the specified duration. This will usually result in audio playback that is slightly less than the specified duration.</p><p>If this option is checked, the smartblock will also schedule one final track which will overflow the specified duration. This final track may be cut off mid-way if the show into which the smartblock is added finishes.</p>" => _("<p>If this option is unchecked, the smartblock will schedule as many tracks as can be played out <strong>in their entirety</strong> within the specified duration. This will usually result in audio playback that is slightly less than the specified duration.</p><p>If this option is checked, the smartblock will also schedule one final track which will overflow the specified duration. This final track may be cut off mid-way if the show into which the smartblock is added finishes.</p>"),
|
||||
"Playlist preview" => _("Playlist preview"),
|
||||
"Smart Block" => _("Smart Block"),
|
||||
"Webstream preview" => _("Webstream preview"),
|
||||
"You don't have permission to view the library." => _("You don't have permission to view the library."),
|
||||
"Now" => _("Now"),
|
||||
"Click 'New' to create one now." => _("Click 'New' to create one now."),
|
||||
"Click 'Upload' to add some now." => _("Click 'Upload' to add some now."),
|
||||
"Feed URL" => _("Feed URL"),
|
||||
"Import Date" => _("Import Date"),
|
||||
"Add New Podcast" => _("Add New Podcast"),
|
||||
"Cannot schedule outside a show.\nTry creating a show first." => _("Cannot schedule outside a show.\nTry creating a show first."),
|
||||
"No files have been uploaded yet." => _("No files have been uploaded yet."),
|
||||
//"Value is required and can't be empty" => _("Value is required and can't be empty"),
|
||||
//"mute" => _("mute"),
|
||||
//"max volume" => _("max volume"),
|
||||
|
||||
//embed player
|
||||
"On Air" => _("On Air"),
|
||||
"Off Air" => _("Off Air"),
|
||||
"Offline" => _("Offline"),
|
||||
"Nothing scheduled" => _("Nothing scheduled"),
|
||||
"Click 'Add' to create one now." => _("Click 'Add' to create one now.")
|
||||
);
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
header("Content-Type: text/javascript");
|
||||
echo "var general_dict=" . json_encode($translations);
|
||||
}
|
||||
}
|
251
legacy/application/controllers/LoginController.php
Normal file
251
legacy/application/controllers/LoginController.php
Normal file
|
@ -0,0 +1,251 @@
|
|||
<?php
|
||||
|
||||
class LoginController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$this->view->headLink(array('rel' => 'icon', 'href' => $baseUrl . 'favicon.ico?' . $CC_CONFIG['airtime_version'], 'type' => 'image/x-icon'), 'PREPEND')
|
||||
->appendStylesheet($baseUrl . 'css/bootstrap.css?' . $CC_CONFIG['airtime_version'])
|
||||
->appendStylesheet($baseUrl . 'css/redmond/jquery-ui-1.8.8.custom.css?' . $CC_CONFIG['airtime_version'])
|
||||
->appendStylesheet($baseUrl . 'css/styles.css?' . $CC_CONFIG['airtime_version']);
|
||||
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$request = $this->getRequest();
|
||||
$response = $this->getResponse();
|
||||
$stationLocale = Application_Model_Preference::GetDefaultLocale();
|
||||
|
||||
//Enable AJAX requests from www.airtime.pro for the sign-in process.
|
||||
CORSHelper::enableCrossOriginRequests($request, $response);
|
||||
|
||||
|
||||
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', $stationLocale));
|
||||
|
||||
if (Zend_Session::isStarted()) {
|
||||
|
||||
//Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization.
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
|
||||
$auth = Zend_Auth::getInstance();
|
||||
$auth->getStorage();
|
||||
|
||||
if ($auth->hasIdentity()) {
|
||||
$this->_redirect('showbuilder');
|
||||
}
|
||||
}
|
||||
|
||||
//uses separate layout without a navigation.
|
||||
$this->_helper->layout->setLayout('login');
|
||||
|
||||
$this->view->error = false;
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$form = new Application_Form_Login();
|
||||
|
||||
$message = _("Please enter your username and password.");
|
||||
|
||||
if ($request->isPost()) {
|
||||
|
||||
//Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization.
|
||||
//session_start();
|
||||
|
||||
|
||||
if ($form->isValid($request->getPost())) {
|
||||
//get the username and password from the form
|
||||
$username = $form->getValue('username');
|
||||
$password = $form->getValue('password');
|
||||
$locale = $form->getValue('locale');
|
||||
|
||||
$authAdapter = Application_Model_Auth::getAuthAdapter();
|
||||
|
||||
//pass to the adapter the submitted username and password
|
||||
$authAdapter->setIdentity($username)
|
||||
->setCredential($password);
|
||||
|
||||
$result = $auth->authenticate($authAdapter);
|
||||
if ($result->isValid()) {
|
||||
Zend_Session::regenerateId();
|
||||
//all info about this user from the login table omit only the password
|
||||
$userInfo = $authAdapter->getResultRowObject(null, 'password');
|
||||
|
||||
//the default storage is a session with namespace Zend_Auth
|
||||
$authStorage = $auth->getStorage();
|
||||
$authStorage->write($userInfo);
|
||||
|
||||
Application_Model_LoginAttempts::resetAttempts($_SERVER['REMOTE_ADDR']);
|
||||
Application_Model_Subjects::resetLoginAttempts($username);
|
||||
|
||||
//set the user locale in case user changed it in when logging in
|
||||
Application_Model_Preference::SetUserLocale($locale);
|
||||
|
||||
$this->_redirect('showbuilder');
|
||||
} else {
|
||||
$form = $this->loginError($username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->form = $form;
|
||||
$this->view->airtimeVersion = $CC_CONFIG['airtime_version'];
|
||||
$this->view->airtimeCopyright = AIRTIME_COPYRIGHT_DATE;
|
||||
if (isset($CC_CONFIG['demo'])) {
|
||||
$this->view->demo = $CC_CONFIG['demo'];
|
||||
}
|
||||
}
|
||||
|
||||
public function logoutAction()
|
||||
{
|
||||
//Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization.
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
|
||||
$auth = Zend_Auth::getInstance();
|
||||
$auth->clearIdentity();
|
||||
// Unset all session variables relating to CSRF prevention on logout
|
||||
$csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
|
||||
$csrf_namespace->unsetAll();
|
||||
$this->_redirect('showbuilder/index');
|
||||
}
|
||||
|
||||
public function passwordRestoreAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl . 'js/airtime/login/password-restore.js?' . $CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
|
||||
$request = $this->getRequest();
|
||||
$stationLocale = Application_Model_Preference::GetDefaultLocale();
|
||||
|
||||
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', $stationLocale));
|
||||
|
||||
//uses separate layout without a navigation.
|
||||
$this->_helper->layout->setLayout('login');
|
||||
|
||||
$form = new Application_Form_PasswordRestore();
|
||||
|
||||
$request = $this->getRequest();
|
||||
if ($request->isPost()) {
|
||||
if ($form->isValid($request->getPost())) {
|
||||
$query = CcSubjsQuery::create();
|
||||
$username = $form->username->getValue();
|
||||
$email = $form->email->getValue();
|
||||
|
||||
if (empty($username)) {
|
||||
$query->filterByDbEmail($email);
|
||||
} else if (empty($email)) {
|
||||
$query->filterByDbLogin($username);
|
||||
} else {
|
||||
$query->filterByDbEmail($email)
|
||||
->filterByDbLogin($username);
|
||||
}
|
||||
$user = $query->findOne();
|
||||
|
||||
if (!empty($user)) {
|
||||
$auth = new Application_Model_Auth();
|
||||
|
||||
$success = $auth->sendPasswordRestoreLink($user, $this->view);
|
||||
if ($success) {
|
||||
$this->_helper->redirector('password-restore-after', 'login');
|
||||
} else {
|
||||
$form->email->addError($this->view->translate(_("Email could not be sent. Check your mail server settings and ensure it has been configured properly.")));
|
||||
}
|
||||
} else {
|
||||
$form->email->addError($this->view->translate(_("That username or email address could not be found.")));
|
||||
}
|
||||
} else { //Form is not valid
|
||||
$form->email->addError($this->view->translate(_("There was a problem with the username or email address you entered.")));
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->form = $form;
|
||||
}
|
||||
|
||||
public function passwordRestoreAfterAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$stationLocale = Application_Model_Preference::GetDefaultLocale();
|
||||
|
||||
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', $stationLocale));
|
||||
|
||||
//uses separate layout without a navigation.
|
||||
$this->_helper->layout->setLayout('login');
|
||||
}
|
||||
|
||||
public function passwordChangeAction()
|
||||
{
|
||||
//uses separate layout without a navigation.
|
||||
$this->_helper->layout->setLayout('login');
|
||||
|
||||
$request = $this->getRequest();
|
||||
$token = $request->getParam("token", false);
|
||||
$user_id = $request->getParam("user_id", 0);
|
||||
|
||||
$form = new Application_Form_PasswordChange();
|
||||
$auth = new Application_Model_Auth();
|
||||
$user = CcSubjsQuery::create()->findPK($user_id);
|
||||
|
||||
$stationLocale = Application_Model_Preference::GetDefaultLocale();
|
||||
|
||||
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', $stationLocale));
|
||||
|
||||
//check validity of token
|
||||
if (!$auth->checkToken($user_id, $token, 'password.restore')) {
|
||||
Logging::debug("token not valid");
|
||||
$this->_helper->redirector('index', 'login');
|
||||
}
|
||||
|
||||
if ($request->isPost() && $form->isValid($request->getPost())) {
|
||||
|
||||
$user->setDbPass(md5($form->password->getValue()));
|
||||
$user->save();
|
||||
|
||||
$auth->invalidateTokens($user, 'password.restore');
|
||||
|
||||
$zend_auth = Zend_Auth::getInstance();
|
||||
$zend_auth->clearIdentity();
|
||||
|
||||
$authAdapter = Application_Model_Auth::getAuthAdapter();
|
||||
$authAdapter->setIdentity($user->getDbLogin())
|
||||
->setCredential($form->password->getValue());
|
||||
|
||||
$zend_auth->authenticate($authAdapter);
|
||||
|
||||
//all info about this user from the login table omit only the password
|
||||
$userInfo = $authAdapter->getResultRowObject(null, 'password');
|
||||
|
||||
//the default storage is a session with namespace Zend_Auth
|
||||
$authStorage = $zend_auth->getStorage();
|
||||
$authStorage->write($userInfo);
|
||||
|
||||
$this->_helper->redirector('index', 'showbuilder');
|
||||
}
|
||||
|
||||
$this->view->form = $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* populates view with results from a login error and adds a new form
|
||||
*
|
||||
* @param String $username user that failed to login
|
||||
* @return new form
|
||||
*/
|
||||
private function loginError($username)
|
||||
{
|
||||
$this->view->message = _("Wrong username or password provided. Please try again.");
|
||||
Application_Model_Subjects::increaseLoginAttempts($username);
|
||||
Application_Model_LoginAttempts::increaseAttempts($_SERVER['REMOTE_ADDR']);
|
||||
$form = new Application_Form_Login();
|
||||
$this->view->error = true;
|
||||
return $form;
|
||||
}
|
||||
}
|
690
legacy/application/controllers/PlaylistController.php
Normal file
690
legacy/application/controllers/PlaylistController.php
Normal file
|
@ -0,0 +1,690 @@
|
|||
<?php
|
||||
|
||||
|
||||
class PlaylistController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('add-items', 'json')
|
||||
->addActionContext('move-items', 'json')
|
||||
->addActionContext('delete-items', 'json')
|
||||
->addActionContext('set-fade', 'json')
|
||||
->addActionContext('set-crossfade', 'json')
|
||||
->addActionContext('set-cue', 'json')
|
||||
->addActionContext('new', 'json')
|
||||
->addActionContext('edit', 'json')
|
||||
->addActionContext('delete', 'json')
|
||||
->addActionContext('close-playlist', 'json')
|
||||
->addActionContext('play', 'json')
|
||||
->addActionContext('set-playlist-fades', 'json')
|
||||
->addActionContext('get-playlist-fades', 'json')
|
||||
->addActionContext('set-playlist-name', 'json')
|
||||
->addActionContext('set-playlist-description', 'json')
|
||||
->addActionContext('playlist-preview', 'json')
|
||||
->addActionContext('get-playlist', 'json')
|
||||
->addActionContext('save', 'json')
|
||||
->addActionContext('smart-block-generate', 'json')
|
||||
->addActionContext('smart-block-shuffle', 'json')
|
||||
->addActionContext('get-block-info', 'json')
|
||||
->addActionContext('shuffle', 'json')
|
||||
->addActionContext('empty-content', 'json')
|
||||
->addActionContext('change-playlist', 'json')
|
||||
->initContext();
|
||||
|
||||
//This controller writes to the session all over the place, so we're going to reopen it for writing here.
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
}
|
||||
|
||||
private function getPlaylist($p_type)
|
||||
{
|
||||
$obj = null;
|
||||
$objInfo = Application_Model_Library::getObjInfo($p_type);
|
||||
|
||||
$obj_sess = new Zend_Session_Namespace(UI_PLAYLISTCONTROLLER_OBJ_SESSNAME);
|
||||
|
||||
if (isset($obj_sess->id)) {
|
||||
$obj = new $objInfo['className']($obj_sess->id);
|
||||
|
||||
$modified = $this->_getParam('modified', null);
|
||||
if ($obj->getLastModified("U") !== $modified) {
|
||||
$this->createFullResponse($obj);
|
||||
throw new PlaylistOutDatedException(sprintf(_("You are viewing an older version of %s"), $obj->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
private function createUpdateResponse($obj, $formIsValid = false)
|
||||
{
|
||||
$formatter = new LengthFormatter($obj->getLength());
|
||||
$this->view->length = $formatter->format();
|
||||
|
||||
$this->view->obj = $obj;
|
||||
$this->view->contents = $obj->getContents();
|
||||
if ($formIsValid && $obj instanceof Application_Model_Block) {
|
||||
$this->view->poolCount = $obj->getListofFilesMeetCriteria()['count'];
|
||||
}
|
||||
$this->view->showPoolCount = true;
|
||||
$this->view->html = $this->view->render('playlist/update.phtml');
|
||||
$this->view->name = $obj->getName();
|
||||
$this->view->description = $obj->getDescription();
|
||||
$this->view->modified = $obj->getLastModified("U");
|
||||
unset($this->view->obj);
|
||||
}
|
||||
|
||||
private function createFullResponse($obj = null, $isJson = false,
|
||||
$formIsValid = false)
|
||||
{
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
if (!$isAdminOrPM && $obj->getCreatorId() != $user->getId()) {
|
||||
$this->view->objType = $obj instanceof Application_Model_Block ? "block" : "playlist";
|
||||
$this->view->obj = $obj;
|
||||
$this->view->html = $this->view->render('playlist/permission-denied.phtml');
|
||||
return;
|
||||
}
|
||||
|
||||
$isBlock = false;
|
||||
$viewPath = 'playlist/playlist.phtml';
|
||||
if ($obj instanceof Application_Model_Block) {
|
||||
$isBlock = true;
|
||||
$viewPath = 'playlist/smart-block.phtml';
|
||||
}
|
||||
if (isset($obj)) {
|
||||
$formatter = new LengthFormatter($obj->getLength());
|
||||
$this->view->length = $formatter->format();
|
||||
|
||||
if ($isBlock) {
|
||||
$form = new Application_Form_SmartBlockCriteria();
|
||||
$form->removeDecorator('DtDdWrapper');
|
||||
$form->startForm($obj->getId(), $formIsValid);
|
||||
$this->view->form = $form;
|
||||
$this->view->obj = $obj;
|
||||
//$this->view->type = "sb";
|
||||
$this->view->id = $obj->getId();
|
||||
|
||||
if ($isJson) {
|
||||
return $this->view->render($viewPath);
|
||||
} else {
|
||||
$this->view->html = $this->view->render($viewPath);
|
||||
}
|
||||
} else {
|
||||
$this->view->obj = $obj;
|
||||
//$this->view->type = "pl";
|
||||
$this->view->id = $obj->getId();
|
||||
if ($isJson) {
|
||||
return $this->view->html = $this->view->render($viewPath);
|
||||
} else {
|
||||
$this->view->html = $this->view->render($viewPath);
|
||||
}
|
||||
unset($this->view->obj);
|
||||
}
|
||||
} else {
|
||||
if ($isJson) {
|
||||
return $this->view->render($viewPath);
|
||||
} else {
|
||||
$this->view->html = $this->view->render($viewPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function playlistOutdated($e)
|
||||
{
|
||||
$this->view->error = $e->getMessage();
|
||||
}
|
||||
|
||||
private function blockDynamic($obj)
|
||||
{
|
||||
$this->view->error = _("You cannot add tracks to dynamic blocks.");
|
||||
$this->createFullResponse($obj);
|
||||
}
|
||||
|
||||
private function playlistNotFound($p_type, $p_isJson = false)
|
||||
{
|
||||
$p_type = ucfirst($p_type);
|
||||
$this->view->error = sprintf(_("%s not found"), $p_type);
|
||||
|
||||
Logging::info("{$p_type} not found");
|
||||
Application_Model_Library::changePlaylist(null, $p_type);
|
||||
|
||||
if (!$p_isJson) {
|
||||
$this->createFullResponse(null);
|
||||
} else {
|
||||
$this->_helper->json->sendJson(array("error"=>$this->view->error, "result"=>1, "html"=>$this->createFullResponse(null, $p_isJson)));
|
||||
}
|
||||
}
|
||||
|
||||
private function playlistNoPermission($p_type)
|
||||
{
|
||||
$this->view->error = sprintf(_("You don't have permission to delete selected %s(s)."), $p_type);
|
||||
$this->changePlaylist(null, $p_type);
|
||||
$this->createFullResponse(null);
|
||||
}
|
||||
|
||||
private function playlistUnknownError($e)
|
||||
{
|
||||
$this->view->error = _("Something went wrong.");
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
|
||||
private function wrongTypeToBlock($obj)
|
||||
{
|
||||
$this->view->error = _("You can only add tracks to smart block.");
|
||||
$this->createFullResponse($obj);
|
||||
}
|
||||
|
||||
private function wrongTypeToPlaylist($obj)
|
||||
{
|
||||
$this->view->error = _("You can only add tracks, smart blocks, and webstreams to playlists.");
|
||||
$this->createFullResponse($obj);
|
||||
}
|
||||
|
||||
public function newAction()
|
||||
{
|
||||
//$pl_sess = $this->pl_sess;
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$type = $this->_getParam('type');
|
||||
|
||||
$objInfo = Application_Model_Library::getObjInfo($type);
|
||||
|
||||
$name = _('Untitled Playlist');
|
||||
if ($type == 'block') {
|
||||
$name = _('Untitled Smart Block');
|
||||
}
|
||||
|
||||
$obj = new $objInfo['className']();
|
||||
$obj->setName($name);
|
||||
$obj->setMetadata('dc:creator', $userInfo->id);
|
||||
|
||||
Application_Model_Library::changePlaylist($obj->getId(), $type);
|
||||
$this->createFullResponse($obj);
|
||||
}
|
||||
|
||||
public function changePlaylistAction() {
|
||||
$this->view->layout()->disableLayout(); // Don't inject the standard Now Playing header.
|
||||
$this->_helper->viewRenderer->setNoRender(true); // Don't use (phtml) templates
|
||||
|
||||
$id = $this->_getParam('id', null);
|
||||
$type = $this->_getParam('type');
|
||||
|
||||
Application_Model_Library::changePlaylist($id, $type);
|
||||
}
|
||||
|
||||
public function editAction()
|
||||
{
|
||||
$id = $this->_getParam('id', null);
|
||||
$type = $this->_getParam('type');
|
||||
$objInfo = Application_Model_Library::getObjInfo($type);
|
||||
|
||||
// if (!is_null($id)) {
|
||||
Application_Model_Library::changePlaylist($id, $type);
|
||||
// }
|
||||
|
||||
try {
|
||||
$obj = new $objInfo['className']($id);
|
||||
$this->createFullResponse($obj);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteAction()
|
||||
{
|
||||
$ids = $this->_getParam('ids');
|
||||
$ids = (!is_array($ids)) ? array($ids) : $ids;
|
||||
$type = $this->_getParam('type');
|
||||
|
||||
$obj = null;
|
||||
|
||||
$objInfo = Application_Model_Library::getObjInfo($type);
|
||||
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
|
||||
$obj_sess = new Zend_Session_Namespace(
|
||||
UI_PLAYLISTCONTROLLER_OBJ_SESSNAME);
|
||||
|
||||
try {
|
||||
Logging::info("Currently active {$type} {$obj_sess->id}");
|
||||
if (in_array($obj_sess->id, $ids)) {
|
||||
Logging::info("Deleting currently active {$type}");
|
||||
// Application_Model_Library::changePlaylist(null, $type);
|
||||
} else {
|
||||
Logging::info("Not deleting currently active {$type}");
|
||||
$obj = new $objInfo['className']($obj_sess->id);
|
||||
}
|
||||
|
||||
if (strcmp($objInfo['className'], 'Application_Model_Playlist')==0) {
|
||||
Application_Model_Playlist::deletePlaylists($ids, $userInfo->id);
|
||||
} else {
|
||||
Application_Model_Block::deleteBlocks($ids, $userInfo->id);
|
||||
}
|
||||
$this->createFullResponse($obj);
|
||||
} catch (PlaylistNoPermissionException $e) {
|
||||
$this->playlistNoPermission($type);
|
||||
} catch (BlockNoPermissionException $e) {
|
||||
$this->playlistNoPermission($type);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function closePlaylistAction() {
|
||||
$type = $this->_getParam('type');
|
||||
$obj = null;
|
||||
Application_Model_Library::changePlaylist($obj, $type);
|
||||
$this->createFullResponse($obj);
|
||||
}
|
||||
|
||||
public function addItemsAction()
|
||||
{
|
||||
$ids = $this->_getParam('aItems', array());
|
||||
$ids = (!is_array($ids)) ? array($ids) : $ids;
|
||||
$afterItem = $this->_getParam('afterItem', null);
|
||||
$addType = $this->_getParam('type', 'after');
|
||||
// this is the obj type of destination
|
||||
$obj_type = $this->_getParam('obj_type');
|
||||
|
||||
try {
|
||||
$obj = $this->getPlaylist($obj_type);
|
||||
if ($obj_type == 'playlist') {
|
||||
foreach ($ids as $id) {
|
||||
if (is_array($id) && isset($id[1])) {
|
||||
if ($id[1] == 'playlist') {
|
||||
throw new WrongTypeToPlaylistException;
|
||||
}
|
||||
}
|
||||
}
|
||||
$obj->addAudioClips($ids, $afterItem, $addType);
|
||||
} elseif ($obj->isStatic()) {
|
||||
// if the dest is a block object
|
||||
//check if any items are playlists
|
||||
foreach ($ids as $id) {
|
||||
if (is_array($id) && isset($id[1])) {
|
||||
if ($id[1] != 'audioclip') {
|
||||
throw new WrongTypeToBlockException;
|
||||
}
|
||||
}
|
||||
}
|
||||
$obj->addAudioClips($ids, $afterItem, $addType);
|
||||
} else {
|
||||
throw new BlockDynamicException;
|
||||
}
|
||||
$this->createUpdateResponse($obj);
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($obj_type);
|
||||
} catch (WrongTypeToBlockException $e) {
|
||||
$this->wrongTypeToBlock($obj);
|
||||
} catch (WrongTypeToPlaylistException $e) {
|
||||
$this->wrongTypeToPlaylist($obj);
|
||||
} catch (BlockDynamicException $e) {
|
||||
$this->blockDynamic($obj);
|
||||
} catch (BlockNotFoundException $e) {
|
||||
$this->playlistNotFound($obj_type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function moveItemsAction()
|
||||
{
|
||||
$ids = $this->_getParam('ids');
|
||||
$ids = (!is_array($ids)) ? array($ids) : $ids;
|
||||
$afterItem = $this->_getParam('afterItem', null);
|
||||
$type = $this->_getParam('obj_type');
|
||||
|
||||
try {
|
||||
$obj = $this->getPlaylist($type);
|
||||
$obj->moveAudioClips($ids, $afterItem);
|
||||
$this->createUpdateResponse($obj);
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteItemsAction()
|
||||
{
|
||||
$ids = $this->_getParam('ids');
|
||||
$ids = (!is_array($ids)) ? array($ids) : $ids;
|
||||
$modified = $this->_getParam('modified');
|
||||
$type = $this->_getParam('obj_type');
|
||||
|
||||
try {
|
||||
$obj = $this->getPlaylist($type);
|
||||
$obj->delAudioClips($ids);
|
||||
$this->createUpdateResponse($obj);
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function emptyContentAction()
|
||||
{
|
||||
$type = $this->_getParam('obj_type');
|
||||
try {
|
||||
$obj = $this->getPlaylist($type);
|
||||
if ($type == 'playlist') {
|
||||
$obj->deleteAllFilesFromPlaylist();
|
||||
} else {
|
||||
$obj->deleteAllFilesFromBlock();
|
||||
}
|
||||
$this->createUpdateResponse($obj);
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function setCueAction()
|
||||
{
|
||||
$id = $this->_getParam('id');
|
||||
$cueIn = $this->_getParam('cueIn', null);
|
||||
$cueOut = $this->_getParam('cueOut', null);
|
||||
$type = $this->_getParam('type');
|
||||
|
||||
try {
|
||||
$obj = $this->getPlaylist($type);
|
||||
$response = $obj->changeClipLength($id, $cueIn, $cueOut);
|
||||
|
||||
if (!isset($response["error"])) {
|
||||
$this->view->response = $response;
|
||||
$this->createUpdateResponse($obj);
|
||||
} else {
|
||||
$this->view->cue_error = $response["error"];
|
||||
$this->view->code = $response["type"];
|
||||
}
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function setFadeAction()
|
||||
{
|
||||
$id = $this->_getParam('id');
|
||||
$fadeIn = $this->_getParam('fadeIn', null);
|
||||
$fadeOut = $this->_getParam('fadeOut', null);
|
||||
$type = $this->_getParam('type');
|
||||
|
||||
try {
|
||||
$obj = $this->getPlaylist($type);
|
||||
$response = $obj->changeFadeInfo($id, $fadeIn, $fadeOut);
|
||||
|
||||
if (!isset($response["error"])) {
|
||||
$this->createUpdateResponse($obj);
|
||||
$this->view->response = $response;
|
||||
} else {
|
||||
$this->view->fade_error = $response["error"];
|
||||
}
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function setCrossfadeAction()
|
||||
{
|
||||
$id1 = $this->_getParam('id1', null);
|
||||
$id2 = $this->_getParam('id2', null);
|
||||
$type = $this->_getParam('type');
|
||||
$fadeIn = $this->_getParam('fadeIn', 0);
|
||||
$fadeOut = $this->_getParam('fadeOut', 0);
|
||||
$offset = $this->_getParam('offset', 0);
|
||||
|
||||
try {
|
||||
$obj = $this->getPlaylist($type);
|
||||
$response = $obj->createCrossfade($id1, $fadeOut, $id2, $fadeIn, $offset);
|
||||
|
||||
if (!isset($response["error"])) {
|
||||
$this->createUpdateResponse($obj);
|
||||
} else {
|
||||
$this->view->error = $response["error"];
|
||||
}
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function getPlaylistFadesAction()
|
||||
{
|
||||
$type = $this->_getParam('type');
|
||||
try {
|
||||
$obj = $this->getPlaylist($type);
|
||||
$fades = $obj->getFadeInfo(0);
|
||||
$this->view->fadeIn = $fades[0];
|
||||
|
||||
$fades = $obj->getFadeInfo($obj->getSize()-1);
|
||||
$this->view->fadeOut = $fades[1];
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The playlist fades are stored in the elements themselves.
|
||||
* The fade in is set to the first elements fade in and
|
||||
* the fade out is set to the last elements fade out.
|
||||
**/
|
||||
public function setPlaylistFadesAction()
|
||||
{
|
||||
$fadeIn = $this->_getParam('fadeIn', null);
|
||||
$fadeOut = $this->_getParam('fadeOut', null);
|
||||
$type = $this->_getParam('type');
|
||||
|
||||
try {
|
||||
$obj = $this->getPlaylist($type);
|
||||
$obj->setfades($fadeIn, $fadeOut);
|
||||
$this->view->modified = $obj->getLastModified("U");
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function setPlaylistNameDescAction()
|
||||
{
|
||||
$name = $this->_getParam('name', _('Unknown Playlist'));
|
||||
$description = $this->_getParam('description', "");
|
||||
$type = $this->_getParam('type');
|
||||
|
||||
try {
|
||||
$obj = $this->getPlaylist($type);
|
||||
$obj->setName(trim($name));
|
||||
$obj->setDescription($description);
|
||||
$this->view->description = $description;
|
||||
$this->view->playlistName = $name;
|
||||
$this->view->modified = $obj->getLastModified("U");
|
||||
} catch (PlaylistOutDatedException $e) {
|
||||
$this->playlistOutdated($e);
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound($type, true);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function saveAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getPost();
|
||||
$result = array();
|
||||
|
||||
if ($params['type'] == 'block') {
|
||||
try {
|
||||
$bl = new Application_Model_Block($params['obj_id']);
|
||||
} catch (BlockNotFoundException $e) {
|
||||
$this->playlistNotFound('block', true);
|
||||
}
|
||||
$form = new Application_Form_SmartBlockCriteria();
|
||||
$form->startForm($params['obj_id']);
|
||||
if ($form->isValid($params)) {
|
||||
$this->setPlaylistNameDescAction();
|
||||
$bl->saveSmartBlockCriteria($params['data']);
|
||||
$this->createUpdateResponse($bl, true);
|
||||
$this->view->result = 0;
|
||||
/*
|
||||
$result['html'] = $this->createFullResponse($bl, true, true);
|
||||
*/
|
||||
} else {
|
||||
$this->view->form = $form;
|
||||
$this->view->unsavedName = $params['name'];
|
||||
$this->view->unsavedDesc = $params['description'];
|
||||
$viewPath = 'playlist/smart-block.phtml';
|
||||
$this->view->obj = $bl;
|
||||
$this->view->id = $bl->getId();
|
||||
$this->view->html = $this->view->render($viewPath);
|
||||
$this->view->result = 1;
|
||||
}
|
||||
$this->view->name = $bl->getName();
|
||||
//$this->view->type = "sb";
|
||||
$this->view->id = $bl->getId();
|
||||
$this->view->modified = $bl->getLastModified("U");
|
||||
} else if ($params['type'] == 'playlist') {
|
||||
$this->setPlaylistNameDescAction();
|
||||
$this->view->modified = $this->view->modified;
|
||||
$this->view->name = $params['name'];
|
||||
}
|
||||
|
||||
|
||||
//$this->_helper->json->sendJson($result);
|
||||
}
|
||||
|
||||
public function smartBlockGenerateAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getPost();
|
||||
|
||||
//make sure block exists
|
||||
try {
|
||||
$bl = new Application_Model_Block($params['obj_id']);
|
||||
|
||||
$form = new Application_Form_SmartBlockCriteria();
|
||||
$form->startForm($params['obj_id']);
|
||||
if ($form->isValid($params)) {
|
||||
$result = $bl->generateSmartBlock($params['data']);
|
||||
$this->view->result = $result['result'];
|
||||
$this->createUpdateResponse($bl, true);
|
||||
#$this->_helper->json->sendJson(array("result"=>0, "html"=>$this->createFullResponse($bl, true, true)));
|
||||
} else {
|
||||
$this->view->obj = $bl;
|
||||
$this->view->id = $bl->getId();
|
||||
$this->view->form = $form;
|
||||
$this->createFullResponse($bl, false, true);
|
||||
}
|
||||
} catch (BlockNotFoundException $e) {
|
||||
$this->playlistNotFound('block', true);
|
||||
} catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function smartBlockShuffleAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getPost();
|
||||
try {
|
||||
$bl = new Application_Model_Block($params['obj_id']);
|
||||
$result = $bl->shuffleSmartBlock();
|
||||
|
||||
$this->view->result = $result["result"];
|
||||
$this->createUpdateResponse($bl,true);
|
||||
|
||||
/*
|
||||
if ($result['result'] == 0) {
|
||||
$this->_helper->json->sendJson(array(
|
||||
"result"=>0,
|
||||
"contents" => $bl->getContents());
|
||||
///"html"=>$this->viwe));
|
||||
|
||||
} else {
|
||||
$this->_helper->json->sendJson($result);
|
||||
}*/
|
||||
} catch (BlockNotFoundException $e) {
|
||||
$this->playlistNotFound('block', true);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function shuffleAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getPost();
|
||||
try {
|
||||
$pl = new Application_Model_Playlist($params['obj_id']);
|
||||
$result = $pl->shuffle();
|
||||
|
||||
$this->view->result = $result["result"];
|
||||
$this->createUpdateResponse($pl,true);
|
||||
/*
|
||||
if ($result['result'] == 0) {
|
||||
$this->_helper->json->sendJson(array(
|
||||
"result"=>0,
|
||||
"contents" => $pl->getContents(),
|
||||
"html"=>$this->createUpdateResponse($pl, true)));
|
||||
} else {
|
||||
$this->_helper->json->sendJson($result);
|
||||
}*/
|
||||
} catch (PlaylistNotFoundException $e) {
|
||||
$this->playlistNotFound('block', true);
|
||||
} catch (Exception $e) {
|
||||
$this->playlistUnknownError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockInfoAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getPost();
|
||||
$bl = new Application_Model_Block($params['id']);
|
||||
if ($bl->isStatic()) {
|
||||
$out = $bl->getContents();
|
||||
$out['isStatic'] = true;
|
||||
} else {
|
||||
$out = $bl->getCriteria();
|
||||
$out['isStatic'] = false;
|
||||
}
|
||||
$this->_helper->json->sendJson($out);
|
||||
}
|
||||
}
|
||||
class WrongTypeToBlockException extends Exception {}
|
||||
class WrongTypeToPlaylistException extends Exception {}
|
||||
class BlockDynamicException extends Exception {}
|
253
legacy/application/controllers/PlayouthistoryController.php
Normal file
253
legacy/application/controllers/PlayouthistoryController.php
Normal file
|
@ -0,0 +1,253 @@
|
|||
<?php
|
||||
|
||||
class PlayouthistoryController extends Zend_Controller_Action
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext
|
||||
->addActionContext('file-history-feed', 'json')
|
||||
->addActionContext('item-history-feed', 'json')
|
||||
->addActionContext('show-history-feed', 'json')
|
||||
->addActionContext('edit-file-item', 'json')
|
||||
->addActionContext('create-list-item', 'json')
|
||||
->addActionContext('edit-list-item', 'json')
|
||||
->addActionContext('delete-list-item', 'json')
|
||||
->addActionContext('delete-list-items', 'json')
|
||||
->addActionContext('update-list-item', 'json')
|
||||
->addActionContext('update-file-item', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Analytics');
|
||||
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($this->getRequest());
|
||||
|
||||
$userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
|
||||
$startsDT->setTimezone($userTimezone);
|
||||
$endsDT->setTimezone($userTimezone);
|
||||
|
||||
$form = new Application_Form_DateRange();
|
||||
$form->populate(array(
|
||||
'his_date_start' => $startsDT->format("Y-m-d"),
|
||||
'his_time_start' => $startsDT->format("H:i"),
|
||||
'his_date_end' => $endsDT->format("Y-m-d"),
|
||||
'his_time_end' => $endsDT->format("H:i")
|
||||
));
|
||||
|
||||
$this->view->date_form = $form;
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/contextmenu/jquery.contextMenu.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/datatables/js/jquery.dataTables.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.pluginAPI.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.fnSetFilteringDelay.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/timepicker/jquery.ui.timepicker.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/bootstrap-datetime/bootstrap-datetimepicker.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/buttons/buttons.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/utilities/utilities.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/CSVexport.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/pdfmake.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/vfs_fonts.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/playouthistory/historytable.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/bootstrap-datetimepicker.min.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.ui.timepicker.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/playouthistory.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/history_styles.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.contextMenu.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
//set datatables columns for display of data.
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$columns = json_encode($historyService->getDatatablesLogSheetColumns());
|
||||
$script = "localStorage.setItem( 'datatables-historyitem-aoColumns', JSON.stringify($columns) ); ";
|
||||
|
||||
$columns = json_encode($historyService->getDatatablesFileSummaryColumns());
|
||||
$script.= "localStorage.setItem( 'datatables-historyfile-aoColumns', JSON.stringify($columns) );";
|
||||
$this->view->headScript()->appendScript($script);
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
$this->view->userType = $user->getType();
|
||||
}
|
||||
|
||||
public function fileHistoryFeedAction()
|
||||
{
|
||||
try {
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getParams();
|
||||
$instance = $request->getParam("instance_id", null);
|
||||
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($request);
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$r = $historyService->getFileSummaryData($startsDT, $endsDT, $params);
|
||||
|
||||
$this->view->sEcho = $r["sEcho"];
|
||||
$this->view->iTotalDisplayRecords = $r["iTotalDisplayRecords"];
|
||||
$this->view->iTotalRecords = $r["iTotalRecords"];
|
||||
$this->view->history = $r["history"];
|
||||
$this->view->history = SecurityHelper::htmlescape_recursive($this->view->history);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function itemHistoryFeedAction()
|
||||
{
|
||||
try {
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getParams();
|
||||
$instance = $request->getParam("instance_id", null);
|
||||
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($request);
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$r = $historyService->getPlayedItemData($startsDT, $endsDT, $params, $instance);
|
||||
|
||||
$this->view->sEcho = $r["sEcho"];
|
||||
$this->view->iTotalDisplayRecords = $r["iTotalDisplayRecords"];
|
||||
$this->view->iTotalRecords = $r["iTotalRecords"];
|
||||
$this->view->history = $r["history"];
|
||||
$this->view->history = SecurityHelper::htmlescape_recursive($this->view->history);
|
||||
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function showHistoryFeedAction()
|
||||
{
|
||||
try {
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getParams();
|
||||
$instance = $request->getParam("instance_id", null);
|
||||
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($request);
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$shows = $historyService->getShowList($startsDT, $endsDT);
|
||||
$shows = SecurityHelper::htmlescape_recursive($shows);
|
||||
|
||||
$this->_helper->json->sendJson($shows);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function editFileItemAction()
|
||||
{
|
||||
$file_id = $this->_getParam('id');
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$form = $historyService->makeHistoryFileForm($file_id);
|
||||
|
||||
$this->view->form = $form;
|
||||
$this->view->dialog = $this->view->render('playouthistory/dialog.phtml');
|
||||
|
||||
unset($this->view->form);
|
||||
}
|
||||
|
||||
public function createListItemAction()
|
||||
{
|
||||
try {
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getPost();
|
||||
Logging::info($params);
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$json = $historyService->createPlayedItem($params);
|
||||
|
||||
if (isset($json["form"])) {
|
||||
$this->view->form = $json["form"];
|
||||
$json["form"] = $this->view->render('playouthistory/dialog.phtml');
|
||||
|
||||
unset($this->view->form);
|
||||
}
|
||||
|
||||
$this->_helper->json->sendJson($json);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function editListItemAction()
|
||||
{
|
||||
$id = $this->_getParam('id', null);
|
||||
|
||||
$populate = isset($id) ? true : false;
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$form = $historyService->makeHistoryItemForm($id, $populate);
|
||||
|
||||
$this->view->form = $form;
|
||||
$this->view->dialog = $this->view->render('playouthistory/dialog.phtml');
|
||||
|
||||
unset($this->view->form);
|
||||
}
|
||||
|
||||
public function deleteListItemAction()
|
||||
{
|
||||
$history_id = $this->_getParam('id');
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$historyService->deletePlayedItem($history_id);
|
||||
}
|
||||
|
||||
public function deleteListItemsAction()
|
||||
{
|
||||
$history_ids = $this->_getParam('ids');
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$historyService->deletePlayedItems($history_ids);
|
||||
}
|
||||
|
||||
public function updateListItemAction()
|
||||
{
|
||||
try {
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getPost();
|
||||
Logging::info($params);
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$json = $historyService->editPlayedItem($params);
|
||||
|
||||
if (isset($json["form"])) {
|
||||
$this->view->form = $json["form"];
|
||||
$json["form"] = $this->view->render('playouthistory/dialog.phtml');
|
||||
|
||||
unset($this->view->form);
|
||||
}
|
||||
|
||||
$this->_helper->json->sendJson($json);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function updateFileItemAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getPost();
|
||||
Logging::info($params);
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$json = $historyService->editPlayedFile($params);
|
||||
|
||||
$this->_helper->json->sendJson($json);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
class PlayouthistorytemplateController extends Zend_Controller_Action
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext
|
||||
->addActionContext('create-template', 'json')
|
||||
->addActionContext('update-template', 'json')
|
||||
->addActionContext('delete-template', 'json')
|
||||
->addActionContext('set-template-default', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Analytics');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/playouthistory/template.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/history_styles.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$this->view->template_list = $historyService->getListItemTemplates();
|
||||
$this->view->template_file = $historyService->getFileTemplates();
|
||||
$this->view->configured = $historyService->getConfiguredTemplateIds();
|
||||
}
|
||||
|
||||
public function configureTemplateAction() {
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Analytics');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/playouthistory/configuretemplate.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/history_styles.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
try {
|
||||
|
||||
$templateId = $this->_getParam('id');
|
||||
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$template = $historyService->loadTemplate($templateId);
|
||||
|
||||
$templateType = $template["type"];
|
||||
$supportedTypes = $historyService->getSupportedTemplateTypes();
|
||||
|
||||
if (!in_array($templateType, $supportedTypes)) {
|
||||
throw new Exception("Error: $templateType is not supported.");
|
||||
}
|
||||
|
||||
$getMandatoryFields = "mandatory".ucfirst($templateType)."Fields";
|
||||
$mandatoryFields = $historyService->$getMandatoryFields();
|
||||
|
||||
$this->view->template_id = $templateId;
|
||||
$this->view->template_name = $template["name"];
|
||||
$this->view->template_fields = $template["fields"];
|
||||
$this->view->template_type = $templateType;
|
||||
$this->view->fileMD = $historyService->getFileMetadataTypes();
|
||||
$this->view->fields = $historyService->getFieldTypes();
|
||||
$this->view->required_fields = $mandatoryFields;
|
||||
$this->view->configured = $historyService->getConfiguredTemplateIds();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info("Error?");
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
|
||||
$this->_forward('index', 'playouthistorytemplate');
|
||||
}
|
||||
}
|
||||
|
||||
public function createTemplateAction()
|
||||
{
|
||||
$templateType = $this->_getParam('type', null);
|
||||
|
||||
$request = $this->getRequest();
|
||||
$params = $request->getPost();
|
||||
|
||||
try {
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$supportedTypes = $historyService->getSupportedTemplateTypes();
|
||||
|
||||
if (!in_array($templateType, $supportedTypes)) {
|
||||
throw new Exception("Error: $templateType is not supported.");
|
||||
}
|
||||
|
||||
$id = $historyService->createTemplate($params);
|
||||
|
||||
$this->view->url = $this->view->baseUrl("Playouthistorytemplate/configure-template/id/{$id}");
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
|
||||
$this->view->error = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public function setTemplateDefaultAction()
|
||||
{
|
||||
$templateId = $this->_getParam('id', null);
|
||||
|
||||
try {
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$historyService->setConfiguredTemplate($templateId);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function updateTemplateAction()
|
||||
{
|
||||
$templateId = $this->_getParam('id', null);
|
||||
$name = $this->_getParam('name', null);
|
||||
$fields = $this->_getParam('fields', array());
|
||||
|
||||
try {
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$historyService->updateItemTemplate($templateId, $name, $fields);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteTemplateAction()
|
||||
{
|
||||
$templateId = $this->_getParam('id');
|
||||
|
||||
try {
|
||||
$historyService = new Application_Service_HistoryService();
|
||||
$historyService->deleteTemplate($templateId);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
Logging::info($e);
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
177
legacy/application/controllers/PluploadController.php
Normal file
177
legacy/application/controllers/PluploadController.php
Normal file
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
|
||||
class PluploadController extends Zend_Controller_Action
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('upload', 'json')
|
||||
->addActionContext('recent-uploads', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$locale = Application_Model_Preference::GetLocale();
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/datatables/js/jquery.dataTables.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/plupload/plupload.full.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/plupload/jquery.plupload.queue.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/plupload.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/plupload/i18n/'.$locale.'.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/dropzone.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/plupload.queue.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/addmedia.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/dashboard.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$this->view->quotaLimitReached = false;
|
||||
if (Application_Model_Systemstatus::isDiskOverQuota()) {
|
||||
$this->view->quotaLimitReached = true;
|
||||
}
|
||||
|
||||
//Because uploads are done via AJAX (and we're not using Zend form for those), we manually add the CSRF
|
||||
//token in here.
|
||||
$csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
|
||||
//The CSRF token is generated in Bootstrap.php
|
||||
|
||||
$csrf_element = new Zend_Form_Element_Hidden('csrf');
|
||||
$csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label');
|
||||
$csrf_form = new Zend_Form();
|
||||
$csrf_form->addElement($csrf_element);
|
||||
$this->view->form = $csrf_form;
|
||||
|
||||
// get max upload files size in MiB for plupload js.
|
||||
$uploadMaxSize = $this->file_upload_max_size() / 1024 / 1024;
|
||||
if ($uploadMaxSize === 0) {
|
||||
// fall back to old default behaviour if unlimited uploads are
|
||||
// configured on the server side.
|
||||
$uploadMaxSize = 500;
|
||||
}
|
||||
$this->view->uploadMaxSize = $uploadMaxSize;
|
||||
}
|
||||
|
||||
public function uploadAction()
|
||||
{
|
||||
$current_namespace = new Zend_Session_Namespace('csrf_namespace');
|
||||
$observed_csrf_token = $this->_getParam('csrf_token');
|
||||
$expected_csrf_token = $current_namespace->authtoken;
|
||||
|
||||
if($observed_csrf_token == $expected_csrf_token){
|
||||
$upload_dir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload";
|
||||
$tempFilePath = Application_Model_StoredFile::uploadFile($upload_dir);
|
||||
$tempFileName = basename($tempFilePath);
|
||||
|
||||
$this->_helper->json->sendJson(array("jsonrpc" => "2.0", "tempfilepath" => $tempFileName));
|
||||
}else{
|
||||
$this->_helper->json->sendJson(array("jsonrpc" => "2.0", "valid" => false, "error" => "CSRF token did not match."));
|
||||
}
|
||||
}
|
||||
|
||||
public function recentUploadsAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
$filter = $request->getParam('uploadFilter', "all");
|
||||
$limit = intval($request->getParam('iDisplayLength', 10));
|
||||
$rowStart = intval($request->getParam('iDisplayStart', 0));
|
||||
|
||||
$recentUploadsQuery = CcFilesQuery::create();
|
||||
//old propel 1.5 to reuse this query item (for counts/finds)
|
||||
$recentUploadsQuery->keepQuery(true);
|
||||
|
||||
//Hide deleted files
|
||||
$recentUploadsQuery->filterByDbFileExists(true);
|
||||
|
||||
$numTotalRecentUploads = $recentUploadsQuery->count();
|
||||
$numTotalDisplayUploads = $numTotalRecentUploads;
|
||||
|
||||
if ($filter == "pending") {
|
||||
$recentUploadsQuery->filterByDbImportStatus(1);
|
||||
$numTotalDisplayUploads = $recentUploadsQuery->count();
|
||||
} else if ($filter == "failed") {
|
||||
$recentUploadsQuery->filterByDbImportStatus(2);
|
||||
$numTotalDisplayUploads = $recentUploadsQuery->count();
|
||||
//TODO: Consider using array('min' => 200)) or something if we have multiple errors codes for failure.
|
||||
}
|
||||
|
||||
$recentUploads = $recentUploadsQuery
|
||||
->orderByDbUtime(Criteria::DESC)
|
||||
->offset($rowStart)
|
||||
->limit($limit)
|
||||
->find();
|
||||
|
||||
$uploadsArray = array();
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
$displayTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
|
||||
|
||||
foreach ($recentUploads as $upload)
|
||||
{
|
||||
$upload = $upload->toArray(BasePeer::TYPE_FIELDNAME);
|
||||
//TODO: $this->sanitizeResponse($upload));
|
||||
$upload['utime'] = new DateTime($upload['utime'], $utcTimezone);
|
||||
$upload['utime']->setTimeZone($displayTimezone);
|
||||
$upload['utime'] = $upload['utime']->format(DEFAULT_TIMESTAMP_FORMAT);
|
||||
|
||||
//TODO: Invoke sanitization here (MediaController's removeBlacklist stuff)
|
||||
array_push($uploadsArray, $upload);
|
||||
}
|
||||
|
||||
$this->view->sEcho = intval($request->getParam('sEcho'));
|
||||
$this->view->iTotalDisplayRecords = $numTotalDisplayUploads;
|
||||
$this->view->iTotalRecords = $numTotalRecentUploads;
|
||||
$this->view->files = SecurityHelper::htmlescape_recursive($uploadsArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* get configured upload max size from php
|
||||
*
|
||||
* Pinched from Drupal: https://github.com/drupal/drupal/blob/4204b0b29a7318008f10765cf88114bf3ed21c32/core/includes/file.inc#L1099
|
||||
*
|
||||
* Drupal seems to be the only framework that does this somewhat the right
|
||||
* way. I'm adding the method here since it's part of their core and I did
|
||||
* not find an easy way to grab that thrrough composer in an isolated way.
|
||||
*/
|
||||
private function file_upload_max_size() {
|
||||
static $max_size = -1;
|
||||
if ($max_size < 0) {
|
||||
|
||||
// Start with post_max_size.
|
||||
$max_size = $this->bytes_to_int(ini_get('post_max_size'));
|
||||
|
||||
// If upload_max_size is less, then reduce. Except if upload_max_size is
|
||||
// zero, which indicates no limit.
|
||||
$upload_max = $this->bytes_to_int(ini_get('upload_max_filesize'));
|
||||
if ($upload_max > 0 && $upload_max < $max_size) {
|
||||
$max_size = $upload_max;
|
||||
}
|
||||
}
|
||||
return $max_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pinched from Drupal: https://github.com/drupal/drupal/blob/4204b0b29a7318008f10765cf88114bf3ed21c32/core/lib/Drupal/Component/Utility/Bytes.php#L27
|
||||
*
|
||||
* This is the real point of importing the Drupal solution. They have done
|
||||
* an implementation for figuring out what the user specified in the
|
||||
* post_max_size and upload_max_size configuration. Sadly php does not
|
||||
* support a nice way to get at the results of this config after it is
|
||||
* parsed by the engine, hence the below hack.
|
||||
*/
|
||||
private function bytes_to_int($size) {
|
||||
// Remove the non-unit characters from the size.
|
||||
$unit = preg_replace('/[^bkmgtpezy]/i', '', $size);
|
||||
// Remove the non-numeric characters from the size.
|
||||
$size = preg_replace('/[^0-9\.]/', '', $size);
|
||||
if ($unit) {
|
||||
// Find the position of the unit in the ordered string which is the power
|
||||
// of magnitude to multiply a kilobyte by.
|
||||
return round($size * pow(1024, stripos('bkmgtpezy', $unit[0])));
|
||||
} else {
|
||||
return round($size);
|
||||
}
|
||||
}
|
||||
}
|
36
legacy/application/controllers/PodcastController.php
Normal file
36
legacy/application/controllers/PodcastController.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
class PodcastController extends Zend_Controller_Action {
|
||||
|
||||
public function init() {
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$headScript = $this->view->headScript();
|
||||
AirtimeTableView::injectTableJavaScriptDependencies($headScript, $baseUrl, $CC_CONFIG['airtime_version']);
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/library.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/events/library_showbuilder.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/widgets/table.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/podcast.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/ColVis.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/dataTables.colReorder.min.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/station_podcast.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/dashboard.css?'.$CC_CONFIG['airtime_version']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the Station podcast view
|
||||
*/
|
||||
public function stationAction() {
|
||||
|
||||
$stationPodcastId = Application_Model_Preference::getStationPodcastId();
|
||||
$podcast = Application_Service_PodcastService::getPodcastById($stationPodcastId);
|
||||
$this->view->podcast = json_encode($podcast);
|
||||
$this->view->form = new Application_Form_StationPodcast();
|
||||
}
|
||||
|
||||
}
|
576
legacy/application/controllers/PreferenceController.php
Normal file
576
legacy/application/controllers/PreferenceController.php
Normal file
|
@ -0,0 +1,576 @@
|
|||
<?php
|
||||
|
||||
class PreferenceController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
/* Initialize action controller here */
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('server-browse', 'json')
|
||||
->addActionContext('change-stor-directory', 'json')
|
||||
->addActionContext('reload-watch-directory', 'json')
|
||||
->addActionContext('remove-watch-directory', 'json')
|
||||
->addActionContext('is-import-in-progress', 'json')
|
||||
->addActionContext('change-stream-setting', 'json')
|
||||
->addActionContext('get-liquidsoap-status', 'json')
|
||||
->addActionContext('set-source-connection-url', 'json')
|
||||
->addActionContext('get-admin-password-status', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$request = $this->getRequest();
|
||||
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Settings');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/preferences/preferences.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->statusMsg = "";
|
||||
|
||||
$form = new Application_Form_Preferences();
|
||||
$values = array();
|
||||
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
|
||||
if ($request->isPost()) {
|
||||
$values = $request->getPost();
|
||||
if ($form->isValid($values))
|
||||
{
|
||||
Application_Model_Preference::SetHeadTitle($values["stationName"], $this->view);
|
||||
Application_Model_Preference::SetStationDescription($values["stationDescription"]);
|
||||
Application_Model_Preference::SetTrackTypeDefault($values["tracktypeDefault"]);
|
||||
Application_Model_Preference::SetDefaultCrossfadeDuration($values["stationDefaultCrossfadeDuration"]);
|
||||
Application_Model_Preference::SetDefaultFadeIn($values["stationDefaultFadeIn"]);
|
||||
Application_Model_Preference::SetDefaultFadeOut($values["stationDefaultFadeOut"]);
|
||||
Application_Model_Preference::SetPodcastAlbumOverride($values["podcastAlbumOverride"]);
|
||||
Application_Model_Preference::SetPodcastAutoSmartblock($values["podcastAutoSmartblock"]);
|
||||
Application_Model_Preference::SetIntroPlaylist($values["introPlaylistSelect"]);
|
||||
Application_Model_Preference::SetOutroPlaylist($values["outroPlaylistSelect"]);
|
||||
Application_Model_Preference::SetAllow3rdPartyApi($values["thirdPartyApi"]);
|
||||
Application_Model_Preference::SetAllowedCorsUrls($values["allowedCorsUrls"]);
|
||||
Application_Model_Preference::SetDefaultLocale($values["locale"]);
|
||||
Application_Model_Preference::SetDefaultTimezone($values["timezone"]);
|
||||
Application_Model_Preference::SetWeekStartDay($values["weekStartDay"]);
|
||||
Application_Model_Preference::setRadioPageDisplayLoginButton($values["radioPageLoginButton"]);
|
||||
Application_Model_Preference::SetFeaturePreviewMode($values["featurePreviewMode"]);
|
||||
|
||||
$logoUploadElement = $form->getSubForm('preferences_general')->getElement('stationLogo');
|
||||
$logoUploadElement->receive();
|
||||
$imagePath = $logoUploadElement->getFileName();
|
||||
|
||||
// Only update the image logo if the new logo is non-empty
|
||||
if (!empty($imagePath) && $imagePath != "") {
|
||||
Application_Model_Preference::SetStationLogo($imagePath);
|
||||
}
|
||||
|
||||
Application_Model_Preference::setTuneinEnabled($values["enable_tunein"]);
|
||||
Application_Model_Preference::setTuneinStationId($values["tunein_station_id"]);
|
||||
Application_Model_Preference::setTuneinPartnerKey($values["tunein_partner_key"]);
|
||||
Application_Model_Preference::setTuneinPartnerId($values["tunein_partner_id"]);
|
||||
|
||||
$this->view->statusMsg = "<div class='success'>". _("Preferences updated.")."</div>";
|
||||
$form = new Application_Form_Preferences();
|
||||
$this->view->form = $form;
|
||||
//$this->_helper->json->sendJson(array("valid"=>"true", "html"=>$this->view->render('preference/index.phtml')));
|
||||
} else {
|
||||
$this->view->form = $form;
|
||||
//$this->_helper->json->sendJson(array("valid"=>"false", "html"=>$this->view->render('preference/index.phtml')));
|
||||
}
|
||||
}
|
||||
$this->view->logoImg = Application_Model_Preference::GetStationLogo();
|
||||
|
||||
$this->view->form = $form;
|
||||
}
|
||||
|
||||
public function stationPodcastSettingsAction() {
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$values = json_decode($this->getRequest()->getRawBody());
|
||||
|
||||
if (!Application_Model_Preference::getStationPodcastPrivacy() && $values->stationPodcastPrivacy == 1) {
|
||||
// Refresh the download key when enabling privacy
|
||||
Application_Model_Preference::setStationPodcastDownloadKey();
|
||||
}
|
||||
|
||||
// Append sharing token (download key) to Station podcast URL
|
||||
$stationPodcast = PodcastQuery::create()->findOneByDbId(Application_Model_Preference::getStationPodcastId());
|
||||
$key = Application_Model_Preference::getStationPodcastDownloadKey();
|
||||
$url = Application_Common_HTTPHelper::getStationUrl() .
|
||||
(((int) $values->stationPodcastPrivacy) ? "feeds/station-rss?sharing_token=$key" : "feeds/station-rss");
|
||||
$stationPodcast->setDbUrl($url)->save();
|
||||
Application_Model_Preference::setStationPodcastPrivacy($values->stationPodcastPrivacy);
|
||||
|
||||
$this->_helper->json->sendJson(array("url" => $url));
|
||||
}
|
||||
|
||||
public function directoryConfigAction()
|
||||
{
|
||||
}
|
||||
|
||||
public function removeLogoAction()
|
||||
{
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
|
||||
$this->view->layout()->disableLayout();
|
||||
// Remove reliance on .phtml files to render requests
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
if (!SecurityHelper::verifyCSRFToken($this->_getParam('csrf_token'))) {
|
||||
Logging::error(__FILE__ . ': Invalid CSRF token');
|
||||
$this->_helper->json->sendJson(array("jsonrpc" => "2.0", "valid" => false, "error" => "CSRF token did not match."));
|
||||
return;
|
||||
}
|
||||
|
||||
Application_Model_Preference::SetStationLogo("");
|
||||
}
|
||||
|
||||
public function streamSettingAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Settings');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/preferences/streamsetting.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
|
||||
$name_map = array(
|
||||
'ogg' => 'Ogg Vorbis',
|
||||
'fdkaac' => 'AAC+',
|
||||
'aac' => 'AAC',
|
||||
'opus' => 'Opus',
|
||||
'mp3' => 'MP3',
|
||||
);
|
||||
|
||||
$num_of_stream = intval(Application_Model_Preference::GetNumOfStreams());
|
||||
$form = new Application_Form_StreamSetting();
|
||||
|
||||
$csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
|
||||
$csrf_element = new Zend_Form_Element_Hidden('csrf');
|
||||
$csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label');
|
||||
$form->addElement($csrf_element);
|
||||
|
||||
$live_stream_subform = new Application_Form_LiveStreamingPreferences();
|
||||
$form->addSubForm($live_stream_subform, "live_stream_subform");
|
||||
|
||||
// get predefined type and bitrate from pref table
|
||||
$temp_types = Application_Model_Preference::GetStreamType();
|
||||
$stream_types = array();
|
||||
foreach ($temp_types as $type) {
|
||||
$type = strtolower(trim($type));
|
||||
if (isset($name_map[$type])) {
|
||||
$name = $name_map[$type];
|
||||
} else {
|
||||
$name = $type;
|
||||
}
|
||||
$stream_types[$type] = $name;
|
||||
}
|
||||
|
||||
$temp_bitrate = Application_Model_Preference::GetStreamBitrate();
|
||||
$max_bitrate = intval(Application_Model_Preference::GetMaxBitrate());
|
||||
$stream_bitrates = array();
|
||||
foreach ($temp_bitrate as $type) {
|
||||
if (intval($type) <= $max_bitrate) {
|
||||
$stream_bitrates[trim($type)] = strtoupper(trim($type))." kbit/s";
|
||||
}
|
||||
}
|
||||
|
||||
// get current settings
|
||||
$setting = Application_Model_StreamSetting::getStreamSetting();
|
||||
$form->setSetting($setting);
|
||||
|
||||
for ($i=1; $i<=$num_of_stream; $i++) {
|
||||
$subform = new Application_Form_StreamSettingSubForm();
|
||||
$subform->setPrefix($i);
|
||||
$subform->setSetting($setting);
|
||||
$subform->setStreamTypes($stream_types);
|
||||
$subform->setStreamBitrates($stream_bitrates);
|
||||
$subform->startForm();
|
||||
$subform->toggleState();
|
||||
$form->addSubForm($subform, "s".$i."_subform");
|
||||
}
|
||||
|
||||
$live_stream_subform->updateVariables();
|
||||
$form->startFrom();
|
||||
|
||||
if ($request->isPost()) {
|
||||
$params = $request->getPost();
|
||||
/* Parse through post data and put in format
|
||||
* $form->isValid() is expecting it in
|
||||
*/
|
||||
$postData = explode('&', $params['data']);
|
||||
$s1_data = array();
|
||||
$s2_data = array();
|
||||
$s3_data = array();
|
||||
$s4_data = array();
|
||||
$values = array();
|
||||
foreach($postData as $k=>$v) {
|
||||
$v = explode('=', urldecode($v));
|
||||
if (strpos($v[0], "s1_data") !== false) {
|
||||
/* In this case $v[0] may be 's1_data[enable]' , for example.
|
||||
* We only want the 'enable' part
|
||||
*/
|
||||
preg_match('/\[(.*)\]/', $v[0], $matches);
|
||||
$s1_data[$matches[1]] = $v[1];
|
||||
} elseif (strpos($v[0], "s2_data") !== false) {
|
||||
preg_match('/\[(.*)\]/', $v[0], $matches);
|
||||
$s2_data[$matches[1]] = $v[1];
|
||||
} elseif (strpos($v[0], "s3_data") !== false) {
|
||||
preg_match('/\[(.*)\]/', $v[0], $matches);
|
||||
$s3_data[$matches[1]] = $v[1];
|
||||
} elseif (strpos($v[0], "s4_data") !== false) {
|
||||
preg_match('/\[(.*)\]/', $v[0], $matches);
|
||||
$s4_data[$matches[1]] = $v[1];
|
||||
} else {
|
||||
$values[$v[0]] = $v[1];
|
||||
}
|
||||
}
|
||||
$values["s1_data"] = $s1_data;
|
||||
$values["s2_data"] = $s2_data;
|
||||
$values["s3_data"] = $s3_data;
|
||||
$values["s4_data"] = $s4_data;
|
||||
|
||||
if ($form->isValid($values)) {
|
||||
Application_Model_StreamSetting::setStreamSetting($values);
|
||||
|
||||
/* If the admin password values are empty then we should not
|
||||
* set the pseudo password ('xxxxxx') on the front-end
|
||||
*/
|
||||
$s1_set_admin_pass = !empty($values["s1_data"]["admin_pass"]);
|
||||
$s2_set_admin_pass = !empty($values["s2_data"]["admin_pass"]);
|
||||
$s3_set_admin_pass = !empty($values["s3_data"]["admin_pass"]);
|
||||
$s4_set_admin_pass = !empty($values["s4_data"]["admin_pass"]);
|
||||
|
||||
// this goes into cc_pref table
|
||||
$this->setStreamPreferences($values);
|
||||
|
||||
// compare new values with current value
|
||||
$changeRGenabled = Application_Model_Preference::GetEnableReplayGain() != $values["enableReplayGain"];
|
||||
$changeRGmodifier = Application_Model_Preference::getReplayGainModifier() != $values["replayGainModifier"];
|
||||
if ($changeRGenabled || $changeRGmodifier) {
|
||||
Application_Model_Preference::SetEnableReplayGain($values["enableReplayGain"]);
|
||||
Application_Model_Preference::setReplayGainModifier($values["replayGainModifier"]);
|
||||
$md = array('schedule' => Application_Model_Schedule::getSchedule());
|
||||
Application_Model_RabbitMq::SendMessageToPypo("update_schedule", $md);
|
||||
//Application_Model_RabbitMq::PushSchedule();
|
||||
}
|
||||
|
||||
// pulling this from the 2.5.x branch
|
||||
if (!Application_Model_Preference::GetMasterDjConnectionUrlOverride()) {
|
||||
$master_connection_url = "http://".$_SERVER['SERVER_NAME'].":".$values["master_source_port"].$values["master_source_mount"];
|
||||
if (empty($values["master_source_port"]) || empty($values["master_source_mount"])) {
|
||||
Application_Model_Preference::SetMasterDJSourceConnectionURL('N/A');
|
||||
} else {
|
||||
Application_Model_Preference::SetMasterDJSourceConnectionURL($master_connection_url);
|
||||
}
|
||||
} else {
|
||||
Application_Model_Preference::SetMasterDJSourceConnectionURL($values["master_source_host"]);
|
||||
}
|
||||
|
||||
if (!Application_Model_Preference::GetLiveDjConnectionUrlOverride()) {
|
||||
$live_connection_url = "http://".$_SERVER['SERVER_NAME'].":".$values["show_source_port"].$values["show_source_mount"];
|
||||
if (empty($values["show_source_port"]) || empty($values["show_source_mount"])) {
|
||||
Application_Model_Preference::SetLiveDJSourceConnectionURL('N/A');
|
||||
} else {
|
||||
Application_Model_Preference::SetLiveDJSourceConnectionURL($live_connection_url);
|
||||
}
|
||||
} else {
|
||||
Application_Model_Preference::SetLiveDJSourceConnectionURL($values["show_source_host"]);
|
||||
}
|
||||
|
||||
|
||||
Application_Model_StreamSetting::setMasterLiveStreamPort($values["master_source_port"]);
|
||||
Application_Model_StreamSetting::setMasterLiveStreamMountPoint($values["master_source_mount"]);
|
||||
Application_Model_StreamSetting::setDjLiveStreamPort($values["show_source_port"]);
|
||||
Application_Model_StreamSetting::setDjLiveStreamMountPoint($values["show_source_mount"]);
|
||||
|
||||
Application_Model_StreamSetting::setOffAirMeta($values['offAirMeta']);
|
||||
|
||||
// store stream update timestamp
|
||||
Application_Model_Preference::SetStreamUpdateTimestamp();
|
||||
|
||||
$data = array();
|
||||
$info = Application_Model_StreamSetting::getStreamSetting();
|
||||
$data['setting'] = $info;
|
||||
for ($i=1; $i<=$num_of_stream; $i++) {
|
||||
Application_Model_StreamSetting::setLiquidsoapError($i, "waiting");
|
||||
}
|
||||
|
||||
Application_Model_RabbitMq::SendMessageToPypo("update_stream_setting", $data);
|
||||
$this->view->statusMsg = "<div class='success'>"._("Stream Setting Updated.")."</div>";
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->num_stream = $num_of_stream;
|
||||
$this->view->enable_stream_conf = Application_Model_Preference::GetEnableStreamConf();
|
||||
$this->view->form = $form;
|
||||
if ($request->isPost()) {
|
||||
if ($form->isValid($values)) {
|
||||
$this->_helper->json->sendJson(array(
|
||||
"valid" => "true",
|
||||
"html" => $this->view->render('preference/stream-setting.phtml'),
|
||||
"s1_set_admin_pass" => $s1_set_admin_pass,
|
||||
"s2_set_admin_pass" => $s2_set_admin_pass,
|
||||
"s3_set_admin_pass" => $s3_set_admin_pass,
|
||||
"s4_set_admin_pass" => $s4_set_admin_pass,
|
||||
));
|
||||
} else {
|
||||
$this->_helper->json->sendJson(array("valid" => "false", "html" => $this->view->render('preference/stream-setting.phtml')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stream settings preferences
|
||||
*
|
||||
* @param array $values stream setting preference values
|
||||
*/
|
||||
private function setStreamPreferences($values) {
|
||||
Application_Model_Preference::setUsingCustomStreamSettings($values['customStreamSettings']);
|
||||
Application_Model_Preference::SetStreamLabelFormat($values['streamFormat']);
|
||||
Application_Model_Preference::SetLiveStreamMasterUsername($values["master_username"]);
|
||||
Application_Model_Preference::SetLiveStreamMasterPassword($values["master_password"]);
|
||||
Application_Model_Preference::SetDefaultTransitionFade($values["transition_fade"]);
|
||||
Application_Model_Preference::SetAutoTransition($values["auto_transition"]);
|
||||
Application_Model_Preference::SetAutoSwitch($values["auto_switch"]);
|
||||
|
||||
}
|
||||
|
||||
public function serverBrowseAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$path = $request->getParam("path", null);
|
||||
|
||||
$result = array();
|
||||
|
||||
if (is_null($path)) {
|
||||
$element = array();
|
||||
$element["name"] = _("path should be specified");
|
||||
$element["isFolder"] = false;
|
||||
$element["isError"] = true;
|
||||
$result[$path] = $element;
|
||||
} else {
|
||||
$path = $path.'/';
|
||||
$handle = opendir($path);
|
||||
if ($handle !== false) {
|
||||
while (false !== ($file = readdir($handle))) {
|
||||
if ($file != "." && $file != "..") {
|
||||
//only show directories that aren't private.
|
||||
if (is_dir($path.$file) && substr($file, 0, 1) != ".") {
|
||||
$element = array();
|
||||
$element["name"] = $file;
|
||||
$element["isFolder"] = true;
|
||||
$element["isError"] = false;
|
||||
$result[$file] = $element;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ksort($result);
|
||||
//returns format serverBrowse is looking for.
|
||||
$this->_helper->json->sendJson($result);
|
||||
}
|
||||
|
||||
public function changeStorDirectoryAction()
|
||||
{
|
||||
$chosen = $this->getRequest()->getParam("dir");
|
||||
$element = $this->getRequest()->getParam("element");
|
||||
$watched_dirs_form = new Application_Form_WatchedDirPreferences();
|
||||
|
||||
$res = Application_Model_MusicDir::setStorDir($chosen);
|
||||
if ($res['code'] != 0) {
|
||||
$watched_dirs_form->populate(array('storageFolder' => $chosen));
|
||||
$watched_dirs_form->getElement($element)->setErrors(array($res['error']));
|
||||
}
|
||||
|
||||
$this->view->subform = $watched_dirs_form->render();
|
||||
}
|
||||
|
||||
public function reloadWatchDirectoryAction()
|
||||
{
|
||||
$chosen = $this->getRequest()->getParam("dir");
|
||||
$element = $this->getRequest()->getParam("element");
|
||||
$watched_dirs_form = new Application_Form_WatchedDirPreferences();
|
||||
|
||||
$res = Application_Model_MusicDir::addWatchedDir($chosen);
|
||||
if ($res['code'] != 0) {
|
||||
$watched_dirs_form->populate(array('watchedFolder' => $chosen));
|
||||
$watched_dirs_form->getElement($element)->setErrors(array($res['error']));
|
||||
}
|
||||
|
||||
$this->view->subform = $watched_dirs_form->render();
|
||||
}
|
||||
|
||||
public function rescanWatchDirectoryAction()
|
||||
{
|
||||
$dir_path = $this->getRequest()->getParam('dir');
|
||||
$dir = Application_Model_MusicDir::getDirByPath($dir_path);
|
||||
$data = array( 'directory' => $dir->getDirectory(),
|
||||
'id' => $dir->getId());
|
||||
Application_Model_RabbitMq::SendMessageToMediaMonitor('rescan_watch', $data);
|
||||
Logging::info("Unhiding all files belonging to:: $dir_path");
|
||||
$dir->unhideFiles();
|
||||
$this->_helper->json->sendJson(null);
|
||||
}
|
||||
|
||||
public function removeWatchDirectoryAction()
|
||||
{
|
||||
$chosen = $this->getRequest()->getParam("dir");
|
||||
|
||||
$dir = Application_Model_MusicDir::removeWatchedDir($chosen);
|
||||
|
||||
$watched_dirs_form = new Application_Form_WatchedDirPreferences();
|
||||
$this->view->subform = $watched_dirs_form->render();
|
||||
}
|
||||
|
||||
public function isImportInProgressAction()
|
||||
{
|
||||
$now = time();
|
||||
$res = false;
|
||||
if (Application_Model_Preference::GetImportTimestamp()+10 > $now) {
|
||||
$res = true;
|
||||
}
|
||||
$this->_helper->json->sendJson($res);
|
||||
}
|
||||
|
||||
public function getLiquidsoapStatusAction()
|
||||
{
|
||||
$out = array();
|
||||
$num_of_stream = intval(Application_Model_Preference::GetNumOfStreams());
|
||||
for ($i=1; $i<=$num_of_stream; $i++) {
|
||||
$status = Application_Model_StreamSetting::getLiquidsoapError($i);
|
||||
$status = $status == NULL?_("Problem with Liquidsoap..."):$status;
|
||||
if (!Application_Model_StreamSetting::getStreamEnabled($i)) {
|
||||
$status = "N/A";
|
||||
}
|
||||
$out[] = array("id"=>$i, "status"=>$status);
|
||||
}
|
||||
$this->_helper->json->sendJson($out);
|
||||
}
|
||||
|
||||
public function setSourceConnectionUrlAction()
|
||||
{
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
|
||||
$request = $this->getRequest();
|
||||
$type = $request->getParam("type", null);
|
||||
$url = urldecode($request->getParam("url", null));
|
||||
$override = $request->getParam("override", false);
|
||||
|
||||
if ($type == 'masterdj') {
|
||||
Application_Model_Preference::SetMasterDJSourceConnectionURL($url);
|
||||
Application_Model_Preference::SetMasterDjConnectionUrlOverride($override);
|
||||
} elseif ($type == 'livedj') {
|
||||
Application_Model_Preference::SetLiveDJSourceConnectionURL($url);
|
||||
Application_Model_Preference::SetLiveDjConnectionUrlOverride($override);
|
||||
}
|
||||
|
||||
$this->_helper->json->sendJson(null);
|
||||
}
|
||||
|
||||
public function getAdminPasswordStatusAction()
|
||||
{
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
|
||||
$out = array();
|
||||
$num_of_stream = intval(Application_Model_Preference::GetNumOfStreams());
|
||||
for ($i=1; $i<=$num_of_stream; $i++) {
|
||||
if (Application_Model_StreamSetting::getAdminPass('s'.$i)=='') {
|
||||
$out["s".$i] = false;
|
||||
} else {
|
||||
$out["s".$i] = true;
|
||||
}
|
||||
}
|
||||
$this->_helper->json->sendJson($out);
|
||||
}
|
||||
|
||||
public function deleteAllFilesAction()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
if (!SecurityHelper::verifyCSRFToken($this->_getParam('csrf_token'))) {
|
||||
Logging::error(__FILE__ . ': Invalid CSRF token');
|
||||
$this->_helper->json->sendJson(array("jsonrpc" => "2.0", "valid" => false, "error" => "CSRF token did not match."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Only admin users should get here through ACL permissioning
|
||||
// Only allow POST requests
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
if (!($method == 'POST')) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(405)
|
||||
->appendBody(_("Request method not accepted") . ": $method");
|
||||
return;
|
||||
}
|
||||
|
||||
$this->deleteFutureScheduleItems();
|
||||
$this->deleteCloudFiles();
|
||||
$this->deleteStoredFiles();
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody("OK");
|
||||
}
|
||||
|
||||
private function deleteFutureScheduleItems() {
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
$nowDateTime = new DateTime("now", $utcTimezone);
|
||||
$scheduleItems = CcScheduleQuery::create()
|
||||
->filterByDbEnds($nowDateTime->format(DEFAULT_TIMESTAMP_FORMAT), Criteria::GREATER_THAN)
|
||||
->find();
|
||||
|
||||
// Delete all the schedule items
|
||||
foreach ($scheduleItems as $i) {
|
||||
// If this is the currently playing track, cancel the current show
|
||||
if ($i->isCurrentItem()) {
|
||||
$instanceId = $i->getDbInstanceId();
|
||||
$instance = CcShowInstancesQuery::create()->findPk($instanceId);
|
||||
$showId = $instance->getDbShowId();
|
||||
|
||||
// From ScheduleController
|
||||
$scheduler = new Application_Model_Scheduler();
|
||||
$scheduler->cancelShow($showId);
|
||||
Application_Model_StoredFile::updatePastFilesIsScheduled();
|
||||
}
|
||||
|
||||
$i->delete();
|
||||
}
|
||||
}
|
||||
|
||||
private function deleteCloudFiles() {
|
||||
try {
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
foreach ($CC_CONFIG["supportedStorageBackends"] as $storageBackend) {
|
||||
$proxyStorageBackend = new ProxyStorageBackend($storageBackend);
|
||||
$proxyStorageBackend->deleteAllCloudFileObjects();
|
||||
}
|
||||
} catch(Exception $e) {
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function deleteStoredFiles() {
|
||||
// Delete all files from the database
|
||||
$files = CcFilesQuery::create()->find();
|
||||
foreach ($files as $file) {
|
||||
$storedFile = new Application_Model_StoredFile($file, null);
|
||||
// Delete the files quietly to avoid getting Sentry errors for
|
||||
// every S3 file we delete.
|
||||
$storedFile->delete(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
20
legacy/application/controllers/RenderController.php
Normal file
20
legacy/application/controllers/RenderController.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
class RenderController extends Zend_Controller_Action {
|
||||
|
||||
public function init() {
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
|
||||
$csrf_element = new Zend_Form_Element_Hidden('csrf_token');
|
||||
$csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label');
|
||||
$this->view->csrf = $csrf_element;
|
||||
}
|
||||
|
||||
public function podcastUrlDialogAction() {
|
||||
$path = 'podcast/podcast_url_dialog.phtml';
|
||||
$this->_helper->json->sendJson(array("html"=>$this->view->render($path)));
|
||||
}
|
||||
|
||||
}
|
773
legacy/application/controllers/ScheduleController.php
Normal file
773
legacy/application/controllers/ScheduleController.php
Normal file
|
@ -0,0 +1,773 @@
|
|||
<?php
|
||||
|
||||
class ScheduleController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
protected $sched_sess = null;
|
||||
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('event-feed', 'json')
|
||||
->addActionContext('event-feed-preload', 'json')
|
||||
->addActionContext('make-context-menu', 'json')
|
||||
->addActionContext('add-show-dialog', 'json')
|
||||
->addActionContext('add-show', 'json')
|
||||
->addActionContext('edit-show', 'json')
|
||||
->addActionContext('move-show', 'json')
|
||||
->addActionContext('resize-show', 'json')
|
||||
->addActionContext('delete-show-instance', 'json')
|
||||
->addActionContext('show-content-dialog', 'json')
|
||||
->addActionContext('clear-show', 'json')
|
||||
->addActionContext('get-current-playlist', 'json')
|
||||
->addActionContext('remove-group', 'json')
|
||||
->addActionContext('populate-show-form', 'json')
|
||||
->addActionContext('populate-repeating-show-instance-form', 'json')
|
||||
->addActionContext('delete-show', 'json')
|
||||
->addActionContext('cancel-current-show', 'json')
|
||||
->addActionContext('get-form', 'json')
|
||||
->addActionContext('upload-to-sound-cloud', 'json')
|
||||
->addActionContext('content-context-menu', 'json')
|
||||
->addActionContext('set-time-scale', 'json')
|
||||
->addActionContext('set-time-interval', 'json')
|
||||
->addActionContext('edit-repeating-show-instance', 'json')
|
||||
->addActionContext('dj-edit-show', 'json')
|
||||
->addActionContext('calculate-duration', 'json')
|
||||
->addActionContext('get-current-show', 'json')
|
||||
->addActionContext('update-future-is-scheduled', 'json')
|
||||
->addActionContext('localize-start-end-time', 'json')
|
||||
->initContext();
|
||||
|
||||
$this->sched_sess = new Zend_Session_Namespace("schedule");
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
//Embed the schedule in our page response so we don't have to make an AJAX request to get this data after the page load.
|
||||
$scheduleController = new ScheduleController($this->getRequest(), $this->getResponse());
|
||||
$scheduleController->eventFeedPreloadAction();
|
||||
$events = json_encode($scheduleController->view->events);
|
||||
|
||||
$this->view->headScript()->appendScript(
|
||||
"var calendarPref = {};\n".
|
||||
"calendarPref.weekStart = ".Application_Model_Preference::GetWeekStartDay().";\n".
|
||||
"calendarPref.timestamp = ".time().";\n".
|
||||
"calendarPref.timezoneOffset = ".Application_Common_DateHelper::getUserTimezoneOffset().";\n".
|
||||
"calendarPref.timeScale = '".Application_Model_Preference::GetCalendarTimeScale()."';\n".
|
||||
"calendarPref.timeInterval = ".Application_Model_Preference::GetCalendarTimeInterval().";\n".
|
||||
"calendarPref.weekStartDay = ".Application_Model_Preference::GetWeekStartDay().";\n".
|
||||
"var calendarEvents = $events;"
|
||||
);
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/contextmenu/jquery.contextMenu.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
//full-calendar-functions.js requires this variable, so that datePicker widget can be offset to server time instead of client time
|
||||
//this should be as a default, however with our new drop down timezone changing for shows, we should reset this offset then??
|
||||
$this->view->headScript()->appendScript("var timezoneOffset = ".Application_Common_DateHelper::getStationTimezoneOffset()."; //in seconds");
|
||||
//set offset to ensure it loads last
|
||||
$this->view->headScript()->offsetSetFile(90, $baseUrl.'js/airtime/schedule/full-calendar-functions.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/fullcalendar/fullcalendar.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/timepicker/jquery.ui.timepicker.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/colorpicker/js/colorpicker.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
// This block needs to be added before the add-show.js script
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/dayjs.min.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/utc.min.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/timezone.min.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/schedule/add-show.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->offsetSetFile(100, $baseUrl.'js/airtime/schedule/schedule.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/blockui/jquery.blockUI.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.ui.timepicker.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/fullcalendar.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/colorpicker/css/colorpicker.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/add-show.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.contextMenu.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
//Start Show builder JS/CSS requirements
|
||||
$headScript = $this->view->headScript();
|
||||
AirtimeTableView::injectTableJavaScriptDependencies($headScript, $baseUrl, $CC_CONFIG['airtime_version']);
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/utilities/utilities.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/buttons/buttons.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/events/library_showbuilder.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/library.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/showbuilder/builder.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/media_library.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.contextMenu.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/ColVis.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/dataTables.colReorder.min.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/showbuilder.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/dashboard.css?'.$CC_CONFIG['airtime_version']);
|
||||
//End Show builder JS/CSS requirements
|
||||
|
||||
$this->createShowFormAction(true);
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
$this->view->preloadShowForm = true;
|
||||
}
|
||||
|
||||
$this->view->addNewShow = true;
|
||||
}
|
||||
|
||||
public function eventFeedAction()
|
||||
{
|
||||
$service_user = new Application_Service_UserService();
|
||||
$currentUser = $service_user->getCurrentUser();
|
||||
|
||||
$userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
|
||||
|
||||
$start = new DateTime($this->_getParam('start', null), $userTimezone);
|
||||
$start->setTimezone(new DateTimeZone("UTC"));
|
||||
$end = new DateTime($this->_getParam('end', null), $userTimezone);
|
||||
$end->setTimezone(new DateTimeZone("UTC"));
|
||||
|
||||
$events = &Application_Model_Show::getFullCalendarEvents($start, $end,
|
||||
$currentUser->isAdminOrPM());
|
||||
|
||||
$this->view->events = $events;
|
||||
}
|
||||
|
||||
public function eventFeedPreloadAction()
|
||||
{
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
$editable = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
$calendar_interval = Application_Model_Preference::GetCalendarTimeScale();
|
||||
if ($calendar_interval == "agendaDay") {
|
||||
list($start, $end) = Application_Model_Show::getStartEndCurrentDayView();
|
||||
} else if ($calendar_interval == "agendaWeek") {
|
||||
list($start, $end) = Application_Model_Show::getStartEndCurrentWeekView();
|
||||
} else if ($calendar_interval == "month") {
|
||||
list($start, $end) = Application_Model_Show::getStartEndCurrentMonthPlusView();
|
||||
} else {
|
||||
Logging::error("Invalid Calendar Interval '$calendar_interval'");
|
||||
}
|
||||
|
||||
$events = &Application_Model_Show::getFullCalendarEvents($start, $end, $editable);
|
||||
$this->view->events = $events;
|
||||
}
|
||||
|
||||
public function getCurrentShowAction()
|
||||
{
|
||||
$currentShow = Application_Model_Show::getCurrentShow();
|
||||
if (!empty($currentShow)) {
|
||||
$this->view->si_id = $currentShow[0]["instance_id"];
|
||||
$this->view->current_show = true;
|
||||
} else {
|
||||
$this->view->current_show = false;
|
||||
}
|
||||
}
|
||||
|
||||
public function moveShowAction()
|
||||
{
|
||||
$deltaDay = $this->_getParam('day');
|
||||
$deltaMin = $this->_getParam('min');
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "schedule/move-show";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["instance id"] = $this->_getParam('showInstanceId');
|
||||
$log_vars["params"]["delta day"] = $deltaDay;
|
||||
$log_vars["params"]["delta minute"] = $deltaMin;
|
||||
Logging::info($log_vars);
|
||||
|
||||
try {
|
||||
$service_calendar = new Application_Service_CalendarService(
|
||||
$this->_getParam('showInstanceId'));
|
||||
} catch (Exception $e) {
|
||||
$this->view->show_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
$error = $service_calendar->moveShow($deltaDay, $deltaMin);
|
||||
if (isset($error)) {
|
||||
$this->view->error = $error;
|
||||
}
|
||||
}
|
||||
|
||||
public function resizeShowAction()
|
||||
{
|
||||
$deltaDay = $this->_getParam('day');
|
||||
$deltaMin = $this->_getParam('min');
|
||||
$showId = $this->_getParam('showId');
|
||||
$instanceId = $this->_getParam('instanceId');
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "schedule/resize-show";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["instance id"] = $instanceId;
|
||||
$log_vars["params"]["delta day"] = $deltaDay;
|
||||
$log_vars["params"]["delta minute"] = $deltaMin;
|
||||
Logging::info($log_vars);
|
||||
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
|
||||
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
try {
|
||||
$show = new Application_Model_Show($showId);
|
||||
} catch (Exception $e) {
|
||||
$this->view->show_error = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
$error = $show->resizeShow($deltaDay, $deltaMin, $instanceId);
|
||||
}
|
||||
|
||||
if (isset($error)) {
|
||||
$this->view->error = $error;
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteShowInstanceAction()
|
||||
{
|
||||
$instanceId = $this->_getParam('id');
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "schedule/delete-show-instance";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["instance id"] = $instanceId;
|
||||
Logging::info($log_vars);
|
||||
|
||||
$service_show = new Application_Service_ShowService();
|
||||
$showId = $service_show->deleteShow($instanceId, true);
|
||||
|
||||
if (!$showId) {
|
||||
$this->view->show_error = true;
|
||||
}
|
||||
$this->view->show_id = $showId;
|
||||
}
|
||||
|
||||
public function makeContextMenuAction()
|
||||
{
|
||||
$instanceId = $this->_getParam('instanceId');
|
||||
|
||||
$service_calendar = new Application_Service_CalendarService($instanceId);
|
||||
|
||||
$this->view->items = $service_calendar->makeContextMenu();
|
||||
}
|
||||
|
||||
public function clearShowAction()
|
||||
{
|
||||
$instanceId = $this->_getParam('id');
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "schedule/clear-show";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["instance id"] = $instanceId;
|
||||
Logging::info($log_vars);
|
||||
|
||||
$service_scheduler = new Application_Service_SchedulerService();
|
||||
|
||||
if (!$service_scheduler->emptyShowContent($instanceId)) {
|
||||
$this->view->show_error = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** This is a nasty hack to let us embed the the data the dashboard needs into the HTML response for each page.
|
||||
* This was originally loaded AFTER page load by AJAX, which is needlessly slow. This should have been templated in.
|
||||
*/
|
||||
public static function printCurrentPlaylistForEmbedding()
|
||||
{
|
||||
$front = Zend_Controller_Front::getInstance();
|
||||
$scheduleController = new ScheduleController($front->getRequest(), $front->getResponse());
|
||||
$scheduleController->getCurrentPlaylistAction();
|
||||
echo(json_encode($scheduleController->view));
|
||||
}
|
||||
|
||||
public function getCurrentPlaylistAction()
|
||||
{
|
||||
$range = Application_Model_Schedule::GetPlayOrderRangeOld();
|
||||
|
||||
$show = Application_Model_Show::getCurrentShow();
|
||||
|
||||
/* Convert all UTC times to localtime before sending back to user. */
|
||||
$range["schedulerTime"] = Application_Common_DateHelper::UTCStringToUserTimezoneString($range["schedulerTime"]);
|
||||
|
||||
if (isset($range["previous"])) {
|
||||
$range["previous"]["starts"] = Application_Common_DateHelper::UTCStringToUserTimezoneString($range["previous"]["starts"]);
|
||||
$range["previous"]["ends"] = Application_Common_DateHelper::UTCStringToUserTimezoneString($range["previous"]["ends"]);
|
||||
}
|
||||
if (isset($range["current"])) {
|
||||
if (isset($range["current"]["metadata"])) {
|
||||
$get_artwork = FileDataHelper::getArtworkData($range["current"]["metadata"]["artwork"], 256);
|
||||
$range["current"]["metadata"]["artwork_data"] = $get_artwork;
|
||||
}
|
||||
$range["current"]["starts"] = Application_Common_DateHelper::UTCStringToUserTimezoneString($range["current"]["starts"]);
|
||||
$range["current"]["ends"] = Application_Common_DateHelper::UTCStringToUserTimezoneString($range["current"]["ends"]);
|
||||
}
|
||||
if (isset($range["next"])) {
|
||||
$range["next"]["starts"] = Application_Common_DateHelper::UTCStringToUserTimezoneString($range["next"]["starts"]);
|
||||
$range["next"]["ends"] = Application_Common_DateHelper::UTCStringToUserTimezoneString($range["next"]["ends"]);
|
||||
}
|
||||
|
||||
Application_Common_DateHelper::convertTimestamps(
|
||||
$range["currentShow"],
|
||||
array("starts", "ends", "start_timestamp", "end_timestamp"),
|
||||
"user"
|
||||
);
|
||||
Application_Common_DateHelper::convertTimestamps(
|
||||
$range["nextShow"],
|
||||
array("starts", "ends", "start_timestamp", "end_timestamp"),
|
||||
"user"
|
||||
);
|
||||
|
||||
//TODO: Add timezone and timezoneOffset back into the ApiController's results.
|
||||
$range["timezone"] = Application_Common_DateHelper::getUserTimezoneAbbreviation();
|
||||
$range["timezoneOffset"] = Application_Common_DateHelper::getUserTimezoneOffset();
|
||||
|
||||
$source_status = array();
|
||||
$switch_status = array();
|
||||
$live_dj = Application_Model_Preference::GetSourceStatus("live_dj");
|
||||
$master_dj = Application_Model_Preference::GetSourceStatus("master_dj");
|
||||
|
||||
$scheduled_play_switch = Application_Model_Preference::GetSourceSwitchStatus("scheduled_play");
|
||||
$live_dj_switch = Application_Model_Preference::GetSourceSwitchStatus("live_dj");
|
||||
$master_dj_switch = Application_Model_Preference::GetSourceSwitchStatus("master_dj");
|
||||
|
||||
//might not be the correct place to implement this but for now let's just do it here
|
||||
$source_status['live_dj_source'] = $live_dj;
|
||||
$source_status['master_dj_source'] = $master_dj;
|
||||
$this->view->source_status = $source_status;
|
||||
|
||||
$switch_status['live_dj_source'] = $live_dj_switch;
|
||||
$switch_status['master_dj_source'] = $master_dj_switch;
|
||||
$switch_status['scheduled_play'] = $scheduled_play_switch;
|
||||
$this->view->switch_status = $switch_status;
|
||||
|
||||
$this->view->entries = $range;
|
||||
$this->view->show_name = isset($show[0])?$show[0]["name"]:"";
|
||||
}
|
||||
|
||||
public function showContentDialogAction()
|
||||
{
|
||||
$showInstanceId = $this->_getParam('id');
|
||||
try {
|
||||
$show = new Application_Model_ShowInstance($showInstanceId);
|
||||
} catch (Exception $e) {
|
||||
$this->view->show_error = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$originalShowId = $show->isRebroadcast();
|
||||
if (!is_null($originalShowId)) {
|
||||
try {
|
||||
$originalShow = new Application_Model_ShowInstance($originalShowId);
|
||||
} catch (Exception $e) {
|
||||
$this->view->show_error = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
$originalShowName = $originalShow->getName();
|
||||
$originalShowStart = $originalShow->getShowInstanceStart();
|
||||
|
||||
//convert from UTC to user's timezone for display.
|
||||
$displayTimeZone = new DateTimeZone(Application_Model_Preference::GetTimezone());
|
||||
$originalDateTime = new DateTime($originalShowStart, new DateTimeZone("UTC"));
|
||||
$originalDateTime->setTimezone($displayTimeZone);
|
||||
|
||||
$this->view->additionalShowInfo =
|
||||
sprintf(_("Rebroadcast of show %s from %s at %s"),
|
||||
$originalShowName,
|
||||
$originalDateTime->format("l, F jS"),
|
||||
$originalDateTime->format("G:i"));
|
||||
}
|
||||
$this->view->showLength = $show->getShowLength();
|
||||
$this->view->timeFilled = $show->getTimeScheduled();
|
||||
$this->view->percentFilled = $show->getPercentScheduled();
|
||||
$this->view->showContent = $show->getShowListContent();
|
||||
$this->view->dialog = $this->view->render('schedule/show-content-dialog.phtml');
|
||||
$this->view->showTitle = htmlspecialchars($show->getName());
|
||||
unset($this->view->showContent);
|
||||
}
|
||||
|
||||
public function populateRepeatingShowInstanceFormAction()
|
||||
{
|
||||
$showId = $this->_getParam('showId');
|
||||
$instanceId = $this->_getParam('instanceId');
|
||||
$service_showForm = new Application_Service_ShowFormService($showId, $instanceId);
|
||||
|
||||
$forms = $this->createShowFormAction();
|
||||
|
||||
$service_showForm->delegateShowInstanceFormPopulation($forms);
|
||||
|
||||
$this->view->addNewShow = false;
|
||||
$this->view->action = "edit-repeating-show-instance";
|
||||
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
|
||||
}
|
||||
|
||||
public function populateShowFormAction()
|
||||
{
|
||||
$service_user = new Application_Service_UserService();
|
||||
$currentUser = $service_user->getCurrentUser();
|
||||
|
||||
$showId = $this->_getParam('showId');
|
||||
$instanceId = $this->_getParam('instanceId');
|
||||
$service_showForm = new Application_Service_ShowFormService($showId, $instanceId);
|
||||
|
||||
$isAdminOrPM = $currentUser->isAdminOrPM();
|
||||
|
||||
$forms = $this->createShowFormAction();
|
||||
|
||||
$service_showForm->delegateShowFormPopulation($forms);
|
||||
|
||||
if (!$isAdminOrPM) {
|
||||
foreach ($forms as $form) {
|
||||
$form->disable();
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->action = "edit-show";
|
||||
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
|
||||
$this->view->entries = 5;
|
||||
}
|
||||
|
||||
public function getFormAction()
|
||||
{
|
||||
$service_user = new Application_Service_UserService();
|
||||
$currentUser = $service_user->getCurrentUser();
|
||||
|
||||
if ($currentUser->isAdminOrPM()) {
|
||||
$this->createShowFormAction(true);
|
||||
$this->view->addNewShow = true;
|
||||
$this->view->form = $this->view->render('schedule/add-show-form.phtml');
|
||||
}
|
||||
}
|
||||
|
||||
public function editRepeatingShowInstanceAction(){
|
||||
$js = $this->_getParam('data');
|
||||
$data = array();
|
||||
|
||||
//need to convert from serialized jQuery array.
|
||||
foreach ($js as $j) {
|
||||
$data[$j["name"]] = $j["value"];
|
||||
}
|
||||
|
||||
$data['add_show_hosts'] = $this->_getParam('hosts');
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "schedule/edit-repeating-show-instance";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["form_data"] = $data;
|
||||
Logging::info($log_vars);
|
||||
|
||||
$service_showForm = new Application_Service_ShowFormService(
|
||||
$data["add_show_id"], $data["add_show_instance_id"]);
|
||||
$service_show = new Application_Service_ShowService(null, $data);
|
||||
|
||||
$forms = $this->createShowFormAction();
|
||||
|
||||
list($data, $validateStartDate, $validateStartTime, $originalShowStartDateTime) =
|
||||
$service_showForm->preEditShowValidationCheck($data);
|
||||
|
||||
if ($service_showForm->validateShowForms($forms, $data, $validateStartDate,
|
||||
$originalShowStartDateTime, true, $data["add_show_instance_id"])) {
|
||||
|
||||
$service_show->editRepeatingShowInstance($data);
|
||||
|
||||
$this->view->addNewShow = true;
|
||||
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
|
||||
} else {
|
||||
if (!$validateStartDate) {
|
||||
$this->view->when->getElement('add_show_start_date')->setOptions(array('disabled' => true));
|
||||
}
|
||||
if (!$validateStartTime) {
|
||||
$this->view->when->getElement('add_show_start_time')->setOptions(array('disabled' => true));
|
||||
}
|
||||
$this->view->rr->getElement('add_show_record')->setOptions(array('disabled' => true));
|
||||
$this->view->addNewShow = false;
|
||||
$this->view->action = "edit-repeating-show-instance";
|
||||
$this->view->form = $this->view->render('schedule/add-show-form.phtml');
|
||||
}
|
||||
}
|
||||
|
||||
public function editShowAction()
|
||||
{
|
||||
$js = $this->_getParam('data');
|
||||
$data = array();
|
||||
|
||||
//need to convert from serialized jQuery array.
|
||||
foreach ($js as $j) {
|
||||
$data[$j["name"]] = $j["value"];
|
||||
}
|
||||
|
||||
$service_showForm = new Application_Service_ShowFormService(
|
||||
$data["add_show_id"]);
|
||||
$service_show = new Application_Service_ShowService(null, $data, true);
|
||||
|
||||
//TODO: move this to js
|
||||
$data['add_show_hosts'] = $this->_getParam('hosts');
|
||||
$data['add_show_day_check'] = $this->_getParam('days');
|
||||
|
||||
if ($data['add_show_day_check'] == "") {
|
||||
$data['add_show_day_check'] = null;
|
||||
}
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "schedule/edit-show";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["form_data"] = $data;
|
||||
Logging::info($log_vars);
|
||||
|
||||
$forms = $this->createShowFormAction();
|
||||
|
||||
list($data, $validateStartDate, $validateStartTime, $originalShowStartDateTime) =
|
||||
$service_showForm->preEditShowValidationCheck($data);
|
||||
|
||||
if ($service_showForm->validateShowForms($forms, $data, $validateStartDate,
|
||||
$originalShowStartDateTime, true, $data["add_show_instance_id"])) {
|
||||
// Get the show ID from the show service to pass as a parameter to the RESTful ShowImageController
|
||||
$this->view->showId = $service_show->addUpdateShow($data);
|
||||
|
||||
$this->view->addNewShow = true;
|
||||
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
|
||||
} else {
|
||||
if (!$validateStartDate) {
|
||||
$this->view->when->getElement('add_show_start_date')->setOptions(array('disabled' => true));
|
||||
}
|
||||
if (!$validateStartTime) {
|
||||
$this->view->when->getElement('add_show_start_time')->setOptions(array('disabled' => true));
|
||||
}
|
||||
//$this->view->rr->getElement('add_show_record')->setOptions(array('disabled' => true));
|
||||
|
||||
$this->view->addNewShow = false;
|
||||
$this->view->action = "edit-show";
|
||||
$this->view->form = $this->view->render('schedule/add-show-form.phtml');
|
||||
}
|
||||
}
|
||||
|
||||
public function addShowAction()
|
||||
{
|
||||
$service_showForm = new Application_Service_ShowFormService(null);
|
||||
|
||||
$js = $this->_getParam('data');
|
||||
$data = array();
|
||||
|
||||
//need to convert from serialized jQuery array.
|
||||
foreach ($js as $j) {
|
||||
$data[$j["name"]] = $j["value"];
|
||||
}
|
||||
|
||||
$service_show = new Application_Service_ShowService(null, $data);
|
||||
|
||||
// TODO: move this to js
|
||||
$data['add_show_hosts'] = $this->_getParam('hosts');
|
||||
$data['add_show_day_check'] = $this->_getParam('days');
|
||||
|
||||
if ($data['add_show_day_check'] == "") {
|
||||
$data['add_show_day_check'] = null;
|
||||
}
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "schedule/add-show";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["form_data"] = $data;
|
||||
Logging::info($log_vars);
|
||||
|
||||
$forms = $this->createShowFormAction();
|
||||
|
||||
$this->view->addNewShow = true;
|
||||
|
||||
if ($data['add_show_start_now'] == "now") {
|
||||
|
||||
//have to use the timezone the user has entered in the form to check past/present
|
||||
$showTimezone = new DateTimeZone($data["add_show_timezone"]);
|
||||
$nowDateTime = new DateTime("now", $showTimezone);
|
||||
//$showStartDateTime = new DateTime($start_time, $showTimezone);
|
||||
//$showEndDateTime = new DateTime($end_time, $showTimezone);
|
||||
|
||||
$data['add_show_start_time'] = $nowDateTime->format("H:i");
|
||||
$data['add_show_start_date'] = $nowDateTime->format("Y-m-d");
|
||||
}
|
||||
|
||||
|
||||
if ($service_showForm->validateShowForms($forms, $data)) {
|
||||
// Get the show ID from the show service to pass as a parameter to the RESTful ShowImageController
|
||||
$this->view->showId = $service_show->addUpdateShow($data);
|
||||
|
||||
//send new show forms to the user
|
||||
$this->createShowFormAction(true);
|
||||
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
|
||||
|
||||
Logging::debug("Show creation succeeded");
|
||||
} else {
|
||||
$this->view->form = $this->view->render('schedule/add-show-form.phtml');
|
||||
Logging::debug("Show creation failed");
|
||||
}
|
||||
}
|
||||
|
||||
public function createShowFormAction($populateDefaults=false)
|
||||
{
|
||||
$service_showForm = new Application_Service_ShowFormService();
|
||||
|
||||
$forms = $service_showForm->createShowForms();
|
||||
|
||||
// populate forms with default values
|
||||
if ($populateDefaults) {
|
||||
$service_showForm->populateNewShowForms(
|
||||
$forms["what"], $forms["when"], $forms["repeats"]);
|
||||
}
|
||||
|
||||
$this->view->what = $forms["what"];
|
||||
$this->view->autoplaylist = $forms["autoplaylist"];
|
||||
$this->view->when = $forms["when"];
|
||||
$this->view->repeats = $forms["repeats"];
|
||||
$this->view->live = $forms["live"];
|
||||
$this->view->rr = $forms["record"];
|
||||
$this->view->absoluteRebroadcast = $forms["abs_rebroadcast"];
|
||||
$this->view->rebroadcast = $forms["rebroadcast"];
|
||||
$this->view->who = $forms["who"];
|
||||
$this->view->style = $forms["style"];
|
||||
|
||||
return $forms;
|
||||
}
|
||||
|
||||
public function deleteShowAction()
|
||||
{
|
||||
$instanceId = $this->_getParam('id');
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "schedule/delete-show";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["instance id"] = $instanceId;
|
||||
Logging::info($log_vars);
|
||||
|
||||
$service_show = new Application_Service_ShowService();
|
||||
$showId = $service_show->deleteShow($instanceId);
|
||||
|
||||
if (!$showId) {
|
||||
$this->view->show_error = true;
|
||||
}
|
||||
$this->view->show_id = $showId;
|
||||
}
|
||||
|
||||
public function cancelCurrentShowAction()
|
||||
{
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "schedule/cancel-current-show";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["instance id"] = $this->_getParam('id');
|
||||
Logging::info($log_vars);
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
|
||||
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
$id = $this->_getParam('id');
|
||||
|
||||
try {
|
||||
$scheduler = new Application_Model_Scheduler();
|
||||
$scheduler->cancelShow($id);
|
||||
Application_Model_StoredFile::updatePastFilesIsScheduled();
|
||||
// send kick out source stream signal to pypo
|
||||
$data = array("sourcename"=>"live_dj");
|
||||
Application_Model_RabbitMq::SendMessageToPypo("disconnect_source", $data);
|
||||
} catch (Exception $e) {
|
||||
$this->view->error = $e->getMessage();
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function contentContextMenuAction()
|
||||
{
|
||||
$id = $this->_getParam('id');
|
||||
|
||||
$params = '/format/json/id/#id#/';
|
||||
|
||||
$paramsPop = str_replace('#id#', $id, $params);
|
||||
|
||||
// added for download
|
||||
$id = $this->_getParam('id');
|
||||
|
||||
$file_id = $this->_getParam('id', null);
|
||||
$file = Application_Model_StoredFile::RecallById($file_id);
|
||||
|
||||
$baseUrl = $this->getRequest()->getBaseUrl();
|
||||
$url = $file->getRelativeFileUrl($baseUrl).'download/true';
|
||||
$menu = array();
|
||||
$menu[] = array('action' => array('type' => 'gourl', 'url' => $url),
|
||||
'title' => _('Download'));
|
||||
|
||||
//returns format jjmenu is looking for.
|
||||
$this->_helper->json->sendJson($menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user specific preference for which time scale to use in Calendar.
|
||||
* This is only being used by schedule.js at the moment.
|
||||
*/
|
||||
public function setTimeScaleAction()
|
||||
{
|
||||
Application_Model_Preference::SetCalendarTimeScale($this->_getParam('timeScale'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user specific preference for which time interval to use in Calendar.
|
||||
* This is only being used by schedule.js at the moment.
|
||||
*/
|
||||
public function setTimeIntervalAction()
|
||||
{
|
||||
Application_Model_Preference::SetCalendarTimeInterval($this->_getParam('timeInterval'));
|
||||
}
|
||||
|
||||
public function calculateDurationAction()
|
||||
{
|
||||
$start = $this->_getParam('startTime');
|
||||
$end = $this->_getParam('endTime');
|
||||
$timezone = $this->_getParam('timezone');
|
||||
|
||||
$service_showForm = new Application_Service_ShowFormService();
|
||||
$result = $service_showForm->calculateDuration($start, $end, $timezone);
|
||||
|
||||
echo Zend_Json::encode($result);
|
||||
exit();
|
||||
}
|
||||
|
||||
public function updateFutureIsScheduledAction()
|
||||
{
|
||||
$schedId = $this->_getParam('schedId');
|
||||
|
||||
$scheduleService = new Application_Service_SchedulerService();
|
||||
$redrawLibTable = $scheduleService->updateFutureIsScheduled($schedId, false);
|
||||
|
||||
$this->_helper->json->sendJson(array("redrawLibTable" => $redrawLibTable));
|
||||
}
|
||||
|
||||
public function localizeStartEndTimeAction()
|
||||
{
|
||||
$newTimezone = $this->_getParam('newTimezone');
|
||||
$oldTimezone = $this->_getParam('oldTimezone');
|
||||
$localTime = array();
|
||||
|
||||
$localTime["start"] = Application_Service_ShowFormService::localizeDateTime(
|
||||
$this->_getParam('startDate'), $this->_getParam('startTime'), $newTimezone, $oldTimezone);
|
||||
|
||||
$localTime["end"] = Application_Service_ShowFormService::localizeDateTime(
|
||||
$this->_getParam('endDate'), $this->_getParam('endTime'), $newTimezone, $oldTimezone);
|
||||
|
||||
$this->_helper->json->sendJson($localTime);
|
||||
}
|
||||
|
||||
}
|
43
legacy/application/controllers/SetupController.php
Normal file
43
legacy/application/controllers/SetupController.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
/** This class displays the Language and Timezone setup popup dialog that you see on first run. */
|
||||
|
||||
class SetupController extends Zend_Controller_Action
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('setup-language-timezone', 'json');
|
||||
}
|
||||
|
||||
public function setupLanguageTimezoneAction()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$request = $this->getRequest();
|
||||
$form = new Application_Form_SetupLanguageTimezone();
|
||||
|
||||
if ($request->isPost()) {
|
||||
|
||||
$formData = $request->getPost();
|
||||
if ($form->isValid($formData)) {
|
||||
$userService = new Application_Service_UserService();
|
||||
$currentUser = $userService->getCurrentUser();
|
||||
$currentUserId = $currentUser->getDbId();
|
||||
|
||||
Application_Model_Preference::SetUserTimezone($formData["setup_timezone"], $currentUserId);
|
||||
Application_Model_Preference::SetDefaultTimezone($formData["setup_timezone"]);
|
||||
|
||||
Application_Model_Preference::SetUserLocale($formData["setup_language"], $currentUserId);
|
||||
Application_Model_Preference::SetDefaultLocale($formData["setup_language"]);
|
||||
|
||||
Application_Model_Preference::setLangTimezoneSetupComplete(true);
|
||||
|
||||
$this->_redirect('/showbuilder');
|
||||
}
|
||||
}
|
||||
$this->_redirect('/showbuilder');
|
||||
}
|
||||
|
||||
}
|
316
legacy/application/controllers/ShowbuilderController.php
Normal file
316
legacy/application/controllers/ShowbuilderController.php
Normal file
|
@ -0,0 +1,316 @@
|
|||
<?php
|
||||
|
||||
class ShowbuilderController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('schedule-move', 'json')
|
||||
->addActionContext('schedule-add', 'json')
|
||||
->addActionContext('schedule-remove', 'json')
|
||||
->addActionContext('builder-dialog', 'json')
|
||||
->addActionContext('check-builder-feed', 'json')
|
||||
->addActionContext('builder-feed', 'json')
|
||||
->addActionContext('context-menu', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$userType = Application_Model_User::GetCurrentUser()->getType();
|
||||
|
||||
//$this->_helper->layout->setLayout("showbuilder");
|
||||
|
||||
$this->view->headScript()->appendScript("localStorage.setItem( 'user-type', '$userType' );");
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl . 'css/redmond/jquery-ui-1.8.8.custom.css?' . $CC_CONFIG['airtime_version']);
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/contextmenu/jquery.contextMenu.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/blockui/jquery.blockUI.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/buttons/buttons.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/utilities/utilities.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/media_library.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.contextMenu.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/ColVis.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/dataTables.colReorder.min.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/library.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/events/library_showbuilder.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$headScript = $this->view->headScript();
|
||||
AirtimeTableView::injectTableJavaScriptDependencies($headScript, $baseUrl, $CC_CONFIG['airtime_version']);
|
||||
|
||||
// PLUPLOAD
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/dropzone.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/timepicker/jquery.ui.timepicker.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/showbuilder/tabs.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/showbuilder/builder.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/showbuilder/main_builder.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
// MEDIA BUILDER
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/dayjs.min.js','text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/utc.min.js','text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/timezone.min.js','text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/spl.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/podcast.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/library/publish.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/playlist/smart_blockbuilder.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/playlist_builder.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.ui.timepicker.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/showbuilder.css?'.$CC_CONFIG['airtime_version']);
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/dashboard.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
|
||||
$csrf_element = new Zend_Form_Element_Hidden('csrf');
|
||||
$csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label');
|
||||
$this->view->csrf = $csrf_element;
|
||||
|
||||
$request = $this->getRequest();
|
||||
//populate date range form for show builder.
|
||||
$now = time();
|
||||
$from = $request->getParam("from", $now);
|
||||
$to = $request->getParam("to", $now + (3*60*60));
|
||||
|
||||
$utcTimezone = new DateTimeZone("UTC");
|
||||
$displayTimeZone = new DateTimeZone(Application_Model_Preference::GetTimezone());
|
||||
|
||||
$start = DateTime::createFromFormat("U", $from, $utcTimezone);
|
||||
$start->setTimezone($displayTimeZone);
|
||||
$end = DateTime::createFromFormat("U", $to, $utcTimezone);
|
||||
$end->setTimezone($displayTimeZone);
|
||||
|
||||
$this->checkAndShowSetupPopup($request);
|
||||
|
||||
$form = new Application_Form_ShowBuilder();
|
||||
$form->populate(array(
|
||||
'sb_date_start' => $start->format("Y-m-d"),
|
||||
'sb_time_start' => $start->format("H:i"),
|
||||
'sb_date_end' => $end->format("Y-m-d"),
|
||||
'sb_time_end' => $end->format("H:i")
|
||||
));
|
||||
|
||||
$this->view->sb_form = $form;
|
||||
}
|
||||
|
||||
/** Check if we need to show the timezone/language setup popup and display it. (eg. on first run) */
|
||||
public function checkAndShowSetupPopup($request)
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$setupComplete = Application_Model_Preference::getLangTimezoneSetupComplete();
|
||||
$previousPage = strtolower($request->getHeader('Referer'));
|
||||
$userService = new Application_Service_UserService();
|
||||
$currentUser = $userService->getCurrentUser();
|
||||
$previousPageWasLoginScreen = (strpos($previousPage, 'login') !== false) ||
|
||||
(strpos($previousPage, SAAS_LOGIN_REFERRER) !== false);
|
||||
|
||||
// If current user is Super Admin, and they came from the login page,
|
||||
// and they have not seen the setup popup before
|
||||
if ($currentUser->isSuperAdmin() && $previousPageWasLoginScreen && empty($setupComplete)) {
|
||||
$lang_tz_popup_form = new Application_Form_SetupLanguageTimezone();
|
||||
$this->view->lang_tz_popup_form = $lang_tz_popup_form;
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/nowplaying/lang-timezone-setup.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
}
|
||||
}
|
||||
|
||||
public function contextMenuAction()
|
||||
{
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$id = $this->_getParam('id');
|
||||
$now = floatval(microtime(true));
|
||||
|
||||
$request = $this->getRequest();
|
||||
$menu = array();
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
|
||||
$item = CcScheduleQuery::create()->findPK($id);
|
||||
$instance = $item->getCcShowInstances();
|
||||
|
||||
$menu["preview"] = array("name"=> _("Preview"), "icon" => "play");
|
||||
//select the cursor
|
||||
$menu["selCurs"] = array("name"=> _("Select cursor"),"icon" => "select-cursor");
|
||||
$menu["delCurs"] = array("name"=> _("Remove cursor"),"icon" => "select-cursor");
|
||||
|
||||
if ($now < floatval($item->getDbEnds("U.u")) && $user->canSchedule($instance->getDbShowId())) {
|
||||
|
||||
//remove/truncate the item from the schedule
|
||||
$menu["del"] = array("name"=> _("Delete"), "icon" => "delete", "url" => $baseUrl."showbuilder/schedule-remove");
|
||||
}
|
||||
|
||||
$this->view->items = $menu;
|
||||
}
|
||||
|
||||
public function builderDialogAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$id = $request->getParam("id");
|
||||
|
||||
$instance = CcShowInstancesQuery::create()->findPK($id);
|
||||
|
||||
if (is_null($instance)) {
|
||||
$this->view->error = _("show does not exist");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$displayTimeZone = new DateTimeZone(Application_Model_Preference::GetTimezone());
|
||||
|
||||
$start = $instance->getDbStarts(null);
|
||||
$start->setTimezone($displayTimeZone);
|
||||
$end = $instance->getDbEnds(null);
|
||||
$end->setTimezone($displayTimeZone);
|
||||
|
||||
$show_name = $instance->getCcShow()->getDbName();
|
||||
$start_time = $start->format(DEFAULT_TIMESTAMP_FORMAT);
|
||||
$end_time = $end->format(DEFAULT_TIMESTAMP_FORMAT);
|
||||
|
||||
$this->view->title = "{$show_name}: {$start_time} - {$end_time}";
|
||||
$this->view->start = $start_time;
|
||||
$this->view->end = $end_time;
|
||||
|
||||
$form = new Application_Form_ShowBuilder();
|
||||
$form->populate(array(
|
||||
'sb_date_start' => $start->format("Y-m-d"),
|
||||
'sb_time_start' => $start->format("H:i"),
|
||||
'sb_date_end' => $end->format("Y-m-d"),
|
||||
'sb_time_end' => $end->format("H:i")
|
||||
));
|
||||
|
||||
$this->view->sb_form = $form;
|
||||
|
||||
$this->view->dialog = $this->view->render('showbuilder/builderDialog.phtml');
|
||||
}
|
||||
|
||||
public function checkBuilderFeedAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$show_filter = intval($request->getParam("showFilter", 0));
|
||||
$my_shows = intval($request->getParam("myShows", 0));
|
||||
$timestamp = intval($request->getParam("timestamp", -1));
|
||||
$instances = $request->getParam("instances", array());
|
||||
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($request);
|
||||
|
||||
$opts = array("myShows" => $my_shows, "showFilter" => $show_filter);
|
||||
$showBuilder = new Application_Model_ShowBuilder($startsDT, $endsDT, $opts);
|
||||
|
||||
//only send the schedule back if updates have been made.
|
||||
// -1 default will always call the schedule to be sent back if no timestamp is defined.
|
||||
$this->view->update = $showBuilder->hasBeenUpdatedSince(
|
||||
$timestamp, $instances);
|
||||
}
|
||||
|
||||
public function builderFeedAction()
|
||||
{
|
||||
$current_time = time();
|
||||
|
||||
$request = $this->getRequest();
|
||||
$show_filter = intval($request->getParam("showFilter", 0));
|
||||
$show_instance_filter = intval($request->getParam("showInstanceFilter", 0));
|
||||
$my_shows = intval($request->getParam("myShows", 0));
|
||||
|
||||
list($startsDT, $endsDT) = Application_Common_HTTPHelper::getStartEndFromRequest($request);
|
||||
|
||||
$opts = array("myShows" => $my_shows,
|
||||
"showFilter" => $show_filter,
|
||||
"showInstanceFilter" => $show_instance_filter);
|
||||
$showBuilder = new Application_Model_ShowBuilder($startsDT, $endsDT, $opts);
|
||||
|
||||
$data = $showBuilder->getItems();
|
||||
$this->view->schedule = $data["schedule"];
|
||||
$this->view->instances = $data["showInstances"];
|
||||
$this->view->timestamp = $current_time;
|
||||
}
|
||||
|
||||
public function scheduleAddAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
$mediaItems = $request->getParam("mediaIds", array());
|
||||
$scheduledItems = $request->getParam("schedIds", array());
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "showbuilder/schedule-add";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["media_items"] = $mediaItems;
|
||||
$log_vars["params"]["scheduled_items"] = $scheduledItems;
|
||||
Logging::info($log_vars);
|
||||
|
||||
try {
|
||||
$scheduler = new Application_Model_Scheduler();
|
||||
$scheduler->scheduleAfter($scheduledItems, $mediaItems);
|
||||
} catch (OutDatedScheduleException $e) {
|
||||
$this->view->error = $e->getMessage();
|
||||
Logging::info($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
$this->view->error = $e->getMessage();
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function scheduleRemoveAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$items = $request->getParam("items", array());
|
||||
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "showbuilder/schedule-remove";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["removed_items"] = $items;
|
||||
Logging::info($log_vars);
|
||||
|
||||
try {
|
||||
$scheduler = new Application_Model_Scheduler();
|
||||
$scheduler->removeItems($items);
|
||||
} catch (OutDatedScheduleException $e) {
|
||||
$this->view->error = $e->getMessage();
|
||||
Logging::info($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
$this->view->error = $e->getMessage();
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function scheduleMoveAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$selectedItems = $request->getParam("selectedItem");
|
||||
$afterItem = $request->getParam("afterItem");
|
||||
|
||||
/*
|
||||
$log_vars = array();
|
||||
$log_vars["url"] = $_SERVER['HTTP_HOST'];
|
||||
$log_vars["action"] = "showbuilder/schedule-move";
|
||||
$log_vars["params"] = array();
|
||||
$log_vars["params"]["selected_items"] = $selectedItems;
|
||||
$log_vars["params"]["destination_after_item"] = $afterItem;
|
||||
Logging::info($log_vars);
|
||||
*/
|
||||
|
||||
try {
|
||||
$scheduler = new Application_Model_Scheduler();
|
||||
$scheduler->moveItem($selectedItems, $afterItem);
|
||||
} catch (OutDatedScheduleException $e) {
|
||||
$this->view->error = $e->getMessage();
|
||||
Logging::info($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
$this->view->error = $e->getMessage();
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function scheduleReorderAction()
|
||||
{
|
||||
throw new Exception("this controller is/was a no-op please fix your code");
|
||||
}
|
||||
|
||||
}
|
22
legacy/application/controllers/SystemstatusController.php
Normal file
22
legacy/application/controllers/SystemstatusController.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
class SystemstatusController extends Zend_Controller_Action
|
||||
{
|
||||
private $version;
|
||||
public function init()
|
||||
{
|
||||
$config = Config::getConfig();
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/status/status.js?'.$config['airtime_version'],'text/javascript');
|
||||
$this->version = $config['airtime_version'];
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Settings');
|
||||
|
||||
$partitions = Application_Model_Systemstatus::GetDiskInfo();
|
||||
$this->view->status = new StdClass;
|
||||
$this->view->status->partitions = $partitions;
|
||||
$this->view->version = $this->version;
|
||||
}
|
||||
}
|
30
legacy/application/controllers/ThirdPartyController.php
Normal file
30
legacy/application/controllers/ThirdPartyController.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class ThirdPartyController abstract superclass for third-party service authorization
|
||||
*/
|
||||
abstract class ThirdPartyController extends Zend_Controller_Action {
|
||||
|
||||
/**
|
||||
* @var string base url and port for redirection
|
||||
*/
|
||||
protected $_baseUrl;
|
||||
|
||||
/**
|
||||
* @var Application_Service_ThirdPartyService third party service object
|
||||
*/
|
||||
protected $_service;
|
||||
|
||||
/**
|
||||
* Disable controller rendering and initialize
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
$this->_baseUrl = Application_Common_HTTPHelper::getStationUrl();
|
||||
|
||||
$this->view->layout()->disableLayout(); // Don't inject the standard Now Playing header.
|
||||
$this->_helper->viewRenderer->setNoRender(true); // Don't use (phtml) templates
|
||||
}
|
||||
|
||||
}
|
109
legacy/application/controllers/TracktypeController.php
Normal file
109
legacy/application/controllers/TracktypeController.php
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
class TracktypeController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('get-tracktype-data-table-info', 'json')
|
||||
->addActionContext('get-tracktype-data', 'json')
|
||||
->addActionContext('remove-tracktype', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function addTracktypeAction()
|
||||
{
|
||||
// Start the session to re-open write permission to the session so we can
|
||||
// create the namespace for our csrf token verification
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Settings');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$js_files = array(
|
||||
'js/datatables/js/jquery.dataTables.js?',
|
||||
'js/datatables/plugin/dataTables.pluginAPI.js?',
|
||||
'js/airtime/tracktype/tracktype.js?'
|
||||
);
|
||||
|
||||
foreach ($js_files as $js) {
|
||||
$this->view->headScript()->appendFile(
|
||||
$baseUrl.$js.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
}
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/tracktypes.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$form = new Application_Form_AddTracktype();
|
||||
|
||||
$this->view->successMessage = "";
|
||||
|
||||
if ($request->isPost()) {
|
||||
$params = $request->getPost();
|
||||
$postData = explode('&', $params['data']);
|
||||
$formData = array();
|
||||
foreach($postData as $k=>$v) {
|
||||
$v = explode('=', $v);
|
||||
$formData[$v[0]] = urldecode($v[1]);
|
||||
}
|
||||
|
||||
if ($form->validateCode($formData)) {
|
||||
$tracktype = new Application_Model_Tracktype($formData['tracktype_id']);
|
||||
if (empty($formData['tracktype_id'])) {
|
||||
$tracktype->setCode($formData['code']);
|
||||
}
|
||||
$tracktype->setTypeName($formData['type_name']);
|
||||
$tracktype->setDescription($formData['description']);
|
||||
$tracktype->setVisibility($formData['visibility']);
|
||||
$tracktype->save();
|
||||
|
||||
$form->reset();
|
||||
$this->view->form = $form;
|
||||
|
||||
if (strlen($formData['tracktype_id']) == 0) {
|
||||
$this->view->successMessage = "<div class='success'>"._("Track Type added successfully!")."</div>";
|
||||
} else {
|
||||
$this->view->successMessage = "<div class='success'>"._("Track Type updated successfully!")."</div>";
|
||||
}
|
||||
|
||||
$this->_helper->json->sendJson(array("valid"=>"true", "html"=>$this->view->render('tracktype/add-tracktype.phtml')));
|
||||
} else {
|
||||
$this->view->form = $form;
|
||||
$this->_helper->json->sendJson(array("valid"=>"false", "html"=>$this->view->render('tracktype/add-tracktype.phtml')));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->view->form = $form;
|
||||
}
|
||||
|
||||
public function getTracktypeDataTableInfoAction()
|
||||
{
|
||||
$post = $this->getRequest()->getPost();
|
||||
$tracktypes = Application_Model_Tracktype::getTracktypesDataTablesInfo($post);
|
||||
|
||||
$this->_helper->json->sendJson($tracktypes);
|
||||
}
|
||||
|
||||
public function getTracktypeDataAction()
|
||||
{
|
||||
$id = $this->_getParam('id');
|
||||
$this->view->entries = Application_Model_Tracktype::GetTracktypeData($id);
|
||||
}
|
||||
|
||||
public function removeTracktypeAction()
|
||||
{
|
||||
// action body
|
||||
$delId = $this->_getParam('id');
|
||||
|
||||
$tracktype = new Application_Model_Tracktype($delId);
|
||||
|
||||
# Delete the track type
|
||||
$this->view->entries = $tracktype->delete();
|
||||
}
|
||||
|
||||
}
|
65
legacy/application/controllers/UpgradeController.php
Normal file
65
legacy/application/controllers/UpgradeController.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
class UpgradeController extends Zend_Controller_Action
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
if (!RestAuth::verifyAuth(true, false, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$didWePerformAnUpgrade = UpgradeManager::doUpgrade();
|
||||
|
||||
if (!$didWePerformAnUpgrade) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody("No upgrade was performed. The current schema version is " . Application_Model_Preference::GetSchemaVersion() . ".<br>");
|
||||
} else {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody("Upgrade to Airtime schema version " . Application_Model_Preference::GetSchemaVersion() . " OK<br>");
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function downgradeAction() {
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
if (!RestAuth::verifyAuth(true, false, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $this->getRequest();
|
||||
$toVersion = $request->getParam("version");
|
||||
|
||||
try {
|
||||
$downgradePerformed = UpgradeManager::doDowngrade($toVersion);
|
||||
|
||||
if (!$downgradePerformed) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody("No downgrade was performed. The current schema version is " . Application_Model_Preference::GetSchemaVersion() . ".<br>");
|
||||
} else {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody("Downgrade to Airtime schema version " . Application_Model_Preference::GetSchemaVersion() . " OK<br>");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(400)
|
||||
->appendBody($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
246
legacy/application/controllers/UserController.php
Normal file
246
legacy/application/controllers/UserController.php
Normal file
|
@ -0,0 +1,246 @@
|
|||
<?php
|
||||
|
||||
class UserController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('get-hosts', 'json')
|
||||
->addActionContext('get-user-data-table-info', 'json')
|
||||
->addActionContext('get-user-data', 'json')
|
||||
->addActionContext('remove-user', 'json')
|
||||
->addActionContext('edit-user', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function addUserAction()
|
||||
{
|
||||
// Start the session to re-open write permission to the session so we can
|
||||
// create the namespace for our csrf token verification
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Settings');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$js_files = array(
|
||||
'js/datatables/js/jquery.dataTables.js?',
|
||||
'js/datatables/plugin/dataTables.pluginAPI.js?',
|
||||
'js/airtime/user/user.js?'
|
||||
);
|
||||
|
||||
foreach ($js_files as $js) {
|
||||
$this->view->headScript()->appendFile(
|
||||
$baseUrl.$js.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
}
|
||||
|
||||
$this->view->headLink()->appendStylesheet($baseUrl.'css/users.css?'.$CC_CONFIG['airtime_version']);
|
||||
|
||||
$form = new Application_Form_AddUser();
|
||||
|
||||
$this->view->successMessage = "";
|
||||
|
||||
if ($request->isPost()) {
|
||||
$params = $request->getPost();
|
||||
$postData = explode('&', $params['data']);
|
||||
$formData = array();
|
||||
foreach($postData as $k=>$v) {
|
||||
$v = explode('=', $v);
|
||||
$formData[$v[0]] = urldecode($v[1]);
|
||||
}
|
||||
|
||||
if ($form->isValid($formData)) {
|
||||
|
||||
if ($form->validateLogin($formData)) {
|
||||
$user = new Application_Model_User($formData['user_id']);
|
||||
if (empty($formData['user_id'])) {
|
||||
$user->setLogin($formData['login']);
|
||||
}
|
||||
$user->setFirstName($formData['first_name']);
|
||||
$user->setLastName($formData['last_name']);
|
||||
// We don't allow 6 x's as a password.
|
||||
// The reason is because we that as a password placeholder
|
||||
// on the client side.
|
||||
if ($formData['password'] != "xxxxxx") {
|
||||
$user->setPassword($formData['password']);
|
||||
}
|
||||
if (array_key_exists('type', $formData)) {
|
||||
if ($formData['type'] != UTYPE_SUPERADMIN) { //Don't allow any other user to be promoted to Super Admin
|
||||
$user->setType($formData['type']);
|
||||
}
|
||||
}
|
||||
$user->setEmail($formData['email']);
|
||||
$user->setCellPhone($formData['cell_phone']);
|
||||
$user->setSkype($formData['skype']);
|
||||
$user->setJabber($formData['jabber']);
|
||||
$user->save();
|
||||
|
||||
$form->reset();
|
||||
$this->view->form = $form;
|
||||
|
||||
if (strlen($formData['user_id']) == 0) {
|
||||
$this->view->successMessage = "<div class='success'>"._("User added successfully!")."</div>";
|
||||
} else {
|
||||
$this->view->successMessage = "<div class='success'>"._("User updated successfully!")."</div>";
|
||||
}
|
||||
|
||||
$this->_helper->json->sendJson(array("valid"=>"true", "html"=>$this->view->render('user/add-user.phtml')));
|
||||
} else {
|
||||
$this->view->form = $form;
|
||||
$this->_helper->json->sendJson(array("valid"=>"false", "html"=>$this->view->render('user/add-user.phtml')));
|
||||
}
|
||||
} else {
|
||||
$this->view->form = $form;
|
||||
$this->_helper->json->sendJson(array("valid"=>"false", "html"=>$this->view->render('user/add-user.phtml')));
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->form = $form;
|
||||
}
|
||||
|
||||
public function getHostsAction()
|
||||
{
|
||||
$search = $this->_getParam('term');
|
||||
$this->view->hosts = Application_Model_User::getHosts($search);
|
||||
}
|
||||
|
||||
public function getUserDataTableInfoAction()
|
||||
{
|
||||
$post = $this->getRequest()->getPost();
|
||||
$users = Application_Model_User::getUsersDataTablesInfo($post);
|
||||
|
||||
$this->_helper->json->sendJson($users);
|
||||
}
|
||||
|
||||
public function getUserDataAction()
|
||||
{
|
||||
$id = $this->_getParam('id');
|
||||
$this->view->entries = Application_Model_User::GetUserData($id);
|
||||
}
|
||||
|
||||
public function editUserAction()
|
||||
{
|
||||
Zend_Layout::getMvcInstance()->assign('parent_page', 'Settings');
|
||||
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
|
||||
$request = $this->getRequest();
|
||||
$form = new Application_Form_EditUser();
|
||||
if ($request->isPost()) {
|
||||
$formData = $request->getPost();
|
||||
|
||||
if ($form->isValid($formData) &&
|
||||
$form->validateLogin($formData['cu_login'], $formData['cu_user_id'])) {
|
||||
$user = new Application_Model_User($formData['cu_user_id']);
|
||||
//Stupid hack because our schema enforces non-null first_name
|
||||
//even though by default the admin user has no first name... (....)
|
||||
if (Application_Model_User::getCurrentUser()->isSuperAdmin()) {
|
||||
if (empty($formData['cu_first_name'])) {
|
||||
$formData['cu_first_name'] = "admin";
|
||||
$formData['cu_last_name'] = "admin"; //ditto, avoid non-null DB constraint
|
||||
}
|
||||
}
|
||||
if (isset($formData['cu_first_name'])) {
|
||||
$user->setFirstName($formData['cu_first_name']);
|
||||
}
|
||||
|
||||
if (isset($formData['cu_last_name'])) {
|
||||
$user->setLastName($formData['cu_last_name']);
|
||||
}
|
||||
// We don't allow 6 x's as a password.
|
||||
// The reason is because we use that as a password placeholder
|
||||
// on the client side.
|
||||
if (array_key_exists('cu_password', $formData) && ($formData['cu_password'] != "xxxxxx") &&
|
||||
(!empty($formData['cu_password']))) {
|
||||
$user->setPassword($formData['cu_password']);
|
||||
}
|
||||
|
||||
if (array_key_exists('cu_email', $formData)) {
|
||||
$user->setEmail($formData['cu_email']);
|
||||
}
|
||||
|
||||
if (array_key_exists('cu_cell_phone', $formData)) {
|
||||
$user->setCellPhone($formData['cu_cell_phone']);
|
||||
}
|
||||
|
||||
if (array_key_exists('cu_skype', $formData)) {
|
||||
$user->setSkype($formData['cu_skype']);
|
||||
}
|
||||
|
||||
if (array_key_exists('cu_jabber', $formData)) {
|
||||
$user->setJabber($formData['cu_jabber']);
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
Application_Model_Preference::SetUserLocale($formData['cu_locale']);
|
||||
Application_Model_Preference::SetUserTimezone($formData['cu_timezone']);
|
||||
|
||||
//configure localization with new locale setting
|
||||
Application_Model_Locale::configureLocalization($formData['cu_locale']);
|
||||
//reinitialize form so language gets translated
|
||||
$form = new Application_Form_EditUser();
|
||||
|
||||
$this->view->successMessage = "<div class='success'>"._("Settings updated successfully!")."</div>";
|
||||
}
|
||||
$this->view->form = $form;
|
||||
$this->view->html = $this->view->render('user/edit-user.phtml');
|
||||
}
|
||||
$this->view->form = $form;
|
||||
$this->view->html = $this->view->render('user/edit-user.phtml');
|
||||
}
|
||||
|
||||
public function removeUserAction()
|
||||
{
|
||||
// action body
|
||||
$delId = $this->_getParam('id');
|
||||
$valid_actions = array("delete_cascade", "reassign_to");
|
||||
$files_action = $this->_getParam('deleted_files');
|
||||
|
||||
# TODO : remove this. we only use default for now not to break the UI.
|
||||
if (!$files_action) { # set default action
|
||||
$files_action = "reassign_to";
|
||||
$new_owner = Application_Model_User::getFirstAdmin($delId);
|
||||
}
|
||||
|
||||
# only delete when valid action is selected for the owned files
|
||||
if (! in_array($files_action, $valid_actions) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$userId = $userInfo->id;
|
||||
|
||||
# Don't let users delete themselves
|
||||
if ($delId == $userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = new Application_Model_User($delId);
|
||||
|
||||
// Don't allow super admins to be deleted.
|
||||
if ($user->isSuperAdmin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
# Take care of the user's files by either assigning them to somebody
|
||||
# or deleting them all
|
||||
if ($files_action == "delete_cascade") {
|
||||
$user->deleteAllFiles();
|
||||
} elseif ($files_action == "reassign_to") {
|
||||
// TODO : fix code to actually use the line below and pick a
|
||||
// real owner instead of defaulting to the first found admin
|
||||
//$new_owner_id = $this->_getParam("new_owner");
|
||||
//$new_owner = new Application_Model_User($new_owner_id);
|
||||
$user->donateFilesTo( $new_owner );
|
||||
Logging::info("Reassign to user {$new_owner->getDbId()}");
|
||||
}
|
||||
# Finally delete the user
|
||||
$this->view->entries = $user->delete();
|
||||
}
|
||||
}
|
101
legacy/application/controllers/UsersettingsController.php
Normal file
101
legacy/application/controllers/UsersettingsController.php
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
class UsersettingsController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
/* Initialize action controller here */
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('get-now-playing-screen-settings', 'json')
|
||||
->addActionContext('set-now-playing-screen-settings', 'json')
|
||||
->addActionContext('get-library-datatable', 'json')
|
||||
->addActionContext('set-library-datatable', 'json')
|
||||
->addActionContext('get-timeline-datatable', 'json')
|
||||
->addActionContext('set-timeline-datatable', 'json')
|
||||
->addActionContext('remindme', 'json')
|
||||
->addActionContext('remindme-never', 'json')
|
||||
->addActionContext('donotshowregistrationpopup', 'json')
|
||||
->addActionContext('set-library-screen-settings', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function setNowPlayingScreenSettingsAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$settings = $request->getParam("settings");
|
||||
|
||||
Application_Model_Preference::setNowPlayingScreenSettings($settings);
|
||||
}
|
||||
|
||||
public function getNowPlayingScreenSettingsAction()
|
||||
{
|
||||
$data = Application_Model_Preference::getNowPlayingScreenSettings();
|
||||
if (!is_null($data)) {
|
||||
$this->view->settings = $data;
|
||||
}
|
||||
}
|
||||
|
||||
public function setLibraryDatatableAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$settings = $request->getParam("settings");
|
||||
|
||||
Application_Model_Preference::setCurrentLibraryTableSetting($settings);
|
||||
}
|
||||
|
||||
public function getLibraryDatatableAction()
|
||||
{
|
||||
$data = Application_Model_Preference::getCurrentLibraryTableSetting();
|
||||
if (!is_null($data)) {
|
||||
$this->_helper->json($data);
|
||||
} else {
|
||||
$this->_helper->json(false);
|
||||
}
|
||||
}
|
||||
|
||||
public function setTimelineDatatableAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$settings = $request->getParam("settings");
|
||||
|
||||
Application_Model_Preference::setTimelineDatatableSetting($settings);
|
||||
}
|
||||
|
||||
public function getTimelineDatatableAction()
|
||||
{
|
||||
$data = Application_Model_Preference::getTimelineDatatableSetting();
|
||||
if (!is_null($data)) {
|
||||
$this->view->settings = $data;
|
||||
}
|
||||
}
|
||||
|
||||
public function remindmeAction()
|
||||
{
|
||||
// unset session
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
Zend_Session::namespaceUnset('referrer');
|
||||
Application_Model_Preference::SetRemindMeDate();
|
||||
}
|
||||
|
||||
public function remindmeNeverAction()
|
||||
{
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
Zend_Session::namespaceUnset('referrer');
|
||||
//pass in true to indicate 'Remind me never' was clicked
|
||||
Application_Model_Preference::SetRemindMeDate(true);
|
||||
}
|
||||
|
||||
public function donotshowregistrationpopupAction()
|
||||
{
|
||||
// unset session
|
||||
SessionHelper::reopenSessionForWriting();
|
||||
Zend_Session::namespaceUnset('referrer');
|
||||
}
|
||||
|
||||
public function setLibraryScreenSettingsAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$settings = $request->getParam("settings");
|
||||
Application_Model_Preference::setLibraryScreenSettings($settings);
|
||||
}
|
||||
}
|
167
legacy/application/controllers/WebstreamController.php
Normal file
167
legacy/application/controllers/WebstreamController.php
Normal file
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
|
||||
class WebstreamController extends Zend_Controller_Action
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('new', 'json')
|
||||
->addActionContext('save', 'json')
|
||||
->addActionContext('edit', 'json')
|
||||
->addActionContext('delete', 'json')
|
||||
->initContext();
|
||||
}
|
||||
|
||||
public function newAction()
|
||||
{
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
if (!$this->isAuthorized(-1)) {
|
||||
// TODO: this header call does not actually print any error message
|
||||
header("Status: 401 Not Authorized");
|
||||
return;
|
||||
}
|
||||
|
||||
$webstream = new CcWebstream();
|
||||
|
||||
//we're not saving this primary key in the DB so it's OK to be -1
|
||||
$webstream->setDbId(-1);
|
||||
$webstream->setDbName(_("Untitled Webstream"));
|
||||
$webstream->setDbDescription("");
|
||||
$webstream->setDbUrl("http://");
|
||||
$webstream->setDbLength("00:30:00");
|
||||
$webstream->setDbName(_("Untitled Webstream"));
|
||||
$webstream->setDbCreatorId($userInfo->id);
|
||||
$webstream->setDbUtime(new DateTime("now", new DateTimeZone('UTC')));
|
||||
$webstream->setDbMtime(new DateTime("now", new DateTimeZone('UTC')));
|
||||
|
||||
//clear the session in case an old playlist was open: CC-4196
|
||||
Application_Model_Library::changePlaylist(null, null);
|
||||
|
||||
$this->view->obj = new Application_Model_Webstream($webstream);
|
||||
$this->view->action = "new";
|
||||
$this->view->html = $this->view->render('webstream/webstream.phtml');
|
||||
}
|
||||
|
||||
public function editAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
$id = $request->getParam("id");
|
||||
if (is_null($id)) {
|
||||
throw new Exception("Missing parameter 'id'");
|
||||
}
|
||||
|
||||
$webstream = CcWebstreamQuery::create()->findPK($id);
|
||||
if ($webstream) {
|
||||
Application_Model_Library::changePlaylist($id, "stream");
|
||||
}
|
||||
|
||||
$obj = new Application_Model_Webstream($webstream);
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
|
||||
|
||||
if (!$isAdminOrPM && $webstream->getDbCreatorId() != $user->getId()) {
|
||||
$this->view->objType = "webstream";
|
||||
$this->view->type = "webstream";
|
||||
$this->view->obj = $obj;
|
||||
$this->view->id = $id;
|
||||
$this->view->html = $this->view->render('playlist/permission-denied.phtml');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->view->obj = $obj;
|
||||
$this->view->type = "webstream";
|
||||
$this->view->id = $id;
|
||||
$this->view->action = "edit";
|
||||
$this->view->html = $this->view->render('webstream/webstream.phtml');
|
||||
}
|
||||
|
||||
public function deleteAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$id = $request->getParam("ids");
|
||||
|
||||
if (!$this->isAuthorized($id)) {
|
||||
header("Status: 401 Not Authorized");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$type = "stream";
|
||||
Application_Model_Library::changePlaylist(null, $type);
|
||||
|
||||
$webstream = CcWebstreamQuery::create()->findPK($id)->delete();
|
||||
|
||||
$this->view->obj = null;
|
||||
$this->view->action = "delete";
|
||||
$this->view->html = $this->view->render('webstream/webstream.phtml');
|
||||
|
||||
}
|
||||
|
||||
/*TODO : make a user object be passed a parameter into this function so
|
||||
that it does not have to be fetched multiple times.*/
|
||||
public function isAuthorized($webstream_id)
|
||||
{
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($user->isHost()) {
|
||||
// not creating a webstream
|
||||
if ($webstream_id != -1) {
|
||||
$webstream = CcWebstreamQuery::create()->findPK($webstream_id);
|
||||
/*we are updating a playlist. Ensure that if the user is a
|
||||
host/dj, that he has the correct permission.*/
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
//only allow when webstream belongs to the DJ
|
||||
return $webstream->getDbCreatorId() == $user->getId();
|
||||
}
|
||||
/*we are creating a new stream. Don't need to check whether the
|
||||
DJ/Host owns the stream*/
|
||||
return true;
|
||||
} else {
|
||||
Logging::info( $user );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function saveAction()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
$id = $request->getParam("id");
|
||||
|
||||
$parameters = array();
|
||||
foreach (array('id','length','name','description','url') as $p) {
|
||||
$parameters[$p] = trim($request->getParam($p));
|
||||
}
|
||||
|
||||
if (!$this->isAuthorized($id)) {
|
||||
header("Status: 401 Not Authorized");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
list($analysis, $mime, $mediaUrl, $di) = Application_Model_Webstream::analyzeFormData($parameters);
|
||||
try {
|
||||
if (Application_Model_Webstream::isValid($analysis)) {
|
||||
$streamId = Application_Model_Webstream::save($parameters, $mime, $mediaUrl, $di);
|
||||
|
||||
Application_Model_Library::changePlaylist($streamId, "stream");
|
||||
|
||||
$this->view->statusMessage = "<div class='success'>"._("Webstream saved.")."</div>";
|
||||
$this->view->streamId = $streamId;
|
||||
$this->view->length = $di->format("%Hh %Im");
|
||||
} else {
|
||||
throw new Exception("isValid returned false");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Logging::debug($e->getMessage());
|
||||
$this->view->statusMessage = "<div class='errors'>"._("Invalid form values.")."</div>";
|
||||
$this->view->streamId = -1;
|
||||
$this->view->analysis = $analysis;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
-----------------------------------------------------------------------
|
||||
-- third_party_track_references
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS "third_party_track_references" CASCADE;
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- celery_tasks
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS "celery_tasks" CASCADE;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE third_party_track_references ALTER COLUMN file_id SET NOT NULL;
|
|
@ -0,0 +1,11 @@
|
|||
ALTER TABLE cc_files DROP COLUMN description;
|
||||
|
||||
DELETE FROM cc_pref WHERE keystr = 'station_podcast_id';
|
||||
|
||||
DROP TABLE IF EXISTS "podcast" CASCADE;
|
||||
|
||||
DROP TABLE IF EXISTS "imported_podcast" CASCADE;
|
||||
|
||||
DROP TABLE IF EXISTS "station_podcast" CASCADE;
|
||||
|
||||
DROP TABLE IF EXISTS "podcast_episodes" CASCADE;
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE imported_podcast DROP COLUMN IF EXISTS album_override;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id DROP DEFAULT;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id SET NOT NULL;
|
||||
ALTER TABLE cc_show DROP COLUMN IF EXISTS autoplaylist_repeat;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE cc_service_register ALTER COLUMN ip TYPE character varying(18);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE podcast_episodes DROP COLUMN IF EXISTS episode_title;
|
||||
ALTER TABLE podcast_episodes DROP COLUMN IF EXISTS episode_description;
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE cc_blockcriteria DROP COLUMN IF EXISTS criteriagroup;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE podcast_episodes ALTER COLUMN episode_description TYPE VARCHAR(4096);
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE cc_block ALTER COLUMN type SET DEFAULT 'static';
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE cc_files DROP COLUMN IF EXISTS artwork;
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE cc_files DROP COLUMN IF EXISTS track_type;
|
||||
|
||||
DROP TABLE IF EXISTS "cc_track_types" CASCADE;
|
|
@ -0,0 +1,10 @@
|
|||
CREATE TABLE "cc_smemb"
|
||||
(
|
||||
"id" INTEGER NOT NULL,
|
||||
"uid" INTEGER DEFAULT 0 NOT NULL,
|
||||
"gid" INTEGER DEFAULT 0 NOT NULL,
|
||||
"level" INTEGER DEFAULT 0 NOT NULL,
|
||||
"mid" INTEGER,
|
||||
PRIMARY KEY ("id"),
|
||||
CONSTRAINT "cc_smemb_id_idx" UNIQUE ("id")
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
-- we can restore the schema here but you'll need to restore data from a backup
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_id INTEGER;
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_error_code INTEGER;
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_error_msg VARCHAR(512);
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_link_to_file VARCHAR(4096);
|
||||
ALTER TABLE cc_files ADD COLUMN soundcloud_upload_time TIMESTAMP(6);
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE cc_show_instances DROP COLUMN IF EXISTS autoplaylist_built;
|
||||
ALTER TABLE cc_show DROP COLUMN IF EXISTS has_autoplaylist;
|
||||
ALTER TABLE cc_show DROP COLUMN IF EXISTS autoplaylist_id;
|
289
legacy/application/controllers/plugins/Acl_plugin.php
Normal file
289
legacy/application/controllers/plugins/Acl_plugin.php
Normal file
|
@ -0,0 +1,289 @@
|
|||
<?php
|
||||
|
||||
class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
|
||||
{
|
||||
/**
|
||||
* @var Zend_Acl
|
||||
**/
|
||||
protected $_acl;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
**/
|
||||
protected $_roleName;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
**/
|
||||
protected $_errorPage;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param mixed $aclData
|
||||
* @param $roleName
|
||||
* @return void
|
||||
**/
|
||||
public function __construct(Zend_Acl $aclData, $roleName = 'G')
|
||||
{
|
||||
$this->_errorPage = array('module' => 'default',
|
||||
'controller' => 'error',
|
||||
'action' => 'error');
|
||||
|
||||
$this->_roleName = $roleName;
|
||||
|
||||
if (null !== $aclData) {
|
||||
$this->setAcl($aclData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ACL object
|
||||
*
|
||||
* @param mixed $aclData
|
||||
* @return void
|
||||
**/
|
||||
public function setAcl(Zend_Acl $aclData)
|
||||
{
|
||||
$this->_acl = $aclData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ACL object
|
||||
*
|
||||
* @return Zend_Acl
|
||||
**/
|
||||
public function getAcl()
|
||||
{
|
||||
return $this->_acl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ACL role used
|
||||
*
|
||||
* @return string
|
||||
* @author
|
||||
**/
|
||||
public function getRoleName()
|
||||
{
|
||||
return $this->_roleName;
|
||||
}
|
||||
|
||||
public function setRoleName($type)
|
||||
{
|
||||
$this->_roleName = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the error page
|
||||
*
|
||||
* @param string $action
|
||||
* @param string $controller
|
||||
* @param string $module
|
||||
* @return void
|
||||
**/
|
||||
public function setErrorPage($action, $controller = 'error', $module = 'default')
|
||||
{
|
||||
$this->_errorPage = array('module' => $module,
|
||||
'controller' => $controller,
|
||||
'action' => $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error page
|
||||
*
|
||||
* @return array
|
||||
**/
|
||||
public function getErrorPage()
|
||||
{
|
||||
return $this->_errorPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Predispatch
|
||||
* Checks if the current user identified by roleName has rights to the requested url (module/controller/action)
|
||||
* If not, it will call denyAccess to be redirected to errorPage
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function preDispatch(Zend_Controller_Request_Abstract $request)
|
||||
{
|
||||
$controller = strtolower($request->getControllerName());
|
||||
|
||||
if (in_array($controller, array(
|
||||
"index",
|
||||
"login",
|
||||
"api",
|
||||
"auth",
|
||||
"error",
|
||||
"locale",
|
||||
"upgrade",
|
||||
"embed",
|
||||
"feeds"
|
||||
)))
|
||||
{
|
||||
$this->setRoleName("G");
|
||||
}
|
||||
elseif (Zend_Session::isStarted() && !Zend_Auth::getInstance()->hasIdentity()) {
|
||||
|
||||
//The controller uses sessions but we don't have an identity yet.
|
||||
|
||||
// If we don't have an identity and we're making a RESTful request,
|
||||
// we need to do API key verification
|
||||
if ($request->getModuleName() == "rest") {
|
||||
if (!$this->verifyAuth()) {
|
||||
//$this->denyAccess();
|
||||
//$this->getResponse()->sendResponse();
|
||||
//$r->gotoSimpleAndExit('index', 'login', $request->getModuleName());
|
||||
|
||||
//die();
|
||||
throw new Zend_Controller_Exception("Incorrect API key", 401);
|
||||
}
|
||||
}
|
||||
else //Non-REST, regular Airtime web app requests
|
||||
{
|
||||
// Redirect user to the landing page if they are trying to
|
||||
// access a resource that requires a valid session.
|
||||
// Skip the redirection if they are already on the landing page
|
||||
// or the login page.
|
||||
if ($controller !== 'index' && $controller !== 'login') {
|
||||
|
||||
if ($request->isXmlHttpRequest()) {
|
||||
|
||||
$url = 'http://'.$request->getHttpHost().'/';
|
||||
$json = Zend_Json::encode(array('auth' => false, 'url' => $url));
|
||||
|
||||
// Prepare response
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(401)
|
||||
->setBody($json)
|
||||
->sendResponse();
|
||||
|
||||
//redirectAndExit() cleans up, sends the headers and stops the script
|
||||
Zend_Controller_Action_HelperBroker::getStaticHelper('redirector')->redirectAndExit();
|
||||
} else {
|
||||
$r = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
|
||||
$r->gotoSimpleAndExit('index', 'index', $request->getModuleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { //We have a session/identity.
|
||||
|
||||
// If we have an identity and we're making a RESTful request,
|
||||
// we need to check the CSRF token
|
||||
if ($_SERVER['REQUEST_METHOD'] != "GET" && $request->getModuleName() == "rest") {
|
||||
$token = $request->getParam("csrf_token");
|
||||
// PUT requests don't parameterize the data in the body, so we can't
|
||||
// fetch it with getParam or getPost; instead we have to parse the body and
|
||||
// check for the token in the JSON. (Hopefully we can find a better way to do this) -- Duncan
|
||||
if (empty($token)) {
|
||||
$token = json_decode($this->getRequest()->getRawBody(), true)["csrf_token"];
|
||||
}
|
||||
$tokenValid = $this->verifyCSRFToken($token);
|
||||
|
||||
if (!$tokenValid) {
|
||||
$csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
|
||||
$csrf_namespace->authtoken = sha1(openssl_random_pseudo_bytes(128));
|
||||
|
||||
Logging::warn("Invalid CSRF token: $token");
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(401)
|
||||
->appendBody("ERROR: CSRF token mismatch.")
|
||||
->sendResponse();
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$this->setRoleName($userInfo->type);
|
||||
|
||||
Zend_View_Helper_Navigation_HelperAbstract::setDefaultAcl($this->_acl);
|
||||
Zend_View_Helper_Navigation_HelperAbstract::setDefaultRole($this->_roleName);
|
||||
|
||||
$resourceName = '';
|
||||
|
||||
if ($request->getModuleName() != 'default') {
|
||||
$resourceName .= strtolower($request->getModuleName()) . ':';
|
||||
}
|
||||
|
||||
$resourceName .= $controller;
|
||||
|
||||
/** Check if the controller/action can be accessed by the current user */
|
||||
if (!$this->getAcl()->has($resourceName)) {
|
||||
$this->setErrorPage('error404');
|
||||
$this->denyAccess();
|
||||
} else if (!$this->getAcl()->isAllowed($this->_roleName,
|
||||
$resourceName,
|
||||
$request->getActionName())) {
|
||||
/** Redirect to access denied page */
|
||||
$this->setErrorPage('error403');
|
||||
$this->denyAccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function verifyAuth() {
|
||||
if ($this->verifyAPIKey() || $this->isVerifiedDownload()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(401)
|
||||
->appendBody("ERROR: Incorrect API key.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the requested file can be downloaded.
|
||||
* It should satisfy the following requirements:
|
||||
* * request path is /rest/media/:id/download
|
||||
* * download key is correct
|
||||
* * requested file belongs to the station podcast
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isVerifiedDownload() {
|
||||
$request = $this->getRequest();
|
||||
$fileId = $request->getParam("id");
|
||||
$key = $request->getParam("download_key");
|
||||
$module = $request->getModuleName();
|
||||
$controller = $request->getControllerName();
|
||||
$action = $request->getActionName();
|
||||
$stationPodcast = StationPodcastQuery::create()
|
||||
->findOneByDbPodcastId(Application_Model_Preference::getStationPodcastId());
|
||||
return $module == "rest" && $controller == "media" && $action == "download"
|
||||
&& $key === Application_Model_Preference::getStationPodcastDownloadKey()
|
||||
&& $stationPodcast->hasEpisodeForFile($fileId);
|
||||
}
|
||||
|
||||
private function verifyCSRFToken($token) {
|
||||
return SecurityHelper::verifyCSRFToken($token);
|
||||
}
|
||||
|
||||
private function verifyAPIKey() {
|
||||
// The API key is passed in via HTTP "basic authentication":
|
||||
// http://en.wikipedia.org/wiki/Basic_access_authentication
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
// Decode the API key that was passed to us in the HTTP request.
|
||||
$authHeader = $this->getRequest()->getHeader("Authorization");
|
||||
$encodedRequestApiKey = substr($authHeader, strlen("Basic "));
|
||||
$encodedStoredApiKey = base64_encode($CC_CONFIG["apiKey"][0] . ":");
|
||||
|
||||
return ($encodedRequestApiKey === $encodedStoredApiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny Access Function
|
||||
* Redirects to errorPage, this can be called from an action using the action helper
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function denyAccess()
|
||||
{
|
||||
$this->_request->setModuleName($this->_errorPage['module']);
|
||||
$this->_request->setControllerName($this->_errorPage['controller']);
|
||||
$this->_request->setActionName($this->_errorPage['action']);
|
||||
}
|
||||
}
|
15
legacy/application/controllers/plugins/Maintenance.php
Normal file
15
legacy/application/controllers/plugins/Maintenance.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
class Zend_Controller_Plugin_Maintenance extends Zend_Controller_Plugin_Abstract
|
||||
{
|
||||
public function preDispatch(Zend_Controller_Request_Abstract $request) {
|
||||
$maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt";
|
||||
|
||||
if (file_exists($maintenanceFile)) {
|
||||
$request->setModuleName('default')
|
||||
->setControllerName('index')
|
||||
->setActionName('maintenance')
|
||||
->setDispatched(true);
|
||||
}
|
||||
}
|
||||
}
|
251
legacy/application/controllers/plugins/PageLayoutInitPlugin.php
Normal file
251
legacy/application/controllers/plugins/PageLayoutInitPlugin.php
Normal file
|
@ -0,0 +1,251 @@
|
|||
<?php
|
||||
|
||||
/** Our standard page layout initialization has to be done via a plugin
|
||||
* because some of it requires session variables, and some of the routes
|
||||
* run without a session (like API calls). This is an optimization because
|
||||
* starting the session adds a fair amount of overhead.
|
||||
*/
|
||||
class PageLayoutInitPlugin extends Zend_Controller_Plugin_Abstract
|
||||
{
|
||||
protected $_bootstrap = null;
|
||||
|
||||
public function __construct($boostrap) {
|
||||
$this->_bootstrap = $boostrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the session depending on which controller your request is going to.
|
||||
* We start the session explicitly here so that we can avoid starting sessions
|
||||
* needlessly for (stateless) requests to the API.
|
||||
* @param Zend_Controller_Request_Abstract $request
|
||||
* @throws Zend_Session_Exception
|
||||
*/
|
||||
public function routeShutdown(Zend_Controller_Request_Abstract $request)
|
||||
{
|
||||
$controller = strtolower($request->getControllerName());
|
||||
$action = strtolower($request->getActionName());
|
||||
|
||||
//List of controllers where we don't need a session, and we don't need
|
||||
//all the standard HTML / JS boilerplate.
|
||||
if (!in_array($controller, array(
|
||||
"index", //Radio Page
|
||||
"api",
|
||||
"auth",
|
||||
"error",
|
||||
"upgrade",
|
||||
"embed",
|
||||
"feeds"
|
||||
))
|
||||
) {
|
||||
//Start the session
|
||||
Zend_Session::start();
|
||||
Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance());
|
||||
|
||||
//localization configuration
|
||||
Application_Model_Locale::configureLocalization();
|
||||
|
||||
$this->_initGlobals();
|
||||
$this->_initCsrfNamespace();
|
||||
$this->_initHeadLink();
|
||||
$this->_initHeadScript();
|
||||
$this->_initTitle();
|
||||
$this->_initTranslationGlobals();
|
||||
$this->_initViewHelpers();
|
||||
}
|
||||
|
||||
// Skip upgrades and task management when running unit tests
|
||||
if (getenv("AIRTIME_UNIT_TEST") != 1) {
|
||||
$taskManager = TaskManager::getInstance();
|
||||
|
||||
// Run the upgrade on each request (if it needs to be run)
|
||||
// We can't afford to wait 7 minutes to run an upgrade: users could
|
||||
// have several minutes of database errors while waiting for a
|
||||
// schema change upgrade to happen after a deployment
|
||||
$taskManager->runTask('UpgradeTask');
|
||||
|
||||
// Piggyback the TaskManager onto API calls. This provides guaranteed consistency
|
||||
// (there is at least one API call made from pypo to Airtime every 7 minutes) and
|
||||
// greatly reduces the chances of lock contention on cc_pref while the TaskManager runs
|
||||
if ($controller == "api") {
|
||||
$taskManager->runTasks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function _initGlobals()
|
||||
{
|
||||
if (!Zend_Session::isStarted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$view = $this->_bootstrap->getResource('view');
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$view->headScript()->appendScript("var baseUrl = '$baseUrl';");
|
||||
$this->_initTranslationGlobals($view);
|
||||
|
||||
$user = Application_Model_User::GetCurrentUser();
|
||||
if (!is_null($user)) {
|
||||
$userType = $user->getType();
|
||||
} else {
|
||||
$userType = "";
|
||||
}
|
||||
$view->headScript()->appendScript("var userType = '$userType';");
|
||||
|
||||
// Dropzone also accept file extensions and doesn't correctly extract certain mimetypes (eg. FLAC - try it),
|
||||
// so we append the file extensions to the list of mimetypes and that makes it work.
|
||||
$mimeTypes = FileDataHelper::getAudioMimeTypeArray();
|
||||
$fileExtensions = array_values($mimeTypes);
|
||||
foreach($fileExtensions as &$extension) {
|
||||
$extension = '.' . $extension;
|
||||
}
|
||||
$view->headScript()->appendScript("var acceptedMimeTypes = " . json_encode(array_merge(array_keys($mimeTypes), $fileExtensions)) . ";");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a global namespace to hold a session token for CSRF prevention
|
||||
*/
|
||||
protected function _initCsrfNamespace()
|
||||
{
|
||||
/*
|
||||
if (!Zend_Session::isStarted()) {
|
||||
return;
|
||||
}*/
|
||||
|
||||
$csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
|
||||
// Check if the token exists
|
||||
if (!$csrf_namespace->authtoken) {
|
||||
// If we don't have a token, regenerate it and set a 1 week timeout
|
||||
// Should we log the user out here if the token is expired?
|
||||
$csrf_namespace->authtoken = sha1(uniqid(rand(), 1));
|
||||
$csrf_namespace->setExpirationSeconds(168 * 60 * 60);
|
||||
}
|
||||
|
||||
//Here we are closing the session for writing because otherwise no requests
|
||||
//in this session will be handled in parallel. This gives a major boost to the perceived performance
|
||||
//of the application (page load times are more consistent, no lock contention).
|
||||
session_write_close();
|
||||
//Zend_Session::writeClose(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ideally, globals should be written to a single js file once
|
||||
* from a php init function. This will save us from having to
|
||||
* reinitialize them every request
|
||||
*/
|
||||
private function _initTranslationGlobals()
|
||||
{
|
||||
$view = $this->_bootstrap->getResource('view');
|
||||
$view->headScript()->appendScript("var PRODUCT_NAME = '" . PRODUCT_NAME . "';");
|
||||
$view->headScript()->appendScript("var USER_MANUAL_URL = '" . USER_MANUAL_URL . "';");
|
||||
$view->headScript()->appendScript("var COMPANY_NAME = '" . COMPANY_NAME . "';");
|
||||
//Each page refresh or tab open has uniqID, not to be used for security
|
||||
$view->headScript()->appendScript("var UNIQID = '" . uniqid() . "';");
|
||||
|
||||
$track_type_options = array();
|
||||
$track_types = Application_Model_Tracktype::getTracktypes();
|
||||
|
||||
array_multisort(array_map(function($element) {
|
||||
return $element['type_name'];
|
||||
}, $track_types), SORT_ASC, $track_types);
|
||||
|
||||
foreach ($track_types as $key => $tt) {
|
||||
$track_type_options[$tt['code']] = $tt['type_name'];
|
||||
}
|
||||
$ttarr = json_encode($track_type_options, JSON_FORCE_OBJECT);
|
||||
$view->headScript()->appendScript("var TRACKTYPES = " . $ttarr . ";");
|
||||
}
|
||||
|
||||
protected function _initHeadLink()
|
||||
{
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$view = $this->_bootstrap->getResource('view');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$view->headLink(array('rel' => 'icon', 'href' => $baseUrl . 'favicon.ico?' . $CC_CONFIG['airtime_version'], 'type' => 'image/x-icon'), 'PREPEND')
|
||||
->appendStylesheet($baseUrl . 'css/bootstrap.css?' . $CC_CONFIG['airtime_version'])
|
||||
->appendStylesheet($baseUrl . 'css/redmond/jquery-ui-1.8.8.custom.css?' . $CC_CONFIG['airtime_version'])
|
||||
->appendStylesheet($baseUrl . 'css/pro_dropdown_3.css?' . $CC_CONFIG['airtime_version'])
|
||||
->appendStylesheet($baseUrl . 'css/qtip/jquery.qtip.min.css?' . $CC_CONFIG['airtime_version'])
|
||||
->appendStylesheet($baseUrl . 'css/styles.css?' . $CC_CONFIG['airtime_version'])
|
||||
->appendStylesheet($baseUrl . 'css/masterpanel.css?' . $CC_CONFIG['airtime_version'])
|
||||
->appendStylesheet($baseUrl . 'css/tipsy/jquery.tipsy.css?' . $CC_CONFIG['airtime_version']);
|
||||
}
|
||||
|
||||
protected function _initHeadScript()
|
||||
{
|
||||
if (!Zend_Session::isStarted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
$view = $this->_bootstrap->getResource('view');
|
||||
|
||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||
|
||||
$view->headScript()->appendFile($baseUrl . 'js/libs/jquery-1.8.3.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/libs/jquery-ui-1.8.24.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/libs/angular.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/bootstrap/bootstrap.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/libs/underscore-min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
|
||||
->appendFile($baseUrl . 'js/qtip/jquery.qtip.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/jplayer/jquery.jplayer.min.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/sprintf/sprintf-0.7-beta1.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/cookie/js.cookie.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/i18n/jquery.i18n.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'locale/general-translation-table?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'locale/datatables-translation-table?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
|
||||
->appendScript("$.i18n.setDictionary(general_dict)")
|
||||
->appendScript("var baseUrl='$baseUrl'");
|
||||
|
||||
//These timezones are needed to adjust javascript Date objects on the client to make sense to the user's set timezone
|
||||
//or the server's set timezone.
|
||||
$serverTimeZone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone());
|
||||
$now = new DateTime("now", $serverTimeZone);
|
||||
$offset = $now->format("Z") * -1;
|
||||
$view->headScript()->appendScript("var serverTimezoneOffset = {$offset}; //in seconds");
|
||||
|
||||
if (class_exists("Zend_Auth", false) && Zend_Auth::getInstance()->hasIdentity()) {
|
||||
$userTimeZone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
|
||||
$now = new DateTime("now", $userTimeZone);
|
||||
$offset = $now->format("Z") * -1;
|
||||
$view->headScript()->appendScript("var userTimezoneOffset = {$offset}; //in seconds");
|
||||
}
|
||||
|
||||
//scripts for now playing bar
|
||||
$view->headScript()->appendFile($baseUrl . 'js/airtime/airtime_bootstrap.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/airtime/dashboard/helperfunctions.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/airtime/dashboard/dashboard.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/airtime/dashboard/versiontooltip.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/tipsy/jquery.tipsy.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
|
||||
->appendFile($baseUrl . 'js/airtime/common/common.js?' . $CC_CONFIG['airtime_version'], 'text/javascript')
|
||||
->appendFile($baseUrl . 'js/airtime/common/audioplaytest.js?' . $CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
|
||||
$user = Application_Model_User::getCurrentUser();
|
||||
if (!is_null($user)) {
|
||||
$userType = $user->getType();
|
||||
} else {
|
||||
$userType = "";
|
||||
}
|
||||
|
||||
$view->headScript()->appendScript("var userType = '$userType';");
|
||||
}
|
||||
|
||||
protected function _initViewHelpers()
|
||||
{
|
||||
$view = $this->_bootstrap->getResource('view');
|
||||
$view->addHelperPath(APPLICATION_PATH . 'views/helpers', 'Airtime_View_Helper');
|
||||
}
|
||||
|
||||
protected function _initTitle()
|
||||
{
|
||||
$view = $this->_bootstrap->getResource('view');
|
||||
$view->headTitle(Application_Model_Preference::GetHeadTitle());
|
||||
}
|
||||
}
|
19
legacy/application/controllers/plugins/RabbitMqPlugin.php
Normal file
19
legacy/application/controllers/plugins/RabbitMqPlugin.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
class RabbitMqPlugin extends Zend_Controller_Plugin_Abstract
|
||||
{
|
||||
public function dispatchLoopShutdown()
|
||||
{
|
||||
if (Application_Model_RabbitMq::$doPush) {
|
||||
$md = array('schedule' => Application_Model_Schedule::getSchedule());
|
||||
Application_Model_RabbitMq::SendMessageToPypo("update_schedule", $md);
|
||||
}
|
||||
|
||||
if (memory_get_peak_usage() > 30*pow(2, 20)) {
|
||||
Logging::debug("Peak memory usage: "
|
||||
.(memory_get_peak_usage()/1000000)
|
||||
." MB while accessing URI ".$_SERVER['REQUEST_URI']);
|
||||
Logging::debug("Should try to keep memory footprint under 25 MB");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE cc_files ADD COLUMN filesize integer NOT NULL
|
||||
CONSTRAINT filesize_default DEFAULT 0
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE cc_show ALTER COLUMN description TYPE varchar(8192);
|
||||
ALTER TABLE cc_show_instances ALTER COLUMN description TYPE varchar(8192);
|
|
@ -0,0 +1,42 @@
|
|||
-----------------------------------------------------------------------
|
||||
-- third_party_track_references
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "third_party_track_references"
|
||||
(
|
||||
"id" serial NOT NULL,
|
||||
"service" VARCHAR(256) NOT NULL,
|
||||
"foreign_id" VARCHAR(256),
|
||||
"file_id" INTEGER NOT NULL,
|
||||
"upload_time" TIMESTAMP,
|
||||
"status" VARCHAR(256),
|
||||
PRIMARY KEY ("id"),
|
||||
CONSTRAINT "foreign_id_unique" UNIQUE ("foreign_id")
|
||||
);
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- celery_tasks
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "celery_tasks"
|
||||
(
|
||||
"id" serial NOT NULL,
|
||||
"task_id" VARCHAR(256) NOT NULL,
|
||||
"track_reference" INTEGER NOT NULL,
|
||||
"name" VARCHAR(256),
|
||||
"dispatch_time" TIMESTAMP,
|
||||
"status" VARCHAR(256) NOT NULL,
|
||||
PRIMARY KEY ("id"),
|
||||
CONSTRAINT "id_unique" UNIQUE ("id")
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "third_party_track_references" ADD CONSTRAINT "track_reference_fkey"
|
||||
FOREIGN KEY ("file_id")
|
||||
REFERENCES "cc_files" ("id")
|
||||
ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE "celery_tasks" ADD CONSTRAINT "celery_service_fkey"
|
||||
FOREIGN KEY ("track_reference")
|
||||
REFERENCES "third_party_track_references" ("id")
|
||||
ON DELETE CASCADE;
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE cc_pref ALTER COLUMN subjid SET DEFAULT NULL;
|
||||
CREATE UNIQUE INDEX cc_pref_key_idx ON cc_pref (keystr) WHERE subjid IS NULL;
|
||||
ANALYZE cc_pref;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE third_party_track_references ALTER COLUMN file_id DROP NOT NULL;
|
|
@ -0,0 +1,90 @@
|
|||
ALTER TABLE cc_files ADD COLUMN description VARCHAR(512);
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- podcast
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "podcast"
|
||||
(
|
||||
"id" serial NOT NULL,
|
||||
"url" VARCHAR(4096) NOT NULL,
|
||||
"title" VARCHAR(4096) NOT NULL,
|
||||
"creator" VARCHAR(4096),
|
||||
"description" VARCHAR(4096),
|
||||
"language" VARCHAR(4096),
|
||||
"copyright" VARCHAR(4096),
|
||||
"link" VARCHAR(4096),
|
||||
"itunes_author" VARCHAR(4096),
|
||||
"itunes_keywords" VARCHAR(4096),
|
||||
"itunes_summary" VARCHAR(4096),
|
||||
"itunes_subtitle" VARCHAR(4096),
|
||||
"itunes_category" VARCHAR(4096),
|
||||
"itunes_explicit" VARCHAR(4096),
|
||||
"owner" INTEGER,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- station_podcast
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "station_podcast"
|
||||
(
|
||||
"id" serial NOT NULL,
|
||||
"podcast_id" INTEGER NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- imported_podcast
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "imported_podcast"
|
||||
(
|
||||
"id" serial NOT NULL,
|
||||
"auto_ingest" BOOLEAN DEFAULT 'f' NOT NULL,
|
||||
"auto_ingest_timestamp" TIMESTAMP,
|
||||
"podcast_id" INTEGER NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- podcast_episodes
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "podcast_episodes"
|
||||
(
|
||||
"id" serial NOT NULL,
|
||||
"file_id" INTEGER,
|
||||
"podcast_id" INTEGER NOT NULL,
|
||||
"publication_date" TIMESTAMP NOT NULL,
|
||||
"download_url" VARCHAR(4096) NOT NULL,
|
||||
"episode_guid" VARCHAR(4096) NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "podcast" ADD CONSTRAINT "podcast_owner_fkey"
|
||||
FOREIGN KEY ("owner")
|
||||
REFERENCES "cc_subjs" ("id")
|
||||
ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE "station_podcast" ADD CONSTRAINT "podcast_id_fkey"
|
||||
FOREIGN KEY ("podcast_id")
|
||||
REFERENCES "podcast" ("id")
|
||||
ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE "imported_podcast" ADD CONSTRAINT "podcast_id_fkey"
|
||||
FOREIGN KEY ("podcast_id")
|
||||
REFERENCES "podcast" ("id")
|
||||
ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE "podcast_episodes" ADD CONSTRAINT "podcast_episodes_cc_files_fkey"
|
||||
FOREIGN KEY ("file_id")
|
||||
REFERENCES "cc_files" ("id")
|
||||
ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE "podcast_episodes" ADD CONSTRAINT "podcast_episodes_podcast_id_fkey"
|
||||
FOREIGN KEY ("podcast_id")
|
||||
REFERENCES "podcast" ("id")
|
||||
ON DELETE CASCADE;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE cc_files ADD COLUMN artwork TYPE character varying(255);
|
|
@ -0,0 +1,6 @@
|
|||
-- Replacing system_version with schema_version
|
||||
DELETE FROM cc_pref WHERE keystr = 'system_version';
|
||||
INSERT INTO cc_pref (keystr, valstr) VALUES ('schema_version', '2.5.2');
|
||||
|
||||
ALTER TABLE cc_show ADD COLUMN image_path varchar(255) DEFAULT '';
|
||||
ALTER TABLE cc_show_instances ADD COLUMN description varchar(255) DEFAULT '';
|
|
@ -0,0 +1,6 @@
|
|||
DELETE FROM cc_pref WHERE keystr = 'system_version';
|
||||
INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '2.5.3');
|
||||
|
||||
ALTER TABLE cc_files DROP COLUMN state;
|
||||
ALTER TABLE cc_files ADD import_status integer default 1; -- Default is "pending"
|
||||
UPDATE cc_files SET import_status=0; -- Existing files are already "imported"
|
|
@ -0,0 +1,5 @@
|
|||
DELETE FROM cc_pref WHERE keystr = 'system_version';
|
||||
INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '2.5.5');
|
||||
|
||||
ALTER TABLE cc_show ADD COLUMN image_path varchar(255) DEFAULT '';
|
||||
ALTER TABLE cc_show_instances ADD COLUMN description varchar(255) DEFAULT '';
|
|
@ -0,0 +1,11 @@
|
|||
CREATE TABLE cloud_file
|
||||
(
|
||||
id serial NOT NULL,
|
||||
resource_id text NOT NULL,
|
||||
storage_backend text NOT NULL,
|
||||
cc_file_id integer NOT NULL,
|
||||
CONSTRAINT cloud_file_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT "cloud_file_FK_1" FOREIGN KEY (cc_file_id)
|
||||
REFERENCES cc_files (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION ON DELETE CASCADE
|
||||
)
|
|
@ -0,0 +1,4 @@
|
|||
ALTER TABLE imported_podcast ADD COLUMN album_override boolean default 'f' NOT NULL;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id SET DEFAULT 0;
|
||||
ALTER TABLE third_party_track_references ALTER COLUMN file_id DROP NOT NULL;
|
||||
ALTER TABLE cc_show ADD COLUMN autoplaylist_repeat boolean default 'f' NOT NULL;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE cc_service_register ALTER COLUMN ip TYPE character varying(45);
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue