Ejemplo n.º 1
0
 public function validateUpdate($payload, sfWebRequest $request = null)
 {
     parent::validateUpdate($payload, $request);
     $primaryKey = $request->getParameter('id');
     $params = $this->parsePayload($payload);
     $user = $this->getUser()->getGuardUser();
     if (!$user) {
         throw new sfException('Action requires an auth token.', 401);
     }
     $deadline = DeadlineTable::getInstance()->find($request->getParameter('id'));
     $subreddit_id = $deadline->getSubredditId();
     $admin = sfGuardUserSubredditMembershipTable::getInstance()->getFirstByUserSubredditAndMemberships($user->getIncremented(), $subreddit_id, array('admin'));
     if (!$admin && !$this->getUser()->isSuperAdmin()) {
         throw new sfException("Your user does not have permissions to " . "update Deadlines in this Subreddit.", 403);
     }
 }
 public function advanceEpisodeAssignments()
 {
     $subreddit_first_deadlines = array();
     $subreddit_deadline_rules = array();
     // We establish the pool of emails we'll be sending.
     // First to those who pass their deadline
     $passed_deadline_assignments = array();
     // And to the new episode assignments that are reassigned
     $newly_assigned_assignments = array();
     // Now we can start on the assignments that are misassigned
     $assignments = EpisodeAssignmentTable::getInstance()->getMisassignedEpisodes();
     $episodes = new Doctrine_Collection('Episode');
     $e = -1;
     for ($i = 0; $i < count($assignments); $i++) {
         $passed_deadline_assignments[] = $assignments[$i];
         $assignments[$i]->setMissedDeadline(true);
         $episodes[++$e] = $assignments[$i]->getEpisode();
         // Clean up the Episode for any new user to use.
         $episodes[$e]->setEpisodeAssignmentId(null);
         $audio_file = $episodes[$e]->getAudioFile();
         $nice_filename = $episodes[$e]->getNiceFilename();
         $graphic_file = $episodes[$e]->getGraphicFile();
         $episodes[$e]->setAudioFile(null);
         $episodes[$e]->setNiceFilename(null);
         $episodes[$e]->setGraphicFile(null);
         $episodes[$e]->setIsNsfw(false);
         $episodes[$e]->setTitle(null);
         $episodes[$e]->setDescription(null);
         $episodes[$e]->setIsSubmitted(false);
         $episodes[$e]->setSubmittedAt(null);
         $episodes[$e]->setFileIsRemote(null);
         $episodes[$e]->setRemoteUrl(null);
         $episodes[$e]->setRedditPostUrl(null);
     }
     $episodes->save();
     $assignments->save();
     /* Now we make sure that all assignments past deadline are marked as
      * such.  If the assignment is here, however, then it hasn't ever
      * actually BEEN assigned and isn't added to the list of emails to send
      * out. */
     $assignments = EpisodeAssignmentTable::getInstance()->getUnmarkedEpisodesThatMissedDeadlines();
     for ($i = 0; $i < count($assignments); $i++) {
         $assignments[$i]->setMissedDeadline(true);
     }
     $assignments->save();
     /* Now all episodes are cleared and we need to see if they need to be
      * reassigned to an existing asignment. */
     /* Returns assignments closest to the front for each unassigned episode,
      * in order of closeness. */
     $assignments = EpisodeAssignmentTable::getInstance()->getEpisodesPossiblyNeedingAssignment();
     $subreddit_ids = EpisodeAssignmentTable::getInstance()->getSubrbedditsOfEpisodesPossiblyNeedingAssignment();
     $deadlines = DeadlineTable::getInstance()->getDeadlinesForGivenSubreddits($subreddit_ids);
     $subreddit_first_authortypes = array();
     $subreddit_deadline_rules = array();
     $begun = false;
     $prev_subreddit_id = null;
     foreach ($deadlines as $deadline) {
         $subreddit_id = $deadline['subreddit_id'];
         if ($prev_subreddit_id != $subreddit_id && $begun) {
             $begun = false;
             $prev_subreddit_id = $subreddit_id;
         }
         if (!$begun) {
             $subreddit_deadline_rules[$subreddit_id] = array($deadline['author_type_id'] => $deadline['seconds']);
             $subreddit_first_authortypes[$subreddit_id] = $deadline['author_type_id'];
             $begun = true;
         } else {
             $author_type_id = $deadline['author_type_id'];
             $subreddit_deadline_rules[$subreddit_id][$author_type_id] = $deadline['seconds'];
         }
     }
     $episodes_affected = array();
     // Things used from assignment: episode_id, epsiode, author_type_id, id, sf_guard_user_id
     // Things used from episode: subreddit_id, surbeddit, release_date,
     // Things used from subreddit: getFirstDeadlineId(), getDeadlineRules()
     foreach ($assignments as $assignment) {
         if (!in_array($assignment['episode_id'], $episodes_affected)) {
             /* Ignore all subsequent assignments for an episode after the
              * first!  We should only be dealing with assignments that have
              * not missed their deadlines! */
             $episodes_affected[] = $assignment['episode_id'];
             $assign_to_episode = false;
             $subreddit_id = $assignment['subreddit_id'];
             $subreddit = SubredditTable::getInstance()->find($subreddit_id);
             /* If the *first* assignment is in the first spot, then assign
              * it. */
             $deadline_rules = $subreddit_deadline_rules[$subreddit_id];
             $author_type_id = $assignment['author_type_id'];
             if ($author_type_id == $subreddit_first_authortypes[$subreddit_id]) {
                 $assign_to_episode = true;
             } else {
                 /* Otherwise, check if we are past the deadline for the
                  * previous deadline. */
                 /*$previous_author_type_id = DeadlineTable::getInstance()
                   ->getFirstAuthorTypeIdBySubredditWhereDeadlineIsGreaterThan(
                   $deadline_rules[$author_type_id],
                   $subreddit_id);*/
                 $inverse_deadline_rules = array_reverse($deadline_rules, true);
                 $previous_author_type_id = null;
                 foreach ($inverse_deadline_rules as $author_type => $seconds) {
                     if ($seconds > $deadline_rules[$author_type_id]) {
                         $previous_author_type_id = $author_type;
                         break;
                     }
                 }
                 $past_deadline_for_previous = strtotime($assignment['release_date']) - $deadline_rules[$previous_author_type_id] <= time();
                 if ($past_deadline_for_previous) {
                     $assign_to_episode = true;
                 }
             }
             if ($assign_to_episode) {
                 $saved_episode = EpisodeTable::getInstance()->find($assignment['episode_id']);
                 $saved_episode->setEpisodeAssignmentId($assignment['id']);
                 $saved_episode->save();
                 $newly_assigned_assignments[] = $assignment;
             }
         }
     }
     // We send the emails for the current deadline we're checking.
     foreach ($passed_deadline_assignments as $assignment) {
         $this->sendEmailAboutPassedDeadline($assignment['sf_guard_user_id'], $assignment['episode_id']);
     }
     foreach ($newly_assigned_assignments as $assignment) {
         $release_date = strtotime($assignment['release_date']);
         $author_type_id = $assignment['author_type_id'];
         $seconds = $deadline_rules[$author_type_id];
         $deadline = $release_date - $seconds;
         $this->sendEmailAboutNewAssignment($assignment['sf_guard_user_id'], $assignment['episode_id'], $deadline);
     }
 }
