Merge branch 'saas' into saas-embed-player

Conflicts:
	airtime_mvc/application/configs/ACL.php
This commit is contained in:
drigato 2015-03-31 17:44:14 -04:00
commit 220f21ab22
29 changed files with 422 additions and 149 deletions

View File

@ -24,12 +24,14 @@ require_once "FileIO.php";
require_once "OsPath.php"; require_once "OsPath.php";
require_once "Database.php"; require_once "Database.php";
require_once "ProvisioningHelper.php"; require_once "ProvisioningHelper.php";
require_once "GoogleAnalytics.php";
require_once "Timezone.php"; require_once "Timezone.php";
require_once "Auth.php"; require_once "Auth.php";
require_once __DIR__.'/forms/helpers/ValidationTypes.php'; require_once __DIR__.'/forms/helpers/ValidationTypes.php';
require_once __DIR__.'/forms/helpers/CustomDecorators.php'; require_once __DIR__.'/forms/helpers/CustomDecorators.php';
require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php'; require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php';
require_once __DIR__.'/controllers/plugins/Maintenance.php'; require_once __DIR__.'/controllers/plugins/Maintenance.php';
require_once __DIR__.'/controllers/plugins/ConversionTracking.php';
require_once __DIR__.'/modules/rest/controllers/ShowImageController.php'; require_once __DIR__.'/modules/rest/controllers/ShowImageController.php';
require_once __DIR__.'/modules/rest/controllers/MediaController.php'; require_once __DIR__.'/modules/rest/controllers/MediaController.php';
@ -52,6 +54,7 @@ Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance());
$front = Zend_Controller_Front::getInstance(); $front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new RabbitMqPlugin()); $front->registerPlugin(new RabbitMqPlugin());
$front->registerPlugin(new Zend_Controller_Plugin_ConversionTracking());
$front->throwExceptions(false); $front->throwExceptions(false);
//localization configuration //localization configuration

View File

@ -65,7 +65,9 @@ class Application_Common_FileIO
//We can have multiple levels of output buffering. Need to //We can have multiple levels of output buffering. Need to
//keep looping until all have been disabled!!! //keep looping until all have been disabled!!!
//http://www.php.net/manual/en/function.ob-end-flush.php //http://www.php.net/manual/en/function.ob-end-flush.php
while (@ob_end_flush()); while (ob_get_level() > 0) {
ob_end_flush();
}
// NOTE: We can't use fseek here because it does not work with streams // NOTE: We can't use fseek here because it does not work with streams
// (a.k.a. Files stored in the cloud) // (a.k.a. Files stored in the cloud)

View File

@ -0,0 +1,92 @@
<?php
class Application_Common_GoogleAnalytics
{
/** Returns a string containing the JavaScript code to pass some billing account info
* into Google Tag Manager / Google Analytics, so we can track things like the plan type.
*/
public static function generateGoogleTagManagerDataLayerJavaScript()
{
$code = "";
try {
$clientId = Application_Model_Preference::GetClientId();
$plan = Application_Model_Preference::GetPlanLevel();
$isTrial = ($plan == "trial");
//Figure out how long the customer has been around using a mega hack.
//(I'm avoiding another round trip to WHMCS for now...)
//We calculate it based on the trial end date...
$trialEndDateStr = Application_Model_Preference::GetTrialEndingDate();
if ($trialEndDateStr == '') {
$accountDuration = 0;
} else {
$today = new DateTime();
$trialEndDate = new DateTime($trialEndDateStr);
$trialDuration = new DateInterval("P30D"); //30 day trial duration
$accountCreationDate = $trialEndDate->sub($trialDuration);
$interval = $today->diff($accountCreationDate);
$accountDuration = $interval->days;
}
$code = "$( document ).ready(function() {
dataLayer.push({
'UserID': '" . $clientId . "',
'Customer': 'Customer',
'PlanType': '" . $plan . "',
'Trial': '" . $isTrial . "',
'AccountDuration': '" . strval($accountDuration) . "'
});
});";
//No longer sending these variables because we used to make a query to WHMCS
//to fetch them, which was slow.
// 'ZipCode': '" . $postcode . "',
// 'Country': '" . $country . "',
} catch (Exception $e) {
Logging::error($e);
return "";
}
return $code;
}
/** Generate the JavaScript snippet that logs a trial to paid conversion */
public static function generateConversionTrackingJavaScript()
{
$newPlan = Application_Model_Preference::GetPlanLevel();
$oldPlan = Application_Model_Preference::GetOldPlanLevel();
$code = "dataLayer.push({'event': 'Conversion',
'Conversion': 'Trial to Paid',
'Old Plan' : '$oldPlan',
'New Plan' : '$newPlan'});";
return $code;
}
/** Return true if the user used to be on a trial plan and was just converted to a paid plan. */
public static function didPaidConversionOccur($request)
{
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
if ($userInfo) {
$user = new Application_Model_User($userInfo->id);
} else {
return;
}
$oldPlan = Application_Model_Preference::GetOldPlanLevel();
if ($user->isSuperAdmin() &&
!$user->isSourcefabricAdmin() &&
$request->getControllerKey() !== "thank-you")
{
//Only tracking trial->paid conversions for now.
if ($oldPlan == "trial")
{
return true;
}
}
return false;
}
}

