function testCleanupFiles_4Files2Allowed_2Removed()
 {
     $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $project->write();
     $text = new TextModel($project);
     $textId = $text->write();
     $fakeId = new Id();
     $fakeTextId = $fakeId->asString();
     $folderPath = $project->getAssetsFolderPath();
     FileUtilities::createAllFolders($folderPath);
     $allowedExtensions = array(".mp2", ".mp3");
     // put a copy of the test files in the folderPath
     $fileName1 = 'TestAudio1.mp1';
     $filePath1 = SfchecksUploadCommands::mediaFilePath($folderPath, $textId, $fileName1);
     copy(TestPhpPath . 'common/TestAudio.mp3', $filePath1);
     $fileName2 = 'TestAudio2.mp2';
     $filePath2 = SfchecksUploadCommands::mediaFilePath($folderPath, $textId, $fileName2);
     copy(TestPhpPath . 'common/TestAudio.mp3', $filePath2);
     $fileName3 = 'TestAudio3.mp3';
     $filePath3 = SfchecksUploadCommands::mediaFilePath($folderPath, $textId, $fileName3);
     copy(TestPhpPath . 'common/TestAudio.mp3', $filePath3);
     $fileName4 = 'TestAudio4.mp3';
     $filePath4 = SfchecksUploadCommands::mediaFilePath($folderPath, $fakeTextId, $fileName4);
     copy(TestPhpPath . 'common/TestAudio.mp3', $filePath4);
     $this->assertTrue(file_exists($filePath1), 'File should exist before cleanup');
     $this->assertTrue(file_exists($filePath2), 'File should exist before cleanup');
     $this->assertTrue(file_exists($filePath3), 'File should exist before cleanup');
     $this->assertTrue(file_exists($filePath4), 'File should exist before cleanup');
     SfchecksUploadCommands::cleanupFiles($folderPath, $textId, $allowedExtensions);
     $this->assertTrue(file_exists($filePath1), 'File should exist after cleanup');
     $this->assertFalse(file_exists($filePath2), 'File should not exist after cleanup');
     $this->assertFalse(file_exists($filePath3), 'File should not exist after cleanup');
     $this->assertTrue(file_exists($filePath4), 'File should exist after cleanup');
     self::$environ->cleanupTestFiles($folderPath);
 }
 public function testEncode_ProjectWithTexts_DtoReturnsTextCount2()
 {
     $userId = self::$environ->createUser("User", "Name", "*****@*****.**");
     $user = new UserModel($userId);
     $user->role = SystemRoles::SYSTEM_ADMIN;
     $user->write();
     $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $project->ownerRef->id = $userId;
     $project->write();
     $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();
     $text2 = new TextModel($project);
     $text2->title = "Chapter 4";
     $text2->content = "We had gone perhaps ten miles when the ground began to rise very rapidly. …";
     $text2->write();
     $dto = ProjectListDto::encode($userId, self::$environ->website);
     $this->assertEquals(1, $dto['count']);
     $this->assertInternalType('array', $dto['entries']);
     $this->assertEquals($projectId, $dto['entries'][0]['id']);
     $this->assertEquals(SF_TESTPROJECT, $dto['entries'][0]['projectName']);
     $this->assertEquals(ProjectRoles::NONE, $dto['entries'][0]['role']);
 }
 public function testUpdateThenRemove_NewProject_CreatesThenRemovesProjectDatabase()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $databaseName = $project->databaseName();
     $project->remove();
     $this->assertEquals(0, MongoStore::countCollections($databaseName));
     $text = new TextModel($project);
     $text->title = 'Some Title';
     $text->write();
     $this->assertTrue(MongoStore::hasDB($databaseName));
     $this->assertEquals(1, MongoStore::countCollections($databaseName));
     $project->remove();
     $this->assertEquals(0, MongoStore::countCollections($databaseName));
 }
 public function testPublishTexts_2ArchivedTexts_1Published()
 {
     $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text1 = new TextModel($project);
     $text1->title = 'Some Title';
     $text1->isArchived = true;
     $text1->write();
     $text2 = new TextModel($project);
     $text2->title = 'Another Title';
     $text2->isArchived = true;
     $text2->write();
     $this->assertTrue($text1->isArchived);
     $this->assertTrue($text2->isArchived);
     $count = TextCommands::publishTexts($project->id->asString(), array($text1->id->asString()));
     $text1->read($text1->id->asString());
     $text2->read($text2->id->asString());
     $this->assertEquals(1, $count);
     $this->assertNotTrue($text1->isArchived);
     $this->assertTrue($text2->isArchived);
 }
 public function testUserEngagementReport_simpleProjectWithQuestionsAndAnswers_AsExpected()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text = new TextModel($project);
     $text->title = "Text 1";
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $user1Id = $environ->createUser("user1", "user1", "*****@*****.**");
     $user2Id = $environ->createUser("user2", "user2", "*****@*****.**");
     $user3Id = $environ->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;
     QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment1);
     $comment2 = new CommentModel();
     $comment2->content = "second comment";
     $comment2->userRef->id = $user2Id;
     QuestionModel::writeComment($project->databaseName(), $questionId, $answerId, $comment2);
     $data = SfchecksReports::UserEngagementReport($project->id->asString());
     $this->assertNotEmpty($data['output']);
 }
 public function testEncode_ProjectWith2Users1Unvalidated_DtoCorrect1User()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $user1Id = $environ->createUser('', '', '');
     $user1 = new UserModel($user1Id);
     $user1->role = SystemRoles::USER;
     $user2Id = $environ->createUser('User', 'Name', '*****@*****.**');
     $user2 = new UserModel($user2Id);
     $user2->role = SystemRoles::USER;
     $project = $environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     $project->addUser($user1Id, ProjectRoles::CONTRIBUTOR);
     $user1->addProject($projectId);
     $user1->write();
     $project->addUser($user2Id, ProjectRoles::CONTRIBUTOR);
     $user2->addProject($projectId);
     $user2->write();
     $project->write();
     $text1 = new TextModel($project);
     $text1->title = 'Some Title';
     $text1->write();
     $text2 = new TextModel($project);
     $text2->title = 'Archived Title';
     $text2->isArchived = true;
     $text2->write();
     $dto = ProjectSettingsDto::encode($projectId, $user2Id);
     $this->assertEquals(1, $dto['count']);
     $this->assertInternalType('array', $dto['entries']);
     $this->assertEquals($user2Id, $dto['entries'][0]['id']);
     $this->assertEquals('Name', $dto['entries'][0]['name']);
     $this->assertEquals(ProjectRoles::CONTRIBUTOR, $dto['entries'][0]['role']);
     $this->assertCount(1, $dto['archivedTexts']);
     $this->assertEquals('Archived Title', $dto['archivedTexts'][0]['title']);
     $this->assertTrue(count($dto['rights']) > 0, 'No rights in dto');
     $this->assertEquals('settings', $dto['bcs']['op']);
     $this->assertEquals(array('id' => $projectId, 'crumb' => SF_TESTPROJECT), $dto['bcs']['project']);
     $this->assertFalse(isset($dto['project']['users']));
     $this->assertEquals($projectId, $dto['project']['id']);
 }
 /**
  * @param string $projectId
  * @param string $userId
  * @returns array - the DTO array
  */
 public static function encode($projectId, $userId)
 {
     $userModel = new UserModel($userId);
     $projectModel = new SfchecksProjectModel($projectId);
     $textList = new TextListModel($projectModel);
     $textList->read();
     $list = $projectModel->listUsers();
     $data = array();
     $data['count'] = count($list->entries);
     $data['entries'] = array_values($list->entries);
     // re-index array
     $data['project'] = ProjectSettingsDtoEncoder::encode($projectModel);
     unset($data['project']['users']);
     $data['archivedTexts'] = array();
     foreach ($textList->entries as $entry) {
         $textModel = new TextModel($projectModel, $entry['id']);
         if ($textModel->isArchived) {
             $questionList = $textModel->listQuestionsWithAnswers();
             // Just want count of questions and responses, not whole list
             $entry['questionCount'] = $questionList->count;
             $responseCount = 0;
             // "Responses" = answers + comments
             foreach ($questionList->entries as $q) {
                 foreach ($q['answers'] as $a) {
                     $commentCount = count($a['comments']);
                     $responseCount += $commentCount + 1;
                     // +1 for this answer
                 }
             }
             $entry['responseCount'] = $responseCount;
             $entry['dateModified'] = $textModel->dateModified->asDateTimeInterface()->format(\DateTime::RFC2822);
             $data['archivedTexts'][] = $entry;
         }
     }
     $data['rights'] = RightsHelper::encode($userModel, $projectModel);
     $data['bcs'] = BreadCrumbHelper::encode('settings', $projectModel, null, null);
     return $data;
 }
 public function testEncode_2Questions1Archived_DtoCorrect1ArchivedQuestion()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $userId = $environ->createUser("User", "Name", "*****@*****.**");
     $user = new UserModel($userId);
     $user->role = SystemRoles::USER;
     $project = $environ->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->assertInternalType('array', $dto['text']);
     $this->assertEquals($textId, $dto['text']['id']);
     $this->assertEquals('Text Title', $dto['text']['title']);
     $this->assertInternalType('array', $dto['archivedQuestions']);
     $this->assertCount(1, $dto['archivedQuestions']);
     $this->assertEquals('Archived Title', $dto['archivedQuestions'][0]['title']);
     $this->assertTrue(count($dto['rights']) > 0, "No rights in dto");
     $this->assertEquals('settings', $dto['bcs']['op']);
     $this->assertEquals(array('id' => $projectId, 'crumb' => SF_TESTPROJECT), $dto['bcs']['project']);
 }
 public function testExportCommentsForText_QuestionArchived_NoneExported()
 {
     $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $text = new TextModel($project);
     $text->title = 'Text 1';
     $usx = MongoTestEnvironment::usxSample();
     $text->content = $usx;
     $textId = $text->write();
     $user1Id = self::$environ->createUser('user1', 'user1', '*****@*****.**');
     $user2Id = self::$environ->createUser('user2', 'user2', '*****@*****.**');
     $user3Id = self::$environ->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;
     $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;
     $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;
     $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;
     $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->assertNotRegExp('/<Contents>third answer - very very very very long \\(by user3/', $download['xml']);
     $this->assertNotRegExp('/<Contents>second answer/', $download['xml']);
     $this->assertNotRegExp('/<Contents>first answer/', $download['xml']);
 }
 /**
  * @param string $projectId
  * @param string $userId
  * @returns array - the DTO array
  * @throws ResourceNotAvailableException
  */
 public static function encode($projectId, $userId)
 {
     $user = new UserModel($userId);
     $project = new SfchecksProjectModel($projectId);
     if ($project->isArchived && $project->users[$userId]->role != ProjectRoles::MANAGER) {
         throw new ResourceNotAvailableException("This Project is no longer available. If this is incorrect contact your project manager.");
     }
     $textList = new TextListModel($project);
     $textList->read();
     $data = array();
     $data['rights'] = RightsHelper::encode($user, $project);
     $data['project'] = array('name' => $project->projectName, 'id' => $projectId);
     if ($project->isArchived) {
         $data['project']['name'] .= " [ARCHIVED]";
     }
     $data['texts'] = array();
     foreach ($textList->entries as $entry) {
         $text = new TextModel($project, $entry['id']);
         if (!$text->isArchived) {
             $questionList = $text->listQuestionsWithAnswers();
             // Just want count of questions and responses, not whole list
             $entry['questionCount'] = 0;
             $responseCount = 0;
             // "Responses" = answers + comments
             foreach ($questionList->entries as $q) {
                 $question = new QuestionModel($project, $q['id']);
                 if (!$question->isArchived) {
                     $entry['questionCount']++;
                     foreach ($q['answers'] as $a) {
                         $commentCount = count($a['comments']);
                         $responseCount += $commentCount + 1;
                         // +1 for this answer
                     }
                 }
             }
             $entry['responseCount'] = $responseCount;
             $entry['dateCreated'] = $text->dateCreated->asDateTimeInterface()->format(\DateTime::RFC2822);
             $data['texts'][] = $entry;
         }
     }
     // sort Texts with newest at the top
     usort($data['texts'], function ($a, $b) {
         $sortOn = 'dateCreated';
         if (array_key_exists($sortOn, $a) && array_key_exists($sortOn, $b)) {
             return strtotime($a[$sortOn]) < strtotime($b[$sortOn]) ? 1 : -1;
         } else {
             return 0;
         }
     });
     // future support for members
     $data['members'] = array();
     // unread activity count
     $unreadActivity = new UnreadActivityModel($userId, $projectId);
     $unreadItems = $unreadActivity->unreadItems();
     $data['activityUnreadCount'] = count($unreadItems);
     // unread broadcast messages
     $unreadMessages = new UnreadMessageModel($userId, $projectId);
     $messageIds = $unreadMessages->unreadItems();
     $messages = array();
     foreach ($messageIds as $messageId) {
         $message = new MessageModel($project, $messageId);
         $messages[] = array('id' => $message->id->asString(), 'subject' => $message->subject, 'content' => $message->content);
     }
     $data['broadcastMessages'] = $messages;
     return $data;
 }
 public function testMultipleUnreadModels_multipleUsers_multipleUpdates_multipleVisitsToQuestionPage_usersHaveDifferentUnreadStates()
 {
     $project = self::$environ->createProject("unread_test", "unreadCode");
     $projectId = $project->id->asString();
     $userId1 = self::$environ->createUser('user1', 'user1', 'user1');
     $user1 = new UserModel($userId1);
     $user1->addProject($project->id->asString());
     $user1->write();
     $userId2 = self::$environ->createUser('user2', 'user2', 'user2');
     $user2 = new UserModel($userId2);
     $user2->addProject($project->id->asString());
     $user2->write();
     $userId3 = self::$environ->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();
     QuestionCommands::updateAnswer($projectId, $questionId, $answer1, $userId1);
     QuestionCommands::updateAnswer($projectId, $questionId, $answer2, $userId2);
     // the answer author does NOT get their answer marked as unread
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertCount(1, $unreadModel->unreadItems());
     // the answer author does NOT get their answer marked as unread
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertCount(1, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertCount(2, $unreadModel->unreadItems());
     // user1 visits question page
     QuestionCommentDto::encode($projectId, $questionId, $userId1);
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertCount(1, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertCount(2, $unreadModel->unreadItems());
     // user2 visits question page
     QuestionCommentDto::encode($projectId, $questionId, $userId2);
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertCount(2, $unreadModel->unreadItems());
     // user2 visits question page
     QuestionCommentDto::encode($projectId, $questionId, $userId3);
     $unreadModel = new UnreadAnswerModel($userId1, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId2, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
     $unreadModel = new UnreadAnswerModel($userId3, $projectId, $questionId);
     $this->assertCount(0, $unreadModel->unreadItems());
 }
 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();
     }
 }
 /**
  * @expectedException Api\Library\Shared\Palaso\Exception\ResourceNotAvailableException
  */
 public function testEncode_ArchivedText_ManagerCanViewContributorCannot()
 {
     $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $projectId = $project->id->asString();
     // archived Text
     $text = new TextModel($project);
     $text->title = 'Chapter 3';
     $text->isArchived = true;
     $textId = $text->write();
     // Answers are tied to specific users, so let's create some sample users
     $managerId = self::$environ->createUser('jcarter', 'John Carter', '*****@*****.**');
     $contributorId = self::$environ->createUser('dthoris', 'Dejah Thoris', '*****@*****.**');
     $project->addUser($managerId, ProjectRoles::MANAGER);
     $project->addUser($contributorId, ProjectRoles::CONTRIBUTOR);
     $project->write();
     $dto = QuestionListDto::encode($projectId, $textId, $managerId);
     // Manager can view archived Text
     $this->assertEquals('Chapter 3', $dto['text']['title']);
     // Contributor cannot view archived Text, throw Exception
     self::$environ->inhibitErrorDisplay();
     QuestionListDto::encode($projectId, $textId, $contributorId);
     // nothing runs in the current test function after an exception. IJH 2014-11
 }
 /**
  * Upload a file
  *
  * @param string $projectId
  * @param string $mediaType
  * @param string $tmpFilePath
  * @throws \Exception
  * @return UploadResponse
  */
 public static function uploadFile($projectId, $mediaType, $tmpFilePath)
 {
     if ($mediaType != 'audio') {
         throw new \Exception("Unsupported upload type: {$mediaType}");
     }
     if (!$tmpFilePath) {
         throw new \Exception("Upload controller did not move the uploaded file.");
     }
     $textId = $_POST['textId'];
     $file = $_FILES['file'];
     $fileName = $file['name'];
     $finfo = finfo_open(FILEINFO_MIME_TYPE);
     $fileType = finfo_file($finfo, $tmpFilePath);
     finfo_close($finfo);
     $fileName = FileUtilities::replaceSpecialCharacters($fileName);
     $fileExt = false === ($pos = strrpos($fileName, '.')) ? '' : substr($fileName, $pos);
     // allowed types: documented, observed
     $allowedTypes = array("audio/mpeg", "audio/mp3");
     $allowedExtensions = array(".mp3");
     $response = new UploadResponse();
     if (in_array(strtolower($fileType), $allowedTypes) && in_array(strtolower($fileExt), $allowedExtensions)) {
         // make the folders if they don't exist
         $project = new SfchecksProjectModel($projectId);
         ProjectCommands::checkIfArchivedAndThrow($project);
         $folderPath = $project->getAssetsFolderPath();
         FileUtilities::createAllFolders($folderPath);
         // cleanup previous files of any allowed extension
         self::cleanupFiles($folderPath, $textId, $allowedExtensions);
         // move uploaded file from tmp location to assets
         $filePath = self::mediaFilePath($folderPath, $textId, $fileName);
         $moveOk = copy($tmpFilePath, $filePath);
         @unlink($tmpFilePath);
         // update database with file location
         $text = new TextModel($project, $textId);
         $text->audioFileName = '';
         if ($moveOk) {
             $text->audioFileName = $fileName;
         }
         $text->write();
         // construct server response
         if ($moveOk && $tmpFilePath) {
             $data = new MediaResult();
             $data->path = $project->getAssetsRelativePath();
             $data->fileName = $fileName;
             $response->result = true;
         } else {
             $data = new ErrorResult();
             $data->errorType = 'UserMessage';
             $data->errorMessage = "{$fileName} could not be saved to the right location. Contact your Site Administrator.";
             $response->result = false;
         }
     } else {
         $allowedExtensionsStr = implode(", ", $allowedExtensions);
         $data = new ErrorResult();
         $data->errorType = 'UserMessage';
         if (count($allowedExtensions) < 1) {
             $data->errorMessage = "{$fileName} is not an allowed audio file. No audio file formats are currently enabled, contact your Site Administrator.";
         } elseif (count($allowedExtensions) == 1) {
             $data->errorMessage = "{$fileName} is not an allowed audio file. Ensure the file is a {$allowedExtensionsStr}.";
         } else {
             $data->errorMessage = "{$fileName} is not an allowed audio file. Ensure the file is one of the following types: {$allowedExtensionsStr}.";
         }
         $response->result = false;
     }
     $response->data = $data;
     return $response;
 }
 public function testEncode_TextWithQuestions_DtoReturnsExpectedData()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $project = $environ->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->addSeconds(-date_interval_create_from_date_string('1 day')->s);
     $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 = $environ->createUser('jcarter', 'John Carter', '*****@*****.**');
     $user2Id = $environ->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;
     $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;
     $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';
     $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';
     $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;
     QuestionModel::writeComment($project->databaseName(), $question2Id, $answer3Id, $comment1);
     $dto = ProjectPageDto::encode($projectId, $user1Id);
     $encodedTexts = MongoTestEnvironment::indexItemsBy($dto['texts'], 'id');
     $encodedText1 = $encodedTexts[$text1Id];
     $encodedText2 = $encodedTexts[$text2Id];
     // Now check that it all looks right
     $this->assertInternalType('array', $dto['texts']);
     $this->assertEquals($text2Id, $encodedText2['id']);
     $this->assertEquals($text1Id, $encodedText1['id']);
     $this->assertEquals('Chapter 4', $encodedText2['title']);
     $this->assertEquals('Chapter 3', $encodedText1['title']);
     $this->assertEquals(1, $encodedText2['questionCount']);
     $this->assertEquals(2, $encodedText1['questionCount']);
     $this->assertEquals(0, $encodedText2['responseCount']);
     $this->assertEquals(4, $encodedText1['responseCount']);
     // archive 1 Question
     $question2->isArchived = true;
     $question2->write();
     $dto = ProjectPageDto::encode($projectId, $user1Id);
     $encodedTexts = MongoTestEnvironment::indexItemsBy($dto['texts'], 'id');
     $encodedText1 = $encodedTexts[$text1Id];
     $encodedText2 = $encodedTexts[$text2Id];
     $this->assertEquals(1, $encodedText2['questionCount']);
     $this->assertEquals(1, $encodedText1['questionCount']);
     $this->assertEquals(0, $encodedText2['responseCount']);
     $this->assertEquals(1, $encodedText1['responseCount']);
 }
 /**
  * @expectedException Api\Library\Shared\Palaso\Exception\ResourceNotAvailableException
  */
 public function testEncode_ArchivedText_ManagerCanViewContributorCannot()
 {
     $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $managerId = self::$environ->createUser("manager", "manager", "*****@*****.**");
     $contributorId = self::$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->assertEquals('the question', $dto['question']['title']);
     // Contributor cannot view Question of archived Text, throw Exception
     self::$environ->inhibitErrorDisplay();
     QuestionCommentDto::encode($project->id->asString(), $questionId, $contributorId);
     // nothing runs in the current test function after an exception. IJH 2014-11
 }
 public function testGetActivityForProject_ProjectWithTextQuestionAnswerAndComments_DtoAsExpected()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $project = $environ->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 = $environ->createUser("user1", "user1", "*****@*****.**");
     $user2Id = $environ->createUser("user2", "user2", "*****@*****.**");
     $user3Id = $environ->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;
     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);
     $expectedProjectRef = ['id' => $project->id->asString(), 'type' => 'sfchecks'];
     $this->assertEquals('add_text', $dto[$a1]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a1]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a1]['content']['project']);
     $this->assertEquals($textId, $dto[$a1]['textRef']);
     $this->assertEquals($text->title, $dto[$a1]['content']['text']);
     $this->assertEquals('add_user_to_project', $dto[$a2]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a2]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a2]['content']['project']);
     $this->assertEquals($user1Id, $dto[$a2]['userRef']['id']);
     $this->assertEquals('user1', $dto[$a2]['userRef']['username']);
     $this->assertEquals('user1.png', $dto[$a2]['userRef']['avatar_ref']);
     $this->assertEquals('user1', $dto[$a2]['content']['user']);
     $this->assertEquals('add_user_to_project', $dto[$a3]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a3]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a3]['content']['project']);
     $this->assertEquals($user2Id, $dto[$a3]['userRef']['id']);
     $this->assertEquals('user2', $dto[$a3]['userRef']['username']);
     $this->assertEquals('user2.png', $dto[$a3]['userRef']['avatar_ref']);
     $this->assertEquals('user2', $dto[$a3]['content']['user']);
     $this->assertEquals('add_user_to_project', $dto[$a4]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a4]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a4]['content']['project']);
     $this->assertEquals($user3Id, $dto[$a4]['userRef']['id']);
     $this->assertEquals('user3', $dto[$a4]['userRef']['username']);
     $this->assertEquals('user3.png', $dto[$a4]['userRef']['avatar_ref']);
     $this->assertEquals('user3', $dto[$a4]['content']['user']);
     $this->assertEquals('add_question', $dto[$a5]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a5]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a5]['content']['project']);
     $this->assertEquals($textId, $dto[$a5]['textRef']);
     $this->assertEquals($text->title, $dto[$a5]['content']['text']);
     $this->assertEquals($questionId, $dto[$a5]['questionRef']);
     $this->assertEquals($question->title, $dto[$a5]['content']['question']);
     $this->assertEquals('add_answer', $dto[$a6]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a6]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a6]['content']['project']);
     $this->assertEquals($textId, $dto[$a6]['textRef']);
     $this->assertEquals($text->title, $dto[$a6]['content']['text']);
     $this->assertEquals($questionId, $dto[$a6]['questionRef']);
     $this->assertEquals($question->title, $dto[$a6]['content']['question']);
     $this->assertEquals($user3Id, $dto[$a6]['userRef']['id']);
     $this->assertEquals('user3', $dto[$a6]['userRef']['username']);
     $this->assertEquals('user3.png', $dto[$a6]['userRef']['avatar_ref']);
     $this->assertEquals($answer->content, $dto[$a6]['content']['answer']);
     $this->assertEquals('user3', $dto[$a6]['content']['user']);
     $this->assertEquals('add_comment', $dto[$a7]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a7]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a7]['content']['project']);
     $this->assertEquals($textId, $dto[$a7]['textRef']);
     $this->assertEquals($text->title, $dto[$a7]['content']['text']);
     $this->assertEquals($questionId, $dto[$a7]['questionRef']);
     $this->assertEquals($question->title, $dto[$a7]['content']['question']);
     $this->assertEquals($user1Id, $dto[$a7]['userRef']['id']);
     $this->assertEquals('user1', $dto[$a7]['userRef']['username']);
     $this->assertEquals('user1.png', $dto[$a7]['userRef']['avatar_ref']);
     $this->assertEquals('user1', $dto[$a7]['content']['user']);
     $this->assertEquals($user3Id, $dto[$a7]['userRef2']['id']);
     $this->assertEquals('user3', $dto[$a7]['userRef2']['username']);
     $this->assertEquals('user3.png', $dto[$a7]['userRef2']['avatar_ref']);
     $this->assertEquals('user3', $dto[$a7]['content']['user2']);
     $this->assertEquals($answer->content, $dto[$a7]['content']['answer']);
     $this->assertEquals($comment1->content, $dto[$a7]['content']['comment']);
     $this->assertEquals('add_comment', $dto[$a8]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a8]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a8]['content']['project']);
     $this->assertEquals($textId, $dto[$a8]['textRef']);
     $this->assertEquals($text->title, $dto[$a8]['content']['text']);
     $this->assertEquals($questionId, $dto[$a8]['questionRef']);
     $this->assertEquals($question->title, $dto[$a8]['content']['question']);
     $this->assertEquals($user2Id, $dto[$a8]['userRef']['id']);
     $this->assertEquals('user2', $dto[$a8]['userRef']['username']);
     $this->assertEquals('user2.png', $dto[$a8]['userRef']['avatar_ref']);
     $this->assertEquals('user2', $dto[$a8]['content']['user']);
     $this->assertEquals($user3Id, $dto[$a8]['userRef2']['id']);
     $this->assertEquals('user3', $dto[$a8]['userRef2']['username']);
     $this->assertEquals('user3.png', $dto[$a8]['userRef2']['avatar_ref']);
     $this->assertEquals('user3', $dto[$a8]['content']['user2']);
     $this->assertEquals($answer->content, $dto[$a8]['content']['answer']);
     $this->assertEquals($comment2->content, $dto[$a8]['content']['comment']);
     $this->assertEquals('update_answer', $dto[$a9]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a9]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a9]['content']['project']);
     $this->assertEquals($textId, $dto[$a9]['textRef']);
     $this->assertEquals($text->title, $dto[$a9]['content']['text']);
     $this->assertEquals($questionId, $dto[$a9]['questionRef']);
     $this->assertEquals($question->title, $dto[$a9]['content']['question']);
     $this->assertEquals($user3Id, $dto[$a9]['userRef']['id']);
     $this->assertEquals('user3', $dto[$a9]['userRef']['username']);
     $this->assertEquals('user3.png', $dto[$a9]['userRef']['avatar_ref']);
     $this->assertEquals('user3', $dto[$a9]['content']['user']);
     $this->assertEquals($answer_updated->content, $dto[$a9]['content']['answer']);
     $this->assertEquals('update_comment', $dto[$a10]['action']);
     $this->assertEquals($expectedProjectRef, $dto[$a10]['projectRef']);
     $this->assertEquals($project->projectName, $dto[$a10]['content']['project']);
     $this->assertEquals($textId, $dto[$a10]['textRef']);
     $this->assertEquals($text->title, $dto[$a10]['content']['text']);
     $this->assertEquals($questionId, $dto[$a10]['questionRef']);
     $this->assertEquals($question->title, $dto[$a10]['content']['question']);
     $this->assertEquals($user1Id, $dto[$a10]['userRef']['id']);
     $this->assertEquals('user1', $dto[$a10]['userRef']['username']);
     $this->assertEquals('user1.png', $dto[$a10]['userRef']['avatar_ref']);
     $this->assertEquals('user1', $dto[$a10]['content']['user']);
     $this->assertEquals($user3Id, $dto[$a10]['userRef2']['id']);
     $this->assertEquals('user3', $dto[$a10]['userRef2']['username']);
     $this->assertEquals('user3.png', $dto[$a10]['userRef2']['avatar_ref']);
     $this->assertEquals('user3', $dto[$a10]['content']['user2']);
     $this->assertEquals($answer_updated->content, $dto[$a10]['content']['answer']);
     $this->assertEquals($comment1_updated->content, $dto[$a10]['content']['comment']);
 }
 public function run($mode = 'test')
 {
     $testMode = $mode != 'run';
     $message = "";
     $projectlist = new ProjectListModel();
     $projectlist->read();
     $textsExamined = 0;
     $textsUpdated = 0;
     // foreach existing project
     foreach ($projectlist->entries as $projectParams) {
         $projectId = $projectParams['id'];
         if ($projectParams['projectName'] == 'Jamaican Psalms') {
             $project = new SfchecksProjectModel($projectId);
             $textlist = new TextListModel($project);
             $textlist->read();
             // foreach text in project
             foreach ($textlist->entries as $textParams) {
                 $textsExamined++;
                 $textId = $textParams['id'];
                 $legacyText = new TextModel_sf_v0_9_18($project, $textId);
                 $fileName = '';
                 if ($legacyText->audioUrl) {
                     $text = new TextModel($project, $textId);
                     if (!$testMode) {
                         if (!$text->audioFileName) {
                             // legacy audioUrl format "assets/<projectId>/<textId>_<fileName>"
                             $fileNamePrefix = $textId . '_';
                             $pos = strpos($legacyText->audioUrl, $fileNamePrefix);
                             $text->audioFileName = substr($legacyText->audioUrl, $pos + strlen($fileNamePrefix));
                         }
                         $text->write();
                     }
                     $message .= "Changed text: {$text->title}\n";
                     $textsUpdated++;
                 }
             }
             if (!$testMode) {
                 TextModel_sf_v0_9_18::removeAudioProperty($project->databaseName());
                 $message .= "Removed 'audioUrl' property from project: {$project->projectName}\n";
             }
         }
     }
     if ($textsUpdated > 0) {
         $message .= "\n\nChanged {$textsUpdated} legacy texts to only store audio filename\n\n";
     } else {
         $message .= "\n\nNo legacy text audio were found/changed. {$textsExamined} texts examined.\n\n";
     }
     // re-arrange assets folder
     // - remove <siteName> from path for LF
     // - add <appName> to path for SF and change <projectId> in path to <projectSlug (databaseName)>
     $message .= "\n\nRe-arrange assets folder\n~~~~~~~~~~~~~~~~~~~~~~~~\n\n";
     $project = new SfchecksProjectModel();
     $assetsFolderPath = APPPATH . "assets";
     $assetsSubfolders = glob($assetsFolderPath . '/*');
     @mkdir($assetsFolderPath . '/lexicon');
     @mkdir($assetsFolderPath . '/sfchecks');
     foreach ($assetsSubfolders as $assetsSubfolder) {
         if (file_exists($assetsSubfolder) && is_dir($assetsSubfolder)) {
             $assetsSubfolderName = basename($assetsSubfolder);
             if (strpos($assetsSubfolderName, 'languageforge') !== false) {
                 $message .= "Move into lexicon: {$assetsSubfolderName}\n";
                 $oldFolderPath = $assetsSubfolder . '/lexicon';
                 $newFolderPath = $assetsFolderPath . '/lexicon';
             } elseif ($assetsSubfolderName == 'lexicon' || $assetsSubfolderName == 'sfchecks') {
                 $message .= "No change: {$assetsSubfolderName}\n";
                 $oldFolderPath = '';
                 $newFolderPath = '';
                 $assetsSubfolder = '';
             } elseif ($project->exists($assetsSubfolderName)) {
                 $message .= "Move into sfchecks: {$assetsSubfolderName}\n";
                 $oldFolderPath = $assetsSubfolder;
                 $project->read($assetsSubfolderName);
                 $projectSlug = $project->databaseName();
                 $newFolderPath = $assetsFolderPath . "/sfchecks/{$projectSlug}";
                 if (!$testMode) {
                 }
             } else {
                 $message .= "Delete: {$assetsSubfolderName}\n";
                 $oldFolderPath = '';
                 $newFolderPath = '';
             }
             if (!$testMode) {
                 if (file_exists($oldFolderPath) && is_dir($oldFolderPath)) {
                     if (!@rename($oldFolderPath, $newFolderPath)) {
                         $oldFiles = glob($oldFolderPath . '/*');
                         foreach ($oldFiles as $oldFile) {
                             $newFile = $newFolderPath . '/' . basename($oldFile);
                             rename($oldFile, $newFile);
                         }
                     }
                 }
                 if (file_exists($assetsSubfolder) && is_dir($assetsSubfolder)) {
                     $this->recursiveRemoveFolder($assetsSubfolder);
                 }
             }
         }
     }
     return $message;
 }
 public function testUpdateComment_ExistingComment_OriginalAuthorIsPreserved()
 {
     $environ = new MongoTestEnvironment();
     $environ->clean();
     $project = $environ->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 = $environ->createUser('user1', 'user1', 'user1');
     $user2Id = $environ->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->assertEquals($user1Id, $newComment->userRef->asString());
 }
 /**
  * @param string $projectId
  * @param array $textIds
  * @return int Total number of texts removed.
  */
 public static function deleteTexts($projectId, $textIds)
 {
     $projectModel = new ProjectModel($projectId);
     $count = 0;
     foreach ($textIds as $textId) {
         TextModel::remove($projectModel->databaseName(), $textId);
         $count++;
     }
     return $count;
 }