public function run()
 {
     $message = '';
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $projectIds = array_map(function ($e) {
         return $e['id'];
     }, $projectlist->entries);
     $emptyQuestionTitles = 0;
     foreach ($projectIds as $projectId) {
         $project = new ProjectModel($projectId);
         $activityEntries = ActivityListDto::getActivityForProject($project);
         foreach ($activityEntries as $activity) {
             if (key_exists('questionRef', $activity) && key_exists('question', $activity['content'])) {
                 $questionId = $activity['questionRef'];
                 $questionTitle = $activity['content']['question'];
                 if ($questionTitle == '') {
                     $emptyQuestionTitles++;
                     $questionModel = new QuestionModel($project, $questionId);
                     $activityModel = new ActivityModel($project, $activity['id']);
                     $newTitle = $questionModel->getTitleForDisplay();
                     $activityModel->actionContent['question'] = $newTitle;
                     $message .= "Fixing activity " . $activity['action'] . " with title '" . $newTitle . "'\n";
                     $activityModel->write();
                 }
             }
         }
     }
     if ($emptyQuestionTitles > 0) {
         $message .= "\n\nFixed up {$emptyQuestionTitles} empty question titles in the activity log\n\n";
     } else {
         $message .= "\n\nNo empty question titles were found in the activity log \n\n";
     }
     return $message;
 }
 public function testAnswerCRUD_Works()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $textRef = MongoTestEnvironment::mockId();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     // Create Question
     $question = new QuestionModel($project);
     $question->title = "Some Question";
     $question->textRef->id = $textRef;
     $questionId = $question->write();
     // List
     $question->read($questionId);
     $count = count($question->answers);
     $this->assertEqual(0, $count);
     // Create
     $answer = new AnswerModel();
     $answer->content = 'Some answer';
     $id = $question->writeAnswer($answer);
     $comment = new CommentModel();
     $comment->content = 'Some comment';
     $commentId = QuestionModel::writeComment($project->databaseName(), $questionId, $id, $comment);
     $this->assertNotNull($id);
     $this->assertIsA($id, 'string');
     $this->assertEqual(24, strlen($id));
     $this->assertEqual($id, $answer->id->asString());
     // Read back
     $otherQuestion = new QuestionModel($project, $questionId);
     $otherAnswer = $otherQuestion->answers[$id];
     $this->assertEqual($id, $otherAnswer->id->asString());
     $this->assertEqual('Some answer', $otherAnswer->content);
     $this->assertEqual(1, count($otherAnswer->comments));
     // Update
     $otherAnswer->content = 'Other answer';
     // Note: Updates to the AnswerModel should not clobber child nodes such as comments. Hence this test.
     // See https://github.com/sillsdev/sfwebchecks/issues/39
     unset($otherAnswer->comments[$commentId]);
     $otherQuestion->read($otherQuestion->id->asString());
     $otherId = $otherQuestion->writeAnswer($otherAnswer);
     $this->assertEqual($id, $otherId);
     // Read back
     $otherQuestion = new QuestionModel($project, $questionId);
     $otherAnswer = $otherQuestion->answers[$id];
     $this->assertEqual($id, $otherAnswer->id->asString());
     $this->assertEqual('Other answer', $otherAnswer->content);
     $this->assertEqual(1, count($otherAnswer->comments));
     // List
     $this->assertEqual(1, count($otherQuestion->answers));
     // Delete
     QuestionModel::removeAnswer($project->databaseName(), $questionId, $id);
     // List
     $otherQuestion->read($questionId);
     $this->assertEqual(0, count($otherQuestion->answers));
 }
 public function testAnswerCRUD_Works()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $textRef = MongoTestEnvironment::mockId();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     // Create Question
     $question = new QuestionModel($project);
     $question->title = "Some Question";
     $question->textRef->id = $textRef;
     $questionId = $question->write();
     // Create Answer
     $answer = new AnswerModel();
     $answer->content = 'Some answer';
     $answerId = $question->writeAnswer($answer);
     // List
     $question->read($questionId);
     $count = count($question->answers[$answerId]->comments);
     $this->assertEqual(0, $count);
     // Create
     $comment = new CommentModel();
     $comment->content = 'Some comment';
     $id = QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment);
     $this->assertNotNull($id);
     $this->assertIsA($id, 'string');
     $this->assertEqual(24, strlen($id));
     $this->assertEqual($id, $comment->id->asString());
     // Read back
     $otherQuestion = new QuestionModel($project, $questionId);
     $otherComment = $otherQuestion->answers[$answerId]->comments[$id];
     $this->assertEqual($id, $otherComment->id->asString());
     $this->assertEqual('Some comment', $otherComment->content);
     // Update
     $otherComment->content = 'Other comment';
     $otherId = $question->writeComment($project->databaseName(), $questionId, $answerId, $otherComment);
     $this->assertEqual($id, $otherId);
     // Read back
     $otherQuestion = new QuestionModel($project, $questionId);
     $otherComment = $otherQuestion->answers[$answerId]->comments[$id];
     $this->assertEqual($id, $otherComment->id->asString());
     $this->assertEqual('Other comment', $otherComment->content);
     // List
     $count = count($otherQuestion->answers[$answerId]->comments);
     $this->assertEqual(1, $count);
     // Delete
     QuestionModel::removeComment($project->databaseName(), $questionId, $answerId, $id);
     // List
     $otherQuestion->read($questionId);
     $count = count($otherQuestion->answers[$answerId]->comments);
     $this->assertEqual(0, $count);
 }
 public function create()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $this->website = $e->website;
     $this->project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $this->project->appName = 'sfchecks';
     $this->project->write();
     $this->question = new QuestionModel($this->project);
     $this->question->write();
     $this->userId = $e->createUser('test_user', 'Test User', '*****@*****.**');
     $this->projectId = $this->project->id->asString();
     $this->questionId = $this->question->id->asString();
 }
 public static function updateQuestion($projectId, $object)
 {
     $projectModel = new \Api\Model\ProjectModel($projectId);
     $questionModel = new \Api\Model\QuestionModel($projectModel);
     $isNewQuestion = $object['id'] == '';
     if (!$isNewQuestion) {
         $questionModel->read($object['id']);
     }
     JsonDecoder::decode($questionModel, $object);
     $questionId = $questionModel->write();
     if ($isNewQuestion) {
         ActivityCommands::addQuestion($projectModel, $questionId, $questionModel);
     }
     return $questionId;
 }
 public function testTextReference_NullRefValidRef_AllowsNullRef()
 {
     $e = new MongoTestEnvironment();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $mockTextRef = (string) new \MongoId();
     // Test create with null textRef
     $question = new QuestionModel($project);
     $id = $question->write();
     $otherQuestion = new QuestionModel($project, $id);
     $this->assertEqual('', $otherQuestion->textRef->id);
     // Test update with textRef
     $question->textRef->id = $mockTextRef;
     $question->write();
     $otherQuestion = new QuestionModel($project, $id);
     $this->assertEqual($mockTextRef, $otherQuestion->textRef->id);
 }
 public function encodeIdReference($key, $model)
 {
     if ($model->asString() == '') {
         return '';
     }
     if ($key == 'userRef' || $key == 'userRef2') {
         $user = new UserModel();
         if ($user->exists($model->asString())) {
             $user->read($model->asString());
             return array('id' => $user->id->asString(), 'avatar_ref' => $user->avatar_ref, 'username' => $user->username);
         } else {
             return '';
         }
     } elseif ($key == 'projectRef') {
         $project = new ProjectModel($model->asString());
         return array('id' => $project->id->asString(), 'type' => $project->appName);
     } elseif ($key == 'textRef') {
         $text = new TextModel($this->_project);
         if ($text->exists($model->asString())) {
             return $model->asString();
         } else {
             return '';
         }
     } elseif ($key == 'questionRef') {
         $question = new QuestionModel($this->_project);
         if ($question->exists($model->asString())) {
             return $model->asString();
         } else {
             return '';
         }
     } elseif ($key == 'entryRef') {
         $entry = new LexEntryModel($this->_project);
         if ($entry->exists($model->asString())) {
             return $model->asString();
         } else {
             return '';
         }
     } else {
         return $model->asString();
     }
 }
 public function testUserEngagementReport_simpleProjectWithQuestionsAndAnswers_AsExpected()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text = new TextModel($project);
     $text->title = "Text 1";
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $user1Id = $e->createUser("user1", "user1", "*****@*****.**");
     $user2Id = $e->createUser("user2", "user2", "*****@*****.**");
     $user3Id = $e->createUser("user3", "user3", "*****@*****.**");
     ProjectCommands::updateUserRole($project->id->asString(), $user1Id);
     ProjectCommands::updateUserRole($project->id->asString(), $user2Id);
     ProjectCommands::updateUserRole($project->id->asString(), $user3Id);
     // Workflow is first to create a question
     $question = new QuestionModel($project);
     $question->title = "the question";
     $question->description = "question description";
     $question->textRef->id = $textId;
     $questionId = $question->write();
     // Then to add an answer to a question
     $answer = new AnswerModel();
     $answer->content = "first answer";
     $answer->score = 10;
     $answer->userRef->id = $user3Id;
     $answer->textHightlight = "text highlight";
     $answerId = $question->writeAnswer($answer);
     // Followed by comments
     $comment1 = new CommentModel();
     $comment1->content = "first comment";
     $comment1->userRef->id = $user1Id;
     $comment1Id = QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment1);
     $comment2 = new CommentModel();
     $comment2->content = "second comment";
     $comment2->userRef->id = $user2Id;
     $comment2Id = QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment2);
     $data = SfchecksReports::UserEngagementReport($project->id->asString());
     $this->assertTrue($data['output']);
 }
 public function testEncode_2Questions1Archived_DtoCorrect1ArchivedQuestion()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $userId = $e->createUser("User", "Name", "*****@*****.**");
     $user = new UserModel($userId);
     $user->role = SystemRoles::USER;
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $project->addUser($userId, ProjectRoles::MANAGER);
     $user->addProject($projectId);
     $user->write();
     $project->write();
     $text = new TextModel($project);
     $text->title = "Text Title";
     $textId = $text->write();
     $question1 = new QuestionModel($project);
     $question1->title = "Some Title";
     $question1->textRef->id = $textId;
     $question1->write();
     $question2 = new QuestionModel($project);
     $question2->title = "Archived Title";
     $question2->textRef->id = $textId;
     $question2->isArchived = true;
     $question2->write();
     $dto = TextSettingsDto::encode($projectId, $textId, $userId);
     $this->assertIsA($dto['text'], 'array');
     $this->assertEqual($dto['text']['id'], $textId);
     $this->assertEqual($dto['text']['title'], 'Text Title');
     $this->assertIsA($dto['archivedQuestions'], 'array');
     $this->assertEqual(count($dto['archivedQuestions']), 1);
     $this->assertEqual($dto['archivedQuestions'][0]['title'], 'Archived Title');
     $this->assertTrue(count($dto['rights']) > 0, "No rights in dto");
     $this->assertEqual($dto['bcs']['op'], 'settings');
     $this->assertEqual($dto['bcs']['project'], array('id' => $projectId, 'crumb' => SF_TESTPROJECT));
 }
 public function testEncode_ArchivedText_ManagerCanViewContributorCannot()
 {
     $project = $this->environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $managerId = $this->environ->createUser("manager", "manager", "*****@*****.**");
     $contributorId = $this->environ->createUser("contributor1", "contributor1", "*****@*****.**");
     $project->addUser($managerId, ProjectRoles::MANAGER);
     $project->addUser($contributorId, ProjectRoles::CONTRIBUTOR);
     $project->write();
     // Question not archived but Text is archived
     $text = new TextModel($project);
     $text->title = "Text 1";
     $text->isArchived = true;
     $textId = $text->write();
     $question = new QuestionModel($project);
     $question->title = "the question";
     $question->description = "question description";
     $question->textRef->id = $textId;
     $questionId = $question->write();
     $dto = QuestionCommentDto::encode($project->id->asString(), $questionId, $managerId);
     // Manager can view Question of archived Text
     $this->assertEqual($dto['question']['title'], 'the question');
     // Contributor cannot view Question of archived Text, throw Exception
     $this->environ->inhibitErrorDisplay();
     $this->expectException();
     $dto = QuestionCommentDto::encode($project->id->asString(), $questionId, $contributorId);
     // nothing runs in the current test function after an exception. IJH 2014-11
 }
 public function testUpdateComment_ExistingComment_OriginalAuthorIsPreserved()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text = new TextModel($project);
     $text->title = "Text 1";
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $question = new QuestionModel($project);
     $question->textRef->id = $textId;
     $questionId = $question->write();
     $user1Id = $e->createUser("user1", "user1", "user1");
     $user2Id = $e->createUser("user2", "user2", "user2");
     $answer = new AnswerModel();
     $answer->content = "the answer";
     $answer->userRef->id = $user2Id;
     $answerId = $question->writeAnswer($answer);
     $comment = new CommentModel();
     $comment->userRef->id = $user1Id;
     $comment->content = "the comment";
     $commentId = $question->writeComment($project->databaseName(), $questionId, $answerId, $comment);
     $commentArray = array("id" => $commentId, "content" => "updated comment");
     QuestionCommands::updateComment($project->id->asString(), $questionId, $answerId, $commentArray, $user2Id);
     $question->read($questionId);
     $newComment = $question->readComment($answerId, $commentId);
     $this->assertEqual($user1Id, $newComment->userRef->asString());
 }
 public function run($mode = 'test')
 {
     $testMode = $mode == 'test';
     $message = "";
     $userlist = new UserListModel();
     $userlist->read();
     $userIds = array_map(function ($e) {
         return $e['id'];
     }, $userlist->entries);
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $projectIds = array_map(function ($e) {
         return $e['id'];
     }, $projectlist->entries);
     $deadCommentUserRefs = 0;
     $deadAnswerUserRefs = 0;
     foreach ($projectIds as $projectId) {
         $project = new ProjectModel($projectId);
         $textlist = new TextListModel($project);
         $textlist->read();
         $textIds = array_map(function ($e) {
             return $e['id'];
         }, $textlist->entries);
         foreach ($textIds as $textId) {
             $questionlist = new QuestionListModel($project, $textId);
             $questionlist->read();
             $questionIds = array_map(function ($e) {
                 return $e['id'];
             }, $questionlist->entries);
             foreach ($questionIds as $questionId) {
                 $question = new QuestionModel($project, $questionId);
                 foreach ($question->answers as $answerId => $answer) {
                     foreach ($answer->comments as $commentId => $comment) {
                         $ref = $comment->userRef;
                         if (!empty($ref->id) && !in_array($ref->asString(), $userIds)) {
                             $comment->userRef->id = '';
                             if (!$testMode) {
                                 $question->writeComment($project->databaseName(), $questionId, $answerId, $comment);
                             }
                             $deadCommentUserRefs++;
                             $message .= "Removed dead user-comment ref {$ref} from question {$questionId}, answer {$answerId}, comment {$commentId}\n";
                         }
                     }
                     $ref = $answer->userRef;
                     if (!empty($ref->id) && !in_array($ref->asString(), $userIds)) {
                         $answer->userRef->id = '';
                         if (!$testMode) {
                             $question->writeAnswer($answer);
                         }
                         $deadAnswerUserRefs++;
                         $message .= "Removed dead user-answer ref {$ref} from question {$questionId}, answer {$answerId}\n";
                     }
                 }
             }
         }
     }
     if ($deadAnswerUserRefs > 0) {
         $message .= "\n\nRemoved dead user references from {$deadAnswerUserRefs} answers\n\n";
     } else {
         $message .= "\n\nNo dead user references were found in answers\n\n";
     }
     if ($deadCommentUserRefs > 0) {
         $message .= "\n\nRemoved dead user references from {$deadCommentUserRefs} comments\n\n";
     } else {
         $message .= "\n\nNo dead user references were found in comments\n\n";
     }
     return $message;
 }
 public function testEncode_QuestionWithAnswers_DtoReturnsExpectedData()
 {
     $project = $this->environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $text = new TextModel($project);
     $text->title = "Chapter 3";
     $text->content = '<usx version="2.0"> <chapter number="1" style="c" /> <verse number="1" style="v" /> <para style="q1">Blessed is the man</para> <para style="q2">who does not walk in the counsel of the wicked</para> <para style="q1">or stand in the way of sinners</para> <usx>';
     $textId = $text->write();
     // Answers are tied to specific users, so let's create some sample users
     $user1Id = $this->environ->createUser("jcarter", "John Carter", "*****@*****.**");
     $user2Id = $this->environ->createUser("dthoris", "Dejah Thoris", "*****@*****.**");
     // Two questions, with different numbers of answers and different create dates
     $question1 = new QuestionModel($project);
     $question1->title = "Who is speaking?";
     $question1->description = "Who is telling the story in this text?";
     $question1->textRef->id = $textId;
     $question1->write();
     $question1->dateCreated->sub(date_interval_create_from_date_string('1 day'));
     $question1Id = $question1->write();
     $question2 = new QuestionModel($project);
     $question2->title = "Where is the storyteller?";
     $question2->description = "The person telling this story has just arrived somewhere. Where is he?";
     $question2->textRef->id = $textId;
     $question2Id = $question2->write();
     // One answer for question 1...
     $answer1 = new AnswerModel();
     $answer1->content = "Me, John Carter.";
     $answer1->score = 10;
     $answer1->userRef->id = $user1Id;
     $answer1->textHightlight = "I knew that I was on Mars";
     $answer1Id = $question1->writeAnswer($answer1);
     // ... and two answers for question 2
     $answer2 = new AnswerModel();
     $answer2->content = "On Mars.";
     $answer2->score = 1;
     $answer2->userRef->id = $user1Id;
     $answer2->textHightlight = "I knew that I was on Mars";
     $answer2Id = $question2->writeAnswer($answer2);
     $answer3 = new AnswerModel();
     $answer3->content = "On the planet we call Barsoom, which you inhabitants of Earth normally call Mars.";
     $answer3->score = 7;
     $answer3->userRef->id = $user2Id;
     $answer3->textHightlight = "I knew that I was on Mars";
     $answer3Id = $question2->writeAnswer($answer3);
     // Comments should NOT show up in the answer count; let's test this.
     $comment1 = new CommentModel();
     $comment1->content = "By the way, our name for Earth is Jasoom.";
     $comment1->userRef->id = $user2Id;
     $comment1Id = QuestionModel::writeComment($project->databaseName(), $question2Id, $answer3Id, $comment1);
     $dto = QuestionListDto::encode($projectId, $textId, $user1Id);
     // Now check that it all looks right, 1 Text & 2 Questions
     $this->assertEqual($dto['count'], 2);
     $this->assertIsa($dto['entries'], 'array');
     $this->assertEqual($dto['entries'][0]['id'], $question2Id);
     $this->assertEqual($dto['entries'][1]['id'], $question1Id);
     $this->assertEqual($dto['entries'][0]['title'], "Where is the storyteller?");
     $this->assertEqual($dto['entries'][1]['title'], "Who is speaking?");
     $this->assertEqual($dto['entries'][0]['answerCount'], 2);
     $this->assertEqual($dto['entries'][1]['answerCount'], 1);
     // Specifically check if comments got included in answer count
     $this->assertNotEqual($dto['entries'][1]['answerCount'], 3, "Comments should not be included in answer count.");
     $this->assertEqual($dto['entries'][0]['responseCount'], 3);
     $this->assertEqual($dto['entries'][1]['responseCount'], 1);
     // make sure our text content is coming down into the dto
     $this->assertTrue(strlen($dto['text']['content']) > 0);
     // archive 1 Question
     $question2->isArchived = true;
     $question2->write();
     $dto = QuestionListDto::encode($projectId, $textId, $user1Id);
     // Now check that it all still looks right, now only 1 Question
     $this->assertEqual($dto['count'], 1);
     $this->assertEqual($dto['entries'][0]['id'], $question1Id);
     $this->assertEqual($dto['entries'][0]['title'], "Who is speaking?");
 }
 /**
  *
  * @param ProjectModel $projectModel
  * @param string $questionId
  * @param string $answerId
  * @param string $userId
  * @param string $mode
  * @return string activity id
  */
 public static function updateScore($projectModel, $questionId, $answerId, $userId, $mode = 'increase')
 {
     $activity = new ActivityModel($projectModel);
     $question = new QuestionModel($projectModel, $questionId);
     $text = new TextModel($projectModel, $question->textRef->asString());
     $answer = $question->answers[$answerId];
     $user = new UserModel($userId);
     $user2 = new UserModel($answer->userRef->asString());
     $activity = new ActivityModel($projectModel);
     $activity->action = $mode == 'increase' ? ActivityModel::INCREASE_SCORE : ActivityModel::DECREASE_SCORE;
     $activity->userRef->id = $userId;
     $activity->textRef->id = $text->id->asString();
     $activity->questionRef->id = $questionId;
     $activity->addContent(ActivityModel::TEXT, $text->title);
     $activity->addContent(ActivityModel::QUESTION, $question->getTitleForDisplay());
     $activity->addContent(ActivityModel::ANSWER, $answer->content);
     $activity->addContent(ActivityModel::USER, $user->username);
     $activity->addContent(ActivityModel::USER, $user2->username);
     $activityId = $activity->write();
     UnreadActivityModel::markUnreadForProjectMembers($activityId, $projectModel);
     return $activityId;
 }
 public static function voteDown($userId, $projectId, $questionId, $answerId)
 {
     $projectModel = new ProjectModel($projectId);
     $questionModel = new QuestionModel($projectModel, $questionId);
     // Check the vote lock.
     $vote = new UserVoteModel($userId, $projectId, $questionId);
     if (!$vote->hasVote($answerId)) {
         // Don't throw.  There's no harm in this, just don't decrement the vote.
         return self::encodeAnswer($questionModel->readAnswer($answerId));
     }
     // If ok down vote the question and remove the lock.
     $answerModel = $questionModel->readAnswer($answerId);
     $answerModel->score--;
     $questionModel->writeAnswer($answerModel);
     $vote->removeVote($answerId);
     $vote->write();
     // Return the answer dto.
     return self::encodeAnswer($answerModel);
 }
 public function testMultipleUnreadModels_multipleUsers_multipleUpdates_multipleVisitsToQuestionPage_usersHaveDifferentUnreadStates()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $project = $e->createProject("unread_test", "unreadCode");
     $projectId = $project->id->asString();
     $userId1 = $e->createUser('user1', 'user1', 'user1');
     $user1 = new UserModel($userId1);
     $user1->addProject($project->id->asString());
     $user1->write();
     $userId2 = $e->createUser('user2', 'user2', 'user2');
     $user2 = new UserModel($userId2);
     $user2->addProject($project->id->asString());
     $user2->write();
     $userId3 = $e->createUser('user3', 'user3', 'user3');
     $user3 = new UserModel($userId3);
     $user3->addProject($project->id->asString());
     $user3->write();
     $answer1 = array('content' => "test answer 1", 'id' => '');
     $answer2 = array('content' => "test answer 2", 'id' => '');
     $text = new TextModel($project);
     $text->title = "Text 1";
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $question = new QuestionModel($project);
     $question->title = "test question";
     $question->textRef->id = $textId;
     $questionId = $question->write();
     $answer1Dto = QuestionCommands::updateAnswer($projectId, $questionId, $answer1, $userId1);
     $answer2Dto = QuestionCommands::updateAnswer($projectId, $questionId, $answer2, $userId2);
     $answer1 = array_pop($answer1Dto);
     $answer1Id = $answer1['id'];
     $answer2 = array_pop($answer2Dto);
     $answer2Id = $answer2['id'];
     // the answer author does NOT get their answer marked as unread
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 1);
     // the answer author does NOT get their answer marked as unread
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 1);
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 2);
     // user1 visits question page
     $pageDto = QuestionCommentDto::encode($projectId, $questionId, $userId1);
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 0);
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 1);
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 2);
     // user2 visits question page
     $pageDto = QuestionCommentDto::encode($projectId, $questionId, $userId2);
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 0);
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 0);
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 2);
     // user2 visits question page
     $pageDto = QuestionCommentDto::encode($projectId, $questionId, $userId3);
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 0);
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 0);
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertEqual(count($unreadModel->unreadItems()), 0);
 }
 public function testExportCommentsForText_QuestionArchived_NoneExported()
 {
     $e = new MongoTestEnvironment();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text = new TextModel($project);
     $text->title = "Text 1";
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $user1Id = $e->createUser("user1", "user1", "*****@*****.**");
     $user2Id = $e->createUser("user2", "user2", "*****@*****.**");
     $user3Id = $e->createUser("user3", "user3", "*****@*****.**");
     // Workflow is first to create a question
     $question = new QuestionModel($project);
     $question->title = "the question";
     $question->description = "question description";
     $question->textRef->id = $textId;
     $question->isArchived = true;
     $questionId = $question->write();
     // Then to add an answer to a question
     $answer = new AnswerModel();
     $answer->content = "first answer";
     $answer->score = 10;
     $answer->userRef->id = $user1Id;
     $answer->tags->exchangeArray(array('export', 'to review'));
     $answer->isToBeExported = true;
     $answerId = $question->writeAnswer($answer);
     // Then to add an answer to a question
     $answer = new AnswerModel();
     $answer->content = "second answer - very long";
     $answer->score = 2;
     $answer->userRef->id = $user2Id;
     $answer->tags->exchangeArray(array('to review'));
     $answer->isToBeExported = false;
     $answerId = $question->writeAnswer($answer);
     // Then to add an answer to a question
     $answer = new AnswerModel();
     $answer->content = "third answer - very very very very long";
     $answer->userRef->id = $user3Id;
     $answer->tags->exchangeArray(array('export'));
     $answer->isToBeExported = true;
     $answerId = $question->writeAnswer($answer);
     $params = array('textId' => $textId, 'exportComments' => true, 'exportFlagged' => true, 'tags' => array());
     $download = ParatextExport::exportCommentsForText($project->id->asString(), $textId, $params);
     //echo "<pre>" . print_r($download) . "</pre>";
     $this->assertNoPattern('/<Contents>third answer - very very very very long \\(by user3/', $download['xml']);
     $this->assertNoPattern('/<Contents>second answer/', $download['xml']);
     $this->assertNoPattern('/<Contents>first answer/', $download['xml']);
 }
 public function testGetActivityForProject_ProjectWithTextQuestionAnswerAndComments_DtoAsExpected()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text = new TextModel($project);
     $text->title = "Text 1";
     $text->content = "text content";
     $textId = $text->write();
     $a1 = ActivityCommands::addText($project, $textId, $text);
     $user1Id = $e->createUser("user1", "user1", "*****@*****.**");
     $user2Id = $e->createUser("user2", "user2", "*****@*****.**");
     $user3Id = $e->createUser("user3", "user3", "*****@*****.**");
     $a2 = ActivityCommands::addUserToProject($project, $user1Id);
     $a3 = ActivityCommands::addUserToProject($project, $user2Id);
     $a4 = ActivityCommands::addUserToProject($project, $user3Id);
     // Workflow is first to create a question
     $question = new QuestionModel($project);
     $question->title = "the question";
     $question->description = "question description";
     $question->textRef->id = $textId;
     $questionId = $question->write();
     $a5 = ActivityCommands::addQuestion($project, $questionId, $question);
     // Then to add an answer to a question
     $answer = new AnswerModel();
     $answer->content = "first answer";
     $answer->score = 10;
     $answer->userRef->id = $user3Id;
     $answer->textHightlight = "text highlight";
     $answerId = $question->writeAnswer($answer);
     $a6 = ActivityCommands::addAnswer($project, $questionId, $answer);
     // Followed by comments
     $comment1 = new CommentModel();
     $comment1->content = "first comment";
     $comment1->userRef->id = $user1Id;
     $comment1Id = QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment1);
     $a7 = ActivityCommands::addComment($project, $questionId, $answerId, $comment1);
     $comment2 = new CommentModel();
     $comment2->content = "second comment";
     $comment2->userRef->id = $user2Id;
     $comment2Id = QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment2);
     $a8 = ActivityCommands::addComment($project, $questionId, $answerId, $comment2);
     // updated answer
     $question->read($questionId);
     $answer_updated = $question->readAnswer($answerId);
     $answer_updated->content = "first answer revised";
     $question->writeAnswer($answer_updated);
     $a9 = ActivityCommands::updateAnswer($project, $questionId, $answer_updated);
     // updated comment1
     $question->read($questionId);
     $comment1_updated = $question->readComment($answerId, $comment1Id);
     $comment1_updated->content = "first comment revised";
     QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment1_updated);
     $a10 = ActivityCommands::updateComment($project, $questionId, $answerId, $comment1_updated);
     $dto = ActivityListDto::getActivityForProject($project);
     $this->assertEqual($dto[$a1]['action'], 'add_text');
     $this->assertEqual($dto[$a1]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a1]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a1]['textRef'], $textId);
     $this->assertEqual($dto[$a1]['content']['text'], $text->title);
     $this->assertEqual($dto[$a2]['action'], 'add_user_to_project');
     $this->assertEqual($dto[$a2]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a2]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a2]['userRef']['id'], $user1Id);
     $this->assertEqual($dto[$a2]['userRef']['username'], 'user1');
     $this->assertEqual($dto[$a2]['userRef']['avatar_ref'], 'user1.png');
     $this->assertEqual($dto[$a2]['content']['user'], 'user1');
     $this->assertEqual($dto[$a3]['action'], 'add_user_to_project');
     $this->assertEqual($dto[$a3]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a3]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a3]['userRef']['id'], $user2Id);
     $this->assertEqual($dto[$a3]['userRef']['username'], 'user2');
     $this->assertEqual($dto[$a3]['userRef']['avatar_ref'], 'user2.png');
     $this->assertEqual($dto[$a3]['content']['user'], 'user2');
     $this->assertEqual($dto[$a4]['action'], 'add_user_to_project');
     $this->assertEqual($dto[$a4]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a4]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a4]['userRef']['id'], $user3Id);
     $this->assertEqual($dto[$a4]['userRef']['username'], 'user3');
     $this->assertEqual($dto[$a4]['userRef']['avatar_ref'], 'user3.png');
     $this->assertEqual($dto[$a4]['content']['user'], 'user3');
     $this->assertEqual($dto[$a5]['action'], 'add_question');
     $this->assertEqual($dto[$a5]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a5]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a5]['textRef'], $textId);
     $this->assertEqual($dto[$a5]['content']['text'], $text->title);
     $this->assertEqual($dto[$a5]['questionRef'], $questionId);
     $this->assertEqual($dto[$a5]['content']['question'], $question->title);
     $this->assertEqual($dto[$a6]['action'], 'add_answer');
     $this->assertEqual($dto[$a6]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a6]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a6]['textRef'], $textId);
     $this->assertEqual($dto[$a6]['content']['text'], $text->title);
     $this->assertEqual($dto[$a6]['questionRef'], $questionId);
     $this->assertEqual($dto[$a6]['content']['question'], $question->title);
     $this->assertEqual($dto[$a6]['userRef']['id'], $user3Id);
     $this->assertEqual($dto[$a6]['userRef']['username'], 'user3');
     $this->assertEqual($dto[$a6]['userRef']['avatar_ref'], 'user3.png');
     $this->assertEqual($dto[$a6]['content']['answer'], $answer->content);
     $this->assertEqual($dto[$a6]['content']['user'], 'user3');
     $this->assertEqual($dto[$a7]['action'], 'add_comment');
     $this->assertEqual($dto[$a7]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a7]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a7]['textRef'], $textId);
     $this->assertEqual($dto[$a7]['content']['text'], $text->title);
     $this->assertEqual($dto[$a7]['questionRef'], $questionId);
     $this->assertEqual($dto[$a7]['content']['question'], $question->title);
     $this->assertEqual($dto[$a7]['userRef']['id'], $user1Id);
     $this->assertEqual($dto[$a7]['userRef']['username'], 'user1');
     $this->assertEqual($dto[$a7]['userRef']['avatar_ref'], 'user1.png');
     $this->assertEqual($dto[$a7]['content']['user'], 'user1');
     $this->assertEqual($dto[$a7]['userRef2']['id'], $user3Id);
     $this->assertEqual($dto[$a7]['userRef2']['username'], 'user3');
     $this->assertEqual($dto[$a7]['userRef2']['avatar_ref'], 'user3.png');
     $this->assertEqual($dto[$a7]['content']['user2'], 'user3');
     $this->assertEqual($dto[$a7]['content']['answer'], $answer->content);
     $this->assertEqual($dto[$a7]['content']['comment'], $comment1->content);
     $this->assertEqual($dto[$a8]['action'], 'add_comment');
     $this->assertEqual($dto[$a8]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a8]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a8]['textRef'], $textId);
     $this->assertEqual($dto[$a8]['content']['text'], $text->title);
     $this->assertEqual($dto[$a8]['questionRef'], $questionId);
     $this->assertEqual($dto[$a8]['content']['question'], $question->title);
     $this->assertEqual($dto[$a8]['userRef']['id'], $user2Id);
     $this->assertEqual($dto[$a8]['userRef']['username'], 'user2');
     $this->assertEqual($dto[$a8]['userRef']['avatar_ref'], 'user2.png');
     $this->assertEqual($dto[$a8]['content']['user'], 'user2');
     $this->assertEqual($dto[$a8]['userRef2']['id'], $user3Id);
     $this->assertEqual($dto[$a8]['userRef2']['username'], 'user3');
     $this->assertEqual($dto[$a8]['userRef2']['avatar_ref'], 'user3.png');
     $this->assertEqual($dto[$a8]['content']['user2'], 'user3');
     $this->assertEqual($dto[$a8]['content']['answer'], $answer->content);
     $this->assertEqual($dto[$a8]['content']['comment'], $comment2->content);
     $this->assertEqual($dto[$a9]['action'], 'update_answer');
     $this->assertEqual($dto[$a9]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a9]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a9]['textRef'], $textId);
     $this->assertEqual($dto[$a9]['content']['text'], $text->title);
     $this->assertEqual($dto[$a9]['questionRef'], $questionId);
     $this->assertEqual($dto[$a9]['content']['question'], $question->title);
     $this->assertEqual($dto[$a9]['userRef']['id'], $user3Id);
     $this->assertEqual($dto[$a9]['userRef']['username'], 'user3');
     $this->assertEqual($dto[$a9]['userRef']['avatar_ref'], 'user3.png');
     $this->assertEqual($dto[$a9]['content']['user'], 'user3');
     $this->assertEqual($dto[$a9]['content']['answer'], $answer_updated->content);
     $this->assertEqual($dto[$a10]['action'], 'update_comment');
     $this->assertEqual($dto[$a10]['projectRef'], array('id' => $project->id->asString(), 'type' => 'sfchecks'));
     $this->assertEqual($dto[$a10]['content']['project'], $project->projectName);
     $this->assertEqual($dto[$a10]['textRef'], $textId);
     $this->assertEqual($dto[$a10]['content']['text'], $text->title);
     $this->assertEqual($dto[$a10]['questionRef'], $questionId);
     $this->assertEqual($dto[$a10]['content']['question'], $question->title);
     $this->assertEqual($dto[$a10]['userRef']['id'], $user1Id);
     $this->assertEqual($dto[$a10]['userRef']['username'], 'user1');
     $this->assertEqual($dto[$a10]['userRef']['avatar_ref'], 'user1.png');
     $this->assertEqual($dto[$a10]['content']['user'], 'user1');
     $this->assertEqual($dto[$a10]['userRef2']['id'], $user3Id);
     $this->assertEqual($dto[$a10]['userRef2']['username'], 'user3');
     $this->assertEqual($dto[$a10]['userRef2']['avatar_ref'], 'user3.png');
     $this->assertEqual($dto[$a10]['content']['user2'], 'user3');
     $this->assertEqual($dto[$a10]['content']['answer'], $answer_updated->content);
     $this->assertEqual($dto[$a10]['content']['comment'], $comment1_updated->content);
 }
 public function testEncode_TextWithQuestions_DtoReturnsExpectedData()
 {
     $e = new MongoTestEnvironment();
     $e->clean();
     $project = $e->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     // Two texts, with different numbers of questions for each text and different create dates
     $text1 = new TextModel($project);
     $text1->title = "Chapter 3";
     $text1->content = "I opened my eyes upon a strange and weird landscape. I knew that I was on Mars; …";
     $text1->write();
     $text1->dateCreated->sub(date_interval_create_from_date_string('1 day'));
     $text1Id = $text1->write();
     $text2 = new TextModel($project);
     $text2->title = "Chapter 4";
     $text2->content = "We had gone perhaps ten miles when the ground began to rise very rapidly. …";
     $text2Id = $text2->write();
     // Answers are tied to specific users, so let's create some sample users
     $user1Id = $e->createUser("jcarter", "John Carter", "*****@*****.**");
     $user2Id = $e->createUser("dthoris", "Dejah Thoris", "*****@*****.**");
     // Two questions for text 1...
     $question1 = new QuestionModel($project);
     $question1->title = "Who is speaking?";
     $question1->description = "Who is telling the story in this text?";
     $question1->textRef->id = $text1Id;
     $question1Id = $question1->write();
     $question2 = new QuestionModel($project);
     $question2->title = "Where is the storyteller?";
     $question2->description = "The person telling this story has just arrived somewhere. Where is he?";
     $question2->textRef->id = $text1Id;
     $question2Id = $question2->write();
     // ... and one question for text 2.
     $question3 = new QuestionModel($project);
     $question3->title = "How far had they travelled?";
     $question3->description = "How far had the group just travelled when this text begins?";
     $question3->textRef->id = $text2Id;
     $question3Id = $question3->write();
     // One answer for question 1...
     $answer1 = new AnswerModel();
     $answer1->content = "Me, John Carter.";
     $answer1->score = 10;
     $answer1->userRef->id = $user1Id;
     $answer1->textHightlight = "I knew that I was on Mars";
     $answer1Id = $question1->writeAnswer($answer1);
     // ... and two answers for question 2...
     $answer2 = new AnswerModel();
     $answer2->content = "On Mars.";
     $answer2->score = 1;
     $answer2->userRef->id = $user1Id;
     $answer2->textHightlight = "I knew that I was on Mars";
     $answer2Id = $question2->writeAnswer($answer2);
     $answer3 = new AnswerModel();
     $answer3->content = "On the planet we call Barsoom, which you inhabitants of Earth normally call Mars.";
     $answer3->score = 7;
     $answer3->userRef->id = $user2Id;
     $answer3->textHightlight = "I knew that I was on Mars";
     $answer3Id = $question2->writeAnswer($answer3);
     // ... and 1 comment.
     $comment1 = new CommentModel();
     $comment1->content = "By the way, our name for Earth is Jasoom.";
     $comment1->userRef->id = $user2Id;
     $comment1Id = QuestionModel::writeComment($project->databaseName(), $question2Id, $answer3Id, $comment1);
     $dto = ProjectPageDto::encode($projectId, $user1Id);
     // Now check that it all looks right
     $this->assertIsa($dto['texts'], 'array');
     $this->assertEqual($dto['texts'][0]['id'], $text2Id);
     $this->assertEqual($dto['texts'][1]['id'], $text1Id);
     $this->assertEqual($dto['texts'][0]['title'], "Chapter 4");
     $this->assertEqual($dto['texts'][1]['title'], "Chapter 3");
     $this->assertEqual($dto['texts'][0]['questionCount'], 1);
     $this->assertEqual($dto['texts'][1]['questionCount'], 2);
     $this->assertEqual($dto['texts'][0]['responseCount'], 0);
     $this->assertEqual($dto['texts'][1]['responseCount'], 4);
     // archive 1 Question
     $question2->isArchived = true;
     $question2->write();
     $dto = ProjectPageDto::encode($projectId, $user1Id);
     $this->assertEqual($dto['texts'][0]['questionCount'], 1);
     $this->assertEqual($dto['texts'][1]['questionCount'], 1);
     $this->assertEqual($dto['texts'][0]['responseCount'], 0);
     $this->assertEqual($dto['texts'][1]['responseCount'], 1);
 }