View File

@ -27,7 +27,7 @@ class Application_Common_HTTPHelper
if (empty($baseDir)) { if (empty($baseDir)) {
$baseDir = "/"; $baseDir = "/";
} }
if ($baseDir[0] != "") { if ($baseDir[0] != "/") {
$baseDir = "/" . $baseDir; $baseDir = "/" . $baseDir;
} }

View File

@ -36,6 +36,7 @@ $ccAcl->add(new Zend_Acl_Resource('library'))
->add(new Zend_Acl_Resource('rest:media')) ->add(new Zend_Acl_Resource('rest:media'))
->add(new Zend_Acl_Resource('rest:show-image')) ->add(new Zend_Acl_Resource('rest:show-image'))
->add(new Zend_Acl_Resource('billing')) ->add(new Zend_Acl_Resource('billing'))
->add(new Zend_Acl_Resource('thank-you'))
->add(new Zend_Acl_Resource('provisioning')) ->add(new Zend_Acl_Resource('provisioning'))
->add(new Zend_Acl_Resource('embeddableplayer')); ->add(new Zend_Acl_Resource('embeddableplayer'));
@ -70,7 +71,11 @@ $ccAcl->allow('G', 'index')
->allow('A', 'user') ->allow('A', 'user')
->allow('A', 'systemstatus') ->allow('A', 'systemstatus')
->allow('A', 'preference') ->allow('A', 'preference')
<<<<<<< HEAD
->allow('A', 'embeddableplayer') ->allow('A', 'embeddableplayer')
=======
->allow('S', 'thank-you')
>>>>>>> saas
->allow('S', 'billing'); ->allow('S', 'billing');

View File

