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); } }
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); }