sintonia/legacy/application/models/ShowBuilder.php

509 lines
17 KiB
PHP
Raw Permalink Normal View History

<?php
class Application_Model_ShowBuilder
{
private $timezone;
// in UTC timezone
private $startDT;
// in UTC timezone
private $endDT;
private $user;
private $opts;
private $pos;
private $contentDT;
private $epoch_now;
private $currentShow;
2013-04-18 22:12:26 +02:00
private $currentShowId;
2021-10-11 16:10:47 +02:00
private $showInstances = [];
private $defaultRowArray = [
'header' => false,
'footer' => false,
'empty' => false,
'allowed' => false,
'linked_allowed' => true,
'id' => 0,
'instance' => '',
'starts' => '',
'ends' => '',
'runtime' => '',
'title' => '',
'creator' => '',
'album' => '',
'timestamp' => null,
'cuein' => '',
'cueout' => '',
'fadein' => '',
'fadeout' => '',
'image' => false,
'mime' => null,
'color' => '', // in hex without the '#' sign.
'backgroundColor' => '', // in hex without the '#' sign.
2021-10-11 16:10:47 +02:00
];
/*
* @param DateTime $p_startsDT
* @param DateTime $p_endsDT
*/
public function __construct($p_startDT, $p_endDT, $p_opts)
{
$this->startDT = $p_startDT;
$this->endDT = $p_endDT;
$this->timezone = Application_Model_Preference::GetUserTimezone();
$this->user = Application_Model_User::getCurrentUser();
$this->opts = $p_opts;
$this->epoch_now = floatval(microtime(true));
$this->currentShow = false;
}
private function getUsersShows()
{
2021-10-11 16:10:47 +02:00
$shows = [];
$host_shows = CcShowHostsQuery::create()
->setFormatter(ModelCriteria::FORMAT_ON_DEMAND)
->filterByDbHost($this->user->getId())
->find();
foreach ($host_shows as $host_show) {
$shows[] = $host_show->getDbShow();
}
return $shows;
}
// check to see if this row should be editable by the user.
private function isAllowed($p_item, &$row)
{
// cannot schedule in a recorded show.
2021-10-11 16:10:47 +02:00
if (intval($p_item['si_record']) === 1) {
return;
}
2013-04-18 22:12:26 +02:00
if ($this->currentShow) {
2021-10-11 16:10:47 +02:00
$this->currentShowId = $p_item['show_id'];
2013-04-18 22:12:26 +02:00
}
/* If any linked show instance is currently playing
* we have to disable editing, or else the times
* will not make sense for shows scheduled in the future
*/
2021-10-11 16:10:47 +02:00
if ($p_item['linked'] && $p_item['show_id'] == $this->currentShowId) {
$row['linked_allowed'] = false;
2013-04-18 22:12:26 +02:00
}
2021-10-11 16:10:47 +02:00
if ($this->user->canSchedule($p_item['show_id']) == true) {
$row['allowed'] = true;
}
}
private function getItemColor($p_item, &$row)
{
2021-10-11 16:10:47 +02:00
$defaultColor = 'ffffff';
$defaultBackground = DEFAULT_SHOW_COLOR;
2021-10-11 16:10:47 +02:00
$color = $p_item['show_color'];
if ($color === '') {
$color = $defaultColor;
}
2021-10-11 16:10:47 +02:00
$backgroundColor = $p_item['show_background_color'];
if ($backgroundColor === '') {
$backgroundColor = $defaultBackground;
}
2021-10-11 16:10:47 +02:00
$row['color'] = $color;
$row['backgroundColor'] = $backgroundColor;
}
// information about whether a track is inside|boundary|outside a show.
private function getItemStatus($p_item, &$row)
{
2021-10-11 16:10:47 +02:00
$row['status'] = intval($p_item['playout_status']);
}
private function getRowTimestamp($p_item, &$row)
{
2021-10-11 16:10:47 +02:00
if (is_null($p_item['si_last_scheduled'])) {
$ts = 0;
} else {
2021-10-11 16:10:47 +02:00
$dt = new DateTime($p_item['si_last_scheduled'], new DateTimeZone('UTC'));
$ts = intval($dt->format('U'));
}
2021-10-11 16:10:47 +02:00
$row['timestamp'] = $ts;
}
/*
* marks a row's status.
* 0 = past
* 1 = current
* 2 = future
2012-09-17 23:51:50 +02:00
* TODO : change all of the above to real constants -- RG
*/
private function getScheduledStatus($p_epochItemStart, $p_epochItemEnd, &$row)
{
2022-07-07 20:01:15 +02:00
if (
$row['footer'] === true && $this->epoch_now > $p_epochItemStart
&& $this->epoch_now > $p_epochItemEnd
) {
2021-10-11 16:10:47 +02:00
$row['scheduled'] = 0;
} elseif ($row['footer'] === true && $this->epoch_now < $p_epochItemEnd) {
$row['scheduled'] = 2;
} elseif ($row['header'] === true && $this->epoch_now >= $p_epochItemStart) {
$row['scheduled'] = 0;
} elseif ($row['header'] === true && $this->epoch_now < $p_epochItemEnd) {
$row['scheduled'] = 2;
}
// item is in the past.
2021-10-11 16:10:47 +02:00
elseif ($this->epoch_now > $p_epochItemEnd) {
$row['scheduled'] = 0;
}
// item is the currently scheduled item.
2021-10-11 16:10:47 +02:00
elseif ($this->epoch_now >= $p_epochItemStart && $this->epoch_now < $p_epochItemEnd) {
$row['scheduled'] = 1;
// how many seconds the view should wait to redraw itself.
2021-10-11 16:10:47 +02:00
$row['refresh'] = $p_epochItemEnd - $this->epoch_now;
2012-03-01 17:05:50 +01:00
}
// item is in the future.
2021-10-11 16:10:47 +02:00
elseif ($this->epoch_now < $p_epochItemStart) {
$row['scheduled'] = 2;
2012-09-17 23:51:50 +02:00
} else {
2021-10-11 16:10:47 +02:00
Logging::warn('No-op? is this what should happen...printing
debug just in case');
$d = [
2012-09-17 23:51:50 +02:00
'$p_epochItemStart' => $p_epochItemStart,
2021-10-11 16:10:47 +02:00
'$p_epochItemEnd' => $p_epochItemEnd,
2022-07-07 20:01:15 +02:00
'$row' => $row,
];
2012-09-17 23:51:50 +02:00
Logging::warn($d);
}
2012-03-01 17:05:50 +01:00
}
private function makeHeaderRow($p_item)
{
$row = $this->defaultRowArray;
// $this->isAllowed($p_item, $row);
$this->getRowTimestamp($p_item, $row);
$this->getItemColor($p_item, $row);
2021-10-11 16:10:47 +02:00
$showStartDT = new DateTime($p_item['si_starts'], new DateTimeZone('UTC'));
$showStartDT->setTimezone(new DateTimeZone($this->timezone));
2021-10-11 16:10:47 +02:00
$startsEpoch = floatval($showStartDT->format('U.u'));
$showEndDT = new DateTime($p_item['si_ends'], new DateTimeZone('UTC'));
$showEndDT->setTimezone(new DateTimeZone($this->timezone));
2021-10-11 16:10:47 +02:00
$endsEpoch = floatval($showEndDT->format('U.u'));
// is a rebroadcast show
2021-10-11 16:10:47 +02:00
if (intval($p_item['si_rebroadcast']) === 1) {
$row['rebroadcast'] = true;
2021-10-11 16:10:47 +02:00
$parentInstance = CcShowInstancesQuery::create()->findPk($p_item['parent_show']);
$name = $parentInstance->getCcShow()->getDbName();
$dt = $parentInstance->getDbStarts(null);
$dt->setTimezone(new DateTimeZone($this->timezone));
2021-10-11 16:10:47 +02:00
$time = $dt->format('Y-m-d H:i');
2021-10-11 16:10:47 +02:00
$row['rebroadcast_title'] = sprintf(_('Rebroadcast of %s from %s'), $name, $time);
} elseif (intval($p_item['si_record']) === 1) {
$row['record'] = true;
}
if ($startsEpoch < $this->epoch_now && $endsEpoch > $this->epoch_now) {
2021-10-11 16:10:47 +02:00
$row['currentShow'] = true;
$this->currentShow = true;
} else {
$this->currentShow = false;
}
2013-04-18 22:12:26 +02:00
$this->isAllowed($p_item, $row);
2021-10-11 16:10:47 +02:00
$row['header'] = true;
$row['starts'] = $showStartDT->format('Y-m-d H:i');
$row['startDate'] = $showStartDT->format('Y-m-d');
$row['startTime'] = $showStartDT->format('H:i');
$row['refresh'] = floatval($showStartDT->format('U.u')) - $this->epoch_now;
$row['ends'] = $showEndDT->format('Y-m-d H:i');
$row['endDate'] = $showEndDT->format('Y-m-d');
$row['endTime'] = $showEndDT->format('H:i');
$row['duration'] = floatval($showEndDT->format('U.u')) - floatval($showStartDT->format('U.u'));
$row['title'] = htmlspecialchars($p_item['show_name']);
$row['instance'] = intval($p_item['si_id']);
$row['image'] = '';
$this->getScheduledStatus($startsEpoch, $endsEpoch, $row);
$this->contentDT = $showStartDT;
return $row;
}
private function makeScheduledItemRow($p_item)
{
$row = $this->defaultRowArray;
2021-10-11 16:10:47 +02:00
if (isset($p_item['sched_starts'])) {
$schedStartDT = new DateTime(
$p_item['sched_starts'],
new DateTimeZone('UTC')
);
$schedStartDT->setTimezone(new DateTimeZone($this->timezone));
2021-10-11 16:10:47 +02:00
$schedEndDT = new DateTime(
$p_item['sched_ends'],
new DateTimeZone('UTC')
);
$schedEndDT->setTimezone(new DateTimeZone($this->timezone));
2021-10-11 16:10:47 +02:00
$showEndDT = new DateTime($p_item['si_ends'], new DateTimeZone('UTC'));
$this->getItemStatus($p_item, $row);
2021-10-11 16:10:47 +02:00
$startsEpoch = floatval($schedStartDT->format('U.u'));
$endsEpoch = floatval($schedEndDT->format('U.u'));
$showEndEpoch = floatval($showEndDT->format('U.u'));
2012-03-01 17:05:50 +01:00
// don't want an overbooked item to stay marked as current.
$this->getScheduledStatus($startsEpoch, min($endsEpoch, $showEndEpoch), $row);
2012-03-01 17:05:50 +01:00
2021-10-11 16:10:47 +02:00
$row['id'] = intval($p_item['sched_id']);
$row['image'] = $p_item['file_exists'];
$row['instance'] = intval($p_item['si_id']);
$row['starts'] = $schedStartDT->format('H:i:s');
$row['ends'] = $schedEndDT->format('H:i:s');
$cue_out = Application_Common_DateHelper::playlistTimeToSeconds($p_item['cue_out']);
$cue_in = Application_Common_DateHelper::playlistTimeToSeconds($p_item['cue_in']);
2021-10-11 16:10:47 +02:00
$run_time = $cue_out - $cue_in;
$formatter = new LengthFormatter(Application_Common_DateHelper::secondsToPlaylistTime($run_time));
$row['runtime'] = $formatter->format();
2021-10-11 16:10:47 +02:00
$row['title'] = htmlspecialchars($p_item['file_track_title']);
$row['creator'] = htmlspecialchars($p_item['file_artist_name']);
$row['album'] = htmlspecialchars($p_item['file_album_title']);
2021-10-11 16:10:47 +02:00
$row['cuein'] = $p_item['cue_in'];
$row['cueout'] = $p_item['cue_out'];
$row['fadein'] = round(substr($p_item['fade_in'], 6), 6);
$row['fadeout'] = round(substr($p_item['fade_out'], 6), 6);
$row['mime'] = $p_item['file_mime'];
2021-10-11 16:10:47 +02:00
$row['pos'] = $this->pos++;
$this->contentDT = $schedEndDT;
}
// show is empty or is a special kind of show (recording etc)
2021-10-11 16:10:47 +02:00
elseif (intval($p_item['si_record']) === 1) {
$row['record'] = true;
$row['instance'] = intval($p_item['si_id']);
2021-10-11 16:10:47 +02:00
$showStartDT = new DateTime($p_item['si_starts'], new DateTimeZone('UTC'));
$showEndDT = new DateTime($p_item['si_ends'], new DateTimeZone('UTC'));
2021-10-11 16:10:47 +02:00
$startsEpoch = floatval($showStartDT->format('U.u'));
$endsEpoch = floatval($showEndDT->format('U.u'));
$this->getScheduledStatus($startsEpoch, $endsEpoch, $row);
} else {
2021-10-11 16:10:47 +02:00
$row['empty'] = true;
$row['id'] = 0;
$row['instance'] = intval($p_item['si_id']);
}
2021-10-11 16:10:47 +02:00
if (intval($p_item['si_rebroadcast']) === 1) {
$row['rebroadcast'] = true;
}
if ($this->currentShow === true) {
2021-10-11 16:10:47 +02:00
$row['currentShow'] = true;
}
$this->getItemColor($p_item, $row);
$this->getRowTimestamp($p_item, $row);
$this->isAllowed($p_item, $row);
return $row;
}
private function makeFooterRow($p_item)
{
2021-10-11 16:10:47 +02:00
$row = $this->defaultRowArray;
$row['footer'] = true;
$row['instance'] = intval($p_item['si_id']);
$this->getRowTimestamp($p_item, $row);
2021-10-11 16:10:47 +02:00
$showEndDT = new DateTime($p_item['si_ends'], new DateTimeZone('UTC'));
$contentDT = $this->contentDT;
2021-10-11 16:10:47 +02:00
$runtime = bcsub($contentDT->format('U.u'), $showEndDT->format('U.u'), 6);
$row['runtime'] = $runtime;
2021-10-11 16:10:47 +02:00
$timeFilled = new TimeFilledFormatter($runtime);
$row['fRuntime'] = $timeFilled->format();
2021-10-11 16:10:47 +02:00
$showStartDT = new DateTime($p_item['si_starts'], new DateTimeZone('UTC'));
$showStartDT->setTimezone(new DateTimeZone($this->timezone));
2021-10-11 16:10:47 +02:00
$startsEpoch = floatval($showStartDT->format('U.u'));
$showEndDT = new DateTime($p_item['si_ends'], new DateTimeZone('UTC'));
$showEndDT->setTimezone(new DateTimeZone($this->timezone));
2021-10-11 16:10:47 +02:00
$endsEpoch = floatval($showEndDT->format('U.u'));
2021-10-11 16:10:47 +02:00
$row['refresh'] = floatval($showEndDT->format('U.u')) - $this->epoch_now;
if ($this->currentShow === true) {
2021-10-11 16:10:47 +02:00
$row['currentShow'] = true;
}
$this->getScheduledStatus($startsEpoch, $endsEpoch, $row);
$this->isAllowed($p_item, $row);
2021-10-11 16:10:47 +02:00
if (intval($p_item['si_record']) === 1) {
$row['record'] = true;
}
return $row;
}
/*
* @param int $timestamp Unix timestamp in seconds.
*
2012-09-18 16:55:42 +02:00
* @return boolean whether the schedule in the show builder's range has
* been updated.
*
*/
public function hasBeenUpdatedSince($timestamp, $instances)
{
$outdated = false;
$shows = Application_Model_Show::getShows($this->startDT, $this->endDT);
2021-10-11 16:10:47 +02:00
$include = [];
if ($this->opts['showFilter'] !== 0) {
$include[] = $this->opts['showFilter'];
} elseif ($this->opts['myShows'] === 1) {
$include = $this->getUsersShows();
}
2021-10-11 16:10:47 +02:00
$currentInstances = [];
foreach ($shows as $show) {
2021-10-11 16:10:47 +02:00
if (empty($include) || in_array($show['show_id'], $include)) {
$currentInstances[] = $show['instance_id'];
if (isset($show['last_scheduled'])) {
$dt = new DateTime(
$show['last_scheduled'],
new DateTimeZone('UTC')
);
} else {
2021-10-11 16:10:47 +02:00
$dt = new DateTime(
$show['created'],
new DateTimeZone('UTC')
);
}
// check if any of the shows have a more recent timestamp.
2021-10-11 16:10:47 +02:00
$showTimeStamp = intval($dt->format('U'));
if ($timestamp < $showTimeStamp) {
$outdated = true;
2021-10-11 16:10:47 +02:00
break;
}
}
}
// see if the displayed show instances have changed. (deleted,
// empty schedule etc)
2022-07-07 20:01:15 +02:00
if (
$outdated === false && count($instances)
!== count($currentInstances)
) {
2021-10-11 16:10:47 +02:00
Logging::debug('show instances have changed.');
$outdated = true;
}
return $outdated;
}
2012-09-07 22:50:33 +02:00
public function getItems()
{
$current_id = -1;
2021-10-11 16:10:47 +02:00
$display_items = [];
2021-10-11 16:10:47 +02:00
$shows = [];
$showInstance = [];
if ($this->opts['myShows'] === 1) {
$shows = $this->getUsersShows();
2021-10-11 16:10:47 +02:00
} elseif ($this->opts['showFilter'] !== 0) {
$shows[] = $this->opts['showFilter'];
} elseif ($this->opts['showInstanceFilter'] !== 0) {
$showInstance[] = $this->opts['showInstanceFilter'];
}
2012-09-18 16:55:42 +02:00
$scheduled_items = Application_Model_Schedule::GetScheduleDetailItems(
2021-10-11 16:10:47 +02:00
$this->startDT,
$this->endDT,
$shows,
$showInstance
);
2021-10-11 16:10:47 +02:00
for ($i = 0, $rows = count($scheduled_items); $i < $rows; ++$i) {
$item = $scheduled_items[$i];
// don't send back data for filler rows.
2022-07-07 20:01:15 +02:00
if (
isset($item['playout_status'])
&& $item['playout_status'] < 0
) {
continue;
}
// make a header row.
2021-10-11 16:10:47 +02:00
if ($current_id !== $item['si_id']) {
// make a footer row.
if ($current_id !== -1) {
2012-09-18 16:55:42 +02:00
// pass in the previous row as it's the last row for
// the previous show.
$display_items[] = $this->makeFooterRow(
2021-10-11 16:10:47 +02:00
$scheduled_items[$i - 1]
);
}
$display_items[] = $this->makeHeaderRow($item);
2021-10-11 16:10:47 +02:00
$current_id = $item['si_id'];
$this->pos = 1;
}
// make a normal data row.
$row = $this->makeScheduledItemRow($item);
// don't display the empty rows.
if (isset($row)) {
$display_items[] = $row;
}
2022-07-07 20:01:15 +02:00
if (
$current_id !== -1
&& !in_array($current_id, $this->showInstances)
) {
$this->showInstances[] = $current_id;
}
}
// make the last footer if there were any scheduled items.
if (count($scheduled_items) > 0) {
2022-07-07 20:01:15 +02:00
$display_items[] = $this->makeFooterRow($scheduled_items[count($scheduled_items) - 1]);
}
2021-10-11 16:10:47 +02:00
return [
'schedule' => $display_items,
2022-07-07 20:01:15 +02:00
'showInstances' => $this->showInstances,
];
}
}