@ -44,6 +44,13 @@ class Config {
$CC_CONFIG['dev_env'] = 'production'; $CC_CONFIG['dev_env'] = 'production';
} }
//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'] = '/';
}
// Parse separate conf file for cloud storage values // Parse separate conf file for cloud storage values
$cloudStorageConfig = "/etc/airtime-saas/".$CC_CONFIG['dev_env']."/cloud_storage.conf"; $cloudStorageConfig = "/etc/airtime-saas/".$CC_CONFIG['dev_env']."/cloud_storage.conf";
if (!file_exists($cloudStorageConfig)) { if (!file_exists($cloudStorageConfig)) {

View File

@ -35,7 +35,7 @@ class ShowbuilderController extends Zend_Controller_Action
$user = Application_Model_User::GetCurrentUser(); $user = Application_Model_User::GetCurrentUser();
$userType = $user->getType(); $userType = $user->getType();
$this->view->headScript()->appendScript("localStorage.setItem( 'user-type', '$userType' );"); $this->view->headScript()->appendScript("localStorage.setItem( 'user-type', '$userType' );");
$this->view->headScript()->appendScript($this->generateGoogleTagManagerDataLayerJavaScript()); $this->view->headScript()->appendScript(Application_Common_GoogleAnalytics::generateGoogleTagManagerDataLayerJavaScript());
$this->view->headScript()->appendFile($baseUrl.'js/contextmenu/jquery.contextMenu.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); $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/js/jquery.dataTables.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
@ -367,104 +367,5 @@ class ShowbuilderController extends Zend_Controller_Action
throw new Exception("this controller is/was a no-op please fix your throw new Exception("this controller is/was a no-op please fix your
code"); code");
} }
/** Returns a string containing the JavaScript code to pass some billing account info
* into Google Tag Manager / Google Analytics, so we can track things like the plan type.
*/
private static function generateGoogleTagManagerDataLayerJavaScript()
{
$code = "";
try
{
$accessKey = $_SERVER["WHMCS_ACCESS_KEY"];
$username = $_SERVER["WHMCS_USERNAME"];
$password = $_SERVER["WHMCS_PASSWORD"];
$url = "https://account.sourcefabric.com/includes/api.php?accesskey=" . $accessKey; # URL to WHMCS API file goes here
$postfields = array();
$postfields["username"] = $username;
$postfields["password"] = md5($password);
$postfields["action"] = "getclientsdetails";
$postfields["stats"] = true;
$postfields["clientid"] = Application_Model_Preference::GetClientId();
$postfields["responsetype"] = "json";
$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); // WHMCS IP whitelist doesn't support IPv6
curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Aggressive 5 second timeout
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$jsondata = curl_exec($ch);
if (curl_error($ch)) {
//die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
throw new Exception("WHMCS server down or invalid request.");
}
curl_close($ch);
$arr = json_decode($jsondata); # Decode JSON String
if ($arr->result !== "success") {
Logging::warn("WHMCS API call failed in " . __FUNCTION__);
return;
}
$client = $arr->client;
$stats = $arr->stats;
$currencyCode = $client->currency_code;
//$incomeCents = NumberFormatter::parseCurrency($stats->income, $currencyCode);
$isTrial = true;
if (strpos($stats->income, "0.00") === FALSE) {
$isTrial = false;
}
/*
if ($incomeCents > 0) {
$isTrial = false;
}*/
$plan = Application_Model_Preference::GetPlanLevel();
$country = $client->country;
$postcode = $client->postcode;
//Figure out how long the customer has been around using a mega hack.
//(I'm avoiding another round trip to WHMCS for now...)
//We calculate it based on the trial end date...
$trialEndDateStr = Application_Model_Preference::GetTrialEndingDate();
if ($trialEndDateStr == '') {
$accountDuration = 0;
} else {
$today = new DateTime();
$trialEndDate = new DateTime($trialEndDateStr);
$trialDuration = new DateInterval("P30D"); //30 day trial duration
$accountCreationDate = $trialEndDate->sub($trialDuration);
$interval = $today->diff($accountCreationDate);
$accountDuration = $interval->days;
}
$code = "$( document ).ready(function() {
dataLayer.push({
'ZipCode': '" . $postcode . "',
'UserID': '" . $client->id . "',
'Customer': 'Customer',
'PlanType': '" . $plan . "',
'Trial': '" . $isTrial . "',
'Country': '" . $country . "',
'AccountDuration': '" . strval($accountDuration) . "'
});
});";
}
catch (Exception $e)
{
return "";
}
return $code;
}
} }

View File

@ -0,0 +1,48 @@
<?php
class ThankYouController extends Zend_Controller_Action
{
public function indexAction()
{
//Variable for the template (thank-you/index.phtml)
$this->view->stationUrl = Application_Common_HTTPHelper::getStationUrl();
$this->view->conversionUrl = Application_Common_HTTPHelper::getStationUrl() . 'thank-you/confirm-conversion';
$this->view->gaEventTrackingJsCode = ""; //Google Analytics event tracking code that logs an event.
// Embed the Google Analytics conversion tracking code if the
// user is a super admin and old plan level is set to trial.
if (Application_Common_GoogleAnalytics::didPaidConversionOccur($this->getRequest())) {
$this->view->gaEventTrackingJsCode = Application_Common_GoogleAnalytics::generateConversionTrackingJavaScript();
}
$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');
$csrf_form = new Zend_Form();
$csrf_form->addElement($csrf_element);
$this->view->form = $csrf_form;
}
/** Confirm that a conversion was tracked. */
public function confirmConversionAction()
{
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$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) {
Logging::info("Invalid CSRF token");
return;
}
if ($this->getRequest()->isPost()) {
Logging::info("Goal conversion from trial to paid.");
// Clear old plan level so we prevent duplicate events.
// This should only be called from AJAX. See thank-you/index.phtml
Application_Model_Preference::ClearOldPlanLevel();
}
}
}

