sintonia/airtime_mvc/application/models/ShowInstance.php

701 lines
21 KiB
PHP
Raw Normal View History

<?php
class Application_Model_ShowInstance {
private $_instanceId;
private $_showInstance;
public function __construct($instanceId)
{
$this->_instanceId = $instanceId;
$this->_showInstance = CcShowInstancesQuery::create()->findPK($instanceId);
if (is_null($this->_showInstance)){
throw new Exception();
}
}
public function getShowId()
{
return $this->_showInstance->getDbShowId();
}
public function getShowInstanceId()
{
return $this->_instanceId;
}
public function getShow(){
return new Application_Model_Show($this->getShowId());
}
/* This function is weird. It should return a boolean, but instead returns
* an integer if it is a rebroadcast, or returns null if it isn't. You can convert
* it to boolean by using is_null(isRebroadcast), where true means isn't and false
* means that it is. */
public function isRebroadcast()
{
return $this->_showInstance->getDbOriginalShow();
}
public function isRecorded()
{
return $this->_showInstance->getDbRecord();
}
public function getName()
{
$show = CcShowQuery::create()->findPK($this->getShowId());
return $show->getDbName();
}
public function getGenre()
{
$show = CcShowQuery::create()->findPK($this->getShowId());
return $show->getDbGenre();
}
/**
* Return the start time of the Show (UTC time)
* @return string in format "Y-m-d H:i:s" (PHP time notation)
* TODO: make this function return a DateTime object instead.
*/
public function getShowInstanceStart()
{
return $this->_showInstance->getDbStarts();
}
/**
* Return the end time of the Show (UTC time)
* @return string in format "Y-m-d H:i:s" (PHP time notation)
* TODO: make this function return a DateTime object instead.
*/
public function getShowInstanceEnd()
{
return $this->_showInstance->getDbEnds();
}
public function getStartDate()
{
$showStart = $this->getShowInstanceStart();
$showStartExplode = explode(" ", $showStart);
return $showStartExplode[0];
}
public function getStartTime()
{
$showStart = $this->getShowInstanceStart();
$showStartExplode = explode(" ", $showStart);
return $showStartExplode[1];
}
public function setSoundCloudFileId($p_soundcloud_id)
{
$file = Application_Model_StoredFile::Recall($this->_showInstance->getDbRecordedFile());
$file->setSoundCloudFileId($p_soundcloud_id);
}
public function getSoundCloudFileId()
{
$file = Application_Model_StoredFile::Recall($this->_showInstance->getDbRecordedFile());
return $file->getSoundCloudId();
}
public function getRecordedFile()
{
$file_id = $this->_showInstance->getDbRecordedFile();
if(isset($file_id)) {
$file = Application_Model_StoredFile::Recall($file_id);
if (PEAR::isError($file)) {
return null;
}
if(file_exists($file->getFilePath())) {
return $file;
}
}
return null;
}
public function setShowStart($start)
{
$this->_showInstance->setDbStarts($start)
->save();
Application_Model_RabbitMq::PushSchedule();
}
public function setShowEnd($end)
{
$this->_showInstance->setDbEnds($end)
->save();
Application_Model_RabbitMq::PushSchedule();
}
public function updateScheduledTime()
{
$con = Propel::getConnection(CcShowInstancesPeer::DATABASE_NAME);
$this->_showInstance->updateDbTimeFilled($con);
}
public function isDeleted()
{
$this->_showInstance->getDbModifiedInstance();
}
public function correctScheduleStartTimes(){
global $CC_DBC;
$instance_id = $this->getShowInstanceId();
$sql = "SELECT starts from cc_schedule"
." WHERE instance_id = $instance_id"
." ORDER BY starts"
." LIMIT 1";
$scheduleStarts = $CC_DBC->GetOne($sql);
if (!is_null($scheduleStarts)){
$scheduleStartsEpoch = strtotime($scheduleStarts);
$showStartsEpoch = strtotime($this->getShowInstanceStart());
$diff = $showStartsEpoch - $scheduleStartsEpoch;
if ($diff != 0){
$sql = "UPDATE cc_schedule"
." SET starts = starts + INTERVAL '$diff' second,"
." ends = ends + INTERVAL '$diff' second"
." WHERE instance_id = $instance_id";
$CC_DBC->query($sql);
}
}
Application_Model_RabbitMq::PushSchedule();
}
public function moveShow($deltaDay, $deltaMin)
{
global $CC_DBC;
if ($this->getShow()->isRepeating()){
return "Can't drag and drop repeating shows";
}
$hours = $deltaMin/60;
if($hours > 0)
$hours = floor($hours);
else
$hours = ceil($hours);
$mins = abs($deltaMin%60);
$today_timestamp = time();
$starts = $this->getShowInstanceStart();
$ends = $this->getShowInstanceEnd();
$startsDateTime = new DateTime($starts, new DateTimeZone("UTC"));
if($today_timestamp > $startsDateTime->getTimestamp()) {
return "Can't move a past show";
}
$sql = "SELECT timestamp '{$starts}' + interval '{$deltaDay} days' + interval '{$hours}:{$mins}'";
$new_starts = $CC_DBC->GetOne($sql);
$newStartsDateTime = new DateTime($new_starts, new DateTimeZone("UTC"));
$sql = "SELECT timestamp '{$ends}' + interval '{$deltaDay} days' + interval '{$hours}:{$mins}'";
$new_ends = $CC_DBC->GetOne($sql);
$newEndsDateTime = new DateTime($new_ends, new DateTimeZone("UTC"));
if($today_timestamp > $newStartsDateTime->getTimestamp()) {
return "Can't move show into past";
}
$overlap = Application_Model_Show::getShows($newStartsDateTime, $newEndsDateTime, array($this->_instanceId));
if(count($overlap) > 0) {
return "Should not overlap shows";
}
$rebroadcast = $this->isRebroadcast();
if($rebroadcast) {
$sql = "SELECT timestamp '{$new_starts}' < (SELECT starts FROM cc_show_instances WHERE id = {$rebroadcast})";
$isBeforeRecordedOriginal = $CC_DBC->GetOne($sql);
if($isBeforeRecordedOriginal === 't'){
return "Cannot move a rebroadcast show before its original show";
}
}
$this->setShowStart($new_starts);
$this->setShowEnd($new_ends);
$this->correctScheduleStartTimes();
$show = new Application_Model_Show($this->getShowId());
if(!$show->isRepeating() && is_null($this->isRebroadcast())){
$show->setShowFirstShow($newStartsDateTime);
$show->setShowLastShow($newEndsDateTime);
}
Application_Model_RabbitMq::PushSchedule();
}
/*
* FUNCTION SHOULD NOT BE CALLED
* - we are removing ability to resize just a single show instance
* -please use the resize method on the Show.php class.
*/
public function resizeShow($deltaDay, $deltaMin)
{
global $CC_DBC;
$hours = $deltaMin/60;
if($hours > 0)
$hours = floor($hours);
else
$hours = ceil($hours);
$mins = abs($deltaMin%60);
$today_timestamp = gmdate("Y-m-d H:i:s");
$starts = $this->getShowInstanceStart();
$ends = $this->getShowInstanceEnd();
if(strtotime($today_timestamp) > strtotime($starts)) {
return "can't resize a past show";
}
$sql = "SELECT timestamp '{$ends}' + interval '{$deltaDay} days' + interval '{$hours}:{$mins}'";
$new_ends = $CC_DBC->GetOne($sql);
//only need to check overlap if show increased in size.
if(strtotime($new_ends) > strtotime($ends)) {
$utcStartDateTime = new DateTime($ends, new DateTimeZone("UTC"));
$utcEndDateTime = new DateTime($new_ends, new DateTimeZone("UTC"));
$overlap = Application_Model_Show::getShows($utcStartDateTime, $utcEndDateTime);
if(count($overlap) > 0) {
return "Should not overlap shows";
}
}
//with overbooking no longer need to check already scheduled content still fits.
//must update length of all rebroadcast instances.
if($this->isRecorded()) {
$sql = "UPDATE cc_show_instances SET ends = (ends + interval '{$deltaDay} days' + interval '{$hours}:{$mins}')
WHERE rebroadcast = 1 AND instance_id = {$this->_instanceId}";
$CC_DBC->query($sql);
}
$this->setShowEnd($new_ends);
Application_Model_RabbitMq::PushSchedule();
}
/**
* Get the group ID for this show.
*
*/
private function getLastGroupId()
{
global $CC_DBC;
$sql = "SELECT group_id FROM cc_schedule WHERE instance_id = '{$this->_instanceId}' ORDER BY ends DESC LIMIT 1";
$res = $CC_DBC->GetOne($sql);
return $res;
}
/**
* Add a playlist as the last item of the current show.
*
* @param int $plId
* Playlist ID.
*/
public function addPlaylistToShow($plId)
{
$sched = new Application_Model_ScheduleGroup();
$lastGroupId = $this->getLastGroupId();
if (is_null($lastGroupId)) {
$groupId = $sched->add($this->_instanceId, $this->getShowInstanceStart(), null, $plId);
}
else {
$groupId = $sched->addPlaylistAfter($this->_instanceId, $lastGroupId, $plId);
}
Application_Model_RabbitMq::PushSchedule();
$this->updateScheduledTime();
}
/**
* Add a media file as the last item in the show.
*
* @param int $file_id
*/
public function addFileToShow($file_id)
{
$sched = new Application_Model_ScheduleGroup();
$lastGroupId = $this->getLastGroupId();
if (is_null($lastGroupId)) {
$groupId = $sched->add($this->_instanceId, $this->getShowInstanceStart(), $file_id);
}
else {
$groupId = $sched->addFileAfter($this->_instanceId, $lastGroupId, $file_id);
}
Application_Model_RabbitMq::PushSchedule();
$this->updateScheduledTime();
}
/**
* Add the given playlists to the show.
*
* @param array $plIds
* An array of playlist IDs.
*/
public function scheduleShow($plIds)
{
foreach ($plIds as $plId) {
$this->addPlaylistToShow($plId);
}
}
public function removeGroupFromShow($group_id)
{
global $CC_DBC;
$sql = "SELECT MAX(ends) as end_timestamp, (MAX(ends) - MIN(starts)) as length
FROM cc_schedule
WHERE group_id = '{$group_id}'";
$groupBoundry = $CC_DBC->GetRow($sql);
$group = CcScheduleQuery::create()
->filterByDbGroupId($group_id)
->delete();
$sql = "UPDATE cc_schedule
SET starts = (starts - INTERVAL '{$groupBoundry["length"]}'), ends = (ends - INTERVAL '{$groupBoundry["length"]}')
WHERE starts >= '{$groupBoundry["end_timestamp"]}' AND instance_id = {$this->_instanceId}";
$CC_DBC->query($sql);
Application_Model_RabbitMq::PushSchedule();
$this->updateScheduledTime();
}
public function clearShow()
{
CcScheduleQuery::create()
->filterByDbInstanceId($this->_instanceId)
->delete();
Application_Model_RabbitMq::PushSchedule();
$this->updateScheduledTime();
}
public function deleteShow()
{
global $CC_DBC;
// see if it was recording show
$recording = CcShowInstancesQuery::create()
->findPK($this->_instanceId)
->getDbRecord();
// get show id
$showId = CcShowInstancesQuery::create()
->findPK($this->_instanceId)
->getDbShowId();
CcShowInstancesQuery::create()
->findPK($this->_instanceId)
->setDbModifiedInstance(true)
->save();
/* Automatically delete all files scheduled in cc_schedules table. */
CcScheduleQuery::create()
->filterByDbInstanceId($this->_instanceId)
->delete();
// check if we can safely delete the show
$showInstancesRow = CcShowInstancesQuery::create()
->filterByDbShowId($showId)
->filterByDbModifiedInstance(false)
->findOne();
/* If we didn't find any instances of the show that haven't
* been deleted, then just erase everything related to that show.
* We can just delete, the show and the foreign key-constraint should
* take care of deleting all of its instances. */
if(is_null($showInstancesRow)){
CcShowQuery::create()
->filterByDbId($showId)
->delete();
}
Application_Model_RabbitMq::PushSchedule();
if($recording){
Application_Model_RabbitMq::SendMessageToShowRecorder("cancel_recording");
}
}
public function setRecordedFile($file_id)
{
$showInstance = CcShowInstancesQuery::create()
->findPK($this->_instanceId);
$showInstance->setDbRecordedFile($file_id)
->save();
$rebroadcasts = CcShowInstancesQuery::create()
->filterByDbOriginalShow($this->_instanceId)
->find();
foreach ($rebroadcasts as $rebroadcast) {
$rebroad = new Application_Model_ShowInstance($rebroadcast->getDbId());
$rebroad->addFileToShow($file_id);
}
}
public function getTimeScheduled()
{
$time = $this->_showInstance->getDbTimeFilled();
if(is_null($time)) {
$time = "00:00:00";
}
return $time;
}
public function getPercentScheduled()
{
$start_timestamp = $this->getShowInstanceStart();
$end_timestamp = $this->getShowInstanceEnd();
$time_filled = $this->getTimeScheduled();
$s_epoch = strtotime($start_timestamp);
$e_epoch = strtotime($end_timestamp);
$i_epoch = Application_Model_Schedule::WallTimeToMillisecs($time_filled) / 1000;
$percent = ceil(($i_epoch / ($e_epoch - $s_epoch)) * 100);
if ($percent > 100)
$percent = 100;
return $percent;
}
public function getShowLength()
{
global $CC_DBC;
$start_timestamp = $this->getShowInstanceStart();
$end_timestamp = $this->getShowInstanceEnd();
$sql = "SELECT TIMESTAMP '{$end_timestamp}' - TIMESTAMP '{$start_timestamp}' ";
$length = $CC_DBC->GetOne($sql);
return $length;
}
public function searchPlaylistsForShow($datatables)
{
return Application_Model_StoredFile::searchPlaylistsForSchedule($datatables);
}
public function getShowListContent()
{
global $CC_DBC;
$sql = "SELECT *
FROM (cc_schedule AS s LEFT JOIN cc_files AS f ON f.id = s.file_id
LEFT JOIN cc_playlist AS p ON p.id = s.playlist_id )
WHERE s.instance_id = '{$this->_instanceId}' ORDER BY starts";
return $CC_DBC->GetAll($sql);
}
public function getShowContent()
{
global $CC_DBC;
$res = $this->getShowListContent();
if(count($res) <= 0) {
return $res;
}
$items = array();
$currGroupId = -1;
$pl_counter = -1;
$f_counter = -1;
foreach ($res as $row) {
if($currGroupId != $row["group_id"]){
$currGroupId = $row["group_id"];
$pl_counter = $pl_counter + 1;
$f_counter = -1;
$items[$pl_counter]["pl_name"] = $row["name"];
$items[$pl_counter]["pl_creator"] = $row["creator"];
$items[$pl_counter]["pl_description"] = $row["description"];
$items[$pl_counter]["pl_group"] = $row["group_id"];
$sql = "SELECT SUM(clip_length) FROM cc_schedule WHERE group_id = '{$currGroupId}'";
$length = $CC_DBC->GetOne($sql);
$items[$pl_counter]["pl_length"] = $length;
}
$f_counter = $f_counter + 1;
$items[$pl_counter]["pl_content"][$f_counter]["f_name"] = $row["track_title"];
$items[$pl_counter]["pl_content"][$f_counter]["f_artist"] = $row["artist_name"];
$items[$pl_counter]["pl_content"][$f_counter]["f_length"] = $row["length"];
}
return $items;
}
public static function GetShowsInstancesIdsInRange($p_timeNow, $p_start, $p_end)
{
global $CC_DBC;
$sql = "SELECT id FROM cc_show_instances AS si "
."WHERE modified_instance != TRUE AND ("
."(si.starts < TIMESTAMP '$p_timeNow' - INTERVAL '$p_start seconds' "
."AND si.ends > TIMESTAMP '$p_timeNow' - INTERVAL '$p_start seconds') "
."OR (si.starts > TIMESTAMP '$p_timeNow' - INTERVAL '$p_start seconds' "
."AND si.ends < TIMESTAMP '$p_timeNow' + INTERVAL '$p_end seconds') "
."OR (si.starts < TIMESTAMP '$p_timeNow' + INTERVAL '$p_end seconds' "
."AND si.ends > TIMESTAMP '$p_timeNow' + INTERVAL '$p_end seconds') "
.") "
." ORDER BY si.starts";
$rows = $CC_DBC->GetAll($sql);
return $rows;
}
public function getScheduleItemsInRange($timeNow, $start, $end)
{
global $CC_DBC, $CC_CONFIG;
$instanceId = $this->_instanceId;
$sql = "SELECT"
." si.starts as show_starts,"
." si.ends as show_ends,"
." si.rebroadcast as rebroadcast,"
." st.starts as item_starts,"
." st.ends as item_ends,"
." st.clip_length as clip_length,"
." ft.track_title as track_title,"
." ft.artist_name as artist_name,"
." ft.album_title as album_title,"
." s.name as show_name,"
." si.id as instance_id,"
." pt.name as playlist_name"
." FROM $CC_CONFIG[showInstances] si"
." LEFT JOIN $CC_CONFIG[scheduleTable] st"
." ON st.instance_id = si.id"
." LEFT JOIN $CC_CONFIG[playListTable] pt"
." ON st.playlist_id = pt.id"
." LEFT JOIN $CC_CONFIG[filesTable] ft"
." ON st.file_id = ft.id"
." LEFT JOIN $CC_CONFIG[showTable] s"
." ON si.show_id = s.id"
." WHERE ((si.starts < TIMESTAMP '$timeNow' - INTERVAL '$start seconds' AND si.ends > TIMESTAMP '$timeNow' - INTERVAL '$start seconds')"
." OR (si.starts > TIMESTAMP '$timeNow' - INTERVAL '$start seconds' AND si.ends < TIMESTAMP '$timeNow' + INTERVAL '$end seconds')"
." OR (si.starts < TIMESTAMP '$timeNow' + INTERVAL '$end seconds' AND si.ends > TIMESTAMP '$timeNow' + INTERVAL '$end seconds'))"
." AND (st.starts < si.ends)"
." AND si.id = $instanceId"
." ORDER BY si.starts, st.starts";
return $CC_DBC->GetAll($sql);
}
public function getLastAudioItemEnd(){
global $CC_DBC;
$sql = "SELECT ends FROM cc_schedule "
."WHERE instance_id = {$this->_instanceId} "
."ORDER BY ends DESC "
."LIMIT 1";
return $CC_DBC->GetOne($sql);
}
public function getShowEndGapTime(){
$showEnd = $this->getShowInstanceEnd();
$lastItemEnd = $this->getLastAudioItemEnd();
if (is_null($lastItemEnd)){
$lastItemEnd = $this->getShowInstanceStart();
}
$diff = strtotime($showEnd) - strtotime($lastItemEnd);
return ($diff < 0) ? 0 : $diff;
}
public static function GetLastShowInstance($p_timeNow){
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT si.id"
." FROM $CC_CONFIG[showInstances] si"
." WHERE si.ends < TIMESTAMP '$p_timeNow'"
." ORDER BY si.ends DESC"
." LIMIT 1";
$id = $CC_DBC->GetOne($sql);
if (is_null($id)){
return null;
} else {
return new Application_Model_ShowInstance($id);
}
}
public static function GetCurrentShowInstance($p_timeNow){
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT si.id"
." FROM $CC_CONFIG[showInstances] si"
." WHERE si.starts <= TIMESTAMP '$p_timeNow'"
." AND si.ends > TIMESTAMP '$p_timeNow'"
." LIMIT 1";
$id = $CC_DBC->GetOne($sql);
if (is_null($id)){
return null;
} else {
return new Application_Model_ShowInstance($id);
}
}
public static function GetNextShowInstance($p_timeNow){
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT si.id"
." FROM $CC_CONFIG[showInstances] si"
." WHERE si.starts > TIMESTAMP '$p_timeNow'"
." ORDER BY si.starts"
." LIMIT 1";
$id = $CC_DBC->GetOne($sql);
if (is_null($id)){
return null;
} else {
return new Application_Model_ShowInstance($id);
}
}
// returns number of show instances that ends later than $day
public static function GetShowInstanceCount($day){
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT count(*) as cnt FROM $CC_CONFIG[showInstances] WHERE ends < '$day'";
return $CC_DBC->GetOne($sql);
}
}