/**
  * Updates the given LexEntry in $projectId
  * @param string $projectId
  * @param array $params
  * @param string $userId
  * @param string $mergeQueuePath
  * @param string $pidFilePath
  * @param string $command
  * @return bool|array<encoded LexEntryModel> if the project is syncing (or on hold) return false (no save)FixSe
  */
 public static function updateEntry($projectId, $params, $userId, $mergeQueuePath = null, $pidFilePath = null, $command = null)
 {
     CodeGuard::checkTypeAndThrow($params, 'array');
     $project = new LexProjectModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($project);
     $now = UniversalTimestamp::now();
     if (array_key_exists('id', $params) && $params['id'] != '') {
         $entry = new LexEntryModel($project, $params['id']);
         $action = 'update';
     } else {
         $entry = new LexEntryModel($project);
         $entry->authorInfo->createdByUserRef->id = $userId;
         $entry->authorInfo->createdDate = $now;
         $entry->guid = Guid::create();
         $action = 'create';
         // TODO: Consider adding more specific activity entry: which fields were modified? 2014-09-03 RM
         // E.g., "User _____ updated entry _____ by adding a new sense with definition ______"
     }
     $entry->authorInfo->modifiedDate = $now;
     $entry->authorInfo->modifiedByUserRef->id = $userId;
     if ($project->hasSendReceive()) {
         //            $entry->dirtySR++;
         $entry->dirtySR = 0;
         $status = SendReceiveCommands::getProjectStatus($projectId);
         if ($status && $status['SRState'] != 'IDLE') {
             return false;
         }
     }
     LexEntryDecoder::decode($entry, $params);
     $entry->write();
     ActivityCommands::writeEntry($project, $userId, $entry, $action);
     //        SendReceiveCommands::queueProjectForUpdate($project, $mergeQueuePath);
     //        SendReceiveCommands::startLFMergeIfRequired($projectId, 'merge', $pidFilePath, $command);
     return JsonEncoder::encode($entry);
 }
 public static function updateTemplate($projectId, $params)
 {
     $projectModel = new ProjectModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($projectModel);
     $questionTemplate = new QuestionTemplateModel($projectModel);
     JsonDecoder::decode($questionTemplate, $params);
     $result = $questionTemplate->write();
     return $result;
 }
 /**
  * @expectedException Api\Library\Shared\Palaso\Exception\ResourceNotAvailableException
  */
 public function testCheckIfArchivedAndThrow_ArchivedProject_Throw()
 {
     self::$environ->clean();
     $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $project->isArchived = true;
     $project->write();
     $this->assertTrue($project->isArchived);
     ProjectCommands::checkIfArchivedAndThrow($project);
 }
 /**
  * Update the optionlist with params
  * @param $projectId
  * @param array $params (encoded LexOptionListModel)
  * @return string $optionlistId
  */
 public static function updateList($projectId, $params)
 {
     CodeGuard::checkTypeAndThrow($params, 'array');
     $project = new LexProjectModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($project);
     if (array_key_exists('id', $params) && $params['id'] != '') {
         $optionlist = new LexOptionListModel($project, $params['id']);
     } else {
         $optionlist = new LexOptionListModel($project);
     }
     JsonDecoder::decode($optionlist, $params);
     return $optionlist->write();
 }
 /**
  * Create or update project
  * @param string $projectId
  * @param string $userId
  * @param array<projectModel> $object
  * @throws UserUnauthorizedException
  * @throws \Exception
  * @return string projectId
  */
 public static function updateProject($projectId, $userId, $object)
 {
     $project = new LexProjectModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($project);
     if (!$project->hasRight($userId, Domain::USERS + Operation::EDIT)) {
         throw new UserUnauthorizedException("Insufficient privileges to update project in method 'updateProject'");
     }
     $oldDBName = $project->databaseName();
     $object['id'] = $projectId;
     JsonDecoder::decode($project, $object);
     $newDBName = $project->databaseName();
     if ($oldDBName != '' && $oldDBName != $newDBName) {
         if (MongoStore::hasDB($newDBName)) {
             throw new \Exception("Cannot rename '{$oldDBName}' to ' {$newDBName}' . New project name {$newDBName} already exists.  Not renaming.");
         }
         MongoStore::renameDB($oldDBName, $newDBName);
     }
     $projectId = $project->write();
     return $projectId;
 }
 /**
  * @param string $projectId
  * @param array $object (json encoded)
  * @return string Id of text updated/added
  */
 public static function updateText($projectId, $object)
 {
     $projectModel = new ProjectModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($projectModel);
     $textModel = new TextModel($projectModel);
     $isNewText = $object['id'] == '';
     if (!$isNewText) {
         $textModel->read($object['id']);
     }
     JsonDecoder::decode($textModel, $object);
     TextCommands::makeValidRange($object);
     if (TextCommands::hasRange($object)) {
         $usxTrimHelper = new UsxTrimHelper($textModel->content, $object['startCh'] || 0, $object['startVs'] || 0, $object['endCh'] || 0, $object['endVs'] || 0);
         $textModel->content = $usxTrimHelper->trimUsx();
     }
     $textId = $textModel->write();
     if ($isNewText) {
         ActivityCommands::addText($projectModel, $textId, $textModel);
     }
     return $textId;
 }
 /**
  * Updates the ProjectSettingsModel which are settings accessible only to site administrators
  * @param string $projectId
  * @param array<SmsSettings> $smsSettingsArray
  * @param array<EmailSettings> $emailSettingsArray
  * @return string $result id to the projectSettingsModel
  */
 public static function updateProjectSettings($projectId, $smsSettingsArray, $emailSettingsArray)
 {
     $projectSettings = new ProjectSettingsModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($projectSettings);
     $smsSettings = new SmsSettings();
     $emailSettings = new EmailSettings();
     JsonDecoder::decode($smsSettings, $smsSettingsArray);
     JsonDecoder::decode($emailSettings, $emailSettingsArray);
     $projectSettings->smsSettings = $smsSettings;
     $projectSettings->emailSettings = $emailSettings;
     $result = $projectSettings->write();
     return $result;
 }
 /**
  *
  * @param string $projectId
  * @param string $mediaType, options are 'image'.
  * @param string $fileName
  * @throws \Exception
  * @return UploadResponse
  */
 public static function deleteMediaFile($projectId, $mediaType, $fileName)
 {
     $response = new UploadResponse();
     $response->result = false;
     $project = new LexProjectModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($project);
     switch ($mediaType) {
         case 'audio':
             $folderPath = $project->getAudioFolderPath();
             break;
         case 'sense-image':
             $folderPath = $project->getImageFolderPath();
             break;
         default:
             $errorMsg = "Error in function deleteImageFile, unsupported mediaType: {$mediaType}";
             throw new \Exception($errorMsg);
             $data = new ErrorResult();
             $data->errorType = 'Exception';
             $data->errorMessage = $errorMsg;
             return $response;
     }
     $filePath = $folderPath . '/' . $fileName;
     if (file_exists($filePath) and !is_dir($filePath)) {
         if (unlink($filePath)) {
             $data = new MediaResult();
             $data->path = $folderPath;
             $data->fileName = $fileName;
             $response->result = true;
         } else {
             $data = new ErrorResult();
             $data->errorType = 'UserMessage';
             $data->errorMessage = "{$fileName} could not be deleted. Contact your Site Administrator.";
         }
         return $response;
     }
     $data = new ErrorResult();
     $data->errorType = 'UserMessage';
     $data->errorMessage = "{$fileName} does not exist in this project. Contact your Site Administrator.";
     return $response;
 }
 /**
  * @param  string $projectId
  * @param  string $userId
  * @param  \Api\Library\Shared\Website $website
  * @param  string $commentId
  * @param  string $replyId
  * @throws \Exception
  * @return string $commentId
  */
 public static function deleteReply($projectId, $userId, $website, $commentId, $replyId)
 {
     // if the userId is different from the author, throw if user does not have DELETE privilege
     $project = new LexProjectModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($project);
     $comment = new LexCommentModel($project, $commentId);
     $reply = $comment->getReply($replyId);
     if ($reply->authorInfo->createdByUserRef->asString() != $userId) {
         // if the userId is different from the author, throw if user does not have DELETE privilege
         $rh = new RightsHelper($userId, $project, $website);
         if (!$rh->userHasProjectRight(Domain::COMMENTS + Operation::DELETE)) {
             throw new \Exception("No permission to delete other people's comment replies!");
         }
     }
     $comment->deleteReply($replyId);
     return $comment->write();
 }
 public static function voteDown($userId, $projectId, $questionId, $answerId)
 {
     $projectModel = new ProjectModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($projectModel);
     $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);
 }
 /**
  * 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;
 }
 /**
  * @param string $projectId
  * @param string $pidFilePath
  * @param string $command
  * @return bool true if process started or already running, otherwise false
  * @throws ResourceNotAvailableException
  * @throws \Exception
  */
 public static function startLFMergeIfRequired($projectId, $pidFilePath = null, $command = null)
 {
     $project = new LexProjectModel($projectId);
     ProjectCommands::checkIfArchivedAndThrow($project);
     if (!$project->hasSendReceive()) {
         return false;
     }
     if (is_null($pidFilePath)) {
         $pidFilePath = self::$lfmergePidFilePaths[0];
         foreach (self::$lfmergePidFilePaths as $path) {
             if (file_exists($path)) {
                 $pidFilePath = $path;
                 break;
             }
         }
     }
     if (self::isProcessRunningByPidFile($pidFilePath)) {
         return true;
     }
     if (is_null($command)) {
         $command = self::LFMERGE_EXE . ' -p ' . $project->projectCode;
     }
     if (!self::commandExists($command)) {
         throw new \Exception('LFMerge is not installed. Contact the website administrator.');
     }
     $pid = self::runInBackground($command);
     return self::isProcessRunningByPid($pid);
 }