View File

@ -20,7 +20,8 @@ class UpgradeController extends Zend_Controller_Action
array_push($upgraders, new AirtimeUpgrader259()); array_push($upgraders, new AirtimeUpgrader259());
array_push($upgraders, new AirtimeUpgrader2510()); array_push($upgraders, new AirtimeUpgrader2510());
array_push($upgraders, new AirtimeUpgrader2511()); array_push($upgraders, new AirtimeUpgrader2511());
array_push($upgraders, new AirtimeUpgrader2512());
$didWePerformAnUpgrade = false; $didWePerformAnUpgrade = false;
try try
{ {

View File

@ -0,0 +1,21 @@
<?php
class Zend_Controller_Plugin_ConversionTracking extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
//If user is a super admin and old plan level is set to trial....
if (Application_Common_GoogleAnalytics::didPaidConversionOccur($request))
{
//Redirect to Thank you page, unless the request was already going there...
if ($request->getControllerName() != 'thank-you')
{
$request->setModuleName('default')
->setControllerName('thank-you')
->setActionName('index')
->setDispatched(true);
}
}
}
}

View File

@ -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);

View File

@ -21,7 +21,6 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
<?php echo $this->partial('partialviews/trialBox.phtml', array("is_trial"=>$this->isTrial(), "trial_remain"=> $this->trialRemaining())) ?> <?php echo $this->partial('partialviews/trialBox.phtml', array("is_trial"=>$this->isTrial(), "trial_remain"=> $this->trialRemaining())) ?>
<div id="Panel"> <div id="Panel">
<div class="logo"></div>
<?php echo $this->versionNotify(); <?php echo $this->versionNotify();
$sss = $this->SourceSwitchStatus(); $sss = $this->SourceSwitchStatus();
$scs = $this->SourceConnectionStatus(); $scs = $this->SourceConnectionStatus();
@ -30,17 +29,21 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
"scheduled_play_switch"=>$sss['scheduled_play'])) ?> "scheduled_play_switch"=>$sss['scheduled_play'])) ?>
<?php $partial = array('menu.phtml', 'default'); <?php $partial = array('menu.phtml', 'default');
$this->navigation()->menu()->setPartial($partial); ?> $this->navigation()->menu()->setPartial($partial); ?>
<div class="personal-block solo"> <div id="nav">
<ul> <div class="logo"></div>
<li> <div class="personal-block solo">
<!-- <span class="trial-box-button"><a title="Billing" href=<?php echo $baseUrl . 'billing/upgrade'?>>Upgrade</a></span>&nbsp;--> <ol>
<a id="current-user" href=<?php echo $baseUrl . "User/edit-user"?>><span class="name"><?php echo $this->escape($this->loggedInAs()); ?></span></a> <li>
| <a href=<?php echo $baseUrl . "Login/logout"?>><?php echo _("Logout")?></a> <!-- <span class="trial-box-button"><a title="Billing" href=<?php echo $baseUrl . 'billing/upgrade'?>>Upgrade</a></span>&nbsp;-->
</li> <a id="current-user" href=<?php echo $baseUrl . "User/edit-user"?>><span class="name"><?php echo $this->escape($this->loggedInAs()); ?></span></a>
</ul> | <a href=<?php echo $baseUrl . "Login/logout"?>><?php echo _("Logout")?></a>
</div> </li>
</ol>
</div>
<?php echo $this->navigation()->menu() ?> <?php echo $this->navigation()->menu() ?>
<div style="clear:both;"></div>
</div>
</div> </div>
<div class="wrapper" id="content"><?php echo $this->layout()->content ?></div> <div class="wrapper" id="content"><?php echo $this->layout()->content ?></div>

View File