Ejemplo n.º 3
0
 public function advanceEpisodeAssignments()
 {
     // We grab the Deadlines in descending order for the Subreddit;
     $deadline_rules = $this->getDeadlineRules();
     $first_deadline_id = $this->getFirstDeadlineId();
     $first_deadline = DeadlineTable::getInstance()->find($first_deadline_id);
     // We establish the pool of emails we'll be sending.
     // First to those who pass their deadline
     $passed_deadline_assignments = array();
     // And to the new episode assignments that are reassigned
     $newly_assigned_assignments = array();
     // Now we can start on the assignments that are misassigned
     $assignments = EpisodeAssignmentTable::getInstance()->getMisassignedEpisodes($this->getIncremented());
     $episodes = new Doctrine_Collection('Episode');
     $e = -1;
     for ($i = 0; $i < count($assignments); $i++) {
         $passed_deadline_assignments[] = $assignments[$i];
         $assignments[$i]->setMissedDeadline(true);
         $episodes[++$e] = $assignments[$i]->getEpisode();
         // Clean up the Episode for any new user to use.
         $episodes[$e]->setEpisodeAssignmentId(null);
         $audio_file = $episodes[$e]->getAudioFile();
         $nice_filename = $episodes[$e]->getNiceFilename();
         $graphic_file = $episodes[$e]->getGraphicFile();
         $episodes[$e]->setAudioFile(null);
         $episodes[$e]->setNiceFilename(null);
         $episodes[$e]->setGraphicFile(null);
         $episodes[$e]->setIsNsfw(false);
         $episodes[$e]->setTitle(null);
         $episodes[$e]->setDescription(null);
         $episodes[$e]->setIsSubmitted(false);
         $episodes[$e]->setSubmittedAt(null);
         $episodes[$e]->setFileIsRemote(null);
         $episodes[$e]->setRemoteUrl(null);
         $episodes[$e]->setRedditPostUrl(null);
     }
     $episodes->save();
     $assignments->save();
     /* Now we make sure that all assignments past deadline are marked as
      * such.  If the assignment is here, however, then it hasn't ever
      * actually BEEN assigned and isn't added to the list of emails to send
      * out. */
     $assignments = EpisodeAssignmentTable::getInstance()->getUnmarkedEpisodesThatMissedDeadlines($this->getIncremented());
     for ($i = 0; $i < count($assignments); $i++) {
         $assignments[$i]->setMissedDeadline(true);
     }
     $assignments->save();
     /* Now all episodes are cleared and we need to see if they need to be
      * reassigned to an existing asignment. */
     /* Returns assignments closest to the front for each unassigned episode,
      * in order of closeness. */
     $assignments = EpisodeAssignmentTable::getInstance()->getEpisodesPossiblyNeedingAssignment($this->getIncremented());
     $episodes_affected = array();
     foreach ($assignments as $assignment) {
         if (!in_array($assignment->getEpisodeId(), $episodes_affected)) {
             /* Ignore all subsequent assignments for an episode after the
              * first!  We should only be dealing with assignments that have
              * not missed their deadlines! */
             $episodes_affected[] = $assignment->getEpisodeId();
             $episode = $assignment->getEpisode();
             $assign_to_episode = false;
             /* If the *first* assignment is in the first spot, then assign
              * it. */
             if ($assignment->getAuthorTypeId() == $first_deadline->getAuthorTypeId()) {
                 $assign_to_episode = true;
             } else {
                 /* Otherwise, check if we are past the deadline for the
                  * previous deadline. */
                 $previous_author_type_id = DeadlineTable::getInstance()->getFirstAuthorTypeIdBySubredditWhereDeadlineIsGreaterThan($deadline_rules[$assignment->getAuthorTypeId()], $episode->getSubredditId());
                 $past_deadline_for_previous = strtotime($episode->getReleaseDate()) - $deadline_rules[$previous_author_type_id] <= time();
                 if ($past_deadline_for_previous) {
                     $assign_to_episode = true;
                 }
             }
             if ($assign_to_episode) {
                 $episode->setEpisodeAssignmentId($assignment->getIncremented());
                 $episode->save();
                 $newly_assigned_assignments[] = $assignment;
             }
         }
     }
     // We send the emails for the current deadline we're checking.
     foreach ($passed_deadline_assignments as $assignment) {
         $this->sendEmailAboutPassedDeadline($assignment->getSfGuardUserId(), $assignment->getEpisodeId());
     }
     foreach ($newly_assigned_assignments as $assignment) {
         $episode = $assignment->getEpisode();
         $release_date = strtotime($episode->getReleaseDate());
         $seconds = $deadline_rules[$assignment->getAuthorTypeId()];
         $deadline = $release_date - $seconds;
         $this->sendEmailAboutNewAssignment($assignment->getSfGuardUserId(), $episode->getIncremented(), $deadline);
     }
 }
 /**
  * applies the changes made to this object into database
  * this method is smart enough to know if any changes are made
  * and whether to use INSERT or UPDATE statement
  *
  * this method also saves the related components
  * 
  * Before creating a new EpisodeAssignment, this function verifies the
  * following rules:
  * 
  * 101) Blocked users should not be able to sign up for an Episode. Throws
  *      an sfException upon this failure.
  * 
  * 102) Only one sfGuardUser can sign up for one Episode with the same
  *      AuthorType for each Application period. Throws an sfException upon
  *      this failure.
  * 
  * 103) An sfGuardUser can only sign up for the same Episode with one
  *      AuthorType. Throws an sfException upon this failure.
  * 
  * 104) The EpisodeAssignment must be within the deadline for the
  *      AuthorType. Throws an sfException upon this failure.
  * 
  * 105) If the current AuthorType is flagged to be unavailable before the
  *      previous AuthorType has passed its Deadline by its Application
  *      record for the Subreddit and this previous Deadline has not passed,
  *      then the object will not be saved.  Throws an sfException upon this
  *      failure.
  * 
  * 106) The user attached to the EpisodeAssignment must be validated.
  * 
  * @see Doctrine_Record::save()
  * @throws sfException
  *
  * @param Doctrine_Connection $conn     optional connection parameter
  * @throws Exception                    if record is not valid and validation is active
  * @return void
  */
 public function save(Doctrine_Connection $conn = null)
 {
     /* If an EpisodeAssignment already exists we don't care about it. */
     if ($this->isNew()) {
         /* Blocked users should not be able to sign up for an Episode.
          */
         if (!$this->isAMember()) {
             $this->deleteWithException("Cannot create EpisodeAssignment " . "because User " . $this->getSfGuardUser()->getUsername() . " has not yet joined the Subreddit.", 101);
         }
         /* Blocked users should not be able to sign up for an Episode.
          */
         if ($this->hasBlockedUser()) {
             $this->deleteWithException("Cannot create EpisodeAssignment " . "because User " . $this->getSfGuardUser()->getUsername() . " has a blocked Membership within Subreddit.", 101);
         }
         /* If the Subreddit doesn't allow pending users to post, then we fail if the user is a pending member of the Subreddit. */
         if ($this->subredditBlocksPendingUsers()) {
             $this->deleteWithException("Cannot create EpisodeAssignment " . "because User " . $this->getSfGuardUser()->getUsername() . " has a pending Membership within Subreddit.", 101);
         }
         /* Only one sfGuardUser can sign up for one Episode with the same
          * AuthorType for each Application period.
          */
         if ($this->hasExistingUserAuthorTypeAssignment()) {
             $this->deleteWithException("Cannot create EpisodeAssignment " . "because User " . $this->getSfGuardUser()->getUsername() . " has already registered with AuthorType " . $this->getAuthorType() . " within Subreddit.", 102);
         }
         /* Only one sfGuardUser can sign up for one Episode with the same
          * AuthorType for each Application period.
          */
         if ($this->hasExistingAssignmentOnOtherEpisode()) {
             $this->deleteWithException("Cannot create EpisodeAssignment " . "because User " . $this->getSfGuardUser()->getUsername() . " has already registered with AuthorType " . $this->getAuthorType() . " within Subreddit.", 103);
         }
         /* The EpisodeAssignment must be within the deadline for the
          * AuthorType.
          */
         if (!$this->isBeforeDeadlineForAuthorType()) {
             $this->deleteWithException("Cannot create EpisodeAssignment " . "because the deadline has already passed for " . "AuthorType " . $this->getAuthorType() . " within " . "Subreddit.", 104);
         }
         /* Even if the deadline has not yet passed, we may only sign up an 
          * AuthorType if the AuthorType is allowed to register before the 
          * previous AuthorType (meaning the AuthorType with the next-longest
          * deadline).  The next few checks are for this purpose.
          */
         $deadline_seconds = Doctrine::getTable('Deadline')->getSecondsByAuthorAndSubreddit($this->getAuthorTypeId(), $this->getEpisode()->getSubredditId());
         if ($deadline_seconds === false) {
             $this->deleteWithException("Cannot create EpisodeAssignment " . "because the deadline doesn't exist for AuthorType " . $this->getAuthorType() . " within Subreddit.", 107);
         }
         /* Check to see if there *is* a previous AuthorType by Deadline
          * length.
          */
         if ($previous_author_type_id = DeadlineTable::getInstance()->getFirstAuthorTypeIdBySubredditWhereDeadlineIsGreaterThan($deadline_seconds, $this->getEpisode()->getSubredditId())) {
             /* If a previous AuthorType exists, we need to see if the
              * current AuthorType is restricted until that previous 
              * uthorType is expired.  If it *is* restricted, then we need to
              * see if the previous AuthorType has yet expired.  If the
              * previous AuthorType is still beyond its Deadline for the
              * Episode (and has not expired) then we cannot allow the
              * current EpisodeAssignment to be saved.
              */
             if (DeadlineTable::getInstance()->getIfDeadlineRestrictedByAuthorTypeAndSubreddit($this->getAuthorTypeId(), $this->getEpisode()->getSubredditId()) && $this->isBeforeDeadlineForAuthorType($previous_author_type_id)) {
                 $prev_author_type = AuthorTypeTable::getInstance()->find($previous_author_type_id);
                 $this->deleteWithException("Cannot create " . "EpisodeAssignment because the deadline has " . "not yet passed for the previous AuthorType " . $prev_author_type . " within Subreddit.", 105);
             }
         }
         if (!$this->hasVerifiedUser()) {
             $this->deleteWithException("Cannot create EpisodeAssignment " . "because User " . $this->getSfGuardUser()->getUsername() . " has not validated their Reddit username yet.", 106);
         }
         $isNew = true;
     } else {
         $isNew = false;
     }
     /* If the obejct is not new or has passed all rules for saving, we pass
      * it on to the parent save function.
      */
     $this->setIdHashIfNotSet();
     parent::save($conn);
     if ($isNew) {
         /* Now that we have a new EpisodeAssignment that has passed all
          * rules, let's set it to be valid if it belongs to the first
          * Deadline and send an email to the user about it.
          */
         $subreddit = SubredditTable::getInstance()->find($this->getEpisode()->getSubredditId());
         $deadline = DeadlineTable::getInstance()->find($subreddit->getFirstDeadlineId());
         if ($deadline) {
             if ($this->getAuthorTypeId() == $deadline->getAuthorTypeId()) {
                 $episode = $this->getEpisode();
                 $episode->setEpisodeAssignmentId($this->getIncremented());
                 $episode->save();
                 $release_date = strtotime($episode->getReleaseDate());
                 $seconds = $deadline->getSeconds();
                 $deadline = $release_date - $seconds;
                 $subreddit->sendEmailAboutNewAssignment($this->getSfGuardUserId(), $this->getEpisodeId(), $deadline);
             }
         }
     }
 }
 /**
  * Tests for success at creating the object.
  */
 public function testCreate()
 {
     $t = DeadlineTable::getInstance();
     $this->assertTrue($t instanceof Doctrine_Table);
 }