/** * Tests saving a sfGuardUserSubredditMembership that identifies a User as * "blocked" for a particular Subreddit. When this occurs, all existing * future EpisodeAssignments should be deleted because blocked users cannot * participate with the Subreddit. */ public function testSavingBlockedUser() { // Establish fake Subreddit $subreddit = new Subreddit(); $subreddit->setName(rand(0, 1000)); $subreddit->setDomain(rand(0, 1000)); $subreddit->save(); // Establish User $user = new sfGuardUser(); $user->setEmailAddress(rand(0, 100000)); $user->setUsername(rand(0, 10000)); $user->setIsValidated(1); $user->save(); $user_id = $user->getIncremented(); $this->assertNotEquals(0, $user_id); // Establish Episode for Subreddit $episode = new Episode(); $episode->setSubreddit($subreddit); $episode->setReleaseDate(date('Y-m-d H:i:s', time() + 34000)); $episode->save(); $author_type = AuthorTypeTable::getInstance()->findOneBy('type', 'squid'); $deadline = new Deadline(); $deadline->setSubreddit($subreddit); $deadline->setAuthorType($author_type); $deadline->setSeconds(0); $deadline->save(); $episode_assignment = new EpisodeAssignment(); $episode_assignment->setSfGuardUser($user); $episode_assignment->setEpisode($episode); $episode_assignment->setAuthorType($author_type); $episode_assignment->save(); $number_of_episodes = EpisodeAssignmentTable::getInstance()->createQuery()->select('COUNT(EpisodeAssignment.id)')->leftJoin('Episode')->where('subreddit_id = ?', $subreddit->getIncremented())->andWhere('EpisodeAssignment.sf_guard_user_id = ?', $user_id)->andWhere('Episode.release_date > NOW()')->groupBy('EpisodeAssignment.id')->count(); $this->assertEquals(1, $number_of_episodes); // Establish User Membership as Blocked $blocked = MembershipTable::getInstance()->findOneBy('type', 'blocked'); $user_membership = new sfGuardUserSubredditMembership(); $user_membership->setSubreddit($subreddit); $user_membership->setSfGuardUser($user); $user_membership->setMembership($blocked); // Save Membership $user_membership->save(); // Asert that User has zero Episodes $number_of_episodes = EpisodeAssignmentTable::getInstance()->createQuery()->select('COUNT(EpisodeAssignment.id)')->leftJoin('Episode')->where('subreddit_id = ?', $subreddit->getIncremented())->andWhere('EpisodeAssignment.sf_guard_user_id = ?', $user_id)->andWhere('Episode.release_date > NOW()')->groupBy('EpisodeAssignment.id'); $sql = $number_of_episodes->getSqlQuery(); $number_of_episodes = $number_of_episodes->count(); $this->assertTrue(0 == $number_of_episodes, $sql . "\n" . $subreddit->getIncremented() . "\n" . $user_id); // Remove User Membership $user_membership->delete(); // Delete User $user->delete(); // Delete Episode $episode->delete(); // Delete Deadline $deadline->delete(); // Delete Subreddit $subreddit->delete(); }
public function setIdHashIfNotSet() { if ($this->getIdHash()) { return; } $hash = ''; do { $hash = md5(rand(0, 10) . microtime() . $this->getAuthorTypeId() . $this->getSfGuardUserId() . $this->getEpisodeId()); // Since the hash is meant for uses such as phone call recording, we need to make sure it's only numbers. $hash = str_replace(array('a', 'b', 'c', 'd', 'e', 'f'), array(0, 1, 2, 3, 4, 5), $hash); $hash = substr($hash, 0, ProjectConfiguration::getTropoHashLength()); } while (EpisodeAssignmentTable::getInstance()->getByIdHash($hash, $this->getEpisode()->getSubredditId())); $this->setIdHash($hash); }
/** * Creates a token referring to an sfGuardUser object * @param sfWebRequest $request a request object * @return string */ public function executeValidhash(sfWebRequest $request) { $this->forward404Unless($request->isMethod(sfRequest::GET)); $params = $request->getParameterHolder()->getAll(); // notify an event before the action's body starts $this->dispatcher->notify(new sfEvent($this, 'sfDoctrineRestGenerator.get.pre', array('params' => $params))); $request->setRequestFormat('html'); $this->setTemplate('index'); $params = $this->cleanupParameters($params); $is_valid = false; try { $format = $this->getFormat(); if (!array_key_exists('subreddit_id', $params) && !array_key_exists('id_hash', $params)) { throw new sfException('Missing reference to subreddit_id and id_hash!', 400); } if (!array_key_exists('subreddit_id', $params)) { throw new sfException('Missing reference to subreddit_id!', 400); } if (!array_key_exists('id_hash', $params)) { throw new sfException('Missing reference to id_hash!', 400); } $check = EpisodeAssignmentTable::getInstance()->getByIdHash($params['id_hash'], $params['subreddit_id']); if ($check) { $is_valid = true; } } catch (Exception $e) { $this->getResponse()->setStatusCode($e->getCode() ? $e->getCode() : 406); $serializer = $this->getSerializer(); $this->getResponse()->setContentType($serializer->getContentType()); $error = $e->getMessage(); // event filter to enable customisation of the error message. $result = $this->dispatcher->filter(new sfEvent($this, 'sfDoctrineRestGenerator.filter_error_output'), $error)->getReturnValue(); if ($error === $result) { $error = array(array('message' => $error)); $this->output = $serializer->serialize($error, 'error'); } else { $this->output = $serializer->serialize($result); } return sfView::SUCCESS; } $serializer = $this->getSerializer(); $this->getResponse()->setContentType($serializer->getContentType()); $this->output = $serializer->serialize(array('is_valid' => $is_valid), $this->model, false); }
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); } }
/** * This tests whether the * EpisodeAssignmentTable::getFirstByUserAuthorTypeAndSubreddit() function * retrieves the correct EpisodeAssignment for a particular User in a * Subreddit based on the AuthorType used in the EpisodeAssignment. Users * can sign up for one Episode per AuthorType in each Subreddit, which means * future Episodes (sicne we don't want the existence of past episode to * disqualify Users from ever signing up again). */ public function testGetFirstByUserAuthorTypeAndSubreddit() { // Create two episode assignments: one for a past Episode, one for a future $subreddit = new Subreddit(); $subreddit->setName(rand(0, 10000)); $subreddit->setDomain(rand(0, 10000)); $subreddit->save(); $user = new sfGuardUser(); $user->setUsername(rand(0, 10000)); $user->setEmailAddress(rand(0, 10000)); $user->setisValidated(1); $user->save(); $first = AuthorTypeTable::getInstance()->findOneBy('type', 'squid'); $understudy = AuthorTypeTable::getInstance()->findOneBy('type', 'shark'); $this->assertTrue($first instanceof AuthorType); $this->assertNotEquals(null, $first->getIncremented()); $this->assertTrue($understudy instanceof AuthorType); $this->assertNotEquals(null, $understudy->getIncremented()); $deadline_one = new Deadline(); $deadline_one->setSeconds(100); $deadline_one->setAuthorType($first); $deadline_one->setSubreddit($subreddit); $deadline_one->save(); $deadline_two = new Deadline(); $deadline_two->setSeconds(0); $deadline_two->setAuthorType($understudy); $deadline_two->setSubreddit($subreddit); $deadline_two->save(); $episode_one = new Episode(); $episode_one->setReleaseDate(date('Y-m-d H:i:s', time() + 200000)); $episode_one->setSubreddit($subreddit); $episode_one->save(); $episode_two = new Episode(); $episode_two->setReleaseDate(date('Y-m-d H:i:s', time() + 100000)); $episode_two->setSubreddit($subreddit); $episode_two->save(); $episode_three = new Episode(); $episode_three->setReleaseDate(date('Y-m-d H:i:s', time() + 300000)); $episode_three->setSubreddit($subreddit); $episode_three->save(); $assignment_one = new EpisodeAssignment(); $assignment_one->setEpisode($episode_one); $assignment_one->setSfGuardUser($user); $assignment_one->setAuthorType($first); $assignment_one->save(); $assignment_two = new EpisodeAssignment(); $assignment_two->setEpisode($episode_two); $assignment_two->setSfGuardUser($user); $assignment_two->setAuthorType($understudy); $assignment_two->save(); /* There should only be one Episode Assignment for future episodes per * authortype per subreddit, so saving the third assignment should fail * --- this is covered more in EpisodeAssignmentTest.phop */ $exception_thrown = false; $assignment_three = new EpisodeAssignment(); $assignment_three->setEpisode($episode_three); $assignment_three->setSfGuardUser($user); $assignment_three->setAuthorType($first); try { $assignment_three->save(); } catch (Exception $exception) { $exception_thrown = true; $this->assertEquals(102, $exception->getCode()); unset($exception); } $this->assertTrue($exception_thrown); /* Since we can trust that only one assignment per authortype per user * per subreddit exists for future episodes (based on the failure to * save $assignment_three), we check now to ensure that the * getFirstByUserAuthorTypeAndSubreddit() function returns a valid * EpisodeAssignment. */ $test_one = EpisodeAssignmentTable::getInstance()->getFirstByUserAuthorTypeAndSubreddit($assignment_one->getAuthorTypeId(), $assignment_one->getSfGuardUserId(), $assignment_one->getEpisode()->getSubredditId()); $test_two = EpisodeAssignmentTable::getInstance()->getFirstByUserAuthorTypeAndSubreddit($assignment_two->getAuthorTypeId(), $assignment_two->getSfGuardUserId(), $assignment_two->getEpisode()->getSubredditId()); $this->assertEquals($test_one->getIncremented(), $assignment_one->getIncremented()); $this->assertEquals($test_two->getIncremented(), $assignment_two->getIncremented()); $assignment_one->delete(); $assignment_two->delete(); $episode_one->delete(); $episode_two->delete(); $episode_three->delete(); $deadline_one->delete(); $deadline_two->delete(); $user->delete(); $subreddit->delete(); }
public function getEpisodeAssignments() { return EpisodeAssignmentTable::getInstance()->getAllByEpisodeId($this->getIncremented()); }
public function validateUpload($payload, sfWebRequest $request = null) { if (!$request->hasParameter('id_hash')) { throw new sfException('No "id_hash" argument found.', 400); } if (!$request->hasParameter('subreddit_id')) { throw new sfException('No "subreddit_id" argument found.', 400); } $content_file = $request->getFiles('filename'); $this->_temporary_file_location = array_key_exists('tmp_name', $content_file) ? $content_file['tmp_name'] : null; $this->_nice_filename = array_key_exists('name', $content_file) ? $content_file['name'] : null; $id_hash = $request->getParameter('id_hash'); $subreddit_id = $request->getParameter('subreddit_id'); $episode_assignment = EpisodeAssignmentTable::getInstance()->getByIdHash($id_hash, $subreddit_id); if (!$episode_assignment) { throw new sfException('No assignment found for given id hash in the subreddit', 404); } /* Check that the Episode is assigned to the episode_assignment and that * the current user is the user of the EpisodeAssignment or otherwise * has permission to upload. */ if (!$this->getUser()->isSuperAdmin() && $episode_assignment->getIncremented() != $episode_assignment->getEpisode()->getEpisodeAssignmentId()) { throw new sfException('Your user does not have permissions to ' . 'upload audio for this Episode.', 403); } $this->object = $episode_assignment->getEpisode(); }