@ -138,7 +138,9 @@ class Logging {
switch($err['type']) switch($err['type'])
{ {
case E_ERROR: case E_ERROR:
case E_WARNING:
case E_PARSE: case E_PARSE:
case E_NOTICE:
case E_CORE_ERROR: case E_CORE_ERROR:
case E_CORE_WARNING: case E_CORE_WARNING:
case E_COMPILE_ERROR: case E_COMPILE_ERROR:

View File

@ -824,7 +824,10 @@ class Application_Model_Preference
public static function SetPlanLevel($plan) public static function SetPlanLevel($plan)
{ {
$oldPlanLevel = self::GetPlanLevel();
self::setValue("plan_level", $plan); self::setValue("plan_level", $plan);
//We save the old plan level temporarily to facilitate conversion tracking
self::setValue("old_plan_level", $oldPlanLevel);
} }
public static function GetPlanLevel() public static function GetPlanLevel()
@ -837,6 +840,19 @@ class Application_Model_Preference
return $plan; return $plan;
} }
public static function GetOldPlanLevel()
{
$oldPlan = self::getValue("old_plan_level");
return $oldPlan;
}
/** Clearing the old plan level indicates a change in your plan has been tracked (Google Analytics) */
public static function ClearOldPlanLevel()
{
self::setValue("old_plan_level", '');
}
public static function SetTrialEndingDate($date) public static function SetTrialEndingDate($date)
{ {
self::setValue("trial_end_date", $date); self::setValue("trial_end_date", $date);

View File

@ -984,15 +984,19 @@ SQL;
} else { } else {
Logging::info("Moving file $audio_file to $audio_stor"); Logging::info("Moving file $audio_file to $audio_stor");
//Ensure we have permissions to overwrite the file in stor, in case it already exists.
if (file_exists($audio_stor)) {
chmod($audio_stor, 0644);
}
// Martin K.: changed to rename: Much less load + quicker since this is // Martin K.: changed to rename: Much less load + quicker since this is
// an atomic operation // an atomic operation
if (@rename($audio_file, $audio_stor) === false) { if (rename($audio_file, $audio_stor) === false) {
//something went wrong likely there wasn't enough space in . //something went wrong likely there wasn't enough space in .
//the audio_stor to move the file too warn the user that . //the audio_stor to move the file too warn the user that .
//the file wasn't uploaded and they should check if there . //the file wasn't uploaded and they should check if there .
//is enough disk space . //is enough disk space .
unlink($audio_file); //remove the file after failed rename unlink($audio_file); //remove the file after failed rename
//unlink($id_file); // Also remove the identifier file
throw new Exception("The file was not uploaded, this error can occur if the computer " throw new Exception("The file was not uploaded, this error can occur if the computer "
. "hard drive does not have enough disk space or the stor " . "hard drive does not have enough disk space or the stor "

View File

@ -69,6 +69,15 @@ class Application_Model_User
return $result; return $result;
} }
public function isSourcefabricAdmin()
{
$username = $this->getLogin();
if ($username == "sourcefabric_admin") {
return true;
}
return false;
}
// TODO : refactor code to only accept arrays for isUserType and // TODO : refactor code to only accept arrays for isUserType and
// simplify code even further // simplify code even further
public function isUserType($type) public function isUserType($type)

View File

@ -95,9 +95,10 @@ class CcFiles extends BaseCcFiles {
try { try {
self::createAndImport($fileArray, $tempFilePath, $originalFilename); self::createAndImport($fileArray, $tempFilePath, $originalFilename);
} catch (Exception $e) } catch (Exception $e) {
{ if (file_exists($tempFilePath)) {
@unlink($tempFilePath); unlink($tempFilePath);
}
throw $e; throw $e;
} }
} }

View File

@ -124,6 +124,7 @@ class Rest_MediaController extends Zend_Rest_Controller
catch (Exception $e) { catch (Exception $e) {
$this->unknownErrorResponse(); $this->unknownErrorResponse();
Logging::error($e->getMessage()); Logging::error($e->getMessage());
throw $e;
} }
} }

View File

@ -38,14 +38,17 @@ abstract class AirtimeUpgrader
//create a temporary maintenance notification file //create a temporary maintenance notification file
//when this file is on the server, zend framework redirects all //when this file is on the server, zend framework redirects all
//requests to the maintenance page and sets a 503 response code //requests to the maintenance page and sets a 503 response code
/* DISABLED because this does not work correctly
$this->maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt"; $this->maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt";
$file = fopen($this->maintenanceFile, 'w'); $file = fopen($this->maintenanceFile, 'w');
fclose($file); fclose($file);
*/
} else { } else {
//delete maintenance.txt to give users access back to Airtime //delete maintenance.txt to give users access back to Airtime
/* DISABLED because this does not work correctly
if ($this->maintenanceFile) { if ($this->maintenanceFile) {
unlink($this->maintenanceFile); unlink($this->maintenanceFile);
} }*/
} }
} }
@ -385,3 +388,52 @@ class AirtimeUpgrader2511 extends AirtimeUpgrader
} }
} }
class AirtimeUpgrader2512 extends AirtimeUpgrader
{
protected function getSupportedVersions() {
return array (
'2.5.10',
'2.5.11'
);
}
public function getNewVersion() {
return '2.5.12';
}
public function upgrade($dir = __DIR__) {
Cache::clear();
assert($this->checkIfUpgradeSupported());
$newVersion = $this->getNewVersion();
try {
$this->toggleMaintenanceScreen(true);
Cache::clear();
// Begin upgrade
$airtimeConf = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : "/etc/airtime/airtime.conf";
$values = parse_ini_file($airtimeConf, true);
$username = $values['database']['dbuser'];
$password = $values['database']['dbpass'];
$host = $values['database']['host'];
$database = $values['database']['dbname'];
passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/upgrade_sql/airtime_"
.$this->getNewVersion()."/upgrade.sql $database 2>&1 | grep -v -E \"will create implicit sequence|will create implicit index\"");
Application_Model_Preference::SetAirtimeVersion($newVersion);
Cache::clear();
$this->toggleMaintenanceScreen(false);
} catch(Exception $e) {
$this->toggleMaintenanceScreen(false);
throw $e;
}
}
public function downgrade() {
}
}

