<commit_before><?php
define("MAX_REBROADCAST_DATES", 10);
define("NO_REPEAT", -1);
define("REPEAT_WEEKLY", 0);
define("REPEAT_BI_WEEKLY", 1);
define("REPEAT_MONTHLY_MONTHLY", 2);
define("REPEAT_MONTHLY_WEEKLY", 3);
define("REPEAT_TRI_WEEKLY", 4);
define("REPEAT_QUAD_WEEKLY", 5);

use Airtime\CcShowHosts;
use Airtime\CcShowHostsQuery;
use Airtime\CcShow;
use Airtime\CcShowQuery;
use Airtime\CcShowInstances;
use Airtime\CcShowInstancesPeer;
use Airtime\CcShowInstancesQuery;
use Airtime\CcSchedulePeer;
use Airtime\CcScheduleQuery;
use Airtime\CcShowDays;
use Airtime\CcShowDaysPeer;
use Airtime\CcShowDaysQuery;
use Airtime\CcShowRebroadcast;
use Airtime\CcShowRebroadcastQuery;

class Application_Service_ShowService
{
    private $ccShow;
    private $isRecorded;
    private $isRebroadcast;
    private $repeatType;
    private $isUpdate;
    private $linkedShowContent;
    private $oldShowTimezone;
    private $localShowStartHour;
    private $localShowStartMin;
    private $origCcShowDay;
    private $origShowRepeatStatus;
    private $instanceIdsForScheduleUpdates;

    public function __construct($showId=null, $showData=null, $isUpdate=false)
    {
        if (!is_null($showId)) {
            $this->ccShow = CcShowQuery::create()->findPk($showId);
        }

        if (isset($showData["add_show_repeats"]) && $showData["add_show_repeats"]) {
            $this->repeatType = $showData["add_show_repeat_type"];
            if ($showData["add_show_repeat_type"] == 2) {
                $this->repeatType = $showData["add_show_monthly_repeat_type"];
            }
        } else {
            $this->repeatType = -1;
        }

        $this->isRecorded = (isset($showData['add_show_record']) && $showData['add_show_record']) ? 1 : 0;
        $this->isRebroadcast = (isset($showData['add_show_rebroadcast']) && $showData['add_show_rebroadcast']) ? 1 : 0;
        $this->isUpdate = $isUpdate;
        $this->instanceIdsForScheduleUpdates = array();
    }

    public function editRepeatingShowInstance($showData) {
        $service_user = new Application_Service_UserService();
        $currentUser = $service_user->getCurrentUser();

        $showData["add_show_duration"] = $this->formatShowDuration(
            $showData["add_show_duration"]);

        $con = Propel::getConnection();
        $con->beginTransaction();
        try {
            if (!$currentUser->isAdminOrPM()) {
                throw new Exception("Permission denied");
            }

            $showId = $showData["add_show_id"];

            /****** UPDATE SCHEDULE START TIME ******/
            //get the ccShow object to which this instance belongs
            //so we can get the original start date and time
            $this->ccShow = CcShowQuery::create()
                ->findPk($showId);

            //DateTime in shows's local time
            $newStartDateTime = new DateTime($showData["add_show_start_date"]." ".
            $showData["add_show_start_time"],
                new DateTimeZone($showData["add_show_timezone"]));

            $ccShowInstanceOrig = CcShowInstancesQuery::create()
                ->findPk($showData["add_show_instance_id"]);

            //convert original start time into the show's local timezone
            $origLocalStartDateTime = $ccShowInstanceOrig->getLocalStartDateTime();

            $diff = $this->calculateShowStartDiff($newStartDateTime,
                $origLocalStartDateTime);

            if ($diff != 0) {
                Application_Service_SchedulerService::updateScheduleStartTime(
                    array($showData["add_show_instance_id"]), $diff);
            }
            /****** UPDATE SCHEDULE START TIME ENDS******/

            /*
             * In the case where an instance is being edited for a second
             * (or third, fourth, etc.) time we need to delete the old
             * cc_show_day record
             * 
             * Since we don't store the cc_show_day ids we need to use the
             * original start time from cc_show_instances, convert it to the show's
             * local timezone, and find the record in cc_show_days
             * 
             * *** There is a flaw here: We have to assume the show timezone has
             * *** not changed (make timezone readonly??)
             */
            $origCcShowDay = CcShowDaysQuery::create()
                ->filterByDbShowId($showId)
                ->filterByDbRepeatType(-1)
                ->filterByDbFirstShow($origLocalStartDateTime->format("Y-m-d"))
                ->filterByDbStartTime($origLocalStartDateTime->format("H:i:s"))
                ->delete();

            /*
             * Set the new cc_show_day record
             * Associates it with the current show_id and sets it to non-repeating
             */
            $this->setCcShowDays($showData);

            /*
             * We need to find the new show day rule we just created by passing
             * in the first show and start time in case multiple single
             * instances have been edited out of the repeating sequence.
             */
            $showDay = CcShowDaysQuery::create()
                ->filterByDbShowId($showId)
                ->filterByDbRepeatType(-1)
                ->filterByDbFirstShow($showData["add_show_start_date"])
                ->filterByDbStartTime($showData["add_show_start_time"].":00")
                ->findOne();

            $ccShowInstance = $this->createNonRepeatingInstance($showDay,
                $this->getPopulateShowUntilDateTIme());

            //update cc_schedule with the new instance id
            $con = Propel::getConnection(CcShowInstancesPeer::DATABASE_NAME);
            $selectCriteria = new Criteria();
            $selectCriteria->add(CcSchedulePeer::INSTANCE_ID, $showData["add_show_instance_id"]);
            $updateCriteria = new Criteria();
            $updateCriteria->add(CcSchedulePeer::INSTANCE_ID, $ccShowInstance->getDbId());
            BasePeer::doUpdate($selectCriteria, $updateCriteria, $con);

            $ccShowInstance->updateDbTimeFilled($con);
            $ccShowInstance->updateScheduleStatus($con);

            //delete the edited instance from the repeating sequence
            $ccShowInstanceOrig->setDbModifiedInstance(true)->save();

            $con->commit();
            Application_Model_RabbitMq::PushSchedule();
        } catch (Exception $e) {
            $con->rollback();
            Logging::info("EXCEPTION: Show update failed.");
            Logging::info($e->getMessage());
        }
    }

