Show.php 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463
  1. <?php
  2. class Application_Model_Show
  3. {
  4. private $_showId;
  5. public function __construct($showId=NULL)
  6. {
  7. $this->_showId = $showId;
  8. }
  9. public function getName()
  10. {
  11. $show = CcShowQuery::create()->findPK($this->_showId);
  12. return $show->getDbName();
  13. }
  14. public function setName($name)
  15. {
  16. $show = CcShowQuery::create()->findPK($this->_showId);
  17. $show->setDbName($name);
  18. Application_Model_RabbitMq::PushSchedule();
  19. }
  20. public function setAirtimeAuthFlag($flag)
  21. {
  22. $show = CcShowQuery::create()->findPK($this->_showId);
  23. $show->setDbLiveStreamUsingAirtimeAuth($flag);
  24. $show->save();
  25. }
  26. public function setCustomAuthFlag($flag)
  27. {
  28. $show = CcShowQuery::create()->findPK($this->_showId);
  29. $show->setDbLiveStreamUsingCustomAuth($flag);
  30. $show->save();
  31. }
  32. public function setCustomUsername($username)
  33. {
  34. $show = CcShowQuery::create()->findPK($this->_showId);
  35. $show->setDbLiveStreamUser($username);
  36. $show->save();
  37. }
  38. public function setCustomPassword($password)
  39. {
  40. $show = CcShowQuery::create()->findPK($this->_showId);
  41. $show->setDbLiveStreamPass($password);
  42. $show->save();
  43. }
  44. public function getDescription()
  45. {
  46. $show = CcShowQuery::create()->findPK($this->_showId);
  47. return $show->getDbDescription();
  48. }
  49. public function setDescription($description)
  50. {
  51. $show = CcShowQuery::create()->findPK($this->_showId);
  52. $show->setDbDescription($description);
  53. }
  54. public function getColor()
  55. {
  56. $show = CcShowQuery::create()->findPK($this->_showId);
  57. return $show->getDbColor();
  58. }
  59. public function setColor($color)
  60. {
  61. $show = CcShowQuery::create()->findPK($this->_showId);
  62. $show->setDbColor($color);
  63. }
  64. public function getUrl()
  65. {
  66. $show = CcShowQuery::create()->findPK($this->_showId);
  67. return $show->getDbUrl();
  68. }
  69. /*TODO : This method is not actually used anywhere as far as I can tell. We
  70. can safely remove it and probably many other superfluous methods.
  71. --RG*/
  72. public function setUrl($p_url)
  73. {
  74. $show = CcShowQuery::create()->findPK($this->_showId);
  75. $show->setDbUrl($p_url);
  76. }
  77. public function getGenre()
  78. {
  79. $show = CcShowQuery::create()->findPK($this->_showId);
  80. return $show->getDbGenre();
  81. }
  82. public function setGenre($p_genre)
  83. {
  84. $show = CcShowQuery::create()->findPK($this->_showId);
  85. $show->setDbGenre($p_genre);
  86. }
  87. public function getBackgroundColor()
  88. {
  89. $show = CcShowQuery::create()->findPK($this->_showId);
  90. return $show->getDbBackgroundColor();
  91. }
  92. public function setBackgroundColor($backgroundColor)
  93. {
  94. $show = CcShowQuery::create()->findPK($this->_showId);
  95. $show->setDbBackgroundColor($backgroundColor);
  96. }
  97. public function getId()
  98. {
  99. return $this->_showId;
  100. }
  101. public function getHosts()
  102. {
  103. $sql = <<<SQL
  104. SELECT first_name,
  105. last_name
  106. FROM cc_show_hosts
  107. LEFT JOIN cc_subjs ON cc_show_hosts.subjs_id = cc_subjs.id
  108. WHERE show_id = :show_id
  109. SQL;
  110. $hosts = Application_Common_Database::prepareAndExecute( $sql,
  111. array( ':show_id' => $this->getId() ), 'all');
  112. $res = array();
  113. foreach ($hosts as $host) {
  114. $res[] = $host['first_name']." ".$host['last_name'];
  115. }
  116. return $res;
  117. }
  118. public function getHostsIds()
  119. {
  120. $sql = <<<SQL
  121. SELECT subjs_id
  122. FROM cc_show_hosts
  123. WHERE show_id = :show_id
  124. SQL;
  125. $hosts = Application_Common_Database::prepareAndExecute(
  126. $sql, array( ':show_id' => $this->getId() ), 'all');
  127. return $hosts;
  128. }
  129. /**
  130. * remove everything about this show.
  131. */
  132. public function delete()
  133. {
  134. //usually we hide the show-instance, but in this case we are deleting the show template
  135. //so delete all show-instances as well.
  136. CcShowInstancesQuery::create()->filterByDbOriginalShow($this->_showId)->delete();
  137. $show = CcShowQuery::create()->findPK($this->_showId);
  138. $show->delete();
  139. }
  140. public function resizeShow($deltaDay, $deltaMin, $instanceId)
  141. {
  142. $con = Propel::getConnection();
  143. if ($deltaDay > 0) {
  144. return _("Shows can have a max length of 24 hours.");
  145. }
  146. $utcTimezone = new DateTimeZone("UTC");
  147. $nowDateTime = new DateTime("now", $utcTimezone);
  148. //keep track of cc_show_day entries we need to update
  149. $showDayIds = array();
  150. /*
  151. * If the resized show is an edited instance of a repeating show we
  152. * need to treat it as a separate show and not resize the other instances
  153. *
  154. * Also, if the resized show has edited instances, we need to exclude
  155. * those from the resize
  156. */
  157. $ccShow = CcShowQuery::create()->findPk($this->_showId);
  158. if ($ccShow->isRepeating()) {
  159. //convert instance to local timezone
  160. $ccShowInstance = CcShowInstancesQuery::create()->findPk($instanceId);
  161. $startsDT = $ccShowInstance->getDbStarts(null);
  162. $timezone = $ccShow->getFirstCcShowDay()->getDbTimezone();
  163. $startsDT->setTimezone(new DateTimeZone($timezone));
  164. /* Get cc_show_day for the current instance. If we don't find one
  165. * we know it is a repeat interval of one of cc_show_days first
  166. * show and we can assume we aren't resizing a modified instance
  167. */
  168. $ccShowDay = CcShowDaysQuery::create()
  169. ->filterByDbFirstShow($startsDT->format("Y-m-d"))
  170. ->filterByDbStartTime($startsDT->format("H:i:s"))
  171. ->filterByDbShowId($this->_showId)
  172. ->findOne();
  173. /* Check if this cc_show_day rule is non-repeating. If it is, then
  174. * we know this instance was edited out of the repeating sequence
  175. */
  176. if (!$ccShowDay || $ccShowDay->getDbRepeatType() != -1) {
  177. $ccShowDays = $ccShow->getRepeatingCcShowDays();
  178. foreach ($ccShowDays as $day) {
  179. array_push($showDayIds, $day->getDbId());
  180. }
  181. $excludeIds = $ccShow->getEditedRepeatingInstanceIds();
  182. //exlcude edited instances from resize
  183. $showInstances = CcShowInstancesQuery::create()
  184. ->filterByDbShowId($this->_showId)
  185. ->filterByDbModifiedInstance(false)
  186. ->filterByDbId($excludeIds, criteria::NOT_IN)
  187. ->find();
  188. } elseif ($ccShowDay->getDbRepeatType() == -1) {
  189. array_push($showDayIds, $ccShowDay->getDbId());
  190. //treat edited instance as separate show for resize
  191. $showInstances = CcShowInstancesQuery::create()
  192. ->filterByDbId($instanceId)
  193. ->find();
  194. }
  195. } else {
  196. $ccShowDays = $ccShow->getCcShowDayss();
  197. foreach ($ccShowDays as $day) {
  198. array_push($showDayIds, $day->getDbId());
  199. }
  200. $showInstances = CcShowInstancesQuery::create()
  201. ->filterByDbShowId($this->_showId)
  202. ->find($con);
  203. }
  204. /* Check two things:
  205. 1. If the show being resized and any of its repeats end in the past
  206. 2. If the show being resized and any of its repeats overlap
  207. with other scheduled shows */
  208. //keep track of instance ids for update show instances start/end times
  209. $instanceIds = array();
  210. $displayTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
  211. //check if new show time overlaps with any other shows
  212. foreach ($showInstances as $si) {
  213. array_push($instanceIds, $si->getDbId());
  214. $startsDateTime = $si->getDbStarts(null);
  215. $endsDateTime = $si->getDbEnds(null);
  216. /* The user is moving the show on the calendar from the perspective
  217. of local time. * incase a show is moved across a time change
  218. border offsets should be added to the local * timestamp and
  219. then converted back to UTC to avoid show time changes */
  220. $startsDateTime->setTimezone($displayTimezone);
  221. $endsDateTime->setTimezone($displayTimezone);
  222. //$newStartsDateTime = Application_Model_ShowInstance::addDeltas($startsDateTime, $deltaDay, $deltaMin);
  223. $newEndsDateTime = Application_Model_ShowInstance::addDeltas($endsDateTime, $deltaDay, $deltaMin);
  224. if ($newEndsDateTime->getTimestamp() < $nowDateTime->getTimestamp()) {
  225. return _("End date/time cannot be in the past");
  226. }
  227. //convert our new starts/ends to UTC.
  228. //$newStartsDateTime->setTimezone($utc);
  229. $newEndsDateTime->setTimezone($utcTimezone);
  230. $overlapping = Application_Model_Schedule::checkOverlappingShows(
  231. $startsDateTime, $newEndsDateTime, true, $si->getDbId());
  232. if ($overlapping) {
  233. return _("Cannot schedule overlapping shows.\nNote: Resizing a repeating show ".
  234. "affects all of its repeats.");
  235. }
  236. }
  237. $hours = $deltaMin/60;
  238. $hours = ($hours > 0) ? floor($hours) : ceil($hours);
  239. $mins = abs($deltaMin % 60);
  240. $sql_gen = "UPDATE cc_show_instances ".
  241. "SET ends = (ends + :deltaDay1::INTERVAL + :interval1::INTERVAL) ".
  242. "WHERE (id IN (".implode($instanceIds, ",").") ".
  243. "AND ends > :current_timestamp1) ".
  244. "AND ((ends + :deltaDay2::INTERVAL + :interval2::INTERVAL - starts) <= interval '24:00')";
  245. Application_Common_Database::prepareAndExecute($sql_gen,
  246. array(
  247. ':deltaDay1' => "$deltaDay days",
  248. ':interval1' => "$hours:$mins",
  249. ':current_timestamp1' => $nowDateTime->format("Y-m-d H:i:s"),
  250. ':deltaDay2' => "$deltaDay days",
  251. ':interval2' => "$hours:$mins"
  252. ), "execute");
  253. $sql_gen = "UPDATE cc_show_days ".
  254. "SET duration = (CAST(duration AS interval) + :deltaDay3::INTERVAL + :interval3::INTERVAL) ".
  255. "WHERE id IN (".implode($showDayIds, ",").") ".
  256. "AND ((CAST(duration AS interval) + :deltaDay4::INTERVAL + :interval4::INTERVAL) <= interval '24:00')";
  257. Application_Common_Database::prepareAndExecute($sql_gen,
  258. array(
  259. ':deltaDay3' => "$deltaDay days",
  260. ':interval3' => "$hours:$mins",
  261. ':deltaDay4' => "$deltaDay days",
  262. ':interval4' => "$hours:$mins"
  263. ), "execute");
  264. $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME);
  265. $con->beginTransaction();
  266. try {
  267. //update the status flag in cc_schedule.
  268. /* Since we didn't use a propel object when updating
  269. * cc_show_instances table we need to clear the instances
  270. * so the correct information is retrieved from the db
  271. */
  272. CcShowInstancesPeer::clearInstancePool();
  273. $instances = CcShowInstancesQuery::create()
  274. ->filterByDbEnds($nowDateTime->format("Y-m-d H:i:s"), Criteria::GREATER_THAN)
  275. ->filterByDbId($instanceIds, Criteria::IN)
  276. ->find($con);
  277. foreach ($instances as $instance) {
  278. $instance->updateScheduleStatus($con);
  279. }
  280. $con->commit();
  281. } catch (Exception $e) {
  282. $con->rollback();
  283. Logging::info("Couldn't update schedule status.");
  284. Logging::info($e->getMessage());
  285. }
  286. Application_Model_RabbitMq::PushSchedule();
  287. }
  288. public function cancelShow($day_timestamp)
  289. {
  290. $timeinfo = explode(" ", $day_timestamp);
  291. CcShowDaysQuery::create()
  292. ->filterByDbShowId($this->_showId)
  293. ->update(array('DbLastShow' => $timeinfo[0]));
  294. $sql = <<<SQL
  295. SELECT id from cc_show_instances
  296. WHERE starts >= :dayTimestamp::TIMESTAMP
  297. AND show_id = :showId
  298. SQL;
  299. $rows = Application_Common_Database::prepareAndExecute( $sql, array(
  300. ':dayTimestamp' => $day_timestamp,
  301. ':showId' => $this->getId()), 'all');
  302. foreach ($rows as $row) {
  303. try {
  304. $showInstance = new Application_Model_ShowInstance($row["id"]);
  305. $showInstance->delete($rabbitmqPush = false);
  306. } catch (Exception $e) {
  307. Logging::info($e->getMessage());
  308. }
  309. }
  310. Application_Model_RabbitMq::PushSchedule();
  311. }
  312. /**
  313. * Check whether the current show originated
  314. * from a recording.
  315. *
  316. * @return boolean
  317. * true if originated from recording, otherwise false.
  318. */
  319. public function isRecorded()
  320. {
  321. $showInstancesRow = CcShowInstancesQuery::create()
  322. ->filterByDbShowId($this->getId())
  323. ->filterByDbRecord(1)
  324. ->filterByDbModifiedInstance(false)
  325. ->findOne();
  326. return !is_null($showInstancesRow);
  327. }
  328. /**
  329. * Check whether the current show has rebroadcasts of a recorded
  330. * show. Should be used in conjunction with isRecorded().
  331. *
  332. * @return boolean
  333. * true if show has rebroadcasts, otherwise false.
  334. */
  335. public function isRebroadcast()
  336. {
  337. $showInstancesRow = CcShowInstancesQuery::create()
  338. ->filterByDbShowId($this->_showId)
  339. ->filterByDbRebroadcast(1)
  340. ->filterByDbModifiedInstance(false)
  341. ->findOne();
  342. return !is_null($showInstancesRow);
  343. }
  344. /**
  345. * Get start time and relative start date for a recorded
  346. * shows rebroadcasts. For example start date format would be
  347. * "x days" and time would HH:MM:SS
  348. *
  349. * @return array
  350. * array of associate arrays containing "day_offset" and "start_time"
  351. */
  352. public function getRebroadcastsRelative()
  353. {
  354. $sql = <<<SQL
  355. SELECT day_offset,
  356. start_time
  357. FROM cc_show_rebroadcast
  358. WHERE show_id = :showId
  359. ORDER BY day_offset
  360. SQL;
  361. return Application_Common_Database::prepareAndExecute( $sql,
  362. array( ':showId' => $this->getId() ), 'all' );
  363. }
  364. /**
  365. * Check whether the current show is set to repeat
  366. * repeating shows.
  367. *
  368. * @return boolean
  369. * true if repeating shows, otherwise false.
  370. */
  371. public function isRepeating()
  372. {
  373. $showDaysRow = CcShowDaysQuery::create()
  374. ->filterByDbShowId($this->_showId)
  375. ->findOne();
  376. if (!is_null($showDaysRow)) {
  377. return ($showDaysRow->getDbRepeatType() != -1);
  378. } else {
  379. return false;
  380. }
  381. }
  382. /**
  383. * Get the repeat type of the show. Show can have repeat type of
  384. * "weekly", "every 2 weeks", "monthly", "monthly on the same weekday",
  385. * "every 3 weeks" and "every 4 weeks". These values are represented
  386. * by 0, 1, 2, 3, 4 and 5, respectively.
  387. *
  388. * @return int
  389. * Return the integer corresponding to the repeat type.
  390. */
  391. public function getRepeatType()
  392. {
  393. $showDaysRow = CcShowDaysQuery::create()
  394. ->filterByDbShowId($this->_showId)
  395. ->findOne();
  396. if (!is_null($showDaysRow))
  397. return $showDaysRow->getDbRepeatType();
  398. else
  399. return -1;
  400. }
  401. /**
  402. * Get the end date for a repeating show in the format yyyy-mm-dd
  403. *
  404. * @return string
  405. * Return the end date for the repeating show or the empty
  406. * string if there is no end.
  407. */
  408. public function getRepeatingEndDate()
  409. {
  410. $sql = <<<SQL
  411. SELECT last_show
  412. FROM cc_show_days
  413. WHERE show_id = :showId
  414. ORDER BY last_show DESC
  415. SQL;
  416. $query = Application_Common_Database::prepareAndExecute( $sql,
  417. array( 'showId' => $this->getId() ), 'column' );
  418. /* TODO: Why return empty string instead of false? very confusing --RG
  419. */
  420. return ($query !== false) ? $query : "";
  421. }
  422. /**
  423. * Deletes all future instances of the current show object
  424. * from the show_instances table. This function is used when
  425. * a show is being edited - in some cases, when a show is edited
  426. * we just destroy all future show instances, and let another function
  427. * regenerate them later on. Note that this isn't always the most
  428. * desirable thing to do. Deleting a show instance and regenerating
  429. * it cause any scheduled playlists within those show instances to
  430. * be gone for good.
  431. */
  432. public function deleteAllInstances()
  433. {
  434. $sql = <<<SQL
  435. DELETE
  436. FROM cc_show_instances
  437. WHERE starts > :timestamp::TIMESTAMP
  438. AND show_id = :showId
  439. SQL;
  440. Application_Common_Database::prepareAndExecute( $sql,
  441. array( ':timestamp' => gmdate("Y-m-d H:i:s"),
  442. ':showId' => $this->getId()), 'execute');
  443. }
  444. /**
  445. * Deletes all future rebroadcast instances of the current
  446. * show object from the show_instances table.
  447. */
  448. public function deleteAllRebroadcasts()
  449. {
  450. $sql = <<<SQL
  451. DELETE
  452. FROM cc_show_instances
  453. WHERE starts > :timestamp::TIMESTAMP
  454. AND show_id :showId
  455. AND rebroadcast 1
  456. SQL;
  457. Application_Common_Database::prepareAndExecute( $sql,
  458. array( ':showId' => $this->getId(),
  459. ':timestamp' => gmdate("Y-m-d H:i:s")), 'execute');
  460. }
  461. /**
  462. * Get the start date of the current show in UTC timezone.
  463. *
  464. * @return string
  465. * The start date in the format YYYY-MM-DD or empty string in case
  466. * start date could not be found
  467. */
  468. public function getStartDateAndTime()
  469. {
  470. $con = Propel::getConnection();
  471. $showId = $this->getId();
  472. $stmt = $con->prepare(
  473. "SELECT first_show, start_time, timezone FROM cc_show_days"
  474. ." WHERE show_id = :showId"
  475. ." ORDER BY first_show"
  476. ." LIMIT 1");
  477. $stmt->bindParam(':showId', $showId);
  478. $stmt->execute();
  479. if (!$stmt) {
  480. return "";
  481. }
  482. $rows = $stmt->fetchAll();
  483. $row = $rows[0];
  484. $dt = new DateTime($row["first_show"]." ".$row["start_time"], new DateTimeZone($row["timezone"]));
  485. $dt->setTimezone(new DateTimeZone("UTC"));
  486. return $dt->format("Y-m-d H:i");
  487. }
  488. /**
  489. * Get the start date of the current show in UTC timezone.
  490. *
  491. * @return string
  492. * The start date in the format YYYY-MM-DD
  493. */
  494. public function getStartDate()
  495. {
  496. list($date,) = explode(" ", $this->getStartDateAndTime());
  497. return $date;
  498. }
  499. /**
  500. * Get the start time of the current show in UTC timezone.
  501. *
  502. * @return string
  503. * The start time in the format HH:MM
  504. */
  505. public function getStartTime()
  506. {
  507. list(,$time) = explode(" ", $this->getStartDateAndTime());
  508. return $time;
  509. }
  510. /**
  511. * Get the end date of the current show.
  512. * Note that this is not the end date of repeated show
  513. *
  514. * @return string
  515. * The end date in the format YYYY-MM-DD
  516. */
  517. public function getEndDate()
  518. {
  519. $startDate = $this->getStartDate();
  520. $startTime = $this->getStartTime();
  521. $duration = $this->getDuration();
  522. $startDateTime = new DateTime($startDate.' '.$startTime);
  523. $duration = explode(":", $duration);
  524. $endDate = $startDateTime->add(new DateInterval('PT'.$duration[0].'H'.$duration[1].'M'));
  525. return $endDate->format('Y-m-d');
  526. }
  527. /**
  528. * Get the end time of the current show.
  529. *
  530. * @return string
  531. * The start time in the format HH:MM:SS
  532. */
  533. public function getEndTime()
  534. {
  535. $startDate = $this->getStartDate();
  536. $startTime = $this->getStartTime();
  537. $duration = $this->getDuration();
  538. $startDateTime = new DateTime($startDate.' '.$startTime);
  539. $duration = explode(":", $duration);
  540. $endDate = $startDateTime->add(new DateInterval('PT'.$duration[0].'H'.$duration[1].'M'));
  541. return $endDate->format('H:i:s');
  542. }
  543. /**
  544. * Indicate whether the starting point of the show is in the
  545. * past.
  546. *
  547. * @return boolean
  548. * true if the StartDate is in the past, false otherwise
  549. */
  550. public function isStartDateTimeInPast()
  551. {
  552. return (gmdate("Y-m-d H:i:s") > ($this->getStartDate()." ".$this->getStartTime()));
  553. }
  554. /**
  555. * Get the ID's of future instance of the current show.
  556. *
  557. * @return array
  558. * A simple array containing all ID's of show instance
  559. * scheduled in the future.
  560. */
  561. public function getAllFutureInstanceIds()
  562. {
  563. $sql = <<<SQL
  564. SELECT id
  565. FROM cc_show_instances
  566. WHERE show_id = :showId
  567. AND starts > :timestamp::TIMESTAMP
  568. AND modified_instance != TRUE
  569. SQL;
  570. $rows = Application_Common_Database::prepareAndExecute($sql,
  571. array( ':showId' => $this->getId(),
  572. ':timestamp' => gmdate("Y-m-d H:i:s")), "all");
  573. $res = array();
  574. foreach ($rows as $r) {
  575. $res[] = $r['id'];
  576. }
  577. return $res;
  578. }
  579. /* Called when a show's duration is changed (edited).
  580. *
  581. * @param array $p_data
  582. * array containing the POST data about the show from the
  583. * browser.
  584. *
  585. */
  586. private function updateDurationTime($p_data)
  587. {
  588. //need to update cc_show_instances, cc_show_days
  589. $con = Propel::getConnection();
  590. $timestamp = gmdate("Y-m-d H:i:s");
  591. $stmt = $con->prepare("UPDATE cc_show_days "
  592. ."SET duration = :add_show_duration "
  593. ."WHERE show_id = :add_show_id" );
  594. $stmt->execute( array(
  595. ':add_show_duration' => $p_data['add_show_duration'],
  596. ':add_show_id' => $p_data['add_show_id']
  597. ));
  598. $sql = <<<SQL
  599. UPDATE cc_show_instances
  600. SET ends = starts + :add_show_duration::INTERVAL
  601. WHERE show_id = :show_id
  602. AND ends > :timestamp::TIMESTAMP
  603. SQL;
  604. Application_Common_Database::prepareAndExecute( $sql, array(
  605. ':add_show_duration' => $p_data['add_show_duration'],
  606. ':show_id' => $p_data['add_show_id'],
  607. ':timestamp' => $timestamp), "execute");
  608. }
  609. public function getDuration($format=false)
  610. {
  611. $showDay = CcShowDaysQuery::create()->filterByDbShowId($this->getId())->findOne();
  612. if (!$format) {
  613. return $showDay->getDbDuration();
  614. } else {
  615. $info = explode(':',$showDay->getDbDuration());
  616. return str_pad(intval($info[0]),2,'0',STR_PAD_LEFT).'h '.str_pad(intval($info[1]),2,'0',STR_PAD_LEFT).'m';
  617. }
  618. }
  619. public function getShowDays()
  620. {
  621. $showDays = CcShowDaysQuery::create()->filterByDbShowId(
  622. $this->getId())->find();
  623. $res = array();
  624. foreach ($showDays as $showDay) {
  625. $res[] = $showDay->getDbDay();
  626. }
  627. return $res;
  628. }
  629. /* Only used for shows that aren't repeating.
  630. *
  631. * @return Boolean: true if show has an instance, otherwise false. */
  632. public function hasInstance()
  633. {
  634. return (!is_null($this->getInstance()));
  635. }
  636. /* Only used for shows that aren't repeating.
  637. *
  638. * @return CcShowInstancesQuery: An propel object representing a
  639. * row in the cc_show_instances table. */
  640. public function getInstance()
  641. {
  642. $showInstance = CcShowInstancesQuery::create()
  643. ->filterByDbShowId($this->getId())
  644. ->findOne();
  645. return $showInstance;
  646. }
  647. /**
  648. * returns info about live stream override info
  649. */
  650. public function getLiveStreamInfo()
  651. {
  652. $info = array();
  653. if ($this->getId() == null) {
  654. return $info;
  655. } else {
  656. $ccShow = CcShowQuery::create()->findPK($this->_showId);
  657. $info['custom_username'] = $ccShow->getDbLiveStreamUser();
  658. $info['cb_airtime_auth'] = $ccShow->getDbLiveStreamUsingAirtimeAuth();
  659. $info['cb_custom_auth'] = $ccShow->getDbLiveStreamUsingCustomAuth();
  660. $info['custom_username'] = $ccShow->getDbLiveStreamUser();
  661. $info['custom_password'] = $ccShow->getDbLiveStreamPass();
  662. return $info;
  663. }
  664. }
  665. /* Only used for shows that are repeating. Note that this will return
  666. * true even for dates that only have a "modified" show instance (does not
  667. * check if the "modified_instance" column is set to true). This is intended
  668. * behaviour.
  669. *
  670. * @param $p_dateTime: Date for which we are checking if instance
  671. * exists.
  672. *
  673. * @return Boolean: true if show has an instance on $p_dateTime,
  674. * otherwise false. */
  675. public function hasInstanceOnDate($p_dateTime)
  676. {
  677. return (!is_null($this->getInstanceOnDate($p_dateTime)));
  678. }
  679. /* Only used for shows that are repeating. Note that this will return
  680. * shows that have been "modified" (does not check if the "modified_instance"
  681. * column is set to true). This is intended behaviour.
  682. *
  683. * @param $p_dateTime: Date for which we are getting an instance.
  684. *
  685. * @return CcShowInstancesQuery: An propel object representing a
  686. * row in the cc_show_instances table. */
  687. public function getInstanceOnDate($p_dateTime)
  688. {
  689. $timestamp = $p_dateTime->format("Y-m-d H:i:s");
  690. $sql = <<<SQL
  691. SELECT id
  692. FROM cc_show_instances
  693. WHERE date(starts) = date(:timestamp::TIMESTAMP)
  694. AND show_id = :showId
  695. AND rebroadcast = 0;
  696. SQL;
  697. try {
  698. $row = Application_Common_Database::prepareAndExecute( $sql,
  699. array( ':showId' => $this->getId(),
  700. ':timestamp' => $timestamp ), 'column');
  701. return CcShowInstancesQuery::create()
  702. ->findPk($row);
  703. } catch (Exception $e) {
  704. return null;
  705. }
  706. }
  707. /**
  708. *
  709. * Creates show instances that are scheduled after the shows_populated_until
  710. * value in cc_pref. If the show instances are linked their show content will
  711. * get filled.
  712. *
  713. * This can occur when a user is viewing the next day/week/month in the
  714. * calendar or when pypo is requesting the schedule after the shows_populated_until
  715. * date and time.
  716. */
  717. public static function createAndFillShowInstancesPastPopulatedUntilDate($needScheduleUntil)
  718. {
  719. //UTC DateTime object
  720. $showsPopUntil = Application_Model_Preference::GetShowsPopulatedUntil();
  721. //if application is requesting shows past our previous populated until date, generate shows up until this point.
  722. if (is_null($showsPopUntil) || $showsPopUntil->getTimestamp() < $needScheduleUntil->getTimestamp()) {
  723. $service_show = new Application_Service_ShowService();
  724. $ccShow = $service_show->delegateInstanceCreation(null, $needScheduleUntil, true);
  725. Application_Model_Preference::SetShowsPopulatedUntil($needScheduleUntil);
  726. }
  727. }
  728. /**
  729. * Get all the show instances in the given time range (inclusive).
  730. *
  731. * @param DateTime $start_timestamp
  732. * In UTC time.
  733. * @param DateTime $end_timestamp
  734. * In UTC time.
  735. * @param unknown_type $excludeInstance
  736. * @param boolean $onlyRecord
  737. * @param int $showId
  738. * limits the results to instances of a given showId only
  739. * @return array
  740. */
  741. public static function getShows($start_timestamp, $end_timestamp, $onlyRecord=FALSE, $showId=null)
  742. {
  743. self::createAndFillShowInstancesPastPopulatedUntilDate($end_timestamp);
  744. $sql = <<<SQL
  745. SELECT si1.starts AS starts,
  746. si1.ends AS ends,
  747. si1.record AS record,
  748. si1.rebroadcast AS rebroadcast,
  749. si2.starts AS parent_starts,
  750. si1.instance_id AS record_id,
  751. si1.show_id AS show_id,
  752. show.name AS name,
  753. show.color AS color,
  754. show.background_color AS background_color,
  755. show.linked AS linked,
  756. si1.file_id AS file_id,
  757. si1.id AS instance_id,
  758. si1.created AS created,
  759. si1.last_scheduled AS last_scheduled,
  760. si1.time_filled AS time_filled,
  761. f.soundcloud_id
  762. FROM cc_show_instances AS si1
  763. LEFT JOIN cc_show_instances AS si2 ON si1.instance_id = si2.id
  764. LEFT JOIN cc_show AS show ON show.id = si1.show_id
  765. LEFT JOIN cc_files AS f ON f.id = si1.file_id
  766. WHERE si1.modified_instance = FALSE
  767. SQL;
  768. //only want shows that are starting at the time or later.
  769. $start_string = $start_timestamp->format("Y-m-d H:i:s");
  770. $end_string = $end_timestamp->format("Y-m-d H:i:s");
  771. $params = array();
  772. if ($showId) {
  773. $sql .= " AND (si1.show_id = :show_id)";
  774. $params[':show_id'] = $showId;
  775. }
  776. if ($onlyRecord) {
  777. $sql .= " AND (si1.starts >= :start::TIMESTAMP AND si1.starts < :end::TIMESTAMP)";
  778. $sql .= " AND (si1.record = 1)";
  779. $params[':start'] = $start_string;
  780. $params[':end'] = $end_string;
  781. return Application_Common_Database::prepareAndExecute( $sql, $params, 'all');
  782. } else {
  783. $sql .= " ". <<<SQL
  784. AND ((si1.starts >= :start1::TIMESTAMP AND si1.starts < :end1::TIMESTAMP)
  785. OR (si1.ends > :start2::TIMESTAMP AND si1.ends <= :end2::TIMESTAMP)
  786. OR (si1.starts <= :start3::TIMESTAMP AND si1.ends >= :end3::TIMESTAMP))
  787. ORDER BY si1.starts
  788. SQL;
  789. $params = array_merge($params, array(
  790. 'start1' => $start_string,
  791. 'start2' => $start_string,
  792. 'start3' => $start_string,
  793. 'end1' => $end_string,
  794. 'end2' => $end_string,
  795. 'end3' => $end_string
  796. )
  797. );
  798. return Application_Common_Database::prepareAndExecute( $sql, $params, 'all');
  799. }
  800. }
  801. private static function setNextPop($next_date, $show_id, $day)
  802. {
  803. $nextInfo = explode(" ", $next_date);
  804. $repeatInfo = CcShowDaysQuery::create()
  805. ->filterByDbShowId($show_id)
  806. ->filterByDbDay($day)
  807. ->findOne();
  808. $repeatInfo->setDbNextPopDate($nextInfo[0])
  809. ->save();
  810. }
  811. /**
  812. *
  813. * @param DateTime $start
  814. * -in UTC time
  815. * @param DateTime $end
  816. * -in UTC time
  817. * @param boolean $editable
  818. */
  819. public static function &getFullCalendarEvents($p_start, $p_end, $p_editable=false)
  820. {
  821. $events = array();
  822. $interval = $p_start->diff($p_end);
  823. $days = $interval->format('%a');
  824. $shows = Application_Model_Show::getShows($p_start, $p_end);
  825. $content_count = Application_Model_ShowInstance::getContentCount(
  826. $p_start, $p_end);
  827. $isFull = Application_Model_ShowInstance::getIsFull($p_start, $p_end);
  828. $displayTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
  829. $utcTimezone = new DateTimeZone("UTC");
  830. $now = new DateTime("now", $utcTimezone);
  831. foreach ($shows as &$show) {
  832. $options = array();
  833. //only bother calculating percent for week or day view.
  834. if (intval($days) <= 7) {
  835. $options["percent"] = Application_Model_Show::getPercentScheduled($show["starts"], $show["ends"], $show["time_filled"]);
  836. }
  837. if (isset($show["parent_starts"])) {
  838. $parentStartsDT = new DateTime($show["parent_starts"], $utcTimezone);
  839. }
  840. $startsDT = DateTime::createFromFormat("Y-m-d G:i:s",
  841. $show["starts"], $utcTimezone);
  842. $endsDT = DateTime::createFromFormat("Y-m-d G:i:s",
  843. $show["ends"], $utcTimezone);
  844. if( $p_editable ) {
  845. if ($show["record"] && $now > $startsDT) {
  846. $options["editable"] = false;
  847. } elseif ($show["rebroadcast"] &&
  848. $now > $parentStartsDT) {
  849. $options["editable"] = false;
  850. } elseif ($now < $endsDT) {
  851. $options["editable"] = true;
  852. }
  853. }
  854. $startsDT->setTimezone($displayTimezone);
  855. $endsDT->setTimezone($displayTimezone);
  856. $options["show_empty"] = (array_key_exists($show['instance_id'],
  857. $content_count)) ? 0 : 1;
  858. if (array_key_exists($show['instance_id'], $isFull)) {
  859. $options["show_partial_filled"] = !$isFull[$show['instance_id']];
  860. } else {
  861. $options["show_partial_filled"] = true;
  862. }
  863. $event = array();
  864. $event["id"] = intval($show["instance_id"]);
  865. $event["title"] = $show["name"];
  866. $event["start"] = $startsDT->format("Y-m-d H:i:s");
  867. $event["end"] = $endsDT->format("Y-m-d H:i:s");
  868. $event["allDay"] = false;
  869. $event["showId"] = intval($show["show_id"]);
  870. $event["linked"] = intval($show["linked"]);
  871. $event["record"] = intval($show["record"]);
  872. $event["rebroadcast"] = intval($show["rebroadcast"]);
  873. $event["soundcloud_id"] = is_null($show["soundcloud_id"])
  874. ? -1 : $show["soundcloud_id"];
  875. //for putting the now playing icon on the show.
  876. if ($now > $startsDT && $now < $endsDT) {
  877. $event["nowPlaying"] = true;
  878. }
  879. else {
  880. $event["nowPlaying"] = false;
  881. }
  882. //event colouring
  883. if ($show["color"] != "") {
  884. $event["textColor"] = "#".$show["color"];
  885. }
  886. if ($show["background_color"] != "") {
  887. $event["color"] = "#".$show["background_color"];
  888. }
  889. foreach ($options as $key => $value) {
  890. $event[$key] = $value;
  891. }
  892. $events[] = $event;
  893. }
  894. return $events;
  895. }
  896. /**
  897. * Calculates the percentage of a show scheduled given the start and end times in date/time format
  898. * and the time_filled as the total time the schow is scheduled for in time format.
  899. *
  900. * TODO when using propel properly this should be a method on the propel show instance model.
  901. **/
  902. private static function getPercentScheduled($p_starts, $p_ends, $p_time_filled)
  903. {
  904. $utcTimezone = new DatetimeZone("UTC");
  905. $startDt = new DateTime($p_starts, $utcTimezone);
  906. $endDt = new DateTime($p_ends, $utcTimezone);
  907. $durationSeconds = intval($endDt->format("U")) - intval($startDt->format("U"));
  908. $time_filled = Application_Common_DateHelper::playlistTimeToSeconds($p_time_filled);
  909. if ($durationSeconds != 0) { //Prevent division by zero if the show duration somehow becomes zero.
  910. $percent = ceil(( $time_filled / $durationSeconds) * 100);
  911. } else {
  912. $percent = 0;
  913. }
  914. return $percent;
  915. }
  916. /**
  917. * Given time $timeNow, returns the show being played right now.
  918. * Times are all in UTC time.
  919. *
  920. * @param String $timeNow - current time (in UTC)
  921. * @return array - show being played right now
  922. */
  923. public static function getCurrentShow($timeNow=null)
  924. {
  925. $con = Propel::getConnection();
  926. if ($timeNow == null) {
  927. $timeNow = gmdate("Y-m-d H:i:s");
  928. }
  929. //TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin
  930. $sql = <<<SQL
  931. SELECT si.starts AS start_timestamp,
  932. si.ends AS end_timestamp,
  933. s.name,
  934. s.id,
  935. si.id AS instance_id,
  936. si.record,
  937. s.url,
  938. starts,
  939. ends
  940. FROM cc_show_instances si
  941. LEFT JOIN cc_show s
  942. ON si.show_id = s.id
  943. WHERE si.show_id = s.id
  944. AND si.starts <= :timeNow1::timestamp
  945. AND si.ends > :timeNow2::timestamp
  946. AND modified_instance != TRUE
  947. SQL;
  948. $stmt = $con->prepare($sql);
  949. $stmt->bindParam(':timeNow1', $timeNow);
  950. $stmt->bindParam(':timeNow2', $timeNow);
  951. if ($stmt->execute()) {
  952. $rows = $stmt->fetchAll();
  953. } else {
  954. $msg = implode(',', $stmt->errorInfo());
  955. throw new Exception("Error: $msg");
  956. }
  957. return $rows;
  958. }
  959. /**
  960. * Gets the current show, previous and next with an n-day window from
  961. * the given timeNow, so timeNow-2days and timeNow+$daysToRetrieve days.
  962. *
  963. * @param $utcNow A DateTime object containing the current time in UTC.
  964. * @return An array containing the previous show,
  965. * current show, and next show.
  966. */
  967. public static function getPrevCurrentNext($utcNow, $utcEndStr, $showsToRetrieve)
  968. {
  969. $timeZone = new DateTimeZone("UTC"); //This function works entirely in UTC.
  970. assert(get_class($utcNow) === "DateTime");
  971. assert($utcNow->getTimeZone() == $timeZone);
  972. $CC_CONFIG = Config::getConfig();
  973. $con = Propel::getConnection();
  974. // This will fetch the currently playing show first, then any
  975. // upcoming shows within our interval, and finally move on to
  976. // previous shows in the past 2 days.
  977. $sql = <<<SQL
  978. SELECT s.name,
  979. s.description,
  980. s.genre,
  981. s.id,
  982. si.id AS instance_id,
  983. si.record,
  984. s.url,
  985. s.image_path,
  986. starts,
  987. ends
  988. FROM cc_show_instances si
  989. LEFT JOIN cc_show s
  990. ON si.show_id = s.id
  991. WHERE si.show_id = s.id
  992. AND si.starts >= :timeNow::timestamp - INTERVAL '2 days'
  993. AND si.starts < :timeEnd::timestamp
  994. AND modified_instance != TRUE
  995. ORDER BY
  996. CASE
  997. WHEN si.ends > :timeNow::timestamp
  998. AND si.starts < :timeNow::timestamp THEN 1
  999. WHEN si.starts > :timeNow::timestamp THEN 2
  1000. ELSE 3
  1001. END
  1002. LIMIT :lim
  1003. SQL;
  1004. $stmt = $con->prepare($sql);
  1005. $utcNowStr = $utcNow->format("Y-m-d H:i:s");
  1006. $stmt->bindValue(':timeNow', $utcNowStr);
  1007. $stmt->bindValue(':timeEnd', $utcEndStr);
  1008. $stmt->bindValue(':lim', $showsToRetrieve);
  1009. if ($stmt->execute()) {
  1010. // use PDO::FETCH_ASSOC to only get the associative values
  1011. // note that fetchAll() defaults to PDO::FETCH_BOTH, which we don't want
  1012. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  1013. } else {
  1014. $msg = implode(',', $stmt->errorInfo());
  1015. throw new Exception("Error: $msg");
  1016. }
  1017. $numberOfRows = count($rows);
  1018. $results['previousShow'] = array();
  1019. $results['currentShow'] = null;
  1020. $results['nextShow'] = array();
  1021. for ($i = 0; $i < $numberOfRows; ++$i) {
  1022. // all shows start/end times are stored in the database as UTC.
  1023. $showStartTime = new DateTime($rows[$i]['starts'], $timeZone);
  1024. $showEndTime = new DateTime($rows[$i]['ends'], $timeZone);
  1025. // Find the show that is within the current time.
  1026. if (($showStartTime <= $utcNow) && ($showEndTime > $utcNow)) {
  1027. $results['currentShow'] = $rows[$i];
  1028. } else if ($showEndTime < $utcNow ) {
  1029. array_push($results['previousShow'], $rows[$i]);
  1030. } else if ($showStartTime > $utcNow) {
  1031. array_push($results['nextShow'], $rows[$i]);
  1032. }
  1033. }
  1034. return $results;
  1035. }
  1036. /**
  1037. * Gets the current show, previous and next with an 2day window from
  1038. * the given timeNow, so timeNow-2days and timeNow+2days.
  1039. *
  1040. * @param $utcNow A DateTime object containing the current time in UTC.
  1041. * @return An array (with stupid sub-arrays) containing the previous show id,
  1042. * current show id, and next show id.
  1043. * @deprecated
  1044. */
  1045. public static function getPrevCurrentNextOld($utcNow)
  1046. {
  1047. $timeZone = new DateTimeZone("UTC"); //This function works entirely in UTC.
  1048. assert(get_class($utcNow) === "DateTime");
  1049. assert($utcNow->getTimeZone() == $timeZone);
  1050. $CC_CONFIG = Config::getConfig();
  1051. $con = Propel::getConnection();
  1052. //TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin
  1053. $sql = <<<SQL
  1054. SELECT si.starts AS start_timestamp,
  1055. si.ends AS end_timestamp,
  1056. s.name,
  1057. s.description,
  1058. s.id,
  1059. si.id AS instance_id,
  1060. si.record,
  1061. s.url,
  1062. s.image_path,
  1063. starts,
  1064. ends
  1065. FROM cc_show_instances si
  1066. LEFT JOIN cc_show s
  1067. ON si.show_id = s.id
  1068. WHERE si.show_id = s.id
  1069. AND si.starts > :timeNow1::timestamp - INTERVAL '2 days'
  1070. AND si.ends < :timeNow2::timestamp + INTERVAL '2 days'
  1071. AND modified_instance != TRUE
  1072. ORDER BY si.starts
  1073. SQL;
  1074. $stmt = $con->prepare($sql);
  1075. $utcNowStr = $utcNow->format("Y-m-d H:i:s");
  1076. $stmt->bindValue(':timeNow1', $utcNowStr);
  1077. $stmt->bindValue(':timeNow2', $utcNowStr);
  1078. if ($stmt->execute()) {
  1079. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  1080. } else {
  1081. $msg = implode(',', $stmt->errorInfo());
  1082. throw new Exception("Error: $msg");
  1083. }
  1084. $numberOfRows = count($rows);
  1085. $results['previousShow'] = array();
  1086. $results['currentShow'] = array();
  1087. $results['nextShow'] = array();
  1088. for ($i = 0; $i < $numberOfRows; ++$i) {
  1089. //All shows start/end times are stored in the database as UTC.
  1090. $showStartTime = new DateTime($rows[$i]['starts'], $timeZone);
  1091. $showEndTime = new DateTime($rows[$i]['ends'], $timeZone);
  1092. //Find the show that is within the current time.
  1093. if (($showStartTime <= $utcNow) && ($showEndTime > $utcNow))
  1094. {
  1095. if ($i-1 >= 0) {
  1096. $results['previousShow'][0] = array(
  1097. "id" => $rows[$i-1]['id'],
  1098. "instance_id" => $rows[$i-1]['instance_id'],
  1099. "name" => $rows[$i-1]['name'],
  1100. "description" => $rows[$i-1]['description'],
  1101. "url" => $rows[$i-1]['url'],
  1102. "start_timestamp" => $rows[$i-1]['start_timestamp'],
  1103. "end_timestamp" => $rows[$i-1]['end_timestamp'],
  1104. "starts" => $rows[$i-1]['starts'],
  1105. "ends" => $rows[$i-1]['ends'],
  1106. "record" => $rows[$i-1]['record'],
  1107. "image_path" => $rows[$i-1]['image_path'],
  1108. "type" => "show");
  1109. }
  1110. $results['currentShow'][0] = $rows[$i];
  1111. if (isset($rows[$i+1])) {
  1112. $results['nextShow'][0] = array(
  1113. "id" => $rows[$i+1]['id'],
  1114. "instance_id" => $rows[$i+1]['instance_id'],
  1115. "name" => $rows[$i+1]['name'],
  1116. "description" => $rows[$i+1]['description'],
  1117. "url" => $rows[$i+1]['url'],
  1118. "start_timestamp" => $rows[$i+1]['start_timestamp'],
  1119. "end_timestamp" => $rows[$i+1]['end_timestamp'],
  1120. "starts" => $rows[$i+1]['starts'],
  1121. "ends" => $rows[$i+1]['ends'],
  1122. "record" => $rows[$i+1]['record'],
  1123. "image_path" => $rows[$i+1]['image_path'],
  1124. "type" => "show");
  1125. }
  1126. break;
  1127. }
  1128. //Previous is any row that ends after time now capture it in case we need it later.
  1129. if ($showEndTime < $utcNow ) {
  1130. $previousShowIndex = $i;
  1131. }
  1132. //if we hit this we know we've gone to far and can stop looping.
  1133. if ($showStartTime > $utcNow) {
  1134. $results['nextShow'][0] = array(
  1135. "id" => $rows[$i]['id'],
  1136. "instance_id" => $rows[$i]['instance_id'],
  1137. "name" => $rows[$i]['name'],
  1138. "description" => $rows[$i]['description'],
  1139. "url" => $rows[$i]['url'],
  1140. "start_timestamp" => $rows[$i]['start_timestamp'],
  1141. "end_timestamp" => $rows[$i]['end_timestamp'],
  1142. "starts" => $rows[$i]['starts'],
  1143. "ends" => $rows[$i]['ends'],
  1144. "record" => $rows[$i]['record'],
  1145. "image_path" => $rows[$i]['image_path'],
  1146. "type" => "show");
  1147. break;
  1148. }
  1149. }
  1150. //If we didn't find a a current show because the time didn't fit we may still have
  1151. //found a previous show so use it.
  1152. if (count($results['previousShow']) == 0 && isset($previousShowIndex)) {
  1153. $results['previousShow'][0] = array(
  1154. "id" => $rows[$previousShowIndex]['id'],
  1155. "instance_id" => $rows[$previousShowIndex]['instance_id'],
  1156. "name" => $rows[$previousShowIndex]['name'],
  1157. "description" => $rows[$previousShowIndex]['description'],
  1158. "start_timestamp" => $rows[$previousShowIndex]['start_timestamp'],
  1159. "end_timestamp" => $rows[$previousShowIndex]['end_timestamp'],
  1160. "starts" => $rows[$previousShowIndex]['starts'],
  1161. "ends" => $rows[$previousShowIndex]['ends'],
  1162. "record" => $rows[$previousShowIndex]['record'],
  1163. "type" => "show");
  1164. }
  1165. return $results;
  1166. }
  1167. /**
  1168. * Given a start time $timeStart and end time $timeEnd, returns the next $limit
  1169. * number of shows within the time interval
  1170. * If $timeEnd not given, shows within next 48 hours from $timeStart are returned
  1171. * If $limit not given, all shows within the intervals are returned
  1172. * Times are all in UTC time.
  1173. *
  1174. * @param String $timeStart - interval start time (in UTC)
  1175. * @param int $limit - number of shows to return
  1176. * @param String $timeEnd - interval end time (in UTC)
  1177. * @return array - the next $limit number of shows within the time interval
  1178. */
  1179. public static function getNextShows($timeStart, $limit = "ALL", $timeEnd = "")
  1180. {
  1181. // defaults to retrieving shows from next 2 days if no end time has
  1182. // been specified
  1183. if ($timeEnd == "") {
  1184. $timeEnd = "'$timeStart' + INTERVAL '2 days'";
  1185. }
  1186. //TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin
  1187. $sql = <<<SQL
  1188. SELECT si.starts AS start_timestamp,
  1189. si.ends AS end_timestamp,
  1190. s.name,
  1191. s.id,
  1192. si.id AS instance_id,
  1193. si.record,
  1194. s.url,
  1195. starts,
  1196. ends
  1197. FROM cc_show_instances si
  1198. LEFT JOIN cc_show s
  1199. ON si.show_id = s.id
  1200. WHERE si.show_id = s.id
  1201. AND si.starts >= :timeStart::timestamp
  1202. AND si.starts < :timeEnd::timestamp
  1203. AND modified_instance != TRUE
  1204. ORDER BY si.starts
  1205. SQL;
  1206. //PDO won't accept "ALL" as a limit value (complains it is not an
  1207. //integer, and so we must completely remove the limit clause if we
  1208. //want to show all results - MK
  1209. if ($limit != "ALL") {
  1210. $sql .= PHP_EOL."LIMIT :lim";
  1211. $params = array(
  1212. ':timeStart' => $timeStart,
  1213. ':timeEnd' => $timeEnd,
  1214. ':lim' => $limit);
  1215. } else {
  1216. $params = array(
  1217. ':timeStart' => $timeStart,
  1218. ':timeEnd' => $timeEnd);
  1219. }
  1220. return Application_Common_Database::prepareAndExecute( $sql, $params, 'all');
  1221. }
  1222. public static function getMaxLengths()
  1223. {
  1224. $sql = <<<SQL
  1225. SELECT column_name, character_maximum_length FROM information_schema.columns
  1226. WHERE table_name = 'cc_show' AND character_maximum_length > 0
  1227. SQL;
  1228. $result = Application_Common_Database::prepareAndExecute($sql);
  1229. $assocArray = array();
  1230. foreach ($result as $row) {
  1231. $assocArray[$row['column_name']] = $row['character_maximum_length'];
  1232. }
  1233. return $assocArray;
  1234. }
  1235. public static function getStartEndCurrentMonthView() {
  1236. $first_day_of_calendar_month_view = mktime(0, 0, 0, date("n"), 1);
  1237. $weekStart = Application_Model_Preference::GetWeekStartDay();
  1238. while (date('w', $first_day_of_calendar_month_view) != $weekStart) {
  1239. $first_day_of_calendar_month_view -= 60*60*24;
  1240. }
  1241. $last_day_of_calendar_view = $first_day_of_calendar_month_view + 3600*24*42;
  1242. $start = new DateTime("@".$first_day_of_calendar_month_view);
  1243. $end = new DateTime("@".$last_day_of_calendar_view);
  1244. return array($start, $end);
  1245. }
  1246. public static function getStartEndCurrentWeekView() {
  1247. $first_day_of_calendar_week_view = mktime(0, 0, 0, date("n"), date("j"));
  1248. $weekStart = Application_Model_Preference::GetWeekStartDay();
  1249. while (date('w', $first_day_of_calendar_week_view) != $weekStart) {
  1250. $first_day_of_calendar_week_view -= 60*60*24;
  1251. }
  1252. $last_day_of_calendar_view = $first_day_of_calendar_week_view + 3600*24*7;
  1253. $start = new DateTime("@".$first_day_of_calendar_week_view);
  1254. $end = new DateTime("@".$last_day_of_calendar_view);
  1255. return array($start, $end);
  1256. }
  1257. public static function getStartEndCurrentDayView() {
  1258. $today = mktime(0, 0, 0, date("n"), date("j"));
  1259. $tomorrow = $today + 3600*24;
  1260. $start = new DateTime("@".$today);
  1261. $end = new DateTime("@".$tomorrow);
  1262. return array($start, $end);
  1263. }
  1264. }