View File

@ -1,4 +1,4 @@
<ul id="nav"> <ol id="navlist">
<?php foreach ($this->container as $page) : ?> <?php foreach ($this->container as $page) : ?>
<?php if($this->navigation()->accept($page)) : ?> <?php if($this->navigation()->accept($page)) : ?>
<li class="top <?php if($page->isActive(true)){echo 'active';} ?>"> <li class="top <?php if($page->isActive(true)){echo 'active';} ?>">
@ -29,4 +29,4 @@
</li> </li>
<?php endif; ?> <?php endif; ?>
<?php endforeach; ?> <?php endforeach; ?>
</ul> </ol>

View File

@ -0,0 +1,20 @@
<script type="text/javascript">
$(document).ready(function() {
<?php if ($this->gaEventTrackingJsCode != "") {
echo($this->gaEventTrackingJsCode);
?>
jQuery.post("<?=$this->conversionUrl?>", { "csrf_token" : $("#csrf").attr('value')},
function( data ) {});
<?php }; //endif ?>
});
</script>
<?php echo $this->form->getElement('csrf') ?>
<div class="ui-widget ui-widget-content block-shadow clearfix padded-strong thankyou-panel">
<center>
<div class="logobox" style="margin-left: 32px;"></div>
<h2><?php echo _pro("Thank you!")?></h2>
<h3><?php echo _pro("Your station has been upgraded successfully.")?></h3>
<p><a href="<?=$this->stationUrl?>"><?php echo _pro("Return to Airtime")?></a></p>
</center>
</div>

View File

