From 2717c0845b47d1c4c9541cfec5e8a5219acc59dc Mon Sep 17 00:00:00 2001 From: denise Date: Tue, 26 Feb 2013 10:20:02 -0500 Subject: [PATCH] Created show service --- airtime_mvc/application/models/Show.php | 8 +- airtime_mvc/application/models/_old_Show.php | 2241 +++++++++++++++++ .../application/services/ScheduleService.php | 11 +- .../application/services/ShowService.php | 145 ++ 4 files changed, 2397 insertions(+), 8 deletions(-) create mode 100644 airtime_mvc/application/models/_old_Show.php create mode 100644 airtime_mvc/application/services/ShowService.php diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php index 493f3ca37..d6f9db98b 100644 --- a/airtime_mvc/application/models/Show.php +++ b/airtime_mvc/application/models/Show.php @@ -1229,7 +1229,7 @@ SQL; //adding rows to cc_show_rebroadcast /* TODO: Document magic constant 10 and define it properly somewhere --RG */ - if (($isRecorded && $data['add_show_rebroadcast']) && ($repeatType != -1)) { + /*if (($isRecorded && $data['add_show_rebroadcast']) && ($repeatType != -1)) { for ($i=1; $i<=10; $i++) { if ($data['add_show_rebroadcast_date_'.$i]) { $showRebroad = new CcShowRebroadcast(); @@ -1266,14 +1266,14 @@ SQL; $showRebroad->save(); } } - } + }*/ //check if we are adding or updating a show, and if updating //erase all the show's show_rebroadcast information first. if ($data['add_show_id'] != -1) { CcShowHostsQuery::create()->filterByDbShow($data['add_show_id'])->delete(); } - if (is_array($data['add_show_hosts'])) { + /*if (is_array($data['add_show_hosts'])) { //add selected hosts to cc_show_hosts table. foreach ($data['add_show_hosts'] as $host) { $showHost = new CcShowHosts(); @@ -1281,7 +1281,7 @@ SQL; $showHost->setDbHost($host); $showHost->save(); } - } + }*/ if ($data['add_show_id'] != -1) { $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME); diff --git a/airtime_mvc/application/models/_old_Show.php b/airtime_mvc/application/models/_old_Show.php new file mode 100644 index 000000000..f485e41bc --- /dev/null +++ b/airtime_mvc/application/models/_old_Show.php @@ -0,0 +1,2241 @@ +_showId = $showId; + } + + public function getName() + { + $show = CcShowQuery::create()->findPK($this->_showId); + + return $show->getDbName(); + } + + public function setName($name) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbName($name); + Application_Model_RabbitMq::PushSchedule(); + } + + public function setAirtimeAuthFlag($flag) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbLiveStreamUsingAirtimeAuth($flag); + $show->save(); + } + + public function setCustomAuthFlag($flag) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbLiveStreamUsingCustomAuth($flag); + $show->save(); + } + + public function setCustomUsername($username) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbLiveStreamUser($username); + $show->save(); + } + + public function setCustomPassword($password) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbLiveStreamPass($password); + $show->save(); + } + + public function getDescription() + { + $show = CcShowQuery::create()->findPK($this->_showId); + + return $show->getDbDescription(); + } + + public function setDescription($description) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbDescription($description); + } + + public function getColor() + { + $show = CcShowQuery::create()->findPK($this->_showId); + + return $show->getDbColor(); + } + + public function setColor($color) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbColor($color); + } + + public function getUrl() + { + $show = CcShowQuery::create()->findPK($this->_showId); + + return $show->getDbUrl(); + } + + /*TODO : This method is not actually used anywhere as far as I can tell. We + can safely remove it and probably many other superfluous methods. + --RG*/ + + public function setUrl($p_url) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbUrl($p_url); + } + + public function getGenre() + { + $show = CcShowQuery::create()->findPK($this->_showId); + + return $show->getDbGenre(); + } + + public function setGenre($p_genre) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbGenre($p_genre); + } + + public function getBackgroundColor() + { + $show = CcShowQuery::create()->findPK($this->_showId); + + return $show->getDbBackgroundColor(); + } + + public function setBackgroundColor($backgroundColor) + { + $show = CcShowQuery::create()->findPK($this->_showId); + $show->setDbBackgroundColor($backgroundColor); + } + + public function getId() + { + return $this->_showId; + } + + public function getHosts() + { + $sql = << $this->getId() ), 'all'); + + $res = array(); + foreach ($hosts as $host) { + $res[] = $host['first_name']." ".$host['last_name']; + } + return $res; + } + + public function getHostsIds() + { + $sql = << $this->getId() ), 'all'); + + return $hosts; + } + + /** + * remove everything about this show. + */ + public function delete() + { + //usually we hide the show-instance, but in this case we are deleting the show template + //so delete all show-instances as well. + CcShowInstancesQuery::create()->filterByDbOriginalShow($this->_showId)->delete(); + + $show = CcShowQuery::create()->findPK($this->_showId); + $show->delete(); + } + + public function resizeShow($deltaDay, $deltaMin) + { + $con = Propel::getConnection(); + + if ($deltaDay > 0) { + return _("Shows can have a max length of 24 hours."); + } + + $utc = new DateTimeZone("UTC"); + + $nowDateTime = new DateTime("now", $utc); + + $showInstances = CcShowInstancesQuery::create() + ->filterByDbShowId($this->_showId) + ->find($con); + + /* Check two things: + 1. If the show being resized and any of its repeats end in the past + 2. If the show being resized and any of its repeats overlap + with other scheduled shows */ + + foreach ($showInstances as $si) { + $startsDateTime = new DateTime($si->getDbStarts(), new DateTimeZone("UTC")); + $endsDateTime = new DateTime($si->getDbEnds(), new DateTimeZone("UTC")); + + /* The user is moving the show on the calendar from the perspective + of local time. * incase a show is moved across a time change + border offsets should be added to the local * timestamp and + then converted back to UTC to avoid show time changes */ + $startsDateTime->setTimezone(new DateTimeZone(date_default_timezone_get())); + $endsDateTime->setTimezone(new DateTimeZone(date_default_timezone_get())); + + $newStartsDateTime = Application_Model_ShowInstance::addDeltas($startsDateTime, $deltaDay, $deltaMin); + $newEndsDateTime = Application_Model_ShowInstance::addDeltas($endsDateTime, $deltaDay, $deltaMin); + + if ($newEndsDateTime->getTimestamp() < $nowDateTime->getTimestamp()) { + return _("End date/time cannot be in the past"); + } + + //convert our new starts/ends to UTC. + $newStartsDateTime->setTimezone($utc); + $newEndsDateTime->setTimezone($utc); + + $overlapping = Application_Model_Schedule::checkOverlappingShows( + $newStartsDateTime, $newEndsDateTime, true, $si->getDbId()); + + if ($overlapping) { + return _("Cannot schedule overlapping shows.\nNote: Resizing a repeating show ". + "affects all of its repeats."); + } + } + + $hours = $deltaMin/60; + $hours = ($hours > 0) ? floor($hours) : ceil($hours); + $mins = abs($deltaMin % 60); + + //current timesamp in UTC. + $current_timestamp = gmdate("Y-m-d H:i:s"); + + $sql_gen = << :current_timestamp1) + AND ((ends + :deltaDay2::INTERVAL + :interval2::INTERVAL - starts) <= interval '24:00') +SQL; + + Application_Common_Database::prepareAndExecute($sql_gen, + array( + ':deltaDay1' => "$deltaDay days", + ':interval1' => "$hours:$mins", + ':show_id1' => $this->_showId, + ':current_timestamp1' => $current_timestamp, + ':deltaDay2' => "$deltaDay days", + ':interval2' => "$hours:$mins" + ), "execute"); + + $sql_gen = << "$deltaDay days", + ':interval3' => "$hours:$mins", + ':show_id2' => $this->_showId, + ':deltaDay4' => "$deltaDay days", + ':interval4' => "$hours:$mins" + ), "execute"); + + $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME); + $con->beginTransaction(); + + try { + //update the status flag in cc_schedule. + + /* Since we didn't use a propel object when updating + * cc_show_instances table we need to clear the instances + * so the correct information is retrieved from the db + */ + CcShowInstancesPeer::clearInstancePool(); + + $instances = CcShowInstancesQuery::create() + ->filterByDbEnds($current_timestamp, Criteria::GREATER_THAN) + ->filterByDbShowId($this->_showId) + ->find($con); + + foreach ($instances as $instance) { + $instance->updateScheduleStatus($con); + } + + $con->commit(); + } catch (Exception $e) { + $con->rollback(); + Logging::info("Couldn't update schedule status."); + Logging::info($e->getMessage()); + } + + Application_Model_RabbitMq::PushSchedule(); + } + + public function cancelShow($day_timestamp) + { + $timeinfo = explode(" ", $day_timestamp); + + CcShowDaysQuery::create() + ->filterByDbShowId($this->_showId) + ->update(array('DbLastShow' => $timeinfo[0])); + + $sql = <<= :dayTimestamp::TIMESTAMP + AND show_id = :showId +SQL; + + $rows = Application_Common_Database::prepareAndExecute( $sql, array( + ':dayTimestamp' => $day_timestamp, + ':showId' => $this->getId()), 'all'); + + foreach ($rows as $row) { + try { + $showInstance = new Application_Model_ShowInstance($row["id"]); + $showInstance->delete($rabbitmqPush = false); + } catch (Exception $e) { + Logging::info($e->getMessage()); + } + } + + Application_Model_RabbitMq::PushSchedule(); + } + + /** + * This function is called when a repeating show is edited and the + * days that is repeats on have changed. More specifically, a day + * that the show originally repeated on has been "unchecked". + * + * Removes Show Instances that occur on days of the week specified + * by input array. For example, if array contains one value of "0", + * (0 = Sunday, 1=Monday) then all show instances that occur on + * Sunday are removed. + * + * @param array p_uncheckedDays + * An array specifying which days should be removed. (in the local timezone) + */ + public function removeUncheckedDaysInstances($p_uncheckedDays) + { + //need to convert local doftw to UTC doftw (change made for 2.0 since shows are stored in UTC) + $daysRemovedUTC = array(); + + $showDays = CcShowDaysQuery::create() + ->filterByDbShowId($this->getId()) + ->find(); + + Logging::info("Unchecked days:"); + foreach ($p_uncheckedDays as $day) { + Logging::info($day); + } + + foreach ($showDays as $showDay) { + //Logging::info("Local show day is: {$showDay->getDbDay()}"); + //Logging::info("First show day is: {$showDay->getDbFirstShow()}"); + //Logging::info("Id show days is: {$showDay->getDbId()}"); + + if (in_array($showDay->getDbDay(), $p_uncheckedDays)) { + $showDay->reload(); + //Logging::info("Local show day is: {$showDay->getDbDay()}"); + //Logging::info("First show day is: {$showDay->getDbFirstShow()}"); + //Logging::info("Id show days is: {$showDay->getDbId()}"); + $startDay = new DateTime("{$showDay->getDbFirstShow()} {$showDay->getDbStartTime()}", new DateTimeZone($showDay->getDbTimezone())); + //Logging::info("Show start day: {$startDay->format('Y-m-d H:i:s')}"); + $startDay->setTimezone(new DateTimeZone("UTC")); + //Logging::info("Show start day UTC: {$startDay->format('Y-m-d H:i:s')}"); + $daysRemovedUTC[] = $startDay->format('w'); + //Logging::info("UTC show day is: {$startDay->format('w')}"); + } + } + + $uncheckedDaysImploded = implode(",", $daysRemovedUTC); + $showId = $this->getId(); + + $esc_uncheckedDays = pg_escape_string($uncheckedDaysImploded); + $timestamp = gmdate("Y-m-d H:i:s"); + + $sql = << :timestamp::TIMESTAMP + AND show_id = :showId +SQL; + + Application_Common_Database::prepareAndExecute( $sql, + array( + ":timestamp" => $timestamp, + ":showId" => $showId, + ), "execute"); + } + + /** + * Check whether the current show originated + * from a recording. + * + * @return boolean + * true if originated from recording, otherwise false. + */ + public function isRecorded() + { + $showInstancesRow = CcShowInstancesQuery::create() + ->filterByDbShowId($this->getId()) + ->filterByDbRecord(1) + ->filterByDbModifiedInstance(false) + ->findOne(); + + return !is_null($showInstancesRow); + } + + /** + * Check whether the current show has rebroadcasts of a recorded + * show. Should be used in conjunction with isRecorded(). + * + * @return boolean + * true if show has rebroadcasts, otherwise false. + */ + public function isRebroadcast() + { + $showInstancesRow = CcShowInstancesQuery::create() + ->filterByDbShowId($this->_showId) + ->filterByDbRebroadcast(1) + ->filterByDbModifiedInstance(false) + ->findOne(); + + return !is_null($showInstancesRow); + } + + /** + * Get start time and absolute start date for a recorded + * shows rebroadcasts. For example start date format would be + * YYYY-MM-DD and time would HH:MM + * + * @return array + * array of associate arrays containing "start_date" and "start_time" + */ + public function getRebroadcastsAbsolute() + { + $sql = << $this->getId() ), 'all' ); + + $rebroadcastsLocal = array(); + //get each rebroadcast show in cc_show_instances, convert to current timezone to get start date/time. + /*TODO: refactor the following code to get rid of the $i temporary + variable. -- RG*/ + $i = 0; + + $utc = new DateTimeZone("UTC"); + $dtz = new DateTimeZone( date_default_timezone_get() ); + + foreach ($rebroadcasts as $show) { + $startDateTime = new DateTime($show["starts"], $utc); + $startDateTime->setTimezone($dtz); + + $rebroadcastsLocal[$i]["start_date"] = + $startDateTime->format("Y-m-d"); + $rebroadcastsLocal[$i]["start_time"] = + $startDateTime->format("H:i"); + + $i = $i + 1; + } + + return $rebroadcastsLocal; + } + + /** + * Get start time and relative start date for a recorded + * shows rebroadcasts. For example start date format would be + * "x days" and time would HH:MM:SS + * + * @return array + * array of associate arrays containing "day_offset" and "start_time" + */ + public function getRebroadcastsRelative() + { + $sql = << $this->getId() ), 'all' ); + } + + /** + * Check whether the current show is set to repeat + * repeating shows. + * + * @return boolean + * true if repeating shows, otherwise false. + */ + public function isRepeating() + { + $showDaysRow = CcShowDaysQuery::create() + ->filterByDbShowId($this->_showId) + ->findOne(); + + if (!is_null($showDaysRow)) { + return ($showDaysRow->getDbRepeatType() != -1); + } else { + return false; + } + } + + /** + * Get the repeat type of the show. Show can have repeat + * type of "weekly", "bi-weekly" and "monthly". These values + * are represented by 0, 1, and 2 respectively. + * + * @return int + * Return the integer corresponding to the repeat type. + */ + public function getRepeatType() + { + $showDaysRow = CcShowDaysQuery::create() + ->filterByDbShowId($this->_showId) + ->findOne(); + + if (!is_null($showDaysRow)) + return $showDaysRow->getDbRepeatType(); + else + return -1; + } + + /** + * Get the end date for a repeating show in the format yyyy-mm-dd + * + * @return string + * Return the end date for the repeating show or the empty + * string if there is no end. + */ + public function getRepeatingEndDate() + { + $sql = << $this->getId() ), 'column' ); + + /* TODO: Why return empty string instead of false? very confusing --RG + */ + return ($query !== false) ? $query : ""; + } + + /** + * Deletes all future instances of the current show object + * from the show_instances table. This function is used when + * a show is being edited - in some cases, when a show is edited + * we just destroy all future show instances, and let another function + * regenerate them later on. Note that this isn't always the most + * desirable thing to do. Deleting a show instance and regenerating + * it cause any scheduled playlists within those show instances to + * be gone for good. + */ + public function deleteAllInstances() + { + $sql = << :timestamp::TIMESTAMP + AND show_id = :showId +SQL; + Application_Common_Database::prepareAndExecute( $sql, + array( ':timestamp' => gmdate("Y-m-d H:i:s"), + ':showId' => $this->getId()), 'execute'); + } + + /** + * Deletes all future rebroadcast instances of the current + * show object from the show_instances table. + */ + public function deleteAllRebroadcasts() + { + $sql = << :timestamp::TIMESTAMP + AND show_id :showId + AND rebroadcast 1 +SQL; + Application_Common_Database::prepareAndExecute( $sql, + array( ':showId' => $this->getId(), + ':timestamp' => gmdate("Y-m-d H:i:s")), 'execute'); + + $con->exec($sql); + } + + /** + * Deletes all show instances of current show after a + * certain date. Note that although not enforced, $p_date + * should never be in the past, as we never want to allow + * deletion of shows that have already occured. + * + * @param string $p_date + * The date which to delete after, if null deletes from the current timestamp. + */ + public function removeAllInstancesFromDate($p_date=null) + { + $con = Propel::getConnection(); + + $timestamp = gmdate("Y-m-d H:i:s"); + + if (is_null($p_date)) { + $date = new Application_Common_DateHelper; + $p_date = $date->getDate(); + } + + $showId = $this->getId(); + $sql = "DELETE FROM cc_show_instances " + ." WHERE date(starts) >= DATE '$p_date'" + ." AND starts > TIMESTAMP '$timestamp'" + ." AND show_id = $showId"; + + $con->exec($sql); + + } + + /** + * Deletes all show instances of current show before a + * certain date. + * + * This function is used in the case where a repeating show is being + * edited and the start date of the first show has been changed more + * into the future. In this case, delete any show instances that + * exist before the new start date. + * + * @param string $p_date + * The date which to delete before + */ + public function removeAllInstancesBeforeDate($p_date) + { + $con = Propel::getConnection(); + + $timestamp = gmdate("Y-m-d H:i:s"); + + $showId = $this->getId(); + $sql = "DELETE FROM cc_show_instances " + ." WHERE date(starts) < DATE '$p_date'" + ." AND starts > TIMESTAMP '$timestamp'" + ." AND show_id = $showId"; + + $con->exec($sql); + } + + public function getNextFutureRepeatShowTime() + { + $sql = << now() at time zone 'UTC' +AND show_id = :showId +ORDER BY starts +LIMIT 1 +SQL; + $result = Application_Common_Database::prepareAndExecute( $sql, + array( 'showId' => $this->getId() ), 'all' ); + + foreach ($result as $r) { + $show["starts"] = new DateTime($r["starts"], new DateTimeZone('UTC')); + $show["ends"] = new DateTime($r["ends"], new DateTimeZone('UTC')); + } + $currentUser = Application_Model_User::getCurrentUser(); + $currentUserId = $currentUser->getId(); + $userTimezone = Application_Model_Preference::GetUserTimezone($currentUserId); + $show["starts"]->setTimezone(new DateTimeZone($userTimezone)); + $show["ends"]->setTimezone(new DateTimeZone($userTimezone)); + return $show; + } + + /** + * Get the start date of the current show in UTC timezone. + * + * @return string + * The start date in the format YYYY-MM-DD or empty string in case + * start date could not be found + */ + public function getStartDateAndTime() + { + $con = Propel::getConnection(); + + $showId = $this->getId(); + $stmt = $con->prepare( + "SELECT first_show, start_time, timezone FROM cc_show_days" + ." WHERE show_id = :showId" + ." ORDER BY first_show" + ." LIMIT 1"); + + $stmt->bindParam(':showId', $showId); + $stmt->execute(); + + if (!$stmt) { + return ""; + } + + $rows = $stmt->fetchAll(); + $row = $rows[0]; + + $dt = new DateTime($row["first_show"]." ".$row["start_time"], new DateTimeZone($row["timezone"])); + $dt->setTimezone(new DateTimeZone("UTC")); + + return $dt->format("Y-m-d H:i"); + } + + /** + * Get the start date of the current show in UTC timezone. + * + * @return string + * The start date in the format YYYY-MM-DD + */ + public function getStartDate() + { + list($date,) = explode(" ", $this->getStartDateAndTime()); + + return $date; + } + + /** + * Get the start time of the current show in UTC timezone. + * + * @return string + * The start time in the format HH:MM + */ + + public function getStartTime() + { + list(,$time) = explode(" ", $this->getStartDateAndTime()); + + return $time; + } + + /** + * Get the end date of the current show. + * Note that this is not the end date of repeated show + * + * @return string + * The end date in the format YYYY-MM-DD + */ + public function getEndDate() + { + $startDate = $this->getStartDate(); + $startTime = $this->getStartTime(); + $duration = $this->getDuration(); + + $startDateTime = new DateTime($startDate.' '.$startTime); + $duration = explode(":", $duration); + + $endDate = $startDateTime->add(new DateInterval('PT'.$duration[0].'H'.$duration[1].'M')); + + return $endDate->format('Y-m-d'); + } + + /** + * Get the end time of the current show. + * + * @return string + * The start time in the format HH:MM:SS + */ + public function getEndTime() + { + $startDate = $this->getStartDate(); + $startTime = $this->getStartTime(); + $duration = $this->getDuration(); + + $startDateTime = new DateTime($startDate.' '.$startTime); + $duration = explode(":", $duration); + + $endDate = $startDateTime->add(new DateInterval('PT'.$duration[0].'H'.$duration[1].'M')); + + return $endDate->format('H:i:s'); + } + + /** + * Indicate whether the starting point of the show is in the + * past. + * + * @return boolean + * true if the StartDate is in the past, false otherwise + */ + public function isStartDateTimeInPast() + { + $date = new Application_Common_DateHelper; + $current_timestamp = $date->getUtcTimestamp(); + + return ($current_timestamp > ($this->getStartDate()." ".$this->getStartTime())); + } + + /** + * Get the ID's of future instance of the current show. + * + * @return array + * A simple array containing all ID's of show instance + * scheduled in the future. + */ + public function getAllFutureInstanceIds() + { + $sql = << :timestamp::TIMESTAMP + AND modified_instance != TRUE +SQL; + $rows = Application_Common_Database::prepareAndExecute($sql, + array( ':showId' => $this->getId(), + ':timestamp' => gmdate("Y-m-d H:i:s")), "all"); + + $res = array(); + foreach ($rows as $r) { + $res[] = $r['id']; + } + return $res; + } + + /* Called when a show's duration is changed (edited). + * + * @param array $p_data + * array containing the POST data about the show from the + * browser. + * + */ + private function updateDurationTime($p_data) + { + //need to update cc_show_instances, cc_show_days + $con = Propel::getConnection(); + + $date = new Application_Common_DateHelper; + $timestamp = $date->getUtcTimestamp(); + + $stmt = $con->prepare("UPDATE cc_show_days " + ."SET duration = :add_show_duration " + ."WHERE show_id = :add_show_id" ); + $stmt->execute( array( + ':add_show_duration' => $p_data['add_show_duration'], + ':add_show_id' => $p_data['add_show_id'] + )); + + + $sql = << :timestamp::TIMESTAMP +SQL; + + Application_Common_Database::prepareAndExecute( $sql, array( + ':add_show_duration' => $p_data['add_show_duration'], + ':show_id' => $p_data['add_show_id'], + ':timestamp' => $timestamp), "execute"); + } + + private function updateStartDateTime($p_data, $p_endDate) + { + //need to update cc_schedule, cc_show_instances, cc_show_days + $con = Propel::getConnection(); + + $date = new Application_Common_DateHelper; + $timestamp = $date->getTimestamp(); + + //TODO fix this from overwriting info. + $sql = "UPDATE cc_show_days " + ."SET start_time = TIME '$p_data[add_show_start_time]', " + ."first_show = DATE '$p_data[add_show_start_date]', "; + if (strlen ($p_endDate) == 0) { + $sql .= "last_show = NULL "; + } else { + $sql .= "last_show = DATE '$p_endDate' "; + } + $sql .= "WHERE show_id = $p_data[add_show_id]"; + $con->exec($sql); + + $dtOld = new DateTime($this->getStartDate()." ".$this->getStartTime(), new DateTimeZone("UTC")); + $dtNew = new DateTime($p_data['add_show_start_date']." ".$p_data['add_show_start_time'], new DateTimeZone(date_default_timezone_get())); + $diff = $dtOld->getTimestamp() - $dtNew->getTimestamp(); + + $sql = "UPDATE cc_show_instances " + ."SET starts = starts + INTERVAL '$diff sec', " + ."ends = ends + INTERVAL '$diff sec' " + ."WHERE show_id = $p_data[add_show_id] " + ."AND starts > TIMESTAMP '$timestamp'"; + $con->exec($sql); + + $showInstanceIds = $this->getAllFutureInstanceIds(); + if (count($showInstanceIds) > 0 && $diff != 0) { + $showIdsImploded = implode(",", $showInstanceIds); + $sql = "UPDATE cc_schedule " + ."SET starts = starts + INTERVAL '$diff sec', " + ."ends = ends + INTERVAL '$diff sec' " + ."WHERE instance_id IN ($showIdsImploded)"; + $con->exec($sql); + } + } + + public function getDuration($format=false) + { + $showDay = CcShowDaysQuery::create()->filterByDbShowId($this->getId())->findOne(); + if (!$format) { + return $showDay->getDbDuration(); + } else { + $info = explode(':',$showDay->getDbDuration()); + + return str_pad(intval($info[0]),2,'0',STR_PAD_LEFT).'h '.str_pad(intval($info[1]),2,'0',STR_PAD_LEFT).'m'; + } + } + + public function getShowDays() + { + $showDays = CcShowDaysQuery::create()->filterByDbShowId( + $this->getId())->find(); + $res = array(); + foreach ($showDays as $showDay) { + $res[] = $showDay->getDbDay(); + } + return $res; + } + + /* Only used for shows that aren't repeating. + * + * @return Boolean: true if show has an instance, otherwise false. */ + public function hasInstance() + { + return (!is_null($this->getInstance())); + } + + /* Only used for shows that aren't repeating. + * + * @return CcShowInstancesQuery: An propel object representing a + * row in the cc_show_instances table. */ + public function getInstance() + { + $showInstance = CcShowInstancesQuery::create() + ->filterByDbShowId($this->getId()) + ->findOne(); + + return $showInstance; + } + + /** + * returns info about live stream override info + */ + public function getLiveStreamInfo() + { + $info = array(); + if ($this->getId() == null) { + return $info; + } else { + $ccShow = CcShowQuery::create()->findPK($this->_showId); + $info['custom_username'] = $ccShow->getDbLiveStreamUser(); + $info['cb_airtime_auth'] = $ccShow->getDbLiveStreamUsingAirtimeAuth(); + $info['cb_custom_auth'] = $ccShow->getDbLiveStreamUsingCustomAuth(); + $info['custom_username'] = $ccShow->getDbLiveStreamUser(); + $info['custom_password'] = $ccShow->getDbLiveStreamPass(); + return $info; + } + } + + /* Only used for shows that are repeating. Note that this will return + * true even for dates that only have a "modified" show instance (does not + * check if the "modified_instance" column is set to true). This is intended + * behaviour. + * + * @param $p_dateTime: Date for which we are checking if instance + * exists. + * + * @return Boolean: true if show has an instance on $p_dateTime, + * otherwise false. */ + public function hasInstanceOnDate($p_dateTime) + { + return (!is_null($this->getInstanceOnDate($p_dateTime))); + } + + /* Only used for shows that are repeating. Note that this will return + * shows that have been "modified" (does not check if the "modified_instance" + * column is set to true). This is intended behaviour. + * + * @param $p_dateTime: Date for which we are getting an instance. + * + * @return CcShowInstancesQuery: An propel object representing a + * row in the cc_show_instances table. */ + public function getInstanceOnDate($p_dateTime) + { + $timestamp = $p_dateTime->format("Y-m-d H:i:s"); + $sql = << $this->getId(), + ':timestamp' => $timestamp ), 'column'); + return CcShowInstancesQuery::create() + ->findPk($row); + } catch (Exception $e) { + return null; + } + + } + + public function deletePossiblyInvalidInstances($p_data, $p_endDate, $isRecorded, $repeatType) + { + if ($p_data['add_show_repeats'] != $this->isRepeating()) { + //repeat option was toggled + $this->deleteAllInstances(); + } + + if ($p_data['add_show_duration'] != $this->getDuration()) { + //duration has changed + $this->updateDurationTime($p_data); + } + + if ($p_data['add_show_repeats']) { + if (($repeatType == 1 || $repeatType == 2) && + $p_data['add_show_start_date'] != $this->getStartDate()){ + + //start date has changed when repeat type is bi-weekly or monthly. + //This screws up the repeating positions of show instances, so lets + //just delete them for now. (CC-2351) + + $this->deleteAllInstances(); + } + + if ($repeatType != $this->getRepeatType()) { + //repeat type changed. + $this->deleteAllInstances(); + } else { + //repeat type is the same, check if the days of the week are the same + $repeatingDaysChanged = false; + $showDaysArray = $this->getShowDays(); + if (count($p_data['add_show_day_check']) == count($showDaysArray)) { + //same number of days checked, lets see if they are the same numbers + $intersect = array_intersect($p_data['add_show_day_check'], $showDaysArray); + if (count($intersect) != count($p_data['add_show_day_check'])) { + $repeatingDaysChanged = true; + } + } else { + $repeatingDaysChanged = true; + } + + if ($repeatingDaysChanged) { + $daysRemoved = array_diff($showDaysArray, $p_data['add_show_day_check']); + + if (count($daysRemoved) > 0) { + + $this->removeUncheckedDaysInstances($daysRemoved); + } + } + + if ($p_data['add_show_start_date'] != $this->getStartDate() + || $p_data['add_show_start_time'] != $this->getStartTime()){ + //start date/time has changed + + $newDate = strtotime($p_data['add_show_start_date']); + $oldDate = strtotime($this->getStartDate()); + if ($newDate > $oldDate) { + $this->removeAllInstancesBeforeDate($p_data['add_show_start_date']); + } + + $this->updateStartDateTime($p_data, $p_endDate); + } + } + + //Check if end date for the repeat option has changed. If so, need to take care + //of deleting possible invalid Show Instances. + if ((strlen($this->getRepeatingEndDate()) == 0) == $p_data['add_show_no_end']) { + //show "Never Ends" option was toggled. + if ($p_data['add_show_no_end']) { + } else { + $this->removeAllInstancesFromDate($p_endDate); + } + } + if ($this->getRepeatingEndDate() != $p_data['add_show_end_date']) { + //end date was changed. + + $newDate = strtotime($p_data['add_show_end_date']); + $oldDate = strtotime($this->getRepeatingEndDate()); + if ($newDate < $oldDate) { + $this->removeAllInstancesFromDate($p_endDate); + } + } + } + } + + /** + * Create a show. + * + * Note: end dates are non inclusive. + * + * @param array $data + * @return int + * Show ID + */ + public static function create($data) + { + $startDateTime = new DateTime($data['add_show_start_date']." ".$data['add_show_start_time']); + $utcStartDateTime = clone $startDateTime; + $utcStartDateTime->setTimezone(new DateTimeZone('UTC')); + + if ($data['add_show_no_end']) { + $endDate = NULL; + } elseif ($data['add_show_repeats']) { + $endDateTime = new DateTime($data['add_show_end_date']); + //$endDateTime->setTimezone(new DateTimeZone('UTC')); + $endDateTime->add(new DateInterval("P1D")); + $endDate = $endDateTime->format("Y-m-d"); + } else { + $endDateTime = new DateTime($data['add_show_start_date']); + //$endDateTime->setTimezone(new DateTimeZone('UTC')); + $endDateTime->add(new DateInterval("P1D")); + $endDate = $endDateTime->format("Y-m-d"); + } + + //What we are doing here is checking if the show repeats or if + //any repeating days have been checked. If not, then by default + //the "selected" DOW is the initial day. + //DOW in local time. + $startDow = date("w", $startDateTime->getTimestamp()); + if (!$data['add_show_repeats']) { + $data['add_show_day_check'] = array($startDow); + } elseif ($data['add_show_repeats'] && $data['add_show_day_check'] == "") { + $data['add_show_day_check'] = array($startDow); + } + + //find repeat type or set to a non repeating show. + $repeatType = ($data['add_show_repeats']) ? $data['add_show_repeat_type'] : -1; + + if ($data['add_show_id'] == -1) { + $ccShow = new CcShow(); + } else { + $ccShow = CcShowQuery::create()->findPK($data['add_show_id']); + } + $ccShow->setDbName($data['add_show_name']); + $ccShow->setDbDescription($data['add_show_description']); + $ccShow->setDbUrl($data['add_show_url']); + $ccShow->setDbGenre($data['add_show_genre']); + $ccShow->setDbColor($data['add_show_color']); + $ccShow->setDbBackgroundColor($data['add_show_background_color']); + $ccShow->setDbLiveStreamUsingAirtimeAuth($data['cb_airtime_auth'] == 1); + $ccShow->setDbLiveStreamUsingCustomAuth($data['cb_custom_auth'] == 1); + $ccShow->setDbLiveStreamUser($data['custom_username']); + $ccShow->setDbLiveStreamPass($data['custom_password']); + $ccShow->save(); + + $showId = $ccShow->getDbId(); + + $isRecorded = (isset($data['add_show_record']) && $data['add_show_record']) ? 1 : 0; + + if ($data['add_show_id'] != -1) { + $show = new Application_Model_Show($showId); + $show->deletePossiblyInvalidInstances($data, $endDate, $isRecorded, $repeatType); + } + + //check if we are adding or updating a show, and if updating + //erase all the show's show_days information first. + if ($data['add_show_id'] != -1) { + CcShowDaysQuery::create()->filterByDbShowId($data['add_show_id'])->delete(); + } + + //don't set day for monthly repeat type, it's invalid. + if ($data['add_show_repeats'] && $data['add_show_repeat_type'] == 2) { + $showDay = new CcShowDays(); + $showDay->setDbFirstShow($startDateTime->format("Y-m-d")); + $showDay->setDbLastShow($endDate); + $showDay->setDbStartTime($startDateTime->format("H:i:s")); + $showDay->setDbTimezone(date_default_timezone_get()); + $showDay->setDbDuration($data['add_show_duration']); + $showDay->setDbRepeatType($repeatType); + $showDay->setDbShowId($showId); + $showDay->setDbRecord($isRecorded); + $showDay->save(); + } else { + foreach ($data['add_show_day_check'] as $day) { + $daysAdd=0; + $startDateTimeClone = clone $startDateTime; + if ($startDow !== $day) { + if ($startDow > $day) + $daysAdd = 6 - $startDow + 1 + $day; + else + $daysAdd = $day - $startDow; + + $startDateTimeClone->add(new DateInterval("P".$daysAdd."D")); + } + if (is_null($endDate) || $startDateTimeClone->getTimestamp() <= $endDateTime->getTimestamp()) { + $showDay = new CcShowDays(); + $showDay->setDbFirstShow($startDateTimeClone->format("Y-m-d")); + $showDay->setDbLastShow($endDate); + $showDay->setDbStartTime($startDateTimeClone->format("H:i")); + $showDay->setDbTimezone(date_default_timezone_get()); + $showDay->setDbDuration($data['add_show_duration']); + $showDay->setDbDay($day); + $showDay->setDbRepeatType($repeatType); + $showDay->setDbShowId($showId); + $showDay->setDbRecord($isRecorded); + $showDay->save(); + } + } + } + + //check if we are adding or updating a show, and if updating + //erase all the show's future show_rebroadcast information first. + if (($data['add_show_id'] != -1) && isset($data['add_show_rebroadcast']) && $data['add_show_rebroadcast']) { + CcShowRebroadcastQuery::create() + ->filterByDbShowId($data['add_show_id']) + ->delete(); + } + //adding rows to cc_show_rebroadcast + /* TODO: Document magic constant 10 and define it properly somewhere + --RG */ + if (($isRecorded && $data['add_show_rebroadcast']) && ($repeatType != -1)) { + for ($i=1; $i<=10; $i++) { + if ($data['add_show_rebroadcast_date_'.$i]) { + $showRebroad = new CcShowRebroadcast(); + $showRebroad->setDbDayOffset($data['add_show_rebroadcast_date_'.$i]); + $showRebroad->setDbStartTime($data['add_show_rebroadcast_time_'.$i]); + $showRebroad->setDbShowId($showId); + $showRebroad->save(); + } + } + } elseif ($isRecorded && $data['add_show_rebroadcast'] && ($repeatType == -1)) { + for ($i=1; $i<=10; $i++) { + if ($data['add_show_rebroadcast_date_absolute_'.$i]) { + //$con = Propel::getConnection(CcShowPeer::DATABASE_NAME); + //$sql = "SELECT date '{$data['add_show_rebroadcast_date_absolute_'.$i]}' - date '{$data['add_show_start_date']}' "; + $sql = << + $data["add_show_rebroadcast_date_absolute_$i"], + 'start' => + $data['add_show_start_date']), "column" ); + + //$r = $con->query($sql); + //$offset_days = $r->fetchColumn(0); + + $showRebroad = new CcShowRebroadcast(); + $showRebroad->setDbDayOffset($offset_days." days"); + $showRebroad->setDbStartTime($data['add_show_rebroadcast_time_absolute_'.$i]); + $showRebroad->setDbShowId($showId); + $showRebroad->save(); + } + } + } + + //check if we are adding or updating a show, and if updating + //erase all the show's show_rebroadcast information first. + if ($data['add_show_id'] != -1) { + CcShowHostsQuery::create()->filterByDbShow($data['add_show_id'])->delete(); + } + if (is_array($data['add_show_hosts'])) { + //add selected hosts to cc_show_hosts table. + foreach ($data['add_show_hosts'] as $host) { + $showHost = new CcShowHosts(); + $showHost->setDbShow($showId); + $showHost->setDbHost($host); + $showHost->save(); + } + } + + if ($data['add_show_id'] != -1) { + $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME); + $con->beginTransaction(); + + + //current timesamp in UTC. + $current_timestamp = gmdate("Y-m-d H:i:s"); + + try { + //update the status flag in cc_schedule. + $instances = CcShowInstancesQuery::create() + ->filterByDbEnds($current_timestamp, Criteria::GREATER_THAN) + ->filterByDbShowId($data['add_show_id']) + ->find($con); + + foreach ($instances as $instance) { + $instance->updateScheduleStatus($con); + } + + $con->commit(); + } catch (Exception $e) { + $con->rollback(); + Logging::info("Couldn't update schedule status."); + Logging::info($e->getMessage()); + } + } + + Application_Model_Show::populateShowUntil($showId); + Application_Model_RabbitMq::PushSchedule(); + + return $showId; + } + + /** + * Generate repeating show instances for a single show up to the given date. + * It will always try to use enddate from DB but if that's empty, it will use + * time now. + * + * @param int $p_showId + */ + public static function populateShowUntil($p_showId) + { + $con = Propel::getConnection(); + $date = Application_Model_Preference::GetShowsPopulatedUntil(); + + if (is_null($date)) { + $p_populateUntilDateTime = new DateTime("now", new DateTimeZone('UTC')); + Application_Model_Preference::SetShowsPopulatedUntil($p_populateUntilDateTime); + } else { + $p_populateUntilDateTime = $date; + } + + $stmt = $con->prepare("SELECT * FROM cc_show_days WHERE show_id = :show_id"); + $stmt->bindParam(':show_id', $p_showId); + $stmt->execute(); + + $res = $stmt->fetchAll(); + + foreach ($res as $showDaysRow) { + Application_Model_Show::populateShow($showDaysRow, $p_populateUntilDateTime); + } + } + + /** + * We are going to use cc_show_days as a template, to generate Show Instances. This function + * is basically a dispatcher that looks at the show template, and sends it to the correct function + * so that Show Instance generation can begin. After the all show instances have been created, pushes + * the schedule to Pypo. + * + * @param array $p_showRow + * A row from cc_show_days table + * @param DateTime $p_populateUntilDateTime + * DateTime object in UTC time. + */ + private static function populateShow($p_showDaysRow, $p_populateUntilDateTime) + { + // TODO : use constants instead of int values here? or maybe php will + // get enum types by the time somebody gets around to fix this. -- RG + if ($p_showDaysRow["repeat_type"] == -1) { + Application_Model_Show::populateNonRepeatingShow($p_showDaysRow, $p_populateUntilDateTime); + } elseif ($p_showDaysRow["repeat_type"] == 0) { + Application_Model_Show::populateRepeatingShow($p_showDaysRow, $p_populateUntilDateTime, 'P7D'); + } elseif ($p_showDaysRow["repeat_type"] == 1) { + Application_Model_Show::populateRepeatingShow($p_showDaysRow, $p_populateUntilDateTime, 'P14D'); + } elseif ($p_showDaysRow["repeat_type"] == 2) { + Application_Model_Show::populateRepeatingShow($p_showDaysRow, $p_populateUntilDateTime, 'P1M'); + } + Application_Model_RabbitMq::PushSchedule(); + } + + /** + * Creates a single show instance. If the show is recorded, it may have multiple + * rebroadcast dates, and so this function will create those as well. + * + * @param array $p_showRow + * A row from cc_show_days table + * @param DateTime $p_populateUntilDateTime + * DateTime object in UTC time. + */ + private static function populateNonRepeatingShow($p_showRow, $p_populateUntilDateTime) + { + $show_id = $p_showRow["show_id"]; + $first_show = $p_showRow["first_show"]; //non-UTC + $start_time = $p_showRow["start_time"]; //non-UTC + $duration = $p_showRow["duration"]; + $record = $p_showRow["record"]; + $timezone = $p_showRow["timezone"]; + $start = $first_show." ".$start_time; + + //start & end UTC DateTimes for the show. + list($utcStartDateTime, $utcEndDateTime) = Application_Model_Show::createUTCStartEndDateTime($start, $duration, $timezone); + if ($utcStartDateTime->getTimestamp() < $p_populateUntilDateTime->getTimestamp()) { + $currentUtcTimestamp = gmdate("Y-m-d H:i:s"); + + $show = new Application_Model_Show($show_id); + if ($show->hasInstance()) { + $ccShowInstance = $show->getInstance(); + $newInstance = false; + } else { + $ccShowInstance = new CcShowInstances(); + $newInstance = true; + } + + if ($newInstance || $ccShowInstance->getDbStarts() > $currentUtcTimestamp) { + $ccShowInstance->setDbShowId($show_id); + $ccShowInstance->setDbStarts($utcStartDateTime); + $ccShowInstance->setDbEnds($utcEndDateTime); + $ccShowInstance->setDbRecord($record); + $ccShowInstance->save(); + } + + $show_instance_id = $ccShowInstance->getDbId(); + $showInstance = new Application_Model_ShowInstance($show_instance_id); + + if (!$newInstance) { + $showInstance->correctScheduleStartTimes(); + } + + $sql = "SELECT * FROM cc_show_rebroadcast WHERE show_id=:show_id"; + $rebroadcasts = Application_Common_Database::prepareAndExecute($sql, + array( ':show_id' => $show_id ), 'all'); + + if ($showInstance->isRecorded()) { + $showInstance->deleteRebroadcasts(); + self::createRebroadcastInstances($rebroadcasts, $currentUtcTimestamp, $show_id, $show_instance_id, $start, $duration, $timezone); + } + } + } + + /** + * Creates a 1 or more than 1 show instances (user has stated this show repeats). If the show + * is recorded, it may have multiple rebroadcast dates, and so this function will create + * those as well. + * + * @param array $p_showRow + * A row from cc_show_days table + * @param DateTime $p_populateUntilDateTime + * DateTime object in UTC time. "shows_populated_until" date YY-mm-dd in cc_pref + * @param string $p_interval + * Period of time between repeating shows (in php DateInterval notation 'P7D') + */ + private static function populateRepeatingShow($p_showDaysRow, $p_populateUntilDateTime, $p_interval) + { + $show_id = $p_showDaysRow["show_id"]; + $next_pop_date = $p_showDaysRow["next_pop_date"]; + $first_show = $p_showDaysRow["first_show"]; //non-UTC + $last_show = $p_showDaysRow["last_show"]; //non-UTC + $start_time = $p_showDaysRow["start_time"]; //non-UTC + $duration = $p_showDaysRow["duration"]; + $day = $p_showDaysRow["day"]; + $record = $p_showDaysRow["record"]; + $timezone = $p_showDaysRow["timezone"]; + + $currentUtcTimestamp = gmdate("Y-m-d H:i:s"); + + if (isset($next_pop_date)) { + $start = $next_pop_date." ".$start_time; + } else { + $start = $first_show." ".$start_time; + } + + $utcStartDateTime = Application_Common_DateHelper::ConvertToUtcDateTime($start, $timezone); + //convert $last_show into a UTC DateTime object, or null if there is no last show. + $utcLastShowDateTime = $last_show ? Application_Common_DateHelper::ConvertToUtcDateTime($last_show, $timezone) : null; + + $sql = "SELECT * FROM cc_show_rebroadcast WHERE show_id=:show_id"; + + $rebroadcasts = Application_Common_Database::prepareAndExecute( $sql, + array( ':show_id' => $show_id ), 'all'); + + $show = new Application_Model_Show($show_id); + + while ($utcStartDateTime->getTimestamp() <= $p_populateUntilDateTime->getTimestamp() + && (is_null($utcLastShowDateTime) || $utcStartDateTime->getTimestamp() < $utcLastShowDateTime->getTimestamp())){ + + list($utcStartDateTime, $utcEndDateTime) = self::createUTCStartEndDateTime($start, $duration, $timezone); + + if ($show->hasInstanceOnDate($utcStartDateTime)) { + $ccShowInstance = $show->getInstanceOnDate($utcStartDateTime); + + if ($ccShowInstance->getDbModifiedInstance()) { + //show instance on this date has been deleted. + list($start, $utcStartDateTime) = self::advanceRepeatingDate($p_interval, $start, $timezone); + continue; + } + + $newInstance = false; + } else { + $ccShowInstance = new CcShowInstances(); + $newInstance = true; + } + + /* When editing the start/end time of a repeating show, we don't want to + * change shows that started in the past. So check the start time. + */ + if ($newInstance || $ccShowInstance->getDbStarts() > $currentUtcTimestamp) { + $ccShowInstance->setDbShowId($show_id); + $ccShowInstance->setDbStarts($utcStartDateTime); + $ccShowInstance->setDbEnds($utcEndDateTime); + $ccShowInstance->setDbRecord($record); + $ccShowInstance->save(); + } + + + $show_instance_id = $ccShowInstance->getDbId(); + $showInstance = new Application_Model_ShowInstance($show_instance_id); + + /* If we are updating a show then make sure that the scheduled content within + * the show is updated to the correct time. */ + if (!$newInstance) { + $showInstance->correctScheduleStartTimes(); + } + + $showInstance->deleteRebroadcasts(); + self::createRebroadcastInstances($rebroadcasts, $currentUtcTimestamp, $show_id, $show_instance_id, $start, $duration, $timezone); + list($start, $utcStartDateTime) = self::advanceRepeatingDate($p_interval, $start, $timezone); + + } + + Application_Model_Show::setNextPop($start, $show_id, $day); + } + + private static function advanceRepeatingDate($p_interval, $start, $timezone) + { + $startDt = new DateTime($start, new DateTimeZone($timezone)); + if ($p_interval == 'P1M') { + /* When adding months, there is a problem if we are on January 31st and add one month with PHP. + * What ends up happening is that since February 31st doesn't exist, the date returned is + * March 3rd. For now let's ignore the day and assume we are always working with the + * first of each month, and use PHP to add 1 month to this (this will take care of rolling + * over the years 2011->2012, etc.). Then let's append the actual day, and use the php + * checkdate() function, to see if it is valid. If not, then we'll just skip this month. */ + + /* pass in only the year and month (not the day) */ + $dt = new DateTime($startDt->format("Y-m"), new DateTimeZone($timezone)); + + + /* Keep adding 1 month, until we find the next month that contains the day + * we are looking for (31st day for example) */ + do { + $dt->add(new DateInterval($p_interval)); + } while (!checkdate($dt->format("m"), $startDt->format("d"), $dt->format("Y"))); + + $dt->setDate($dt->format("Y"), $dt->format("m"), $startDt->format("d")); + + } else { + $dt = new DateTime($start, new DateTimeZone($timezone)); + $dt->add(new DateInterval($p_interval)); + } + + $start = $dt->format("Y-m-d H:i:s"); + + $dt->setTimezone(new DateTimeZone('UTC')); + $utcStartDateTime = $dt; + + return array($start, $utcStartDateTime); + } + + /* + * @param $p_start + * timestring format "Y-m-d H:i:s" (not UTC) + * @param $p_duration + * string time interval (h)h:(m)m(:ss) + * @param $p_timezone + * string "Europe/Prague" + * @param $p_offset + * array (days, hours, mins) used for rebroadcast shows. + * + * @return + * array of 2 DateTime objects, start/end time of the show in UTC. + */ + private static function createUTCStartEndDateTime($p_start, $p_duration, $p_timezone=null, $p_offset=null) + { + $timezone = $p_timezone ? $p_timezone : date_default_timezone_get(); + + $startDateTime = new DateTime($p_start, new DateTimeZone($timezone)); + if (isset($p_offset)) { + $startDateTime->add(new DateInterval("P{$p_offset["days"]}DT{$p_offset["hours"]}H{$p_offset["mins"]}M")); + } + //convert time to UTC + $startDateTime->setTimezone(new DateTimeZone('UTC')); + + $endDateTime = clone $startDateTime; + $duration = explode(":", $p_duration); + list($hours, $mins) = array_slice($duration, 0, 2); + $endDateTime->add(new DateInterval("PT{$hours}H{$mins}M")); + + return array($startDateTime, $endDateTime); + } + + /* Create rebroadcast instances for a created show marked for recording + * + * @param $p_rebroadcasts + * rows gotten from the db table cc_show_rebroadcasts, tells airtime when to schedule the rebroadcasts. + * @param $p_currentUtcTimestamp + * a timestring in format "Y-m-d H:i:s", current UTC time. + * @param $p_showId + * int of the show it belongs to (from cc_show) + * @param $p_showInstanceId + * the instance id of the created recorded show instance + * (from cc_show_instances), used to associate rebroadcasts to this show. + * @param $p_startTime + * a timestring in format "Y-m-d H:i:s" in the timezone, not UTC of the rebroadcasts' parent recorded show. + * @param $p_duration + * string time interval (h)h:(m)m:(ss) length of the show. + * @param $p_timezone + * string of user's timezone "Europe/Prague" + * + */ + private static function createRebroadcastInstances($p_rebroadcasts, $p_currentUtcTimestamp, $p_showId, $p_showInstanceId, $p_startTime, $p_duration, $p_timezone=null) + { + //Y-m-d + //use only the date part of the show start time stamp for the offsets to work properly. + $date = explode(" ", $p_startTime); + $start_date = $date[0]; + + foreach ($p_rebroadcasts as $rebroadcast) { + + $days = explode(" ", $rebroadcast["day_offset"]); + $time = explode(":", $rebroadcast["start_time"]); + $offset = array("days"=>$days[0], "hours"=>$time[0], "mins"=>$time[1]); + + list($utcStartDateTime, $utcEndDateTime) = Application_Model_Show::createUTCStartEndDateTime($start_date, $p_duration, $p_timezone, $offset); + + if ($utcStartDateTime->format("Y-m-d H:i:s") > $p_currentUtcTimestamp) { + + $newRebroadcastInstance = new CcShowInstances(); + $newRebroadcastInstance->setDbShowId($p_showId); + $newRebroadcastInstance->setDbStarts($utcStartDateTime); + $newRebroadcastInstance->setDbEnds($utcEndDateTime); + $newRebroadcastInstance->setDbRecord(0); + $newRebroadcastInstance->setDbRebroadcast(1); + $newRebroadcastInstance->setDbOriginalShow($p_showInstanceId); + $newRebroadcastInstance->save(); + } + } + } + + /** + * Get all the show instances in the given time range (inclusive). + * + * @param DateTime $start_timestamp + * In UTC time. + * @param DateTime $end_timestamp + * In UTC time. + * @param unknown_type $excludeInstance + * @param boolean $onlyRecord + * @return array + */ + public static function getShows($start_timestamp, $end_timestamp, $onlyRecord=FALSE) + { + //UTC DateTime object + $showsPopUntil = Application_Model_Preference::GetShowsPopulatedUntil(); + //if application is requesting shows past our previous populated until date, generate shows up until this point. + if (is_null($showsPopUntil) || $showsPopUntil->getTimestamp() < $end_timestamp->getTimestamp()) { + Application_Model_Show::populateAllShowsInRange($showsPopUntil, $end_timestamp); + Application_Model_Preference::SetShowsPopulatedUntil($end_timestamp); + } + + $sql = <<format("Y-m-d H:i:s"); + $end_string = $end_timestamp->format("Y-m-d H:i:s"); + if ($onlyRecord) { + $sql .= " AND (si1.starts >= :start::TIMESTAMP AND si1.starts < :end::TIMESTAMP)"; + $sql .= " AND (si1.record = 1)"; + + return Application_Common_Database::prepareAndExecute( $sql, + array( ':start' => $start_string, + ':end' => $end_string ), 'all'); + + } else { + $sql .= " ". <<= :start1::TIMESTAMP AND si1.starts < :end1::TIMESTAMP) + OR (si1.ends > :start2::TIMESTAMP AND si1.ends <= :end2::TIMESTAMP) + OR (si1.starts <= :start3::TIMESTAMP AND si1.ends >= :end3::TIMESTAMP)) +SQL; + return Application_Common_Database::prepareAndExecute( $sql, + array( + 'start1' => $start_string, + 'start2' => $start_string, + 'start3' => $start_string, + 'end1' => $end_string, + 'end2' => $end_string, + 'end3' => $end_string + ), 'all'); + } + } + + private static function setNextPop($next_date, $show_id, $day) + { + $nextInfo = explode(" ", $next_date); + + $repeatInfo = CcShowDaysQuery::create() + ->filterByDbShowId($show_id) + ->filterByDbDay($day) + ->findOne(); + + $repeatInfo->setDbNextPopDate($nextInfo[0]) + ->save(); + } + + /** + * Generate all the repeating shows in the given range. + * + * @param DateTime $p_startTimestamp + * In UTC format. + * @param DateTime $p_endTimestamp + * In UTC format. + */ + public static function populateAllShowsInRange($p_startTimestamp, $p_endTimestamp) + { + $con = Propel::getConnection(); + + $endTimeString = $p_endTimestamp->format("Y-m-d H:i:s"); + if (!is_null($p_startTimestamp)) { + $startTimeString = $p_startTimestamp->format("Y-m-d H:i:s"); + } else { + $today_timestamp = new DateTime("now", new DateTimeZone("UTC")); + $startTimeString = $today_timestamp->format("Y-m-d H:i:s"); + } + + $stmt = $con->prepare(" + SELECT * FROM cc_show_days + WHERE last_show IS NULL + OR first_show < :endTimeString AND last_show > :startTimeString"); + + $stmt->bindParam(':endTimeString', $endTimeString); + $stmt->bindParam(':startTimeString', $startTimeString); + $stmt->execute(); + + $res = $stmt->fetchAll(); + foreach ($res as $row) { + Application_Model_Show::populateShow($row, $p_endTimestamp); + } + } + + /** + * + * @param DateTime $start + * -in UTC time + * @param DateTime $end + * -in UTC time + * @param boolean $editable + */ + public static function &getFullCalendarEvents($p_start, $p_end, $p_editable=false) + { + $events = array(); + $interval = $p_start->diff($p_end); + $days = $interval->format('%a'); + $shows = Application_Model_Show::getShows($p_start, $p_end); + $content_count = Application_Model_ShowInstance::getContentCount( + $p_start, $p_end); + $isFull = Application_Model_ShowInstance::getIsFull($p_start, $p_end); + $timezone = date_default_timezone_get(); + $current_timezone = new DateTimeZone($timezone); + $utc = new DateTimeZone("UTC"); + $now = new DateTime("now", $utc); + + foreach ($shows as &$show) { + $options = array(); + + //only bother calculating percent for week or day view. + if (intval($days) <= 7) { + $options["percent"] = Application_Model_Show::getPercentScheduled($show["starts"], $show["ends"], $show["time_filled"]); + } + + if (isset($show["parent_starts"])) { + $parentStartsDT = new DateTime($show["parent_starts"], $utc); + } + + $startsDT = DateTime::createFromFormat("Y-m-d G:i:s", + $show["starts"],$utc); + $endsDT = DateTime::createFromFormat("Y-m-d G:i:s", + $show["ends"], $utc); + + if( $p_editable ) { + if ($show["record"] && $now > $startsDT) { + $options["editable"] = false; + } elseif ($show["rebroadcast"] && + $now > $parentStartsDT) { + $options["editable"] = false; + } elseif ($now < $endsDT) { + $options["editable"] = true; + } + } + + $startsDT->setTimezone($current_timezone); + $endsDT->setTimezone($current_timezone); + + $options["show_empty"] = (array_key_exists($show['instance_id'], + $content_count)) ? 0 : 1; + + $options["show_partial_filled"] = !$isFull[$show['instance_id']]; + + $event = array(); + + $event["id"] = intval($show["instance_id"]); + $event["title"] = $show["name"]; + $event["start"] = $startsDT->format("Y-m-d H:i:s"); + $event["end"] = $endsDT->format("Y-m-d H:i:s"); + $event["allDay"] = false; + $event["showId"] = intval($show["show_id"]); + $event["record"] = intval($show["record"]); + $event["rebroadcast"] = intval($show["rebroadcast"]); + $event["soundcloud_id"] = is_null($show["soundcloud_id"]) + ? -1 : $show["soundcloud_id"]; + + //event colouring + if ($show["color"] != "") { + $event["textColor"] = "#".$show["color"]; + } + + if ($show["background_color"] != "") { + $event["color"] = "#".$show["background_color"]; + } + + foreach ($options as $key => $value) { + $event[$key] = $value; + } + + $events[] = $event; + } + return $events; + } + + /** + * Calculates the percentage of a show scheduled given the start and end times in date/time format + * and the time_filled as the total time the schow is scheduled for in time format. + **/ + private static function getPercentScheduled($p_starts, $p_ends, $p_time_filled) + { + $durationSeconds = (strtotime($p_ends) - strtotime($p_starts)); + $time_filled = Application_Model_Schedule::WallTimeToMillisecs($p_time_filled) / 1000; + $percent = ceil(( $time_filled / $durationSeconds) * 100); + + return $percent; + } + +/* private static function &makeFullCalendarEvent(&$show, $options=array(), $startDateTime, $endDateTime, $startsEpoch, $endsEpoch) + { + $event = array(); + + $event["id"] = intval($show["instance_id"]); + $event["title"] = $show["name"]; + $event["start"] = $startDateTime->format("Y-m-d H:i:s"); + $event["startUnix"] = $startsEpoch; + $event["end"] = $endDateTime->format("Y-m-d H:i:s"); + $event["endUnix"] = $endsEpoch; + $event["allDay"] = false; + $event["showId"] = intval($show["show_id"]); + $event["record"] = intval($show["record"]); + $event["rebroadcast"] = intval($show["rebroadcast"]); + $event["soundcloud_id"] = is_null($show["soundcloud_id"]) + ? -1 : $show["soundcloud_id"]; + + //event colouring + if ($show["color"] != "") { + $event["textColor"] = "#".$show["color"]; + } + + if ($show["background_color"] != "") { + $event["color"] = "#".$show["background_color"]; + } + + foreach ($options as $key => $value) { + $event[$key] = $value; + } + + return $event; + }*/ + + /* Takes in a UTC DateTime object. + * Converts this to local time, since cc_show days + * requires local time. */ + public function setShowFirstShow($p_dt) + { + //clone object since we are modifying it and it was passed by reference. + $dt = clone $p_dt; + + $dt->setTimezone(new DateTimeZone(date_default_timezone_get())); + + $showDay = CcShowDaysQuery::create() + ->filterByDbShowId($this->_showId) + ->findOne(); + + $showDay->setDbFirstShow($dt)->setDbStartTime($dt) + ->save(); + + //Logging::info("setting show's first show."); + } + + /* Takes in a UTC DateTime object + * Converts this to local time, since cc_show days + * requires local time. */ + public function setShowLastShow($p_dt) + { + //clone object since we are modifying it and it was passed by reference. + $dt = clone $p_dt; + + $dt->setTimezone(new DateTimeZone(date_default_timezone_get())); + + //add one day since the Last Show date in CcShowDays is non-inclusive. + $dt->add(new DateInterval("P1D")); + + $showDay = CcShowDaysQuery::create() + ->filterByDbShowId($this->_showId) + ->findOne(); + + $showDay->setDbLastShow($dt) + ->save(); + } + + /** + * Given time $timeNow, returns the show being played right now. + * Times are all in UTC time. + * + * @param String $timeNow - current time (in UTC) + * @return array - show being played right now + */ + public static function getCurrentShow($timeNow=null) + { + $CC_CONFIG = Config::getConfig(); + $con = Propel::getConnection(); + if ($timeNow == null) { + $date = new Application_Common_DateHelper; + $timeNow = $date->getUtcTimestamp(); + } + //TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin + $sql = << :timeNow2::timestamp + AND modified_instance != TRUE +SQL; + + $stmt = $con->prepare($sql); + $stmt->bindParam(':timeNow1', $timeNow); + $stmt->bindParam(':timeNow2', $timeNow); + + if ($stmt->execute()) { + $rows = $stmt->fetchAll(); + } else { + $msg = implode(',', $stmt->errorInfo()); + throw new Exception("Error: $msg"); + } + + return $rows; + } + + /** + * Gets the current show, previous and next with an 2day window from + * the given timeNow, so timeNow-2days and timeNow+2days. + */ + public static function getPrevCurrentNext($p_timeNow) + { + $CC_CONFIG = Config::getConfig(); + $con = Propel::getConnection(); + // + //TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin + $sql = << :timeNow1::timestamp - INTERVAL '2 days' + AND si.ends < :timeNow2::timestamp + INTERVAL '2 days' + AND modified_instance != TRUE +ORDER BY si.starts +SQL; + + $stmt = $con->prepare($sql); + + $stmt->bindValue(':timeNow1', $p_timeNow); + $stmt->bindValue(':timeNow2', $p_timeNow); + + if ($stmt->execute()) { + $rows = $stmt->fetchAll(); + } else { + $msg = implode(',', $stmt->errorInfo()); + throw new Exception("Error: $msg"); + } + + $numberOfRows = count($rows); + + $results['previousShow'] = array(); + $results['currentShow'] = array(); + $results['nextShow'] = array(); + + $timeNowAsMillis = strtotime($p_timeNow); + + for ($i = 0; $i < $numberOfRows; ++$i) { + //Find the show that is within the current time. + if ((strtotime($rows[$i]['starts']) <= $timeNowAsMillis) + && (strtotime($rows[$i]['ends']) > $timeNowAsMillis)) { + if ($i-1 >= 0) { + $results['previousShow'][0] = array( + "id" => $rows[$i-1]['id'], + "instance_id" => $rows[$i-1]['instance_id'], + "name" => $rows[$i-1]['name'], + "url" => $rows[$i-1]['url'], + "start_timestamp" => $rows[$i-1]['start_timestamp'], + "end_timestamp" => $rows[$i-1]['end_timestamp'], + "starts" => $rows[$i-1]['starts'], + "ends" => $rows[$i-1]['ends'], + "record" => $rows[$i-1]['record'], + "type" => "show"); + } + + $results['currentShow'][0] = $rows[$i]; + + if (isset($rows[$i+1])) { + $results['nextShow'][0] = array( + "id" => $rows[$i+1]['id'], + "instance_id" => $rows[$i+1]['instance_id'], + "name" => $rows[$i+1]['name'], + "url" => $rows[$i+1]['url'], + "start_timestamp" => $rows[$i+1]['start_timestamp'], + "end_timestamp" => $rows[$i+1]['end_timestamp'], + "starts" => $rows[$i+1]['starts'], + "ends" => $rows[$i+1]['ends'], + "record" => $rows[$i+1]['record'], + "type" => "show"); + } + break; + } + //Previous is any row that ends after time now capture it in case we need it later. + if (strtotime($rows[$i]['ends']) < $timeNowAsMillis ) { + $previousShowIndex = $i; + } + //if we hit this we know we've gone to far and can stop looping. + if (strtotime($rows[$i]['starts']) > $timeNowAsMillis) { + $results['nextShow'][0] = array( + "id" => $rows[$i]['id'], + "instance_id" => $rows[$i]['instance_id'], + "name" => $rows[$i]['name'], + "url" => $rows[$i]['url'], + "start_timestamp" => $rows[$i]['start_timestamp'], + "end_timestamp" => $rows[$i]['end_timestamp'], + "starts" => $rows[$i]['starts'], + "ends" => $rows[$i]['ends'], + "record" => $rows[$i]['record'], + "type" => "show"); + break; + } + } + //If we didn't find a a current show because the time didn't fit we may still have + //found a previous show so use it. + if (count($results['previousShow']) == 0 && isset($previousShowIndex)) { + $results['previousShow'][0] = array( + "id" => $rows[$previousShowIndex]['id'], + "instance_id" => $rows[$previousShowIndex]['instance_id'], + "name" => $rows[$previousShowIndex]['name'], + "start_timestamp" => $rows[$previousShowIndex]['start_timestamp'], + "end_timestamp" => $rows[$previousShowIndex]['end_timestamp'], + "starts" => $rows[$previousShowIndex]['starts'], + "ends" => $rows[$previousShowIndex]['ends'], + "record" => $rows[$previousShowIndex]['record'], + "type" => "show"); + } + + return $results; + } + + /** + * Given a start time $timeStart and end time $timeEnd, returns the next $limit + * number of shows within the time interval + * If $timeEnd not given, shows within next 48 hours from $timeStart are returned + * If $limit not given, all shows within the intervals are returned + * Times are all in UTC time. + * + * @param String $timeStart - interval start time (in UTC) + * @param int $limit - number of shows to return + * @param String $timeEnd - interval end time (in UTC) + * @return array - the next $limit number of shows within the time interval + */ + public static function getNextShows($timeStart, $limit = "ALL", $timeEnd = "") + { + // defaults to retrieving shows from next 2 days if no end time has + // been specified + if ($timeEnd == "") { + $timeEnd = "'$timeStart' + INTERVAL '2 days'"; + } + + //TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin + $sql = <<= :timeStart::timestamp + AND si.starts < :timeEnd::timestamp + AND modified_instance != TRUE +ORDER BY si.starts +SQL; + + //PDO won't accept "ALL" as a limit value (complains it is not an + //integer, and so we must completely remove the limit clause if we + //want to show all results - MK + if ($limit != "ALL") { + $sql .= PHP_EOL."LIMIT :lim"; + $params = array( + ':timeStart' => $timeStart, + ':timeEnd' => $timeEnd, + ':lim' => $limit); + } else { + $params = array( + ':timeStart' => $timeStart, + ':timeEnd' => $timeEnd); + } + + return Application_Common_Database::prepareAndExecute( $sql, $params, 'all'); + } + + /** + * Convert the columns given in the array $columnsToConvert in the + * database result $rows to local timezone. + * + * @param type $rows arrays of arrays containing database query result + * @param type $columnsToConvert array of column names to convert + */ + public static function convertToLocalTimeZone(&$rows, $columnsToConvert) + { + if (!is_array($rows)) { + return; + } + foreach ($rows as &$row) { + foreach ($columnsToConvert as $column) { + $row[$column] = Application_Common_DateHelper::ConvertToLocalDateTimeString($row[$column]); + } + } + } + + public static function getMaxLengths() + { + $con = Propel::getConnection(); + $sql = << 0 +SQL; + $result = $con->query($sql)->fetchAll(); + $assocArray = array(); + foreach ($result as $row) { + $assocArray[$row['column_name']] = $row['character_maximum_length']; + } + return $assocArray; + } + + public static function getStartEndCurrentMonthView() { + $first_day_of_calendar_month_view = mktime(0, 0, 0, date("n"), 1); + $weekStart = Application_Model_Preference::GetWeekStartDay(); + while (date('w', $first_day_of_calendar_month_view) != $weekStart) { + $first_day_of_calendar_month_view -= 60*60*24; + } + $last_day_of_calendar_view = $first_day_of_calendar_month_view + 3600*24*42; + + $start = new DateTime("@".$first_day_of_calendar_month_view); + $end = new DateTime("@".$last_day_of_calendar_view); + + return array($start, $end); + } + + public static function getStartEndCurrentWeekView() { + $first_day_of_calendar_week_view = mktime(0, 0, 0, date("n"), date("j")); + $weekStart = Application_Model_Preference::GetWeekStartDay(); + while (date('w', $first_day_of_calendar_week_view) != $weekStart) { + $first_day_of_calendar_week_view -= 60*60*24; + } + $last_day_of_calendar_view = $first_day_of_calendar_week_view + 3600*24*7; + + $start = new DateTime("@".$first_day_of_calendar_week_view); + $end = new DateTime("@".$last_day_of_calendar_view); + + return array($start, $end); + } + + public static function getStartEndCurrentDayView() { + $today = mktime(0, 0, 0, date("n"), date("j")); + $tomorrow = $today + 3600*24; + + $start = new DateTime("@".$today); + $end = new DateTime("@".$tomorrow); + + return array($start, $end); + } +} diff --git a/airtime_mvc/application/services/ScheduleService.php b/airtime_mvc/application/services/ScheduleService.php index 1204f689c..e8322882b 100644 --- a/airtime_mvc/application/services/ScheduleService.php +++ b/airtime_mvc/application/services/ScheduleService.php @@ -175,15 +175,18 @@ class Application_Service_ScheduleService //create ccShow $ccShow = new CcShow(); $ccShow = $service_show->setShow($ccShow, $showData); + $showId = $ccShow->getDbId(); //create ccShowDay $service_show->createShowDays( - $showData, $ccShow->getDbId(), $user->getId(), $repeatType, $isRecorded); + $showData, $showId, $user->getId(), $repeatType, $isRecorded); + + //create ccShowRebroadcast + $service_show->createShowRebroadcast($showData, $showId, $repeatType, $isRecorded); //create ccShowHosts - - //create ccShowRebroadcast - + $service_show->createShowHosts($showData, $showId); + //populate ccShowInstances } } diff --git a/airtime_mvc/application/services/ShowService.php b/airtime_mvc/application/services/ShowService.php new file mode 100644 index 000000000..458cc4bd8 --- /dev/null +++ b/airtime_mvc/application/services/ShowService.php @@ -0,0 +1,145 @@ +setDbName($showData['add_show_name']); + $ccShow->setDbDescription($showData['add_show_description']); + $ccShow->setDbUrl($showData['add_show_url']); + $ccShow->setDbGenre($showData['add_show_genre']); + $ccShow->setDbColor($showData['add_show_color']); + $ccShow->setDbBackgroundColor($showData['add_show_background_color']); + $ccShow->setDbLiveStreamUsingAirtimeAuth($showData['cb_airtime_auth'] == 1); + $ccShow->setDbLiveStreamUsingCustomAuth($showData['cb_custom_auth'] == 1); + $ccShow->setDbLiveStreamUser($showData['custom_username']); + $ccShow->setDbLiveStreamPass($showData['custom_password']); + + $ccShow->save(); + return $ccShow; + } + + /** + * Creates new cc_show_days entries + */ + public function createShowDays($showData, $showId, $userId, $repeatType, $isRecorded) + { + $startDateTime = new DateTime($showData['add_show_start_date']." ".$showData['add_show_start_time']); + + if ($showData['add_show_no_end']) { + $endDate = NULL; + } elseif ($showData['add_show_repeats']) { + $endDateTime = new DateTime($showData['add_show_end_date']); + $endDateTime->add(new DateInterval("P1D")); + $endDate = $endDateTime->format("Y-m-d"); + } else { + $endDateTime = new DateTime($showData['add_show_start_date']); + $endDateTime->add(new DateInterval("P1D")); + $endDate = $endDateTime->format("Y-m-d"); + } + + /* What we are doing here is checking if the show repeats or if + * any repeating days have been checked. If not, then by default + * the "selected" DOW is the initial day. + * DOW in local time. + */ + $startDow = date("w", $startDateTime->getTimestamp()); + if (!$showData['add_show_repeats']) { + $showData['add_show_day_check'] = array($startDow); + } elseif ($showData['add_show_repeats'] && $showData['add_show_day_check'] == "") { + $showData['add_show_day_check'] = array($startDow); + } + + // Don't set day for monthly repeat type, it's invalid + if ($showData['add_show_repeats'] && $showData['add_show_repeat_type'] == 2) { + $showDay = new CcShowDays(); + $showDay->setDbFirstShow($startDateTime->format("Y-m-d")); + $showDay->setDbLastShow($endDate); + $showDay->setDbStartTime($startDateTime->format("H:i:s")); + $showDay->setDbTimezone(Application_Model_Preference::GetUserTimezone($userId)); + $showDay->setDbDuration($showData['add_show_duration']); + $showDay->setDbRepeatType($repeatType); + $showDay->setDbShowId($showId); + $showDay->setDbRecord($isRecorded); + $showDay->save(); + } else { + foreach ($showData['add_show_day_check'] as $day) { + $daysAdd=0; + $startDateTimeClone = clone $startDateTime; + if ($startDow !== $day) { + if ($startDow > $day) + $daysAdd = 6 - $startDow + 1 + $day; + else + $daysAdd = $day - $startDow; + + $startDateTimeClone->add(new DateInterval("P".$daysAdd."D")); + } + if (is_null($endDate) || $startDateTimeClone->getTimestamp() <= $endDateTime->getTimestamp()) { + $showDay = new CcShowDays(); + $showDay->setDbFirstShow($startDateTimeClone->format("Y-m-d")); + $showDay->setDbLastShow($endDate); + $showDay->setDbStartTime($startDateTimeClone->format("H:i")); + $showDay->setDbTimezone(Application_Model_Preference::GetUserTimezone($userId)); + $showDay->setDbDuration($showData['add_show_duration']); + $showDay->setDbDay($day); + $showDay->setDbRepeatType($repeatType); + $showDay->setDbShowId($showId); + $showDay->setDbRecord($isRecorded); + $showDay->save(); + } + } + } + } + + /** + * Creates new cc_show_rebroadcast entries + */ + public function createShowRebroadcast($showData, $showId, $repeatType, $isRecorded) + { + define("MAX_REBROADCAST_DATES", 10); + + if (($isRecorded && $showData['add_show_rebroadcast']) && ($repeatType != -1)) { + for ($i=1; $i<=MAX_REBROADCAST_DATES; $i++) { + if ($showData['add_show_rebroadcast_date_'.$i]) { + $showRebroad = new CcShowRebroadcast(); + $showRebroad->setDbDayOffset($showData['add_show_rebroadcast_date_'.$i]); + $showRebroad->setDbStartTime($showData['add_show_rebroadcast_time_'.$i]); + $showRebroad->setDbShowId($showId); + $showRebroad->save(); + } + } + } elseif ($isRecorded && $showData['add_show_rebroadcast'] && ($repeatType == -1)) { + for ($i=1; $i<=MAX_REBROADCAST_DATES; $i++) { + if ($showData['add_show_rebroadcast_date_absolute_'.$i]) { + $rebroadcastDate = new DateTime($showData["add_show_rebroadcast_date_absolute_$i"]); + $startDate = new DateTime($showData['add_show_start_date']); + $offsetDays = $startDate->diff($rebroadcastDate); + + $showRebroad = new CcShowRebroadcast(); + $showRebroad->setDbDayOffset($offsetDays->format("%a days")); + $showRebroad->setDbStartTime($showData['add_show_rebroadcast_time_absolute_'.$i]); + $showRebroad->setDbShowId($showId); + $showRebroad->save(); + } + } + } + } + + /** + * Creates cc_show_hosts entries + */ + public function createShowHosts($showData, $showId) + { + if (is_array($showData['add_show_hosts'])) { + foreach ($showData['add_show_hosts'] as $host) { + $showHost = new CcShowHosts(); + $showHost->setDbShow($showId); + $showHost->setDbHost($host); + $showHost->save(); + } + } + } +} \ No newline at end of file