ShowService.php 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813
  1. <?php
  2. define("MAX_REBROADCAST_DATES", 10);
  3. define("NO_REPEAT", -1);
  4. define("REPEAT_WEEKLY", 0);
  5. define("REPEAT_BI_WEEKLY", 1);
  6. define("REPEAT_MONTHLY_MONTHLY", 2);
  7. define("REPEAT_MONTHLY_WEEKLY", 3);
  8. define("REPEAT_TRI_WEEKLY", 4);
  9. define("REPEAT_QUAD_WEEKLY", 5);
  10. class Application_Service_ShowService
  11. {
  12. private $ccShow;
  13. private $isRecorded;
  14. private $isRebroadcast;
  15. private $repeatType;
  16. private $isUpdate;
  17. private $oldShowTimezone;
  18. private $localShowStartHour;
  19. private $localShowStartMin;
  20. private $origCcShowDay;
  21. private $origShowRepeatStatus;
  22. private $instanceIdsForScheduleUpdates;
  23. //keeps track of which show instances are new from either adding a new show
  24. //day or changing the repeat type day during a show edit, or when a user moves
  25. //forward in the calendar
  26. private $newInstanceIdsCreated;
  27. public function __construct($showId=null, $showData=null, $isUpdate=false)
  28. {
  29. if (!is_null($showId)) {
  30. $this->ccShow = CcShowQuery::create()->findPk($showId);
  31. }
  32. if (isset($showData["add_show_repeats"]) && $showData["add_show_repeats"]) {
  33. $this->repeatType = $showData["add_show_repeat_type"];
  34. if ($showData["add_show_repeat_type"] == 2) {
  35. $this->repeatType = $showData["add_show_monthly_repeat_type"];
  36. }
  37. } else {
  38. $this->repeatType = -1;
  39. }
  40. $this->isRecorded = (isset($showData['add_show_record']) && $showData['add_show_record']) ? 1 : 0;
  41. $this->isRebroadcast = (isset($showData['add_show_rebroadcast']) && $showData['add_show_rebroadcast']) ? 1 : 0;
  42. $this->isUpdate = $isUpdate;
  43. $this->instanceIdsForScheduleUpdates = array();
  44. $this->newInstanceIdsCreated = array();
  45. }
  46. public function editRepeatingShowInstance($showData) {
  47. $service_user = new Application_Service_UserService();
  48. $currentUser = $service_user->getCurrentUser();
  49. $showData["add_show_duration"] = $this->formatShowDuration(
  50. $showData["add_show_duration"]);
  51. $con = Propel::getConnection();
  52. $con->beginTransaction();
  53. try {
  54. if (!$currentUser->isAdminOrPM()) {
  55. throw new Exception("Permission denied");
  56. }
  57. $showId = $showData["add_show_id"];
  58. /****** UPDATE SCHEDULE START TIME ******/
  59. //get the ccShow object to which this instance belongs
  60. //so we can get the original start date and time
  61. $this->ccShow = CcShowQuery::create()
  62. ->findPk($showId);
  63. //DateTime in shows's local time
  64. $newStartDateTime = new DateTime($showData["add_show_start_date"]." ".
  65. $showData["add_show_start_time"],
  66. new DateTimeZone($showData["add_show_timezone"]));
  67. $ccShowInstanceOrig = CcShowInstancesQuery::create()
  68. ->findPk($showData["add_show_instance_id"]);
  69. //convert original start time into the show's local timezone
  70. $origLocalStartDateTime = $ccShowInstanceOrig->getLocalStartDateTime();
  71. $diff = $this->calculateShowStartDiff($newStartDateTime,
  72. $origLocalStartDateTime);
  73. if ($diff != 0) {
  74. Application_Service_SchedulerService::updateScheduleStartTime(
  75. array($showData["add_show_instance_id"]), $diff);
  76. }
  77. /****** UPDATE SCHEDULE START TIME ENDS******/
  78. /*
  79. * In the case where an instance is being edited for a second
  80. * (or third, fourth, etc.) time we need to delete the old
  81. * cc_show_day record
  82. *
  83. * Since we don't store the cc_show_day ids we need to use the
  84. * original start time from cc_show_instances, convert it to the show's
  85. * local timezone, and find the record in cc_show_days
  86. *
  87. * *** There is a flaw here: We have to assume the show timezone has
  88. * *** not changed (make timezone readonly??)
  89. */
  90. $origCcShowDay = CcShowDaysQuery::create()
  91. ->filterByDbShowId($showId)
  92. ->filterByDbRepeatType(-1)
  93. ->filterByDbFirstShow($origLocalStartDateTime->format("Y-m-d"))
  94. ->filterByDbStartTime($origLocalStartDateTime->format("H:i:s"))
  95. ->delete();
  96. /*
  97. * Set the new cc_show_day record
  98. * Associates it with the current show_id and sets it to non-repeating
  99. */
  100. $this->setCcShowDays($showData);
  101. /*
  102. * We need to find the new show day rule we just created by passing
  103. * in the first show and start time in case multiple single
  104. * instances have been edited out of the repeating sequence.
  105. */
  106. $showDay = CcShowDaysQuery::create()
  107. ->filterByDbShowId($showId)
  108. ->filterByDbRepeatType(-1)
  109. ->filterByDbFirstShow($showData["add_show_start_date"])
  110. ->filterByDbStartTime($showData["add_show_start_time"].":00")
  111. ->findOne();
  112. $ccShowInstance = $this->createNonRepeatingInstance($showDay,
  113. $this->getPopulateShowUntilDateTIme());
  114. //update cc_schedule with the new instance id
  115. $con = Propel::getConnection(CcShowInstancesPeer::DATABASE_NAME);
  116. $selectCriteria = new Criteria();
  117. $selectCriteria->add(CcSchedulePeer::INSTANCE_ID, $showData["add_show_instance_id"]);
  118. $updateCriteria = new Criteria();
  119. $updateCriteria->add(CcSchedulePeer::INSTANCE_ID, $ccShowInstance->getDbId());
  120. BasePeer::doUpdate($selectCriteria, $updateCriteria, $con);
  121. $ccShowInstance->updateDbTimeFilled($con);
  122. $ccShowInstance->updateScheduleStatus($con);
  123. //delete the edited instance from the repeating sequence
  124. $ccShowInstanceOrig->setDbModifiedInstance(true)->save();
  125. $con->commit();
  126. Application_Model_RabbitMq::PushSchedule();
  127. } catch (Exception $e) {
  128. $con->rollback();
  129. Logging::info("EXCEPTION: Show update failed.");
  130. Logging::info($e->getMessage());
  131. }
  132. }
  133. /**
  134. *
  135. * If a user is editing a show we need to store the original timezone and
  136. * start time in case the show's timezone is changed and we are crossing
  137. * over DST
  138. */
  139. private function storeOrigLocalShowInfo()
  140. {
  141. if ($this->ccShow->isRepeating()) {
  142. $this->origCcShowDay = clone $this->ccShow->getFirstRepeatingCcShowDay();
  143. $this->origShowRepeatStatus = true;
  144. } else {
  145. $this->origCcShowDay = clone $this->ccShow->getFirstCcShowDay();
  146. $this->origShowRepeatStatus = false;
  147. }
  148. $this->oldShowTimezone = $this->origCcShowDay->getDbTimezone();
  149. $origStartTime = explode(":", $this->origCcShowDay->getDbStartTime());
  150. $this->localShowStartHour = $origStartTime[0];
  151. $this->localShowStartMin = $origStartTime[1];
  152. }
  153. public function addUpdateShow($showData)
  154. {
  155. $service_user = new Application_Service_UserService();
  156. $currentUser = $service_user->getCurrentUser();
  157. $showData["add_show_duration"] = $this->formatShowDuration(
  158. $showData["add_show_duration"]);
  159. $con = Propel::getConnection();
  160. $con->beginTransaction();
  161. try {
  162. if (!$currentUser->isAdminOrPM()) {
  163. throw new Exception("Permission denied");
  164. }
  165. //update ccShow
  166. $this->setCcShow($showData);
  167. $daysAdded = array();
  168. if ($this->isUpdate) {
  169. if (!$this->ccShow->getCcShowDayss()->isEmpty()) {
  170. $this->storeOrigLocalShowInfo();
  171. }
  172. $daysAdded = $this->delegateInstanceCleanup($showData);
  173. $this->deleteRebroadcastInstances();
  174. $this->deleteCcShowHosts();
  175. if ($this->isRebroadcast) {
  176. //delete entry in cc_show_rebroadcast
  177. $this->deleteCcShowRebroadcasts();
  178. }
  179. $this->storeInstanceIds();
  180. }
  181. //update ccShowDays
  182. $this->setCcShowDays($showData);
  183. //update ccShowRebroadcasts
  184. $this->setCcShowRebroadcasts($showData);
  185. //update ccShowHosts
  186. $this->setCcShowHosts($showData);
  187. //create new ccShowInstances
  188. $this->delegateInstanceCreation($daysAdded);
  189. if ($this->isUpdate) {
  190. /* If the show is repeating and the start date changes we need
  191. * to ignore that difference when re-calculating schedule start times.
  192. * Otherwise it might calculate a difference of a week, for example.
  193. */
  194. if ($this->ccShow->isRepeating() &&
  195. $this->origCcShowDay->getLocalStartDateAndTime()->format("Y-m-d") != $showData["add_show_start_date"]) {
  196. $showData["add_show_start_date"] = $this->origCcShowDay->getLocalStartDateAndTime()->format("Y-m-d");
  197. }
  198. $this->adjustSchedule($showData);
  199. }
  200. $con->commit();
  201. Application_Model_RabbitMq::PushSchedule();
  202. } catch (Exception $e) {
  203. $con->rollback();
  204. $this->isUpdate ? $action = "update" : $action = "creation";
  205. Logging::info("EXCEPTION: Show ".$action." failed.");
  206. Logging::info($e->getMessage());
  207. }
  208. }
  209. /**
  210. *
  211. * Returns an array of instance ids that already exist
  212. * We need this if a show is being updated so we can separate the
  213. * instances that already exist and any new instances that
  214. * get created (by adding a new repeat show day)
  215. */
  216. private function storeInstanceIds()
  217. {
  218. $instances = $this->ccShow->getFutureCcShowInstancess();
  219. foreach ($instances as $instance) {
  220. $this->instanceIdsForScheduleUpdates[] = $instance->getDbId();
  221. }
  222. }
  223. /**
  224. *
  225. * Adjusts the items in cc_schedule to reflect the
  226. * new (if one) start and end time of the show getting updated
  227. * @param $showData
  228. */
  229. private function adjustSchedule($showData)
  230. {
  231. $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME);
  232. $this->updateScheduleStartEndTimes($showData);
  233. $ccShowInstances = $this->ccShow->getFutureCcShowInstancess();
  234. foreach ($ccShowInstances as $instance) {
  235. $instance->updateScheduleStatus($con);
  236. }
  237. }
  238. /**
  239. *
  240. * Receives a cc_show id and determines whether to create a
  241. * single show instance or repeating show instances
  242. */
  243. public function delegateInstanceCreation($daysAdded=null, $end=null, $fillInstances=false)
  244. {
  245. $populateUntil = $this->getPopulateShowUntilDateTIme();
  246. if (is_null($this->ccShow)) {
  247. $ccShowDays = $this->getShowDaysInRange($populateUntil, $end);
  248. } else {
  249. if ($this->ccShow->isRepeating()) {
  250. $ccShowDays = $this->ccShow->getRepeatingCcShowDays();
  251. } else {
  252. //$ccShowDays = $this->ccShow->getCcShowDayss();
  253. /* Cannot use the above statement to get the cc_show_days
  254. * object because it's getting the old object before the
  255. * show was edited. clearInstancePool() didn't work.
  256. */
  257. $ccShowDays = CcShowDaysQuery::create()
  258. ->filterByDbShowId($this->ccShow->getDbId())
  259. ->find();
  260. }
  261. }
  262. if (!is_null($end)) {
  263. $populateUntil = $end;
  264. }
  265. /* In case the user is moving forward in the calendar and there are
  266. * linked shows in the schedule we need to keep track of each cc_show
  267. * so we know which shows need to be filled with content
  268. */
  269. $ccShows = array();
  270. foreach ($ccShowDays as $day) {
  271. $this->ccShow = $day->getCcShow();
  272. $this->isRecorded = $this->ccShow->isRecorded();
  273. $this->isRebroadcast = $this->ccShow->isRebroadcast();
  274. $show_id = $day->getDbShowId();
  275. if (!isset($ccShows[$show_id])) {
  276. $ccShows[$show_id] = $day->getccShow();
  277. }
  278. //keep track of the new show instances getting created
  279. //so we can fill their schedule after
  280. if (!isset($this->newInstanceIdsCreated[$show_id])) {
  281. $this->newInstanceIdsCreated[$show_id] = array();
  282. }
  283. switch ($day->getDbRepeatType()) {
  284. case NO_REPEAT:
  285. $this->createNonRepeatingInstance($day, $populateUntil);
  286. break;
  287. case REPEAT_WEEKLY:
  288. $this->createWeeklyRepeatInstances($day, $populateUntil, REPEAT_WEEKLY,
  289. new DateInterval("P7D"), $daysAdded);
  290. break;
  291. case REPEAT_BI_WEEKLY:
  292. $this->createWeeklyRepeatInstances($day, $populateUntil, REPEAT_BI_WEEKLY,
  293. new DateInterval("P14D"), $daysAdded);
  294. break;
  295. case REPEAT_TRI_WEEKLY:
  296. $this->createWeeklyRepeatInstances($day, $populateUntil, REPEAT_TRI_WEEKLY,
  297. new DateInterval("P21D"), $daysAdded);
  298. break;
  299. case REPEAT_QUAD_WEEKLY:
  300. $this->createWeeklyRepeatInstances($day, $populateUntil, REPEAT_QUAD_WEEKLY,
  301. new DateInterval("P28D"), $daysAdded);
  302. break;
  303. case REPEAT_MONTHLY_MONTHLY:
  304. $this->createMonthlyRepeatInstances($day, $populateUntil);
  305. break;
  306. case REPEAT_MONTHLY_WEEKLY:
  307. $this->createMonthlyRepeatInstances($day, $populateUntil);
  308. break;
  309. }
  310. }
  311. foreach ($ccShows as $ccShow) {
  312. if (($this->isUpdate || $fillInstances) && $ccShow->isLinked()) {
  313. Application_Service_SchedulerService::fillLinkedInstances(
  314. $ccShow, $this->newInstanceIdsCreated[$ccShow->getDbId()]);
  315. }
  316. }
  317. /*if (isset($this->linkedShowContent)) {
  318. Application_Service_SchedulerService::fillPreservedLinkedShowContent(
  319. $this->ccShow, $this->linkedShowContent);
  320. }*/
  321. return $this->ccShow;
  322. }
  323. private function getShowDaysInRange($start, $end)
  324. {
  325. $endTimeString = $end->format("Y-m-d H:i:s");
  326. if (!is_null($start)) {
  327. $startTimeString = $start->format("Y-m-d H:i:s");
  328. } else {
  329. $today_timestamp = new DateTime("now", new DateTimeZone("UTC"));
  330. $startTimeString = $today_timestamp->format("Y-m-d H:i:s");
  331. }
  332. $c = new Criteria();
  333. $c->add(CcShowDaysPeer::FIRST_SHOW, $endTimeString, Criteria::LESS_THAN);
  334. $c->addAnd(CcShowDaysPeer::LAST_SHOW, $startTimeString, Criteria::GREATER_THAN);
  335. $c->addAnd(CcShowDaysPeer::REPEAT_TYPE, -1, Criteria::NOT_EQUAL);
  336. $c->addOr(CcShowDaysPeer::LAST_SHOW, null, Criteria::ISNULL);
  337. return CcShowDaysPeer::doSelect($c);
  338. }
  339. public static function formatShowDuration($duration)
  340. {
  341. $hPos = strpos($duration, 'h');
  342. $mPos = strpos($duration, 'm');
  343. $hValue = 0;
  344. $mValue = 0;
  345. if ($hPos !== false) {
  346. $hValue = trim(substr($duration, 0, $hPos));
  347. }
  348. if ($mPos !== false) {
  349. $hPos = $hPos === false ? 0 : $hPos+1;
  350. $mValue = trim(substr($duration, $hPos, -1 ));
  351. }
  352. return $hValue.":".$mValue;
  353. }
  354. /**
  355. *
  356. * Deletes all the cc_show_days entries for a specific show
  357. * that is currently being edited. They will get recreated with
  358. * the new show day specs
  359. */
  360. private function deleteCcShowDays()
  361. {
  362. CcShowDaysQuery::create()->filterByDbShowId($this->ccShow->getDbId())->delete();
  363. }
  364. private function deleteRebroadcastInstances()
  365. {
  366. $sql = <<<SQL
  367. DELETE FROM cc_show_instances
  368. WHERE starts > :timestamp::TIMESTAMP
  369. AND show_id = :showId
  370. AND rebroadcast = 1;
  371. SQL;
  372. Application_Common_Database::prepareAndExecute( $sql, array(
  373. ':showId' => $this->ccShow->getDbId(),
  374. ':timestamp' => gmdate("Y-m-d H:i:s")), 'execute');
  375. }
  376. private function deleteAllShowDays($showId)
  377. {
  378. CcShowDaysQuery::create()
  379. ->filterByDbShowId($showId)
  380. ->delete();
  381. }
  382. /**
  383. * TODO: This function is messy. Needs refactoring
  384. *
  385. * When editing a show we may need to perform some actions to reflect the new specs:
  386. * - Delete some show instances
  387. * - Update duration
  388. * - Update start and end time
  389. *
  390. * @param $showData edit show form values in raw form
  391. * @param $isRecorded value computed from the edit show form
  392. * @param $repeatType value computed from the edit show form
  393. */
  394. private function delegateInstanceCleanup($showData)
  395. {
  396. $showId = $this->ccShow->getDbId();
  397. $daysAdded = array();
  398. //CcShowDay object
  399. if ($this->ccShow->isRepeating()) {
  400. $currentShowDay = $this->ccShow->getFirstRepeatingCcShowDay();
  401. //all cc_show_days
  402. $ccShowDays = $this->ccShow->getRepeatingCcShowDays();
  403. } else {
  404. $currentShowDay = $this->ccShow->getFirstCcShowDay();
  405. //all cc_show_days
  406. $ccShowDays = $this->ccShow->getCcShowDayss();
  407. }
  408. //new end date in the show's timezone (from the select box)
  409. $endDateTime = $this->calculateEndDate($showData);
  410. //repeat option was toggled
  411. if ($showData['add_show_repeats'] != $currentShowDay->isRepeating()) {
  412. $this->deleteAllRepeatInstances($currentShowDay, $showId);
  413. if (!$showData["add_show_repeats"]) {
  414. $this->deleteAllShowDays($showId);
  415. }
  416. //if repeat option was checked we need to treat the current show day
  417. //as a new show day so the repeat instances get created properly
  418. //in createWeeklyRepeatInstances()
  419. if ($showData['add_show_repeats']) {
  420. array_push($daysAdded, $currentShowDay->getDbDay());
  421. }
  422. }
  423. if ($showData['add_show_repeats']) {
  424. $localShowStart = $currentShowDay->getLocalStartDateAndTime();
  425. //if the start date changes, these are the repeat types
  426. //that require show instance deletion
  427. $deleteRepeatTypes = array(REPEAT_BI_WEEKLY, REPEAT_TRI_WEEKLY, REPEAT_QUAD_WEEKLY, REPEAT_MONTHLY_MONTHLY,
  428. REPEAT_MONTHLY_WEEKLY);
  429. if (in_array($this->repeatType, $deleteRepeatTypes) &&
  430. $showData["add_show_start_date"] != $localShowStart->format("Y-m-d")) {
  431. //Start date has changed when repeat type is bi-weekly or monthly.
  432. //This screws up the repeating positions of show instances, so
  433. //we need to delete them (CC-2351)
  434. $this->deleteAllInstances($showId);
  435. }
  436. $currentRepeatType = $currentShowDay->getDbRepeatType();
  437. //only delete instances if the show being edited was already repeating
  438. //and the repeat type changed
  439. if ($currentRepeatType != -1 && $this->repeatType != $currentRepeatType) {
  440. $this->deleteAllInstances($showId);
  441. $this->deleteAllShowDays($showId);
  442. // when repeating by day of the month (1st, 2nd, etc.) we do not store the repeat week days
  443. } elseif ($currentRepeatType != 2) {
  444. //repeat type is the same, check if the days of the week are the same
  445. $repeatingDaysChanged = false;
  446. $showDays = array();
  447. foreach ($ccShowDays as $day) {
  448. $showDays[] = $day->getDbDay();
  449. }
  450. if (count($showData['add_show_day_check']) == count($showDays)) {
  451. //same number of days checked, lets see if they are the same numbers
  452. $intersect = array_intersect($showData['add_show_day_check'], $showDays);
  453. if (count($intersect) != count($showData['add_show_day_check'])) {
  454. $repeatingDaysChanged = true;
  455. }
  456. } else {
  457. $repeatingDaysChanged = true;
  458. }
  459. if ($repeatingDaysChanged) {
  460. $daysRemoved = array_diff($showDays, $showData['add_show_day_check']);
  461. $newDays = array_diff($showData["add_show_day_check"], $showDays);
  462. foreach ($newDays as $newDay) {
  463. array_push($daysAdded, $newDay);
  464. }
  465. if (count($daysRemoved) > 0) {
  466. //delete repeating show instances for the repeating
  467. //days that were removed
  468. /*if ($this->ccShow->isLinked()) {
  469. $this->preserveLinkedShowContent();
  470. }*/
  471. $this->deleteRemovedShowDayInstances($daysRemoved,
  472. $ccShowDays, $showId);
  473. }
  474. }
  475. if ($showData['add_show_start_date'] != $localShowStart->format("Y-m-d")
  476. || $showData['add_show_start_time'] != $localShowStart->format("H:i")) {
  477. //start date has been pushed forward so we need to delete
  478. //any instances of this show scheduled before the new start date
  479. if ($showData['add_show_start_date'] > $localShowStart->format("Y-m-d")) {
  480. $this->deleteInstancesBeforeDate($showData['add_show_start_date'], $showId);
  481. }
  482. }
  483. }
  484. //get the endate from the past for this show.
  485. //check if this is null if "no end"
  486. $currentShowEndDateTime = $this->getRepeatingEndDate();
  487. if ($endDateTime && $currentShowEndDateTime != $endDateTime) {
  488. $endDate = clone $endDateTime;
  489. $endDate->setTimezone(new DateTimeZone("UTC"));
  490. //show's "No End" option was toggled
  491. //or the end date comes earlier
  492. if (is_null($currentShowEndDateTime) || ($endDateTime < $currentShowEndDateTime)) {
  493. //"No End" option was unchecked so we need to delete the
  494. //repeat instances that are scheduled after the new end date
  495. //OR
  496. //end date was pushed back so we have to delete any
  497. //instances of this show scheduled after the new end date
  498. $this->deleteInstancesFromDate($endDate->format("Y-m-d"), $showId);
  499. }
  500. }
  501. }
  502. return $daysAdded;
  503. }
  504. /*private function preserveLinkedShowContent()
  505. {
  506. // Get show content from any future linked instance. It doesn't
  507. // matter which instance since content is the same in all.
  508. //
  509. $ccShowInstance = $this->ccShow->getFutureCcShowInstancess()->getFirst();
  510. if (!$ccShowInstance) {
  511. return;
  512. }
  513. $ccSchedules = CcScheduleQuery::create()
  514. ->filterByDbInstanceId($ccShowInstance->getDbId())
  515. ->find();
  516. if (!$ccSchedules->isEmpty()) {
  517. $this->linkedShowContent = $ccSchedules;
  518. }
  519. }*/
  520. /*
  521. * returns a DateTime of the current show end date set to the timezone of the show.
  522. */
  523. public function getRepeatingEndDate()
  524. {
  525. $sql = <<<SQL
  526. SELECT last_show, timezone
  527. FROM cc_show_days
  528. WHERE show_id = :showId
  529. ORDER BY last_show DESC
  530. LIMIT 1
  531. SQL;
  532. $query = Application_Common_Database::prepareAndExecute( $sql,
  533. array( 'showId' => $this->ccShow->getDbId() ), 'single');
  534. $date = null;
  535. if ($query !== false && isset($query["last_show"])) {
  536. $date = new DateTime(
  537. $query["last_show"],
  538. new DateTimeZone($query["timezone"])
  539. );
  540. }
  541. return $date;
  542. }
  543. private function deleteInstancesFromDate($endDate, $showId)
  544. {
  545. $sql = <<<SQL
  546. DELETE FROM cc_show_instances
  547. WHERE date(starts) >= :endDate::DATE
  548. AND starts > :timestamp::TIMESTAMP
  549. AND show_id = :showId
  550. SQL;
  551. Application_Common_Database::prepareAndExecute($sql, array(
  552. ':endDate' => $endDate, ':timestamp' => gmdate("Y-m-d H:i:s"),
  553. ':showId' => $showId), 'execute');
  554. }
  555. private function deleteInstancesBeforeDate($newStartDate, $showId)
  556. {
  557. $sql = <<<SQL
  558. DELETE
  559. FROM cc_show_instances
  560. WHERE date(starts) < :newStartDate::DATE
  561. AND starts > :timestamp::TIMESTAMP
  562. AND show_id = :showId
  563. SQL;
  564. Application_Common_Database::prepareAndExecute($sql, array(
  565. ":newStartDate" => $newStartDate, ":timestamp" => gmdate("Y-m-d H:i:s"),
  566. ":showId" => $showId), "execute");
  567. }
  568. /**
  569. *
  570. * Enter description here ...
  571. * @param $daysRemoved array of days (days of the week) removed
  572. * (days of the week are represented numerically
  573. * 0=>sunday, 1=>monday, 2=>tuesday, etc.)
  574. * @param $showDays array of ccShowDays objects
  575. * @param $showId
  576. */
  577. private function deleteRemovedShowDayInstances($daysRemoved, $showDays, $showId)
  578. {
  579. $daysRemovedUTC = array();
  580. //convert the start day of the week to UTC
  581. foreach ($showDays as $showDay) {
  582. if (in_array($showDay->getDbDay(), $daysRemoved)) {
  583. $showDay->reload();
  584. $startDay = $showDay->getUTCStartDateAndTime();
  585. $daysRemovedUTC[] = $startDay->format('w');
  586. }
  587. }
  588. foreach ($daysRemoved as $day) {
  589. //delete the cc_show_day entries as well
  590. CcShowDaysQuery::create()
  591. ->filterByDbShowId($showId)
  592. ->filterByDbDay($day)
  593. ->delete();
  594. }
  595. $uncheckedDays = pg_escape_string(implode(",", $daysRemovedUTC));
  596. $sql = <<<SQL
  597. DELETE
  598. FROM cc_show_instances
  599. WHERE EXTRACT(DOW FROM starts) IN ($uncheckedDays)
  600. AND starts > :timestamp::TIMESTAMP
  601. AND show_id = :showId
  602. SQL;
  603. Application_Common_Database::prepareAndExecute( $sql, array(
  604. ":timestamp" => gmdate("Y-m-d H:i:s"), ":showId" => $showId),
  605. "execute");
  606. }
  607. public function deleteShow($instanceId, $singleInstance=false)
  608. {
  609. $service_user = new Application_Service_UserService();
  610. $currentUser = $service_user->getCurrentUser();
  611. $con = Propel::getConnection();
  612. $con->beginTransaction();
  613. try {
  614. if (!$currentUser->isAdminOrPM()) {
  615. throw new Exception("Permission denied");
  616. }
  617. $ccShowInstance = CcShowInstancesQuery::create()
  618. ->findPk($instanceId);
  619. if (!$ccShowInstance) {
  620. throw new Exception("Could not find show instance");
  621. }
  622. $showId = $ccShowInstance->getDbShowId();
  623. if ($singleInstance) {
  624. $ccShowInstances = array($ccShowInstance);
  625. } else {
  626. $ccShowInstances = CcShowInstancesQuery::create()
  627. ->filterByDbShowId($showId)
  628. ->filterByDbStarts($ccShowInstance->getDbStarts(), Criteria::GREATER_EQUAL)
  629. ->find();
  630. }
  631. if (gmdate("Y-m-d H:i:s") <= $ccShowInstance->getDbEnds()) {
  632. $this->deleteShowInstances($ccShowInstances, $showId);
  633. } else {
  634. throw new Exception("Cannot delete a show instance in the past");
  635. }
  636. Application_Model_StoredFile::updatePastFilesIsScheduled();
  637. Application_Model_RabbitMq::PushSchedule();
  638. $con->commit();
  639. return $showId;
  640. } catch (Exception $e) {
  641. $con->rollback();
  642. Logging::info("Delete show instance failed");
  643. Logging::info($e->getMessage());
  644. return false;
  645. }
  646. }
  647. public function deleteShowInstances($ccShowInstances, $showId)
  648. {
  649. foreach ($ccShowInstances as $ccShowInstance) {
  650. $instanceId = $ccShowInstance->getDbId();
  651. $ccShowInstance
  652. ->setDbModifiedInstance(true)
  653. ->save();
  654. //delete the rebroadcasts of the removed recorded show
  655. if ($ccShowInstance->isRecorded()) {
  656. CcShowInstancesQuery::create()
  657. ->filterByDbOriginalShow($instanceId)
  658. ->delete();
  659. }
  660. //delete all files scheduled in cc_schedules table
  661. CcScheduleQuery::create()
  662. ->filterByDbInstanceId($instanceId)
  663. ->delete();
  664. }
  665. if ($this->checkToDeleteCcShow($showId)) {
  666. CcShowQuery::create()
  667. ->filterByDbId($showId)
  668. ->delete();
  669. /* There is only one cc_show_instance if the user selects 'Delete This Instance'
  670. * There is more than one cc_show_instance if the user selects 'Delete This
  671. * Instance and All Following'. We only need to set the last_show value
  672. * when 'Delete This Instance and All Following' has been selected
  673. */
  674. } elseif (count($ccShowInstances) > 1) {
  675. $this->setLastRepeatingShowDate($showId);
  676. }
  677. }
  678. private function setLastRepeatingShowDate($showId)
  679. {
  680. $ccShowInstances = CcShowInstancesQuery::create()
  681. ->filterByDbShowId($showId)
  682. ->filterByDbModifiedInstance(false)
  683. ->filterByDbRebroadcast(0)
  684. ->orderByDbStarts()
  685. ->find();
  686. /* We need to update the last_show in cc_show_days so the instances
  687. * don't get recreated as the user moves forward in the calendar
  688. */
  689. $lastShowDays = array();
  690. //get the show's timezone
  691. $ccShow = CcShowQuery::create()->findPk($showId);
  692. if ($ccShow->isRepeating()) {
  693. $showTimezone = $ccShow->getFirstRepeatingCcShowDay()->getDbTimezone();
  694. } else {
  695. $showTimezone = $ccShow->getFirstCcShowDay()->getDbTimezone();
  696. }
  697. /* Creates an array where the key is the day of the week (monday,
  698. * tuesday, etc.) and the value is the last show date for each
  699. * day of the week. We will use this array to update the last_show
  700. * for each cc_show_days entry of a cc_show
  701. */
  702. foreach ($ccShowInstances as $instance) {
  703. $instanceStartDT = $instance->getDbStarts(null);
  704. $instanceStartDT->setTimezone(new DateTimeZone($showTimezone));
  705. $lastShowDays[$instanceStartDT->format("w")] = $instanceStartDT;
  706. }
  707. foreach ($lastShowDays as $dayOfWeek => $lastShowStartDT) {
  708. $ccShowDay = CcShowDaysQuery::create()
  709. ->filterByDbShowId($showId)
  710. ->filterByDbDay($dayOfWeek)
  711. ->filterByDbRepeatType(-1, Criteria::NOT_EQUAL)
  712. ->findOne();
  713. if (isset($ccShowDay)) {
  714. $lastShowStartDT->setTimeZone(new DateTimeZone(
  715. $ccShowDay->getDbTimezone()));
  716. $lastShowEndDT = Application_Service_CalendarService::addDeltas(
  717. $lastShowStartDT, 1, 0);
  718. $ccShowDay
  719. ->setDbLastShow($lastShowEndDT->format("Y-m-d"))
  720. ->save();
  721. }
  722. }
  723. // NOTE: Some cc_show_day records may not get updated because there may not be an instance
  724. // left on one of the repeating days so we have to find the entries where the last_show is
  725. // still null
  726. $showDays = CcShowDaysQuery::create()
  727. ->filterByDbShowId($showId)
  728. ->filterByDbRepeatType(0, Criteria::GREATER_EQUAL)
  729. ->filterByDbLastShow(null)
  730. ->find();
  731. foreach ($showDays as $showDay) {
  732. $showDay->setDbLastShow($showDay->getDbFirstShow())->save();
  733. }
  734. }
  735. private function checkToDeleteCcShow($showId)
  736. {
  737. // check if there are any non deleted show instances remaining.
  738. $ccShowInstances = CcShowInstancesQuery::create()
  739. ->filterByDbShowId($showId)
  740. ->filterByDbModifiedInstance(false)
  741. ->filterByDbRebroadcast(0)
  742. ->orderByDbStarts()
  743. ->find();
  744. if ($ccShowInstances->isEmpty()) {
  745. return true;
  746. }
  747. return false;
  748. }
  749. private function deleteAllInstances($showId)
  750. {
  751. $sql = <<<SQL
  752. DELETE
  753. FROM cc_show_instances
  754. WHERE starts > :timestamp::TIMESTAMP
  755. AND show_id = :showId
  756. SQL;
  757. Application_Common_Database::prepareAndExecute( $sql,
  758. array( ':timestamp' => gmdate("Y-m-d H:i:s"),
  759. ':showId' => $showId), 'execute');
  760. }
  761. private function deleteAllRepeatInstances($currentShowDay, $showId)
  762. {
  763. $firstShow = $currentShowDay->getUTCStartDateAndTime();
  764. $sql = <<<SQL
  765. DELETE
  766. FROM cc_show_instances
  767. WHERE starts > :timestamp::TIMESTAMP
  768. AND show_id = :showId
  769. AND starts != :firstShow
  770. SQL;
  771. Application_Common_Database::prepareAndExecute( $sql,
  772. array( ':timestamp' => gmdate("Y-m-d H:i:s"),
  773. ':showId' => $showId,
  774. ':firstShow' => $firstShow->format("Y-m-d H:i:s")), 'execute');
  775. }
  776. /**
  777. *
  778. * Determines what the show end date should be based on
  779. * the form data
  780. *
  781. * @param $showData add/edit show form data
  782. * @return DateTime object in user's local timezone
  783. */
  784. private function calculateEndDate($showData)
  785. {
  786. //if no end return null
  787. if ($showData['add_show_no_end']) {
  788. $endDate = null;
  789. }
  790. //if the show is repeating & ends, then return the end date
  791. elseif ($showData['add_show_repeats']) {
  792. $endDate = new DateTime(
  793. $showData['add_show_end_date'],
  794. new DateTimeZone($showData["add_show_timezone"])
  795. );
  796. $endDate->add(new DateInterval("P1D"));
  797. }
  798. //the show doesn't repeat, so add one day to the start date.
  799. else {
  800. $endDate = new DateTime(
  801. $showData['add_show_start_date'],
  802. new DateTimeZone($showData["add_show_timezone"])
  803. );
  804. $endDate->add(new DateInterval("P1D"));
  805. }
  806. return $endDate;
  807. }
  808. private function updateScheduleStartEndTimes($showData)
  809. {
  810. $showId = $this->ccShow->getDbId();
  811. //DateTime in show's local time
  812. $newStartDateTime = new DateTime($showData["add_show_start_date"]." ".
  813. $showData["add_show_start_time"],
  814. new DateTimeZone($showData["add_show_timezone"]));
  815. $diff = $this->calculateShowStartDiff($newStartDateTime,
  816. $this->origCcShowDay->getLocalStartDateAndTime());
  817. Application_Service_SchedulerService::updateScheduleStartTime(
  818. $this->instanceIdsForScheduleUpdates,
  819. $diff);
  820. }
  821. /**
  822. *
  823. * Returns the difference in seconds between a show's new and
  824. * old start time
  825. *
  826. * @param $newStartDateTime DateTime object
  827. * @param $oldStartDateTime DateTime object
  828. */
  829. private function calculateShowStartDiff($newStartDateTime, $oldStartDateTime)
  830. {
  831. return $newStartDateTime->getTimestamp() - $oldStartDateTime->getTimestamp();
  832. }
  833. /**
  834. *
  835. * Updates the start and end time for cc_show_instances
  836. *
  837. * @param $showData edit show form data
  838. */
  839. private function updateInstanceStartEndTime($diff)
  840. {
  841. $sql = <<<SQL
  842. UPDATE cc_show_instances
  843. SET starts = starts + :diff1::INTERVAL,
  844. ends = ends + :diff2::INTERVAL
  845. WHERE show_id = :showId
  846. AND starts > :timestamp::TIMESTAMP
  847. SQL;
  848. Application_Common_Database::prepareAndExecute($sql,
  849. array(':diff1' => $diff, ':diff2' => $diff,
  850. ':showId' => $this->ccShow->getDbId(), ':timestamp' => gmdate("Y-m-d H:i:s")),
  851. 'execute');
  852. }
  853. /**
  854. *
  855. * Enter description here ...
  856. * @param ccShowDays $showDay
  857. * @param DateTime $showStartDate user's local time
  858. * @param $instanceId
  859. */
  860. private function createRebroadcastInstances($showDay, $showStartDate, $instanceId)
  861. {
  862. $currentUtcTimestamp = gmdate("Y-m-d H:i:s");
  863. $showId = $this->ccShow->getDbId();
  864. $sql = "SELECT * FROM cc_show_rebroadcast WHERE show_id=:show_id";
  865. $rebroadcasts = Application_Common_Database::prepareAndExecute($sql,
  866. array( ':show_id' => $showId ), 'all');
  867. foreach ($rebroadcasts as $rebroadcast) {
  868. $days = explode(" ", $rebroadcast["day_offset"]);
  869. $time = explode(":", $rebroadcast["start_time"]);
  870. $offset = array("days"=>$days[0], "hours"=>$time[0], "mins"=>$time[1]);
  871. list($utcStartDateTime, $utcEndDateTime) = $this->createUTCStartEndDateTime(
  872. $showStartDate, $showDay->getDbDuration(), $offset);
  873. if ($utcStartDateTime->format("Y-m-d H:i:s") > $currentUtcTimestamp) {
  874. $ccShowInstance = new CcShowInstances();
  875. $ccShowInstance->setDbShowId($showId);
  876. $ccShowInstance->setDbStarts($utcStartDateTime);
  877. $ccShowInstance->setDbEnds($utcEndDateTime);
  878. $ccShowInstance->setDbRecord(0);
  879. $ccShowInstance->setDbRebroadcast(1);
  880. $ccShowInstance->setDbOriginalShow($instanceId);
  881. $ccShowInstance->save();
  882. }
  883. }
  884. }
  885. /**
  886. *
  887. * Sets a single cc_show_instance table row
  888. * @param $showDay
  889. * @param $populateUntil
  890. */
  891. private function createNonRepeatingInstance($showDay, $populateUntil)
  892. {
  893. //DateTime object
  894. $start = $showDay->getLocalStartDateAndTime();
  895. list($utcStartDateTime, $utcEndDateTime) = $this->createUTCStartEndDateTime(
  896. $start, $showDay->getDbDuration());
  897. if ($utcStartDateTime->getTimestamp() < $populateUntil->getTimestamp()) {
  898. $ccShowInstance = new CcShowInstances();
  899. if ($this->isUpdate) {
  900. //use original cc_show_day object to get the current cc_show_instance
  901. $origStartDateTime = new DateTime(
  902. $this->origCcShowDay->getDbFirstShow()." ".$this->origCcShowDay->getDbStartTime(),
  903. new DateTimeZone($this->origCcShowDay->getDbTimezone())
  904. );
  905. $origStartDateTime->setTimezone(new DateTimeZone("UTC"));
  906. $ccShowInstance = $this->getInstance($origStartDateTime);
  907. if (!$ccShowInstance) {
  908. throw new Exception("Could not find show instance with start time: ".$origStartDateTime->format("Y-m-d H:i:s"));
  909. }
  910. }
  911. $ccShowInstance->setDbShowId($this->ccShow->getDbId());
  912. $ccShowInstance->setDbStarts($utcStartDateTime);
  913. $ccShowInstance->setDbEnds($utcEndDateTime);
  914. $ccShowInstance->setDbRecord($showDay->getDbRecord());
  915. $ccShowInstance->save();
  916. if ($this->isRebroadcast) {
  917. $this->createRebroadcastInstances($showDay, $start, $ccShowInstance->getDbId());
  918. }
  919. }
  920. return $ccShowInstance;
  921. }
  922. /**
  923. *
  924. * Sets multiple cc_show_instances table rows
  925. * @param unknown_type $showDay
  926. * @param unknown_type $populateUntil
  927. * @param unknown_type $repeatInterval
  928. * @param unknown_type $isRebroadcast
  929. */
  930. private function createWeeklyRepeatInstances($showDay, $populateUntil,
  931. $repeatType, $repeatInterval, $daysAdded=null)
  932. {
  933. $show_id = $showDay->getDbShowId();
  934. $first_show = $showDay->getDbFirstShow(); //non-UTC
  935. $last_show = $showDay->getDbLastShow(); //non-UTC
  936. $duration = $showDay->getDbDuration();
  937. $day = $showDay->getDbDay();
  938. $record = $showDay->getDbRecord();
  939. $timezone = $showDay->getDbTimezone();
  940. //DateTime local
  941. $start = $this->getNextRepeatingPopulateStartDateTime($showDay);
  942. if (is_null($repeatInterval)&& $repeatType == REPEAT_MONTHLY_WEEKLY) {
  943. $repeatInterval = self::getMonthlyWeeklyRepeatInterval($start, $timezone);
  944. }
  945. //DatePeriod in user's local time
  946. $datePeriod = $this->getDatePeriod($start, $timezone, $last_show,
  947. $repeatInterval, $populateUntil);
  948. if ($last_show) {
  949. $utcLastShowDateTime = new DateTime($last_show, new DateTimeZone($timezone));
  950. $utcLastShowDateTime->setTimezone(new DateTimeZone("UTC"));
  951. }
  952. else {
  953. $utcLastShowDateTime = null;
  954. }
  955. $previousDate = clone $start;
  956. foreach ($datePeriod as $date) {
  957. list($utcStartDateTime, $utcEndDateTime) = $this->createUTCStartEndDateTime(
  958. $date, $duration);
  959. /*
  960. * Make sure start date is less than populate until date AND
  961. * last show date is null OR start date is less than last show date
  962. */
  963. if ($utcStartDateTime <= $populateUntil &&
  964. ( is_null($utcLastShowDateTime) || $utcStartDateTime < $utcLastShowDateTime) ) {
  965. $lastCreatedShow = clone $utcStartDateTime;
  966. /* There may not always be an instance when editing a show
  967. * This will be the case when we are adding a new show day to
  968. * a repeating show
  969. */
  970. if ($this->isUpdate) {
  971. if ($this->hasInstance($utcStartDateTime)) {
  972. $ccShowInstance = $this->getInstance($utcStartDateTime);
  973. $newInstance = false;
  974. } else {
  975. $newInstance = true;
  976. $ccShowInstance = new CcShowInstances();
  977. }
  978. } else {
  979. $newInstance = true;
  980. $ccShowInstance = new CcShowInstances();
  981. }
  982. /* When editing the start/end time of a repeating show, we don't want to
  983. * change shows that are in the past so we check the end time.
  984. */
  985. if ($newInstance || $ccShowInstance->getDbEnds() > gmdate("Y-m-d H:i:s")) {
  986. $ccShowInstance->setDbShowId($show_id);
  987. $ccShowInstance->setDbStarts($utcStartDateTime);
  988. $ccShowInstance->setDbEnds($utcEndDateTime);
  989. $ccShowInstance->setDbRecord($record);
  990. $ccShowInstance->save();
  991. }
  992. if ($newInstance) {
  993. array_push($this->newInstanceIdsCreated[$show_id], $ccShowInstance->getDbId());
  994. }
  995. if ($this->isRebroadcast) {
  996. $this->createRebroadcastInstances($showDay, $date, $ccShowInstance->getDbId());
  997. }
  998. }
  999. $previousDate = clone $date;
  1000. }
  1001. /* We need to set the next populate date for repeat shows so when a user
  1002. * moves forward in the calendar we know when to start generating new
  1003. * show instances.
  1004. * If $utcStartDateTime is not set then we know zero new shows were
  1005. * created and we shouldn't update the next populate date.
  1006. */
  1007. if (isset($lastCreatedShow)) {
  1008. /* Set UTC to local time before setting the next repeat date. If we don't
  1009. * the next repeat date might be scheduled for the following day
  1010. * THIS MUST BE IN THE TIMEZONE THE SHOW WAS CREATED IN */
  1011. $lastCreatedShow->setTimezone(new DateTimeZone($timezone));
  1012. $nextDate = $lastCreatedShow->add($repeatInterval);
  1013. $this->setNextRepeatingShowDate($nextDate->format("Y-m-d"), $day, $show_id);
  1014. }
  1015. }
  1016. private function createMonthlyRepeatInstances($showDay, $populateUntil)
  1017. {
  1018. $show_id = $showDay->getDbShowId();
  1019. $first_show = $showDay->getDbFirstShow(); //non-UTC
  1020. $last_show = $showDay->getDbLastShow(); //non-UTC
  1021. $duration = $showDay->getDbDuration();
  1022. $day = $showDay->getDbDay();
  1023. $record = $showDay->getDbRecord();
  1024. $timezone = $showDay->getDbTimezone();
  1025. //DateTime local
  1026. $start = $this->getNextRepeatingPopulateStartDateTime($showDay);
  1027. if (isset($last_show)) {
  1028. $end = new DateTime($last_show, new DateTimeZone($timezone));
  1029. } else {
  1030. $end = $populateUntil;
  1031. }
  1032. // We will only need this if the repeat type is MONTHLY_WEEKLY
  1033. list($weekNumberOfMonth, $dayOfWeek) =
  1034. self::getMonthlyWeeklyRepeatInterval(
  1035. new DateTime($first_show, new DateTimeZone($timezone)));
  1036. $this->repeatType = $showDay->getDbRepeatType();
  1037. if ($last_show) {
  1038. $utcLastShowDateTime = new DateTime($last_show, new DateTimeZone($timezone));
  1039. $utcLastShowDateTime->setTimezone(new DateTimeZone("UTC"));
  1040. }
  1041. else {
  1042. $utcLastShowDateTime = null;
  1043. }
  1044. while ($start->getTimestamp() < $end->getTimestamp()) {
  1045. list($utcStartDateTime, $utcEndDateTime) = $this->createUTCStartEndDateTime(
  1046. $start, $duration);
  1047. /*
  1048. * Make sure start date is less than populate until date AND
  1049. * last show date is null OR start date is less than last show date
  1050. */
  1051. if ($utcStartDateTime->getTimestamp() <= $populateUntil->getTimestamp() &&
  1052. ( is_null($utcLastShowDateTime) ||
  1053. $utcStartDateTime->getTimestamp() < $utcLastShowDateTime->getTimestamp()) ) {
  1054. $lastCreatedShow = clone $utcStartDateTime;
  1055. /* There may not always be an instance when editing a show
  1056. * This will be the case when we are adding a new show day to
  1057. * a repeating show
  1058. */
  1059. if ($this->isUpdate && $this->hasInstance($utcStartDateTime)) {
  1060. $ccShowInstance = $this->getInstance($utcStartDateTime);
  1061. $newInstance = false;
  1062. } else {
  1063. $newInstance = true;
  1064. $ccShowInstance = new CcShowInstances();
  1065. }
  1066. /* When editing the start/end time of a repeating show, we don't want to
  1067. * change shows that started in the past. So check the start time.
  1068. */
  1069. if ($newInstance || $ccShowInstance->getDbStarts() > gmdate("Y-m-d H:i:s")) {
  1070. $ccShowInstance->setDbShowId($show_id);
  1071. $ccShowInstance->setDbStarts($utcStartDateTime);
  1072. $ccShowInstance->setDbEnds($utcEndDateTime);
  1073. $ccShowInstance->setDbRecord($record);
  1074. $ccShowInstance->save();
  1075. }
  1076. if ($newInstance) {
  1077. array_push($this->newInstanceIdsCreated[$show_id], $ccShowInstance->getDbId());
  1078. }
  1079. if ($this->isRebroadcast) {
  1080. $this->createRebroadcastInstances($showDay, $start, $ccShowInstance->getDbId());
  1081. }
  1082. }
  1083. if ($this->repeatType == REPEAT_MONTHLY_WEEKLY) {
  1084. $monthlyWeeklyStart = new DateTime($utcStartDateTime->format("Y-m"),
  1085. new DateTimeZone("UTC"));
  1086. $monthlyWeeklyStart->add(new DateInterval("P1M"));
  1087. $start = self::getNextMonthlyWeeklyRepeatDate(
  1088. $monthlyWeeklyStart,
  1089. $timezone,
  1090. $showDay->getDbStartTime(),
  1091. $weekNumberOfMonth,
  1092. $dayOfWeek);
  1093. } else {
  1094. $start = $this->getNextMonthlyMonthlyRepeatDate(
  1095. $start, $timezone, $showDay->getDbStartTime());
  1096. }
  1097. }
  1098. $this->setNextRepeatingShowDate($start->format("Y-m-d"), $day, $show_id);
  1099. }
  1100. /**
  1101. *
  1102. * i.e. last thursday of each month
  1103. * i.e. second monday of each month
  1104. *
  1105. * @param string $showStart
  1106. * @param string $timezone user's local timezone
  1107. */
  1108. public static function getMonthlyWeeklyRepeatInterval($showStart)
  1109. {
  1110. $start = clone $showStart;
  1111. $dayOfMonth = $start->format("j");
  1112. $dayOfWeek = $start->format("l");
  1113. $yearAndMonth = $start->format("Y-m");
  1114. $firstDayOfWeek = strtotime($dayOfWeek." ".$yearAndMonth);
  1115. // if $dayOfWeek is Friday, what number of the month does
  1116. // the first Friday fall on
  1117. $numberOfFirstDayOfWeek = date("j", $firstDayOfWeek);
  1118. $weekCount = 0;
  1119. while ($dayOfMonth >= $numberOfFirstDayOfWeek) {
  1120. $weekCount++;
  1121. $dayOfMonth -= 7;
  1122. }
  1123. switch ($weekCount) {
  1124. case 1:
  1125. $weekNumberOfMonth = "first";
  1126. break;
  1127. case 2:
  1128. $weekNumberOfMonth = "second";
  1129. break;
  1130. case 3:
  1131. $weekNumberOfMonth = "third";
  1132. break;
  1133. case 4:
  1134. $weekNumberOfMonth = "fourth";
  1135. break;
  1136. case 5:
  1137. $weekNumberOfMonth = "fifth";
  1138. break;
  1139. }
  1140. /* return DateInterval::createFromDateString(
  1141. $weekNumberOfMonth." ".$dayOfWeek." of next month"); */
  1142. return array($weekNumberOfMonth, $dayOfWeek);
  1143. }
  1144. /**
  1145. *
  1146. * Enter description here ...
  1147. * @param $start user's local time
  1148. */
  1149. private function getNextMonthlyMonthlyRepeatDate($start, $timezone, $startTime)
  1150. {
  1151. $dt = new DateTime($start->format("Y-m"), new DateTimeZone($timezone));
  1152. do {
  1153. $dt->add(new DateInterval("P1M"));
  1154. } while (!checkdate($dt->format("m"), $start->format("d"), $dt->format("Y")));
  1155. $dt->setDate($dt->format("Y"), $dt->format("m"), $start->format("d"));
  1156. $startTime = explode(":", $startTime);
  1157. $hours = isset($startTime[0]) ? $startTime[0] : "00";
  1158. $minutes = isset($startTime[1]) ? $startTime[1] : "00";
  1159. $seconds = isset($startTime[2]) ? $startTime[2] : "00";
  1160. $dt->setTime($hours, $minutes, $seconds);
  1161. return $dt;
  1162. }
  1163. /**
  1164. *
  1165. * Returns a DateTime object of when the next repeating show that repeats
  1166. * monthly, by day of the week (i.e. every fourth Tuesday) should be created
  1167. *
  1168. * @param DateTime $start
  1169. * $start only has the year and month of the next show
  1170. * @param string $timezone
  1171. * @param string (i.e. '14:30' $startTime
  1172. * @param string (i.e. 'first', 'second') $weekNumberOfMonth
  1173. * @param string (i.e. 'Monday') $dayOfWeek
  1174. */
  1175. public static function getNextMonthlyWeeklyRepeatDate(
  1176. $start,
  1177. $timezone,
  1178. $startTime,
  1179. $weekNumberOfMonth,
  1180. $dayOfWeek)
  1181. {
  1182. $dt = new DateTime($start->format("Y-m"), new DateTimeZone($timezone));
  1183. $tempDT = clone $dt;
  1184. $fifthWeekExists = false;
  1185. do {
  1186. $nextDT = date_create($weekNumberOfMonth." ".$dayOfWeek.
  1187. " of ".$tempDT->format("F")." ".$tempDT->format("Y"));
  1188. $nextDT->setTimezone(new DateTimeZone($timezone));
  1189. /* We have to check if the next date is in the same month in case
  1190. * the repeat day is in the fifth week of the month.
  1191. * If it's not in the same month we know that a fifth week of
  1192. * the next month does not exist. So let's skip it.
  1193. */
  1194. if ($tempDT->format("F") == $nextDT->format("F")) {
  1195. $fifthWeekExists = true;
  1196. }
  1197. $tempDT->add(new DateInterval("P1M"));
  1198. } while (!$fifthWeekExists);
  1199. $dt = $nextDT;
  1200. $startTime = explode(":", $startTime);
  1201. $hours = isset($startTime[0]) ? $startTime[0] : "00";
  1202. $minutes = isset($startTime[1]) ? $startTime[1] : "00";
  1203. $seconds = isset($startTime[2]) ? $startTime[2] : "00";
  1204. $dt->setTime($hours, $minutes, $seconds);
  1205. return $dt;
  1206. }
  1207. private function getNextRepeatingPopulateStartDateTime($showDay)
  1208. {
  1209. $nextPopDate = $showDay->getDbNextPopDate();
  1210. $startTime = $showDay->getDbStartTime();
  1211. if (isset($nextPopDate)) {
  1212. return new DateTime($nextPopDate." ".$startTime, new DateTimeZone($showDay->getDbTimezone()));
  1213. } else {
  1214. return new DateTime($showDay->getDbFirstShow()." ".$startTime, new DateTimeZone($showDay->getDbTimezone()));
  1215. }
  1216. }
  1217. /**
  1218. *
  1219. * Create a DatePeriod object in the user's local time
  1220. * It will get converted to UTC before the show instance gets created
  1221. */
  1222. private function getDatePeriod($start, $timezone, $lastShow, $repeatInterval, $populateUntil)
  1223. {
  1224. if (isset($lastShow)) {
  1225. $endDatePeriod = new DateTime($lastShow, new DateTimeZone($timezone));
  1226. } else {
  1227. $endDatePeriod = $populateUntil;
  1228. }
  1229. return new DatePeriod($start, $repeatInterval, $endDatePeriod);
  1230. }
  1231. private function hasInstance($starts)
  1232. {
  1233. return $this->getInstance($starts) ? true : false;
  1234. }
  1235. /**
  1236. *
  1237. * Attempts to retrieve the cc_show_instance belonging to a cc_show
  1238. * that starts at $starts. We have to pass in the start
  1239. * time in case the show is repeating
  1240. *
  1241. * Returns the instance if one was found (one that is not a recording
  1242. * and modified instance is false (has not been deleted))
  1243. */
  1244. private function getInstance($starts)
  1245. {
  1246. $temp = clone($starts);
  1247. $temp->setTimezone(new DateTimeZone($this->oldShowTimezone));
  1248. $temp->setTime($this->localShowStartHour, $this->localShowStartMin);
  1249. $temp->setTimezone(new DateTimeZone("UTC"));
  1250. $ccShowInstance = CcShowInstancesQuery::create()
  1251. ->filterByDbStarts($temp->format("Y-m-d H:i:s"), Criteria::EQUAL)
  1252. ->filterByDbShowId($this->ccShow->getDbId(), Criteria::EQUAL)
  1253. //->filterByDbModifiedInstance(false, Criteria::EQUAL)
  1254. ->filterByDbRebroadcast(0, Criteria::EQUAL)
  1255. ->limit(1)
  1256. ->find();
  1257. if ($ccShowInstance->isEmpty()) {
  1258. return false;
  1259. } else {
  1260. return $ccShowInstance[0];
  1261. }
  1262. }
  1263. private function hasCcShowDay($repeatType, $day)
  1264. {
  1265. return $this->getCcShowDay($repeatType, $day) ? true : false;
  1266. }
  1267. private function getCcShowDay($repeatType, $day)
  1268. {
  1269. $ccShowDay = CcShowDaysQuery::create()
  1270. ->filterByDbShowId($this->ccShow->getDbId())
  1271. ->filterByDbDay($day)
  1272. ->filterByDbRepeatType($repeatType)
  1273. ->limit(1)
  1274. ->find();
  1275. if ($ccShowDay->isEmpty()) {
  1276. return false;
  1277. } else {
  1278. return $ccShowDay[0];
  1279. }
  1280. }
  1281. /**
  1282. *
  1283. * Sets the fields for a cc_show table row
  1284. * @param $ccShow
  1285. * @param $showData
  1286. */
  1287. public function setCcShow($showData)
  1288. {
  1289. if (!$this->isUpdate) {
  1290. $ccShow = new CcShow();
  1291. } else {
  1292. $ccShow = CcShowQuery::create()->findPk($showData["add_show_id"]);
  1293. }
  1294. $ccShow->setDbName($showData['add_show_name']);
  1295. $ccShow->setDbDescription($showData['add_show_description']);
  1296. $ccShow->setDbUrl($showData['add_show_url']);
  1297. $ccShow->setDbGenre($showData['add_show_genre']);
  1298. $ccShow->setDbColor($showData['add_show_color']);
  1299. $ccShow->setDbBackgroundColor($showData['add_show_background_color']);
  1300. $ccShow->setDbLiveStreamUsingAirtimeAuth($showData['cb_airtime_auth'] == 1);
  1301. $ccShow->setDbLiveStreamUsingCustomAuth($showData['cb_custom_auth'] == 1);
  1302. $ccShow->setDbLiveStreamUser($showData['custom_username']);
  1303. $ccShow->setDbLiveStreamPass($showData['custom_password']);
  1304. //Here a user has edited a show and linked it.
  1305. //We need to grab the existing show instances ids and fill their content
  1306. //with the content from the show instance that was clicked on to edit the show.
  1307. //We do this because linked show instances need to have the same content in each.
  1308. if ($this->isUpdate && (!$ccShow->getDbLinked() && $showData["add_show_linked"])) {
  1309. $existingShowInstanceIds = $ccShow->getFutureInstanceIds(new Criteria());
  1310. Application_Service_SchedulerService::fillLinkedInstances($ccShow, $existingShowInstanceIds, $showData["add_show_instance_id"]);
  1311. }
  1312. $ccShow->setDbLinked($showData["add_show_linked"]);
  1313. $ccShow->save();
  1314. $this->ccShow = $ccShow;
  1315. }
  1316. /**
  1317. *
  1318. * Sets the fields for a cc_show_days table row
  1319. * @param $showData
  1320. * @param $showId
  1321. * @param $userId
  1322. * @param $repeatType
  1323. * @param $isRecorded
  1324. * @param $showDay ccShowDay object we are setting values on
  1325. */
  1326. private function setCcShowDays($showData)
  1327. {
  1328. $showId = $this->ccShow->getDbId();
  1329. $startDateTime = new DateTime(
  1330. $showData['add_show_start_date']." ".$showData['add_show_start_time'],
  1331. new DateTimeZone($showData['add_show_timezone'])
  1332. );
  1333. $endDateTime = $this->calculateEndDate($showData);
  1334. if (!is_null($endDateTime)) {
  1335. $endDate = $endDateTime->format("Y-m-d");
  1336. }
  1337. else {
  1338. $endDate = null;
  1339. }
  1340. //Our calculated start DOW must be used for non repeating since a day has not been selected.
  1341. //For all repeating shows, only the selected days of the week will be repeated on.
  1342. $startDow = $startDateTime->format("w");
  1343. if (!$showData['add_show_repeats']) {
  1344. $showData['add_show_day_check'] = array($startDow);
  1345. }
  1346. // Don't set day for monthly repeat type, it's invalid
  1347. if ($showData['add_show_repeats'] && $showData['add_show_repeat_type'] == 2) {
  1348. if ($this->isUpdate) {
  1349. $showDay = CcShowDaysQuery::create()
  1350. ->filterByDbShowId($showId)
  1351. ->filterByDbRepeatType($this->origCcShowDay->getDbRepeatType())
  1352. ->findOne();
  1353. if (!$showDay) {
  1354. //repeat type changed so we have to create a new show_day rule
  1355. $showDay = new CcShowDays();
  1356. }
  1357. } else {
  1358. $showDay = new CcShowDays();
  1359. }
  1360. $showDay->setDbFirstShow($startDateTime->format("Y-m-d"));
  1361. $showDay->setDbLastShow($endDate);
  1362. $showDay->setDbStartTime($startDateTime->format("H:i:s"));
  1363. $showDay->setDbTimezone($showData['add_show_timezone']);
  1364. $showDay->setDbDuration($showData['add_show_duration']);
  1365. $showDay->setDbRepeatType($this->repeatType);
  1366. $showDay->setDbShowId($showId);
  1367. $showDay->setDbRecord($this->isRecorded);
  1368. //in case we are editing a show we need to set this to the first show
  1369. //so when editing, the date period iterator will start from the beginning
  1370. $showDay->setDbNextPopDate($startDateTime->format("Y-m-d"));
  1371. $showDay->save();
  1372. } else {
  1373. foreach ($showData['add_show_day_check'] as $day) {
  1374. $daysAdd=0;
  1375. $startDateTimeClone = clone $startDateTime;
  1376. if ($startDow !== $day) {
  1377. if ($startDow > $day)
  1378. $daysAdd = 6 - $startDow + 1 + $day;
  1379. else
  1380. $daysAdd = $day - $startDow;
  1381. $startDateTimeClone->add(new DateInterval("P".$daysAdd."D"));
  1382. }
  1383. if (is_null($endDate) || $startDateTimeClone->getTimestamp() <= $endDateTime->getTimestamp()) {
  1384. if ($this->isUpdate) {
  1385. if ($this->origCcShowDay->getDbRepeatType() == 2 ||
  1386. $this->origCcShowDay->getDbRepeatType() == 3) {
  1387. $day = null;
  1388. } else if (!$this->origShowRepeatStatus) {
  1389. //keep current show day to use for updating cc_show_day rule
  1390. $keepDay = $day;
  1391. $day = $this->origCcShowDay->getDbDay();
  1392. }
  1393. $showDay = CcShowDaysQuery::create()
  1394. ->filterByDbShowId($showId)
  1395. ->filterByDbRepeatType($this->origCcShowDay->getDbRepeatType())
  1396. ->filterByDbDay($day)
  1397. ->findOne();
  1398. if (!$showDay) {
  1399. //if no show day object was found it is because a new
  1400. //repeating day of the week was added OR the repeat
  1401. //type has changed
  1402. $showDay = new CcShowDays();
  1403. }
  1404. if (isset($keepDay)) {
  1405. $day = $keepDay;
  1406. }
  1407. } else {
  1408. $showDay = new CcShowDays();
  1409. }
  1410. $showDay->setDbFirstShow($startDateTimeClone->format("Y-m-d"));
  1411. $showDay->setDbLastShow($endDate);
  1412. $showDay->setDbStartTime($startDateTimeClone->format("H:i"));
  1413. $showDay->setDbTimezone($showData['add_show_timezone']);
  1414. $showDay->setDbDuration($showData['add_show_duration']);
  1415. $showDay->setDbDay($day);
  1416. $showDay->setDbRepeatType($this->repeatType);
  1417. $showDay->setDbShowId($showId);
  1418. $showDay->setDbRecord($this->isRecorded);
  1419. //in case we are editing a show we need to set this to the first show
  1420. //so when editing, the date period iterator will start from the beginning
  1421. $showDay->setDbNextPopDate($startDateTimeClone->format("Y-m-d"));
  1422. $showDay->save();
  1423. }
  1424. }
  1425. }
  1426. }
  1427. /**
  1428. *
  1429. * Deletes all the cc_show_rebroadcast entries for a specific show
  1430. * that is currently being edited. They will get recreated with
  1431. * the new show specs
  1432. */
  1433. private function deleteCcShowRebroadcasts()
  1434. {
  1435. CcShowRebroadcastQuery::create()->filterByDbShowId($this->ccShow->getDbId())->delete();
  1436. }
  1437. /**
  1438. *
  1439. * Sets the fields for a cc_show_rebroadcast table row
  1440. * @param $showData
  1441. * @param $showId
  1442. * @param $repeatType
  1443. * @param $isRecorded
  1444. */
  1445. private function setCcShowRebroadcasts($showData)
  1446. {
  1447. $showId = $this->ccShow->getDbId();
  1448. if (($this->isRecorded && $showData['add_show_rebroadcast']) && ($this->repeatType != -1)) {
  1449. for ($i = 1; $i <= MAX_REBROADCAST_DATES; $i++) {
  1450. if ($showData['add_show_rebroadcast_date_'.$i]) {
  1451. $showRebroad = new CcShowRebroadcast();
  1452. $showRebroad->setDbDayOffset($showData['add_show_rebroadcast_date_'.$i]);
  1453. $showRebroad->setDbStartTime($showData['add_show_rebroadcast_time_'.$i]);
  1454. $showRebroad->setDbShowId($showId);
  1455. $showRebroad->save();
  1456. }
  1457. }
  1458. } elseif ($this->isRecorded && $showData['add_show_rebroadcast'] && ($this->repeatType == -1)) {
  1459. for ($i = 1; $i <= MAX_REBROADCAST_DATES; $i++) {
  1460. if ($showData['add_show_rebroadcast_date_absolute_'.$i]) {
  1461. $rebroadcastDate = new DateTime($showData["add_show_rebroadcast_date_absolute_$i"]);
  1462. $startDate = new DateTime($showData['add_show_start_date']);
  1463. $offsetDays = $startDate->diff($rebroadcastDate);
  1464. $showRebroad = new CcShowRebroadcast();
  1465. $showRebroad->setDbDayOffset($offsetDays->format("%a days"));
  1466. $showRebroad->setDbStartTime($showData['add_show_rebroadcast_time_absolute_'.$i]);
  1467. $showRebroad->setDbShowId($showId);
  1468. $showRebroad->save();
  1469. }
  1470. }
  1471. }
  1472. }
  1473. /**
  1474. *
  1475. * Deletes all the cc_show_hosts entries for a specific show
  1476. * that is currently being edited. They will get recreated with
  1477. * the new show specs
  1478. */
  1479. private function deleteCcShowHosts()
  1480. {
  1481. CcShowHostsQuery::create()->filterByDbShow($this->ccShow->getDbId())->delete();
  1482. }
  1483. /**
  1484. *
  1485. * Sets the fields for a cc_show_hosts table row
  1486. * @param $showData
  1487. * @param $showId
  1488. */
  1489. private function setCcShowHosts($showData)
  1490. {
  1491. if (is_array($showData['add_show_hosts'])) {
  1492. foreach ($showData['add_show_hosts'] as $host) {
  1493. $showHost = new CcShowHosts();
  1494. $showHost->setDbShow($this->ccShow->getDbId());
  1495. $showHost->setDbHost($host);
  1496. $showHost->save();
  1497. }
  1498. }
  1499. }
  1500. /**
  1501. *
  1502. * Gets the date and time shows (particularly repeating shows)
  1503. * can be populated until.
  1504. *
  1505. * @return DateTime object
  1506. */
  1507. private static function getPopulateShowUntilDateTIme()
  1508. {
  1509. $populateUntil = Application_Model_Preference::GetShowsPopulatedUntil();
  1510. if (is_null($populateUntil)) {
  1511. $populateUntil = new DateTime("now", new DateTimeZone('UTC'));
  1512. Application_Model_Preference::SetShowsPopulatedUntil($populateUntil);
  1513. }
  1514. return $populateUntil;
  1515. }
  1516. /**
  1517. *
  1518. * Enter description here ...
  1519. * @param DateTime $showStart user's local time
  1520. * @param string $duration time interval (h)h:(m)m(:ss)
  1521. * @param string $timezone "Europe/Prague"
  1522. * @param array $offset (days, hours, mins) used for rebroadcast shows
  1523. *
  1524. * @return array of 2 DateTime objects, start/end time of the show in UTC
  1525. */
  1526. private function createUTCStartEndDateTime($showStart, $duration, $offset=null)
  1527. {
  1528. $startDateTime = clone $showStart;
  1529. $timezone = $startDateTime->getTimezone();
  1530. if (isset($offset)) {
  1531. //$offset["hours"] and $offset["mins"] represents the start time
  1532. //of a rebroadcast show
  1533. $startDateTime = new DateTime($startDateTime->format("Y-m-d")." ".
  1534. $offset["hours"].":".$offset["mins"], $timezone);
  1535. $startDateTime->add(new DateInterval("P{$offset["days"]}D"));
  1536. }
  1537. $endDateTime = clone $startDateTime;
  1538. $duration = explode(":", $duration);
  1539. list($hours, $mins) = array_slice($duration, 0, 2);
  1540. $endDateTime->add(new DateInterval("PT{$hours}H{$mins}M"));
  1541. $startDateTime->setTimezone(new DateTimeZone('UTC'));
  1542. $endDateTime->setTimezone(new DateTimeZone('UTC'));
  1543. return array($startDateTime, $endDateTime);
  1544. }
  1545. /**
  1546. *
  1547. * Show instances for repeating shows only get created up
  1548. * until what is visible on the calendar. We need to set the
  1549. * date for when the next repeating show instance should be created
  1550. * as the user browses the calendar further.
  1551. *
  1552. * @param $nextDate
  1553. * @param $showId
  1554. * @param $day
  1555. */
  1556. private function setNextRepeatingShowDate($nextDate, $day, $showId)
  1557. {
  1558. $nextInfo = explode(" ", $nextDate);
  1559. $repeatInfo = CcShowDaysQuery::create()
  1560. ->filterByDbShowId($showId)
  1561. ->filterByDbDay($day)
  1562. ->filterByDbRepeatType(-1, Criteria::NOT_EQUAL)
  1563. ->findOne();
  1564. $repeatInfo->setDbNextPopDate($nextInfo[0])
  1565. ->save();
  1566. }
  1567. }