@ -139,7 +139,7 @@
<column name="name" phpName="DbName" type="VARCHAR" size="255" required="true" defaultValue=""/> <column name="name" phpName="DbName" type="VARCHAR" size="255" required="true" defaultValue=""/>
<column name="url" phpName="DbUrl" type="VARCHAR" size="255" required="false" defaultValue=""/> <column name="url" phpName="DbUrl" type="VARCHAR" size="255" required="false" defaultValue=""/>
<column name="genre" phpName="DbGenre" type="VARCHAR" size="255" required="false" defaultValue=""/> <column name="genre" phpName="DbGenre" type="VARCHAR" size="255" required="false" defaultValue=""/>
<column name="description" phpName="DbDescription" type="VARCHAR" size="512" required="false"/> <column name="description" phpName="DbDescription" type="VARCHAR" size="8192" required="false"/>
<column name="color" phpName="DbColor" type="VARCHAR" size="6" required="false"/> <column name="color" phpName="DbColor" type="VARCHAR" size="6" required="false"/>
<column name="background_color" phpName="DbBackgroundColor" type="VARCHAR" size="6" required="false"/> <column name="background_color" phpName="DbBackgroundColor" type="VARCHAR" size="6" required="false"/>
<column name="live_stream_using_airtime_auth" phpName="DbLiveStreamUsingAirtimeAuth" type="BOOLEAN" required="false" defaultValue="false"/> <column name="live_stream_using_airtime_auth" phpName="DbLiveStreamUsingAirtimeAuth" type="BOOLEAN" required="false" defaultValue="false"/>
@ -156,7 +156,7 @@
</table> </table>
<table name="cc_show_instances" phpName="CcShowInstances"> <table name="cc_show_instances" phpName="CcShowInstances">
<column name="id" phpName="DbId" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/> <column name="id" phpName="DbId" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/>
<column name="description" phpName="DbDescription" type="VARCHAR" size="512" required="false" defaultValue=""/> <column name="description" phpName="DbDescription" type="VARCHAR" size="8192" required="false" defaultValue=""/>
<column name="starts" phpName="DbStarts" type="TIMESTAMP" required="true"/> <column name="starts" phpName="DbStarts" type="TIMESTAMP" required="true"/>
<column name="ends" phpName="DbEnds" type="TIMESTAMP" required="true"/> <column name="ends" phpName="DbEnds" type="TIMESTAMP" required="true"/>
<column name="show_id" phpName="DbShowId" type="INTEGER" required="true"/> <column name="show_id" phpName="DbShowId" type="INTEGER" required="true"/>

View File

@ -149,7 +149,7 @@ CREATE TABLE "cc_show"
"name" VARCHAR(255) DEFAULT '' NOT NULL, "name" VARCHAR(255) DEFAULT '' NOT NULL,
"url" VARCHAR(255) DEFAULT '', "url" VARCHAR(255) DEFAULT '',
"genre" VARCHAR(255) DEFAULT '', "genre" VARCHAR(255) DEFAULT '',
"description" VARCHAR(512), "description" VARCHAR(8192),
"color" VARCHAR(6), "color" VARCHAR(6),
"background_color" VARCHAR(6), "background_color" VARCHAR(6),
"live_stream_using_airtime_auth" BOOLEAN DEFAULT 'f', "live_stream_using_airtime_auth" BOOLEAN DEFAULT 'f',
@ -171,7 +171,7 @@ DROP TABLE IF EXISTS "cc_show_instances" CASCADE;
CREATE TABLE "cc_show_instances" CREATE TABLE "cc_show_instances"
( (
"id" serial NOT NULL, "id" serial NOT NULL,
"description" VARCHAR(512) DEFAULT '', "description" VARCHAR(8192) DEFAULT '',
"starts" TIMESTAMP NOT NULL, "starts" TIMESTAMP NOT NULL,
"ends" TIMESTAMP NOT NULL, "ends" TIMESTAMP NOT NULL,
"show_id" INTEGER NOT NULL, "show_id" INTEGER NOT NULL,

View File

@ -463,8 +463,10 @@ class AMQPConnection extends AbstractChannel
{ {
debug_msg("closing socket"); debug_msg("closing socket");
} }
@fclose($this->sock); if (is_resource($this->sock)) {
@fclose($this->sock);
}
$this->sock = NULL; $this->sock = NULL;
} }
} }

View File

