diff --git a/airtime_mvc/application/common/Database.php b/airtime_mvc/application/common/Database.php index 8793af03d..a90227ff6 100644 --- a/airtime_mvc/application/common/Database.php +++ b/airtime_mvc/application/common/Database.php @@ -29,4 +29,29 @@ class Application_Common_Database } return $rows; } + /* + Wrapper around prepareAndExecute that allows you to use multipe :xx's + in one query. Transforms $sql to :xx1, :xx2, .... + */ + public static function smartPrepareAndExecute($sql, array $params, + $type='all', $fetchType=PDO::FETCH_ASSOC) + { + $new_params = array(); + $new_sql = $sql; + foreach ($params as $k => $v) { + $matches_count = substr_count($sql, $k); + if ($matches_count == 0) { + throw new Exception("Argument $k is not inside $sql"); + } elseif ($matches_count == 1) { + $new_params[$k] = $new_params[$v]; + } else { + foreach ( range(1,$matches_count) as $i ) { + preg_replace( "/$k(\D)/", "$k.$i${1}", $sql, 1); + $new_params[ $k.$i ] = $v; + } + } + } + return Application_Common_Database::prepareAndExecute( $new_sql, + $new_params, $type, $fetchType); + } } diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index cd0ed19d1..8a968302c 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -371,15 +371,15 @@ class ApiController extends Zend_Controller_Action public function recordedShowsAction() { $today_timestamp = date("Y-m-d H:i:s"); - $now = new DateTime($today_timestamp); - $end_timestamp = $now->add(new DateInterval("PT2H")); - $end_timestamp = $end_timestamp->format("Y-m-d H:i:s"); + $now = new DateTime($today_timestamp); + $end_timestamp = $now->add(new DateInterval("PT2H")); + $end_timestamp = $end_timestamp->format("Y-m-d H:i:s"); $this->view->shows = Application_Model_Show::getShows( Application_Common_DateHelper::ConvertToUtcDateTime($today_timestamp, date_default_timezone_get()), Application_Common_DateHelper::ConvertToUtcDateTime($end_timestamp, date_default_timezone_get()), - $excludeInstance = null, $onlyRecord = true); + $onlyRecord = true); $this->view->is_recording = false; $this->view->server_timezone = Application_Model_Preference::GetTimezone(); diff --git a/airtime_mvc/application/models/RabbitMq.php b/airtime_mvc/application/models/RabbitMq.php index cba216f8e..797cdb145 100644 --- a/airtime_mvc/application/models/RabbitMq.php +++ b/airtime_mvc/application/models/RabbitMq.php @@ -88,7 +88,7 @@ class Application_Model_RabbitMq $temp['server_timezone'] = Application_Model_Preference::GetTimezone(); if ($event_type == "update_recorder_schedule") { $temp['shows'] = Application_Model_Show::getShows($now, - $end_timestamp, $excludeInstance=NULL, $onlyRecord=TRUE); + $end_timestamp, $onlyRecord=TRUE); } $data = json_encode($temp); $msg = new AMQPMessage($data, array('content_type' => 'text/plain')); diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php index afe6e817d..8214f4c03 100644 --- a/airtime_mvc/application/models/Show.php +++ b/airtime_mvc/application/models/Show.php @@ -84,6 +84,10 @@ class Application_Model_Show 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); @@ -178,29 +182,30 @@ class Application_Model_Show ->filterByDbShowId($this->_showId) ->find($con); - /* Check if the show being resized and any of its repeats - * overlap with other scheduled shows - */ + /* Check 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")); + $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 - */ + /* 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); + $newEndsDateTime = Application_Model_ShowInstance::addDeltas($endsDateTime, $deltaDay, $deltaMin); //convert our new starts/ends to UTC. - $newStartsDateTime->setTimezone(new DateTimeZone("UTC")); - $newEndsDateTime->setTimezone(new DateTimeZone("UTC")); + $newStartsDateTime->setTimezone($utc); + $newEndsDateTime->setTimezone($utc); + + $overlapping = Application_Model_Schedule::checkOverlappingShows( + $newStartsDateTime, $newEndsDateTime, true, $si->getDbId()); - $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."; @@ -208,39 +213,23 @@ class Application_Model_Show } $hours = $deltaMin/60; - if ($hours > 0) { - $hours = floor($hours); - } else { - $hours = ceil($hours); - } - - $mins = abs($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"); - //update all cc_show_instances that are in the future. - $sql = "UPDATE cc_show_instances - SET ends = (ends + interval '{$deltaDay} days' + interval '{$hours}:{$mins}') - WHERE (show_id = {$this->_showId} AND ends > '$current_timestamp') - AND ((ends + interval '{$deltaDay} days' + interval '{$hours}:{$mins}' - starts) <= interval '24:00');"; - - //update cc_show_days so future shows can be created with the new duration. - //only setting new duration if it is less than or equal to 24 hours. - $sql = $sql . " - UPDATE cc_show_days SET duration = (CAST(duration AS interval) + interval '{$deltaDay} days' + interval '{$hours}:{$mins}') - WHERE show_id = {$this->_showId} - AND ((CAST(duration AS interval) + interval '{$deltaDay} days' + interval '{$hours}:{$mins}') <= interval '24:00')"; - $sql_gen = << :current_timestamp1) -AND ((ends + interval :deltaDay2 + interval :interval2 - starts) <= interval '24:00') +WHERE (show_id = :show_id1 + AND ends > :current_timestamp1) + AND ((ends + interval :deltaDay2 + interval :interval2 - starts) <= interval '24:00') -UPDATE cc_show_days SET duration = (CAST(duration AS interval) + interval :deltaDay3 + interval :interval3) +UPDATE cc_show_days +SET duration = (CAST(duration AS interval) + interval :deltaDay3 + interval :interval3) WHERE show_id = :show_id2 -AND ((CAST(duration AS interval) + interval :deltaDay4 + interval :interval4) <= interval '24:00') + AND ((CAST(duration AS interval) + interval :deltaDay4 + interval :interval4) <= interval '24:00') SQL; Application_Common_Database::prepareAndExecute($sql_gen, @@ -258,9 +247,6 @@ SQL; ':interval4' => "$hours:$mins" ), "execute"); - //do both the queries at once. - //$con->exec($sql); - $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME); $con->beginTransaction(); @@ -308,7 +294,9 @@ SQL; ->findOne(); if (is_null($showInstancesRow)) { - $sql = "DELETE FROM cc_show WHERE id = {$this->_showId}"; + $sql = "DELETE FROM cc_show WHERE id = :show_id"; + Application_Common_Database::prepareAndExecute( + $sql, array( 'show_id' => $this->_showId ), "execute"); $con->exec($sql); } @@ -366,14 +354,22 @@ SQL; $uncheckedDaysImploded = implode(",", $daysRemovedUTC); $showId = $this->getId(); + $esc_uncheckedDays = pg_escape_string($uncheckedDaysImploded); $timestamp = gmdate("Y-m-d H:i:s"); - $sql = "DELETE FROM cc_show_instances" - ." WHERE EXTRACT(DOW FROM starts) IN ($uncheckedDaysImploded)" - ." AND starts > TIMESTAMP '$timestamp'" - ." AND show_id = $showId"; + $sql = << :timestamp::TIMESTAMP + AND show_id = :showId +SQL; - $con->exec($sql); + Application_Common_Database::prepareAndExecute( $sql, + array( + ":timestamp" => $timestamp, + ":showId" => $showId, + ), "execute"); } /** @@ -422,27 +418,38 @@ SQL; */ public function getRebroadcastsAbsolute() { - $con = Propel::getConnection(); + $sql = <<getId(); - - $sql = "SELECT starts FROM cc_show_instances " - ."WHERE instance_id = (SELECT id FROM cc_show_instances WHERE show_id = $showId ORDER BY starts LIMIT 1) AND rebroadcast = 1 " - ."ORDER BY starts"; - - //Logging::info($sql); - - $rebroadcasts = $con->query($sql)->fetchAll(); + $rebroadcasts = Application_Common_Database::prepareAndExecute( $sql, + array( 'showId' => $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; - foreach ($rebroadcasts as $show) { - $startDateTime = new DateTime($show["starts"], new DateTimeZone("UTC")); - $startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get())); - $rebroadcastsLocal[$i]["start_date"] = $startDateTime->format("Y-m-d"); - $rebroadcastsLocal[$i]["start_time"] = $startDateTime->format("H:i"); + $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; } @@ -460,14 +467,15 @@ SQL; */ public function getRebroadcastsRelative() { - $con = Propel::getConnection(); - - $showId = $this->getId(); - $sql = "SELECT day_offset, start_time FROM cc_show_rebroadcast " - ."WHERE show_id = $showId " - ."ORDER BY day_offset"; - - return $con->query($sql)->fetchAll(); + $sql = << $this->getId() ), 'all' ); } /** @@ -519,15 +527,18 @@ SQL; */ public function getRepeatingEndDate() { - $con = Propel::getConnection(); + $sql = <<getId(); - $sql = "SELECT last_show FROM cc_show_days" - ." WHERE show_id = $showId" - ." ORDER BY last_show DESC"; - - $query = $con->query($sql)->fetchColumn(0); + $query = Application_Common_Database::prepareAndExecute( $sql, + array( 'showId' => $this->getId() ), 'column' ); + /* TODO: Why return empty string instead of false? very confusing --RG + */ return ($query !== false) ? $query : ""; } @@ -543,16 +554,15 @@ SQL; */ public function deleteAllInstances() { - $con = Propel::getConnection(); - - $timestamp = gmdate("Y-m-d H:i:s"); - - $showId = $this->getId(); - $sql = "DELETE FROM cc_show_instances" - ." WHERE starts > TIMESTAMP '$timestamp'" - ." AND show_id = $showId"; - - $con->exec($sql); + $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'); } /** @@ -561,15 +571,16 @@ SQL; */ public function deleteAllRebroadcasts() { - $con = Propel::getConnection(); - - $timestamp = gmdate("Y-m-d H:i:s"); - - $showId = $this->getId(); - $sql = "DELETE FROM cc_show_instances" - ." WHERE starts > TIMESTAMP '$timestamp'" - ." AND show_id = $showId" - ." AND rebroadcast = 1"; + $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); } @@ -652,8 +663,6 @@ SQL; $stmt->bindParam(':showId', $showId); $stmt->execute(); - //$query = $con->query($sql); - if (!$stmt) { return ""; } @@ -759,25 +768,20 @@ SQL; */ public function getAllFutureInstanceIds() { - $con = Propel::getConnection(); + $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"); - $date = new Application_Common_DateHelper; - $timestamp = $date->getTimestamp(); - - $showId = $this->getId(); - $sql = "SELECT id from cc_show_instances" - ." WHERE show_id = $showId" - ." AND starts > TIMESTAMP '$timestamp'" - ." AND modified_instance != TRUE"; - - $rows = $con->query($sql)->fetchAll(); - - $instance_ids = array(); - foreach ($rows as $row) { - $instance_ids[] = $row["id"]; - } - - return $instance_ids; + return array_map( function($i) { + return $i['id']; + }, $rows); } /* Called when a show's duration is changed (edited). @@ -805,12 +809,11 @@ SQL; $sql = << :timestamp::TIMESTAMP + AND ends > :timestamp::TIMESTAMP SQL; - Application_Common_Database::prepareAndExecute( $sql, array( ':add_show_duration' => $p_data['add_show_duration'], @@ -874,14 +877,11 @@ SQL; public function getShowDays() { - $showDays = CcShowDaysQuery::create()->filterByDbShowId($this->getId())->find(); - - $days = array(); - foreach ($showDays as $showDay) { - array_push($days, $showDay->getDbDay()); - } - - return $days; + $showDays = CcShowDaysQuery::create()->filterByDbShowId( + $this->getId())->find(); + return array_map( function($showDay) { + return $showDay->getDbDay(); + }, $showDays); } /* Only used for shows that aren't repeating. @@ -911,7 +911,7 @@ SQL; public function getLiveStreamInfo() { $info = array(); - if ($this->_showId == null) { + if ($this->getId() == null) { return $info; } else { $ccShow = CcShowQuery::create()->findPK($this->_showId); @@ -920,7 +920,6 @@ SQL; $info['cb_custom_auth'] = $ccShow->getDbLiveStreamUsingCustomAuth(); $info['custom_username'] = $ccShow->getDbLiveStreamUser(); $info['custom_password'] = $ccShow->getDbLiveStreamPass(); - return $info; } } @@ -950,20 +949,24 @@ SQL; * row in the cc_show_instances table. */ public function getInstanceOnDate($p_dateTime) { - $con = Propel::getConnection(); - $timestamp = $p_dateTime->format("Y-m-d H:i:s"); - - $showId = $this->getId(); - $sql = "SELECT id FROM cc_show_instances" - ." WHERE date(starts) = date(TIMESTAMP '$timestamp') " - ." AND show_id = $showId AND rebroadcast = 0"; - - $query = $con->query($sql); - $row = ($query !== false) ? $query->fetchColumn(0) : null; - - return CcShowInstancesQuery::create() - ->findPk($row); + $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) @@ -1173,6 +1176,8 @@ SQL; ->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]) { @@ -1186,10 +1191,21 @@ SQL; } 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']}' "; - $r = $con->query($sql); - $offset_days = $r->fetchColumn(0); + //$con = Propel::getConnection(CcShowPeer::DATABASE_NAME); + //$sql = "SELECT date '{$data['add_show_rebroadcast_date_absolute_'.$i]}' - date '{$data['add_show_start_date']}' "; + $sql = << + $date["add_show_rebroadcast_date_absolute_$i"], + 'start' => + $date['add_show_start_date']), "column" ); + + //$r = $con->query($sql); + //$offset_days = $r->fetchColumn(0); $showRebroad = new CcShowRebroadcast(); $showRebroad->setDbDayOffset($offset_days." days"); @@ -1588,7 +1604,7 @@ SQL; * @param boolean $onlyRecord * @return array */ - public static function getShows($start_timestamp, $end_timestamp, $excludeInstance=NULL, $onlyRecord=FALSE) + public static function getShows($start_timestamp, $end_timestamp, $onlyRecord=FALSE) { $con = Propel::getConnection(); @@ -1600,42 +1616,56 @@ SQL; Application_Model_Preference::SetShowsPopulatedUntil($end_timestamp); } - $sql = "SELECT si1.starts AS starts, si1.ends AS ends, si1.record AS record, si1.rebroadcast AS rebroadcast, si2.starts AS parent_starts, - si1.instance_id AS record_id, si1.show_id AS show_id, show.name AS name, - show.color AS color, show.background_color AS background_color, si1.file_id AS file_id, si1.id AS instance_id, - si1.created AS created, si1.last_scheduled AS last_scheduled, si1.time_filled AS time_filled, f.soundcloud_id - FROM cc_show_instances AS si1 - LEFT JOIN cc_show_instances AS si2 ON si1.instance_id = si2.id - LEFT JOIN cc_show AS show ON show.id = si1.show_id - LEFT JOIN cc_files AS f ON f.id = si1.file_id - WHERE si1.modified_instance = FALSE"; + $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'); - $sql = $sql." AND (si1.starts >= '{$start_string}' AND si1.starts < timestamp '{$end_string}')"; - $sql = $sql." AND (si1.record = 1)"; } else { - - $sql = $sql." AND ((si1.starts >= '{$start_string}' AND si1.starts < '{$end_string}') - OR (si1.ends > '{$start_string}' AND si1.ends <= '{$end_string}') - OR (si1.starts <= '{$start_string}' AND si1.ends >= '{$end_string}'))"; + $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'); } - - if (isset($excludeInstance)) { - foreach ($excludeInstance as $instance) { - $sql_exclude[] = "si1.id != {$instance}"; - } - - $exclude = join(" OR ", $sql_exclude); - - $sql = $sql." AND ({$exclude})"; - } - - $result = $con->query($sql)->fetchAll(); - - return $result; } private static function setNextPop($next_date, $show_id, $day) @@ -1696,10 +1726,10 @@ SQL; */ public static function &getFullCalendarEvents($p_start, $p_end, $p_editable=false) { - $events = array(); + $events = array(); $interval = $p_start->diff($p_end); - $days = $interval->format('%a'); - $shows = Application_Model_Show::getShows($p_start, $p_end); + $days = $interval->format('%a'); + $shows = Application_Model_Show::getShows($p_start, $p_end); $nowEpoch = time(); $timezone = date_default_timezone_get(); @@ -2076,7 +2106,6 @@ SQL; throw new Exception("Error: $msg"); } - return $rows; } /** @@ -2102,20 +2131,16 @@ SQL; public static function getMaxLengths() { - global $CC_CONFIG; $con = Propel::getConnection(); - - //Not using prepared statement here since not using an variable input. - $sql = "SELECT column_name, character_maximum_length FROM information_schema.columns" - ." WHERE table_name = 'cc_show' AND character_maximum_length > 0"; - $result = $con->query($sql)->fetchAll(); - - // store result into assoc array + $sql = << 0 +SQL; + $result = $con->query($sql)->fetchAll(); $assocArray = array(); foreach ($result as $row) { $assocArray[$row['column_name']] = $row['character_maximum_length']; } - return $assocArray; } } diff --git a/airtime_mvc/application/models/ShowInstance.php b/airtime_mvc/application/models/ShowInstance.php index afbacdadf..238b08f27 100644 --- a/airtime_mvc/application/models/ShowInstance.php +++ b/airtime_mvc/application/models/ShowInstance.php @@ -22,6 +22,8 @@ class Application_Model_ShowInstance return $this->_showInstance->getDbShowId(); } + /* TODO: A little inconsistent because other models have a getId() method + to get PK --RG */ public function getShowInstanceId() { return $this->_instanceId; @@ -167,26 +169,33 @@ class Application_Model_ShowInstance $con = Propel::getConnection(); $instance_id = $this->getShowInstanceId(); - $sql = "SELECT starts from cc_schedule" - ." WHERE instance_id = $instance_id" - ." ORDER BY starts" - ." LIMIT 1"; - - $scheduleStarts = $con->query($sql)->fetchColumn(0); + $sql = << $instance_id ), 'column' ); if ($scheduleStarts) { $scheduleStartsEpoch = strtotime($scheduleStarts); - $showStartsEpoch = strtotime($this->getShowInstanceStart()); + $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"; - - $con->exec($sql); + $sql = << $diff, + ':diff2' => $diff, + ':instanceId' => $instance_id ), 'execute'); } } Application_Model_RabbitMq::PushSchedule(); @@ -745,69 +754,56 @@ SQL; public static function GetLastShowInstance($p_timeNow) { - global $CC_CONFIG; - $con = Propel::getConnection(); + $sql = << $p_timeNow ), 'column' ); - $sql = "SELECT si.id" - ." FROM $CC_CONFIG[showInstances] si" - ." WHERE si.ends < TIMESTAMP '$p_timeNow'" - ." AND si.modified_instance = 'f'" - ." ORDER BY si.ends DESC" - ." LIMIT 1"; - - $id = $con->query($sql)->fetchColumn(0); - if ($id) { - return new Application_Model_ShowInstance($id); - } else { - return null; - } + return ($id ? new Application_Model_ShowInstance($id) : null ); } public static function GetCurrentShowInstance($p_timeNow) { - global $CC_CONFIG; - $con = Propel::getConnection(); - /* Orderby si.starts descending, because in some cases * we can have multiple shows overlapping each other. In * this case, the show that started later is the one that * is actually playing, and so this is the one we want. */ - $sql = "SELECT si.id" - ." FROM $CC_CONFIG[showInstances] si" - ." WHERE si.starts <= TIMESTAMP '$p_timeNow'" - ." AND si.ends > TIMESTAMP '$p_timeNow'" - ." AND si.modified_instance = 'f'" - ." ORDER BY si.starts DESC" - ." LIMIT 1"; + $sql = << :timeNow2::TIMESTAMP + AND si.modified_instance = 'f' +ORDER BY si.starts DESC LIMIT 1 +SQL; - $id = $con->query($sql)->fetchColumn(0); - if ($id) { - return new Application_Model_ShowInstance($id); - } else { - return null; - } + $id = Application_Common_Database( $sql, array( + ':timeNow1' => $p_timeNow, + ':timeNow2' => $p_timeNow ), 'column'); + + return ( $id ? new Application_Model_ShowInstance($id) : null ); } public static function GetNextShowInstance($p_timeNow) { - global $CC_CONFIG; - $con = Propel::getConnection(); - - $sql = "SELECT si.id" - ." FROM $CC_CONFIG[showInstances] si" - ." WHERE si.starts > TIMESTAMP '$p_timeNow'" - ." AND si.modified_instance = 'f'" - ." ORDER BY si.starts" - ." LIMIT 1"; - - $id = $con->query($sql)->fetchColumn(0); - if ($id) { - return new Application_Model_ShowInstance($id); - } else { - return null; - } + $sql = << :timeNow::TIMESTAMP +AND si.modified_instance = 'f' +ORDER BY si.starts +LIMIT 1 +SQL; + $id = Application_Common_Database::prepareAndExecute( $sql, + array( 'timeNow' => $p_timeNow ), 'column' ); + return ( $id ? new Application_Model_ShowInstance($id) : null ); } // returns number of show instances that ends later than $day diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 9e6463ed9..312208af8 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -413,8 +413,10 @@ class Application_Model_StoredFile return "ogg"; } elseif ($mime == "audio/mp3" || $mime == "audio/mpeg") { return "mp3"; - } elseif ($mime == "audio/x/flac") { + } elseif ($mime == "audio/x-flac") { return "flac"; + } else { + throw new Exception("Unknown $mime"); } } diff --git a/debian/control b/debian/control index c4e5663e9..6e9ae3dee 100644 --- a/debian/control +++ b/debian/control @@ -37,10 +37,12 @@ Depends: apache2, php-pear, php5-pgsql, python, + pwgen, rabbitmq-server, sudo, sysv-rc, tar (>= 1.22), + coreutils (>= 7.5) | timeout, unzip, vorbis-tools, zendframework | libzend-framework-php, @@ -48,7 +50,7 @@ Depends: apache2, Recommends: icecast2 Suggests: airtime-audio-samples, alsa-utils -Description: The open radio software for scheduling and remote station management. +Description: open radio software for scheduling and remote station management. Airtime is an open source application that provides remote automation of a radio station. . diff --git a/install_minimal/include/airtime-upgrade.php b/install_minimal/include/airtime-upgrade.php index 913fcd082..4c7e7f4c0 100644 --- a/install_minimal/include/airtime-upgrade.php +++ b/install_minimal/include/airtime-upgrade.php @@ -5,7 +5,7 @@ * @copyright 2010 Sourcefabric O.P.S. * @license http://www.gnu.org/licenses/gpl.txt */ -if(posix_geteuid() != 0) { +if (posix_geteuid() != 0) { echo "Must be root user.\n"; exit(1); } @@ -13,9 +13,9 @@ if(posix_geteuid() != 0) { require_once(__DIR__.'/airtime-constants.php'); require_once(__DIR__.'/AirtimeIni.php'); require_once(__DIR__.'/AirtimeInstall.php'); -require_once 'propel/runtime/lib/Propel.php'; +require_once 'propel/runtime/lib/Propel.php'; Propel::init(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/db-conf.php"); -Propel::init(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/airtime-conf-production.php"); +Propel::init(AirtimeInstall::GetAirtimeSrcDir()."/application/configs/airtime-conf-production.php"); function pause() @@ -23,7 +23,7 @@ function pause() /* Type "sudo -s" to change to root user then type "export AIRTIME_INSTALL_DEBUG=1" and then * start airtime-install to enable this feature. Is used to pause between upgrade scripts * to examine the state of the system and see if everything is as expected. */ - if (getenv("AIRTIME_INSTALL_DEBUG") === "1"){ + if (getenv("AIRTIME_INSTALL_DEBUG") === "1") { echo "Press Enter to Continue".PHP_EOL; fgets(STDIN); } @@ -44,7 +44,7 @@ $database = $CC_CONFIG['dsn']['database']; $airtime_version = AIRTIME_VERSION; $target_dir = trim(getenv("HOME")); -if (strlen($target_dir) == 0){ +if (strlen($target_dir) == 0) { $target_dir = "/tmp"; } @@ -52,7 +52,7 @@ $target_file = "/airtime_$airtime_version.sql"; $target_path = $target_dir.$target_file; echo "* Backing up current database to $target_path".PHP_EOL; exec("export PGPASSWORD=$password && pg_dump -h $host -U $user -f $target_path $database", $arr, $return_code); -if ($return_code == 0){ +if ($return_code == 0) { echo " * Success".PHP_EOL; } else { echo " * Failed".PHP_EOL; @@ -64,59 +64,39 @@ $version = substr($version, 0, 5); $SCRIPTPATH = __DIR__; -if (strcmp($version, "1.9.0") < 0){ - echo "Unsupported Airtime version. You must upgrade from at least Airtime 1.9.0.".PHP_EOL; +if (strcmp($version, "2.0.0") < 0) { + echo "Unsupported Airtime version. You must upgrade from at least Airtime 2.0.0.".PHP_EOL; exit(1); } -if (strcmp($version, "1.9.2") < 0){ - passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-1.9.2/airtime-upgrade.php"); - pause(); -} -if (strcmp($version, "1.9.3") < 0){ - passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-1.9.3/airtime-upgrade.php"); - pause(); -} -if (strcmp($version, "1.9.4") < 0){ - passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-1.9.4/airtime-upgrade.php"); - pause(); -} -if (strcmp($version, "1.9.5") < 0){ - passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-1.9.5/airtime-upgrade.php"); - pause(); -} -if (strcmp($version, "2.0.0") < 0){ - passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-2.0.0/airtime-upgrade.php"); - pause(); -} -if (strcmp($version, "2.0.1") < 0){ +if (strcmp($version, "2.0.1") < 0) { passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-2.0.1/airtime-upgrade.php"); pause(); } -if (strcmp($version, "2.0.2") < 0){ +if (strcmp($version, "2.0.2") < 0) { passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-2.0.2/airtime-upgrade.php"); pause(); } -if (strcmp($version, "2.0.3") < 0){ +if (strcmp($version, "2.0.3") < 0) { passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-2.0.3/airtime-upgrade.php"); pause(); } -if (strcmp($version, "2.1.0") < 0){ +if (strcmp($version, "2.1.0") < 0) { passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-2.1.0/airtime-upgrade.php"); pause(); } -if (strcmp($version, "2.1.1") < 0){ +if (strcmp($version, "2.1.1") < 0) { passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-2.1.1/airtime-upgrade.php"); pause(); } -if (strcmp($version, "2.1.2") < 0){ +if (strcmp($version, "2.1.2") < 0) { passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-2.1.2/airtime-upgrade.php"); pause(); } -if (strcmp($version, "2.1.3") < 0){ +if (strcmp($version, "2.1.3") < 0) { passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-2.1.3/airtime-upgrade.php"); pause(); } -if (strcmp($version, "2.2.0") < 0){ +if (strcmp($version, "2.2.0") < 0) { passthru("php --php-ini $SCRIPTPATH/../airtime-php.ini $SCRIPTPATH/../upgrades/airtime-2.2.0/airtime-upgrade.php"); pause(); } diff --git a/install_minimal/upgrades/airtime-1.7.0/airtime-upgrade.php b/install_minimal/upgrades/airtime-1.7.0/airtime-upgrade.php deleted file mode 100644 index f43e416f7..000000000 --- a/install_minimal/upgrades/airtime-1.7.0/airtime-upgrade.php +++ /dev/null @@ -1,56 +0,0 @@ - $values['general']['web_server_user'], - - 'rabbitmq' => $values['rabbitmq'], - - 'baseFilesDir' => $values['general']['base_files_dir'], - // main directory for storing binary media files - 'storageDir' => $values['general']['base_files_dir']."/stor", - - // Database config - 'dsn' => array( - 'username' => $values['database']['dbuser'], - 'password' => $values['database']['dbpass'], - 'hostspec' => $values['database']['host'], - 'phptype' => 'pgsql', - 'database' => $values['database']['dbname']), - - // prefix for table names in the database - 'tblNamePrefix' => 'cc_', - - /* ================================================ storage configuration */ - - 'apiKey' => array($values['general']['api_key']), - 'apiPath' => '/api/', - - 'soundcloud-client-id' => '2CLCxcSXYzx7QhhPVHN4A', - 'soundcloud-client-secret' => 'pZ7beWmF06epXLHVUP1ufOg2oEnIt9XhE8l8xt0bBs', - - 'soundcloud-connection-retries' => $values['soundcloud']['connection_retries'], - 'soundcloud-connection-wait' => $values['soundcloud']['time_between_retries'], - - "rootDir" => __DIR__."/../.." -); - -AirtimeInstall::DbConnect(true); -$con = Propel::getConnection(); - -echo PHP_EOL."*** Updating Database Tables ***".PHP_EOL; - -if(AirtimeInstall::DbTableExists('doctrine_migration_versions') === false) { - $migrations = array('20110312121200', '20110331111708', '20110402164819'); - foreach($migrations as $migration) { - AirtimeInstall::BypassMigrations(__DIR__, $migration); - } -} -AirtimeInstall::MigrateTablesToVersion(__DIR__, '20110406182005'); - -//setting data for new aggregate show length column. -$sql = "SELECT id FROM cc_show_instances"; -$show_instances = $con->query($sql)->fetchAll(); - -foreach ($show_instances as $show_instance) { - $sql = "UPDATE cc_show_instances SET time_filled = (SELECT SUM(clip_length) FROM cc_schedule WHERE instance_id = {$show_instance["id"]}) WHERE id = {$show_instance["id"]}"; - $con->exec($sql); -} -//end setting data for new aggregate show length column. - -exec("rm -fr /opt/pypo"); -exec("rm -fr /opt/recorder"); - -const CONF_FILE_AIRTIME = "/etc/airtime/airtime.conf"; -const CONF_FILE_PYPO = "/etc/airtime/pypo.cfg"; -const CONF_FILE_RECORDER = "/etc/airtime/recorder.cfg"; -const CONF_FILE_LIQUIDSOAP = "/etc/airtime/liquidsoap.cfg"; - -$configFiles = array(CONF_FILE_AIRTIME, - CONF_FILE_PYPO, - CONF_FILE_RECORDER, - CONF_FILE_LIQUIDSOAP); - - -/** -* This function creates the /etc/airtime configuration folder -* and copies the default config files to it. -*/ -function CreateIniFiles($suffix) -{ - if (!file_exists("/etc/airtime/")){ - if (!mkdir("/etc/airtime/", 0755, true)){ - echo "Could not create /etc/airtime/ directory. Exiting."; - exit(1); - } - } - - if (!copy(__DIR__."/airtime.conf.$suffix", CONF_FILE_AIRTIME)){ - echo "Could not copy airtime.conf.$suffix to /etc/airtime/. Exiting."; - exit(1); - } - if (!copy(__DIR__."/pypo.cfg.$suffix", CONF_FILE_PYPO)){ - echo "Could not copy pypo.cfg.$suffix to /etc/airtime/. Exiting."; - exit(1); - } - if (!copy(__DIR__."/recorder.cfg.$suffix", CONF_FILE_RECORDER)){ - echo "Could not copy recorder.cfg.$suffix to /etc/airtime/. Exiting."; - exit(1); - } - if (!copy(__DIR__."/liquidsoap.cfg.$suffix", CONF_FILE_LIQUIDSOAP)){ - echo "Could not copy liquidsoap.cfg.$suffix to /etc/airtime/. Exiting."; - exit(1); - } -} - -function ReadPythonConfig($p_filename) -{ - $values = array(); - - $lines = file($p_filename); - $n=count($lines); - for ($i=0; $i<$n; $i++) { - if (strlen($lines[$i]) && !in_array(substr($lines[$i], 0, 1), array('#', PHP_EOL))){ - $info = explode("=", $lines[$i]); - $values[trim($info[0])] = trim($info[1]); - } - } - - return $values; -} - -function UpdateIniValue($p_filename, $p_property, $p_value) -{ - $lines = file($p_filename); - $n=count($lines); - foreach ($lines as &$line) { - if ($line[0] != "#"){ - $key_value = split("=", $line); - $key = trim($key_value[0]); - - if ($key == $p_property){ - $line = "$p_property = $p_value".PHP_EOL; - } - } - } - - $fp=fopen($p_filename, 'w'); - for($i=0; $i<$n; $i++){ - fwrite($fp, $lines[$i]); - } - fclose($fp); -} - -function MergeConfigFiles($configFiles, $suffix) -{ - foreach ($configFiles as $conf) { - if (file_exists("$conf$suffix.bak")) { - - if($conf === CONF_FILE_AIRTIME) { - // Parse with sections - $newSettings = parse_ini_file($conf, true); - $oldSettings = parse_ini_file("$conf$suffix.bak", true); - - $oldSettings['general']['airtime_dir'] = '/var/www/airtime'; - $oldSettings['general']['base_files_dir'] = '/srv/airtime'; - } - else { - $newSettings = ReadPythonConfig($conf); - $oldSettings = ReadPythonConfig("$conf$suffix.bak"); - } - - //override some values needed for 1.8.0. - if($conf === CONF_FILE_PYPO) { - - $oldSettings['cache_dir'] = '/var/tmp/airtime/pypo/cache/'; - $oldSettings['file_dir'] = '/var/tmp/airtime/pypo/files/'; - $oldSettings['tmp_dir'] = '/var/tmp/airtime/pypo/tmp/'; - } - else if($conf === CONF_FILE_RECORDER) { - - $oldSettings['base_recorded_files'] = '/var/tmp/airtime/show-recorder/'; - } - - $settings = array_keys($newSettings); - - foreach($settings as $section) { - if(isset($oldSettings[$section])) { - if(is_array($oldSettings[$section])) { - $sectionKeys = array_keys($newSettings[$section]); - foreach($sectionKeys as $sectionKey) { - if(isset($oldSettings[$section][$sectionKey])) { - UpdateIniValue($conf, $sectionKey, $oldSettings[$section][$sectionKey]); - } - } - } - else { - UpdateIniValue($conf, $section, $oldSettings[$section]); - } - } - } - } - } -} - -function LoadConfig($CC_CONFIG) { - $values = parse_ini_file(CONF_FILE_AIRTIME, true); - - // Name of the web server user - $CC_CONFIG['webServerUser'] = $values['general']['web_server_user']; - $CC_CONFIG['phpDir'] = $values['general']['airtime_dir']; - $CC_CONFIG['rabbitmq'] = $values['rabbitmq']; - - $CC_CONFIG['baseFilesDir'] = $values['general']['base_files_dir']; - // main directory for storing binary media files - $CC_CONFIG['storageDir'] = $values['general']['base_files_dir']."/stor"; - - // Database config - $CC_CONFIG['dsn']['username'] = $values['database']['dbuser']; - $CC_CONFIG['dsn']['password'] = $values['database']['dbpass']; - $CC_CONFIG['dsn']['hostspec'] = $values['database']['host']; - $CC_CONFIG['dsn']['phptype'] = 'pgsql'; - $CC_CONFIG['dsn']['database'] = $values['database']['dbname']; - - $CC_CONFIG['apiKey'] = array($values['general']['api_key']); - - $CC_CONFIG['soundcloud-connection-retries'] = $values['soundcloud']['connection_retries']; - $CC_CONFIG['soundcloud-connection-wait'] = $values['soundcloud']['time_between_retries']; - - return $CC_CONFIG; -} - -function movePhpFiles($CC_CONFIG){ - $phpDir = $CC_CONFIG['phpDir']; - echo "Copying Server files from $phpDir/airtime_mvc to /var/www/airtime"; - exec("mkdir -p /var/www/airtime"); - exec("cp -R $phpDir/airtime_mvc/* /var/www/airtime"); -} - -// Backup the config files -$suffix = date("Ymdhis")."-1.8.0"; -foreach ($configFiles as $conf) { - if (file_exists($conf)) { - echo "Backing up $conf to $conf$suffix.bak".PHP_EOL; - exec("cp $conf $conf$suffix.bak"); - } -} - - -$CC_CONFIG = LoadConfig($CC_CONFIG); -movePhpFiles($CC_CONFIG); - -$default_suffix = "180"; -CreateIniFiles($default_suffix); -echo "* Initializing INI files".PHP_EOL; - - -MergeConfigFiles($configFiles, $suffix); - - - diff --git a/install_minimal/upgrades/airtime-1.8.0/airtime.conf.180 b/install_minimal/upgrades/airtime-1.8.0/airtime.conf.180 deleted file mode 100644 index 9135f09e4..000000000 --- a/install_minimal/upgrades/airtime-1.8.0/airtime.conf.180 +++ /dev/null @@ -1,22 +0,0 @@ -[database] -host = localhost -dbname = airtime -dbuser = airtime -dbpass = airtime - -[rabbitmq] -host = 127.0.0.1 -port = 5672 -user = guest -password = guest -vhost = / - -[general] -api_key = AAA -web_server_user = www-data -airtime_dir = x -base_files_dir = x - -[soundcloud] -connection_retries = 3 -time_between_retries = 60 diff --git a/install_minimal/upgrades/airtime-1.8.0/liquidsoap.cfg.180 b/install_minimal/upgrades/airtime-1.8.0/liquidsoap.cfg.180 deleted file mode 100644 index 360ee107f..000000000 --- a/install_minimal/upgrades/airtime-1.8.0/liquidsoap.cfg.180 +++ /dev/null @@ -1,38 +0,0 @@ -########################################### -# liquidsoap config file # -########################################### - - -########################################### -# general settings # -########################################### - -log_file = "/var/log/airtime/pypo-liquidsoap/