    /**
     * 
     * If a user is editing a show we need to store the original timezone and
     * start time in case the show's timezone is changed and we are crossing
     * over DST
     */
    private function storeOrigLocalShowInfo()
    {
        if ($this->ccShow->isRepeating()) {
            $this->origCcShowDay = clone $this->ccShow->getFirstRepeatingCcShowDay();
            $this->origShowRepeatStatus = true;
        } else {
            $this->origCcShowDay = clone $this->ccShow->getFirstCcShowDay();
            $this->origShowRepeatStatus = false;
        }

        $this->oldShowTimezone = $this->origCcShowDay->getDbTimezone();

        $origStartTime = explode(":", $this->origCcShowDay->getDbStartTime());
        $this->localShowStartHour = $origStartTime[0];
        $this->localShowStartMin = $origStartTime[1];
    }

    public function addUpdateShow($showData)
    {
        $service_user = new Application_Service_UserService();
        $currentUser = $service_user->getCurrentUser();

        $showData["add_show_duration"] = $this->formatShowDuration(
            $showData["add_show_duration"]);

        $con = Propel::getConnection();
        $con->beginTransaction();
        try {
            if (!$currentUser->isAdminOrPM()) {
                throw new Exception("Permission denied");
            }

            //update ccShow
            $this->setCcShow($showData);

            $daysAdded = array();

            if ($this->isUpdate) {
                if (!$this->ccShow->getCcShowDayss()->isEmpty()) {
                    $this->storeOrigLocalShowInfo();
                }

                $daysAdded = $this->delegateInstanceCleanup($showData);

                $this->deleteRebroadcastInstances();

                $this->deleteCcShowHosts();

                if ($this->isRebroadcast) {
                    //delete entry in cc_show_rebroadcast
                    $this->deleteCcShowRebroadcasts();
                }

                $this->storeInstanceIds();
            }

            //update ccShowDays
            $this->setCcShowDays($showData);

            //update ccShowRebroadcasts
            $this->setCcShowRebroadcasts($showData);

            //update ccShowHosts
            $this->setCcShowHosts($showData);

            //create new ccShowInstances
            $this->delegateInstanceCreation($daysAdded);

            if ($this->isUpdate) {

                /* If the show is repeating and the start date changes we need
                 * to ignore that difference when re-calculating schedule start times.
                 * Otherwise it might calculate a difference of a week, for example.
                 */
                if ($this->ccShow->isRepeating() && 
                    $this->origCcShowDay->getLocalStartDateAndTime()->format("Y-m-d") != $showData["add_show_start_date"]) {
                        $showData["add_show_start_date"] = $this->origCcShowDay->getLocalStartDateAndTime()->format("Y-m-d");
                }

                $this->adjustSchedule($showData);
            }

            $con->commit();
            Application_Model_RabbitMq::PushSchedule();
        } catch (Exception $e) {
            $con->rollback();
            $this->isUpdate ? $action = "update" : $action = "creation";
            Logging::info("EXCEPTION: Show ".$action." failed.");
            Logging::info($e->getMessage());
        }
    }