@ -300,13 +300,12 @@
.personal-block.solo { .personal-block.solo {
position: absolute; width: auto;
right: 145px; height:auto;
top: 104px; margin: 0 10px 0 0;
width: auto; }
z-index: 1000; .personal-block.solo ol {
height:auto; margin-top: 6px;
margin:0;
} }
.time-info-block.pull-right { .time-info-block.pull-right {
margin-right:0; margin-right:0;

View File

@ -48,14 +48,12 @@ select {
} }
.logo { .logo {
position:absolute; background: transparent url(images/airtime_logo.png) no-repeat 0 0;
right:20px; height: 35px;
top:104px; width: 66px;
background:transparent url(images/airtime_logo.png) no-repeat 0 0; float: right;
height:35px; padding: 0 5px 0 10px;
width:66px; margin-top: -5px;
z-index:1000;
display:block;
} }
/* Version Notification Starts*/ /* Version Notification Starts*/
@ -286,8 +284,74 @@ select {
background:url(images/masterpanel_spacer.png) no-repeat right 0; background:url(images/masterpanel_spacer.png) no-repeat right 0;
} }
.time-info-block { .time-info-block {
padding:0 14px 0 2px; position: absolute;
min-width:105px; top: 0;
right: 0;
}
#navlist {
padding: 0;
margin: 0;
}
#nav li.top {
/*float: none;*/
}
@media screen and (max-width: 1200px) {
.now-playing-block {
width: 30%;
}
.show-block {
width: 25%;
}
}
@media screen and (max-width: 920px) {
.now-playing-block {
width: 50%;
}
.show-block {
display: none;
}
.personal-block.solo {
right: 10px !important;
}
}
@media screen and (max-width: 810px) {
.now-playing-block {
width: 40%;
}
}
@media screen and (max-width: 863px) {
#nav {
height: inherit;
overflow-y: visible;
}
}
@media screen and (max-width: 680px) {
.now-playing-block {
display: none;
}
#nav li.top {
display: -webkit-flex;
width: 110px;
}
.personal-block.solo {
float: none;
text-align: left;
}
.personal-block.solo ol {
padding-left: 12px;
}
.logo {
float: none;
margin-left: 12px;
}
}
@media screen and (max-width: 380px) {
.time-info-block {
display: none;
}
.on-air-block {
margin: 0;
}
} }
.time-info-block ul { .time-info-block ul {
margin:0; margin:0;
@ -3141,3 +3205,15 @@ dd .stream-status {
.quota-reached { .quota-reached {
font-size: 14px !important; font-size: 14px !important;
} }
.thankyou-panel
{
width: 400px;
margin: 0 auto;
margin-bottom: 30px;
}
.thankyou-panel h3
{
color: #222;
}

View File

@ -82,7 +82,7 @@ function closeAddShowForm(event) {
redrawAddShowForm($el, json.form); redrawAddShowForm($el, json.form);
}); });
makeAddShowButton(); makeAddShowButton();
} }
@ -742,7 +742,7 @@ function setAddShowEvents(form) {
image = new FormData(); image = new FormData();
image.append('file', $('#add_show_logo')[0].files[0]); image.append('file', $('#add_show_logo')[0].files[0]);
} }
$.ajax({ $.ajax({
url: action, url: action,
data: {format: "json", data: data, hosts: hosts, days: days}, data: {format: "json", data: data, hosts: hosts, days: days},
@ -784,6 +784,7 @@ function setAddShowEvents(form) {
} else { } else {
redrawAddShowForm($addShowForm, json.newForm); redrawAddShowForm($addShowForm, json.newForm);
scheduleRefetchEvents(json); scheduleRefetchEvents(json);
$addShowForm.hide();
} }
} }
}); });

View File

@ -129,6 +129,7 @@ def send_http_request(picklable_request, retry_queue):
retry_queue.append(picklable_request) # Retry it later retry_queue.append(picklable_request) # Retry it later
except Exception as e: except Exception as e:
logging.error("HTTP request failed with unhandled exception. %s" % str(e)) logging.error("HTTP request failed with unhandled exception. %s" % str(e))
logging.error(traceback.format_exc())
# Don't put the request into the retry queue, just give up on this one. # Don't put the request into the retry queue, just give up on this one.
# I'm doing this to protect against us getting some pathological request # I'm doing this to protect against us getting some pathological request
# that breaks our code. I don't want us pickling data that potentially # that breaks our code. I don't want us pickling data that potentially

View File

@ -2,10 +2,14 @@
post_file() { post_file() {
#kill process after 30 minutes (360*5=30 minutes) #kill process after 30 minutes (360*5=30 minutes)
max_retry=360 max_retry=5
retry_count=0 retry_count=0
file_path="${1}" file_path="${1}"
# Give us write permissions on the file to prevent problems if the user
# uploads a read-only file.
chmod +w "${file_path}"
#We must remove commas because CURL can't upload files with commas in the name #We must remove commas because CURL can't upload files with commas in the name
# http://curl.haxx.se/mail/archive-2009-07/0029.html # http://curl.haxx.se/mail/archive-2009-07/0029.html
stripped_file_path=${file_path//','/''} stripped_file_path=${file_path//','/''}