    /**
     * 
     * Returns an array of instance ids that already exist
     * We need this if a show is being updated so we can separate the 
     * instances that already exist and any new instances that
     * get created (by adding a new repeat show day)
     */
    private function storeInstanceIds()
    {
        $instances = $this->ccShow->getCcShowInstancess();
        foreach ($instances as $instance) {
            $this->instanceIdsForScheduleUpdates[] = $instance->getDbId();
        }
    }

    private function adjustSchedule($showData)
    {
        $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME);

        $this->updateScheduleStartEndTimes($showData);

        $ccShowInstances = $this->ccShow->getCcShowInstancess();
        foreach ($ccShowInstances as $instance) {
            $instance->updateScheduleStatus($con);
        }
    }

    /**
     *
     * Receives a cc_show id and determines whether to create a
     * single show instance or repeating show instances
     */
    public function delegateInstanceCreation($daysAdded=null, $end=null, $fillInstances=false)
    {
        $populateUntil = $this->getPopulateShowUntilDateTIme();

        if (is_null($this->ccShow)) {
            $ccShowDays = $this->getShowDaysInRange($populateUntil, $end);
        } else {
            if ($this->ccShow->isRepeating()) {
                $ccShowDays = $this->ccShow->getRepeatingCcShowDays();
            } else {
                $ccShowDays = $this->ccShow->getCcShowDayss();
            }
        }

        if (!is_null($end)) {
            $populateUntil = $end;
        }
<commit_msg>CC-5869: Changing a repeating show to non-repeating and changing start time does not work<commit_after><?php
define("MAX_REBROADCAST_DATES", 10);
define("NO_REPEAT", -1);
define("REPEAT_WEEKLY", 0);
define("REPEAT_BI_WEEKLY", 1);
define("REPEAT_MONTHLY_MONTHLY", 2);
define("REPEAT_MONTHLY_WEEKLY", 3);
define("REPEAT_TRI_WEEKLY", 4);
define("REPEAT_QUAD_WEEKLY", 5);

use Airtime\CcShowHosts;
use Airtime\CcShowHostsQuery;
use Airtime\CcShow;
use Airtime\CcShowQuery;
use Airtime\CcShowInstances;
use Airtime\CcShowInstancesPeer;
use Airtime\CcShowInstancesQuery;
use Airtime\CcSchedulePeer;
use Airtime\CcScheduleQuery;
use Airtime\CcShowDays;
use Airtime\CcShowDaysPeer;
use Airtime\CcShowDaysQuery;
use Airtime\CcShowRebroadcast;
use Airtime\CcShowRebroadcastQuery;

class Application_Service_ShowService
{
    private $ccShow;
    private $isRecorded;
    private $isRebroadcast;
    private $repeatType;
    private $isUpdate;
    private $linkedShowContent;
    private $oldShowTimezone;
    private $localShowStartHour;
    private $localShowStartMin;
    private $origCcShowDay;
    private $origShowRepeatStatus;
    private $instanceIdsForScheduleUpdates;

    public function __construct($showId=null, $showData=null, $isUpdate=false)
    {
        if (!is_null($showId)) {
            $this->ccShow = CcShowQuery::create()->findPk($showId);
        }

        if (isset($showData["add_show_repeats"]) && $showData["add_show_repeats"]) {
            $this->repeatType = $showData["add_show_repeat_type"];
            if ($showData["add_show_repeat_type"] == 2) {
                $this->repeatType = $showData["add_show_monthly_repeat_type"];
            }
        } else {
            $this->repeatType = -1;
        }

        $this->isRecorded = (isset($showData['add_show_record']) && $showData['add_show_record']) ? 1 : 0;
        $this->isRebroadcast = (isset($showData['add_show_rebroadcast']) && $showData['add_show_rebroadcast']) ? 1 : 0;
        $this->isUpdate = $isUpdate;
        $this->instanceIdsForScheduleUpdates = array();
    }

    public function editRepeatingShowInstance($showData) {
        $service_user = new Application_Service_UserService();
        $currentUser = $service_user->getCurrentUser();

        $showData["add_show_duration"] = $this->formatShowDuration(
            $showData["add_show_duration"]);

        $con = Propel::getConnection();
        $con->beginTransaction();
        try {
            if (!$currentUser->isAdminOrPM()) {
                throw new Exception("Permission denied");
            }

            $showId = $showData["add_show_id"];

            /****** UPDATE SCHEDULE START TIME ******/
            //get the ccShow object to which this instance belongs
            //so we can get the original start date and time
            $this->ccShow = CcShowQuery::create()
                ->findPk($showId);

            //DateTime in shows's local time
            $newStartDateTime = new DateTime($showData["add_show_start_date"]." ".
            $showData["add_show_start_time"],
                new DateTimeZone($showData["add_show_timezone"]));

            $ccShowInstanceOrig = CcShowInstancesQuery::create()
                ->findPk($showData["add_show_instance_id"]);

            //convert original start time into the show's local timezone
            $origLocalStartDateTime = $ccShowInstanceOrig->getLocalStartDateTime();

            $diff = $this->calculateShowStartDiff($newStartDateTime,
                $origLocalStartDateTime);

            if ($diff != 0) {
                Application_Service_SchedulerService::updateScheduleStartTime(
                    array($showData["add_show_instance_id"]), $diff);
            }
            /****** UPDATE SCHEDULE START TIME ENDS******/

            /*
             * In the case where an instance is being edited for a second
             * (or third, fourth, etc.) time we need to delete the old
             * cc_show_day record
             * 
             * Since we don't store the cc_show_day ids we need to use the
             * original start time from cc_show_instances, convert it to the show's
             * local timezone, and find the record in cc_show_days
             * 
             * *** There is a flaw here: We have to assume the show timezone has
             * *** not changed (make timezone readonly??)
             */
            $origCcShowDay = CcShowDaysQuery::create()
                ->filterByDbShowId($showId)
                ->filterByDbRepeatType(-1)
                ->filterByDbFirstShow($origLocalStartDateTime->format("Y-m-d"))
                ->filterByDbStartTime($origLocalStartDateTime->format("H:i:s"))
                ->delete();

            /*
             * Set the new cc_show_day record
             * Associates it with the current show_id and sets it to non-repeating
             */
            $this->setCcShowDays($showData);

            /*
             * We need to find the new show day rule we just created by passing
             * in the first show and start time in case multiple single
             * instances have been edited out of the repeating sequence.
             */
            $showDay = CcShowDaysQuery::create()
                ->filterByDbShowId($showId)
                ->filterByDbRepeatType(-1)
                ->filterByDbFirstShow($showData["add_show_start_date"])
                ->filterByDbStartTime($showData["add_show_start_time"].":00")
                ->findOne();

            $ccShowInstance = $this->createNonRepeatingInstance($showDay,
                $this->getPopulateShowUntilDateTIme());

            //update cc_schedule with the new instance id
            $con = Propel::getConnection(CcShowInstancesPeer::DATABASE_NAME);
            $selectCriteria = new Criteria();
            $selectCriteria->add(CcSchedulePeer::INSTANCE_ID, $showData["add_show_instance_id"]);
            $updateCriteria = new Criteria();
            $updateCriteria->add(CcSchedulePeer::INSTANCE_ID, $ccShowInstance->getDbId());
            BasePeer::doUpdate($selectCriteria, $updateCriteria, $con);

            $ccShowInstance->updateDbTimeFilled($con);
            $ccShowInstance->updateScheduleStatus($con);

            //delete the edited instance from the repeating sequence
            $ccShowInstanceOrig->setDbModifiedInstance(true)->save();

            $con->commit();
            Application_Model_RabbitMq::PushSchedule();
        } catch (Exception $e) {
            $con->rollback();
            Logging::info("EXCEPTION: Show update failed.");
            Logging::info($e->getMessage());
        }
    }

    /**
     * 
     * If a user is editing a show we need to store the original timezone and
     * start time in case the show's timezone is changed and we are crossing
     * over DST
     */
    private function storeOrigLocalShowInfo()
    {
        if ($this->ccShow->isRepeating()) {
            $this->origCcShowDay = clone $this->ccShow->getFirstRepeatingCcShowDay();
            $this->origShowRepeatStatus = true;
        } else {
            $this->origCcShowDay = clone $this->ccShow->getFirstCcShowDay();
            $this->origShowRepeatStatus = false;
        }

        $this->oldShowTimezone = $this->origCcShowDay->getDbTimezone();

        $origStartTime = explode(":", $this->origCcShowDay->getDbStartTime());
        $this->localShowStartHour = $origStartTime[0];
        $this->localShowStartMin = $origStartTime[1];
    }

    public function addUpdateShow($showData)
    {
        $service_user = new Application_Service_UserService();
        $currentUser = $service_user->getCurrentUser();

        $showData["add_show_duration"] = $this->formatShowDuration(
            $showData["add_show_duration"]);

        $con = Propel::getConnection();
        $con->beginTransaction();
        try {
            if (!$currentUser->isAdminOrPM()) {
                throw new Exception("Permission denied");
            }

            //update ccShow
            $this->setCcShow($showData);

            $daysAdded = array();

            if ($this->isUpdate) {
                if (!$this->ccShow->getCcShowDayss()->isEmpty()) {
                    $this->storeOrigLocalShowInfo();
                }

                $daysAdded = $this->delegateInstanceCleanup($showData);

                $this->deleteRebroadcastInstances();

                $this->deleteCcShowHosts();

                if ($this->isRebroadcast) {
                    //delete entry in cc_show_rebroadcast
                    $this->deleteCcShowRebroadcasts();
                }

                $this->storeInstanceIds();
            }

            //update ccShowDays
            $this->setCcShowDays($showData);

            //update ccShowRebroadcasts
            $this->setCcShowRebroadcasts($showData);

            //update ccShowHosts
            $this->setCcShowHosts($showData);

            //create new ccShowInstances
            $this->delegateInstanceCreation($daysAdded);

            if ($this->isUpdate) {

                /* If the show is repeating and the start date changes we need
                 * to ignore that difference when re-calculating schedule start times.
                 * Otherwise it might calculate a difference of a week, for example.
                 */
                if ($this->ccShow->isRepeating() && 
                    $this->origCcShowDay->getLocalStartDateAndTime()->format("Y-m-d") != $showData["add_show_start_date"]) {
                        $showData["add_show_start_date"] = $this->origCcShowDay->getLocalStartDateAndTime()->format("Y-m-d");
                }

                $this->adjustSchedule($showData);
            }

            $con->commit();
            Application_Model_RabbitMq::PushSchedule();
        } catch (Exception $e) {
            $con->rollback();
            $this->isUpdate ? $action = "update" : $action = "creation";
            Logging::info("EXCEPTION: Show ".$action." failed.");
            Logging::info($e->getMessage());
        }
    }

    /**
     * 
     * Returns an array of instance ids that already exist
     * We need this if a show is being updated so we can separate the 
     * instances that already exist and any new instances that
     * get created (by adding a new repeat show day)
     */
    private function storeInstanceIds()
    {
        $instances = $this->ccShow->getCcShowInstancess();
        foreach ($instances as $instance) {
            $this->instanceIdsForScheduleUpdates[] = $instance->getDbId();
        }
    }

    private function adjustSchedule($showData)
    {
        $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME);

        $this->updateScheduleStartEndTimes($showData);

        $ccShowInstances = $this->ccShow->getCcShowInstancess();
        foreach ($ccShowInstances as $instance) {
            $instance->updateScheduleStatus($con);
        }
    }

    /**
     *
     * Receives a cc_show id and determines whether to create a
     * single show instance or repeating show instances
     */
    public function delegateInstanceCreation($daysAdded=null, $end=null, $fillInstances=false)
    {
        $populateUntil = $this->getPopulateShowUntilDateTIme();

        if (is_null($this->ccShow)) {
            $ccShowDays = $this->getShowDaysInRange($populateUntil, $end);
        } else {
            if ($this->ccShow->isRepeating()) {
                $ccShowDays = $this->ccShow->getRepeatingCcShowDays();
            } else {
                //$ccShowDays = $this->ccShow->getCcShowDayss();
                
                /* Cannot use the above statement to get the cc_show_days
                 * object because it's getting the old object before the
                 * show was edited. clearInstancePool() didn't work.
                 */
                $ccShowDays = CcShowDaysQuery::create()
                    ->filterByDbShowId($this->ccShow->getDbId())
                    ->find();
            }
        }

        if (!is_null($end)) {
            $populateUntil = $end;
        }

{'fraction_non_alphanumeric': 0.11710759868143014, 'fraction_numerical': 0.002028569013608317, 'mean_word_length': 2.2277997544673305, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 229, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5519157', 'n_tokens_mistral': 6771, 'n_tokens_neox': 6485, 'n_words': 1350}