/**
  * Create a project, checking permissions as necessary
  * @param string $projectName
  * @param string $projectCode
  * @param string $appName
  * @param string $userId
  * @param Website $website
  * @param array $srProject send receive project data
  * @return string - projectId
  */
 public static function createProject($projectName, $projectCode, $appName, $userId, $website, $srProject = null)
 {
     // Check for unique project code
     if (ProjectCommands::projectCodeExists($projectCode)) {
         return false;
     }
     $project = new ProjectModel();
     $project->projectName = $projectName;
     $project->projectCode = $projectCode;
     $project->appName = $appName;
     $project->siteName = $website->domain;
     $project->ownerRef->id = $userId;
     $project->addUser($userId, ProjectRoles::MANAGER);
     $projectId = $project->write();
     if ($srProject) {
         SendReceiveCommands::updateSRProject($projectId, $srProject);
     }
     $user = new UserModel($userId);
     $user->addProject($projectId);
     $user->write();
     $project = ProjectModel::getById($projectId);
     $project->initializeNewProject();
     ActivityCommands::addUserToProject($project, $userId);
     return $projectId;
 }
 /**
  * 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);
 }
 /**
  * @param string $projectId
  * @param string $userId
  * @return array - the DTO array
  */
 public static function encode($projectId, $userId)
 {
     $data = array();
     $user = new UserProfileModel($userId);
     $project = new LexProjectModel($projectId);
     $config = JsonEncoder::encode($project->config);
     $config['inputSystems'] = JsonEncoder::encode($project->inputSystems);
     $data['config'] = $config;
     // comment out at the moment until a refactor can be done that is more efficient (language data in the database?)
     /*
     $interfaceLanguageCode = $project->interfaceLanguageCode;
     if ($user->interfaceLanguageCode) {
         $interfaceLanguageCode = $user->interfaceLanguageCode;
     }
     $options = self::getInterfaceLanguages(APPPATH . 'angular-app/languageforge/lexicon/lang');
     asort($options);    // sort by language name
     $selectInterfaceLanguages = array(
         'optionsOrder' => array_keys($options),
         'options' => $options
     );
     $data['interfaceConfig'] = array('userLanguageCode' => $interfaceLanguageCode);
     $data['interfaceConfig']['selectLanguages'] = $selectInterfaceLanguages;
     */
     // a stand in for the code above
     $data['interfaceConfig'] = array('userLanguageCode' => 'en', 'selectLanguages' => array('options' => array('en' => 'English'), 'optionsOrder' => array('en')));
     $optionlistListModel = new LexOptionListListModel($project);
     $optionlistListModel->read();
     $data['optionlists'] = $optionlistListModel->entries;
     if ($project->hasSendReceive()) {
         $data['sendReceive'] = array();
         $data['sendReceive']['status'] = SendReceiveCommands::getProjectStatus($projectId);
     }
     return $data;
 }
 /**
  * Cleanup associated project files
  */
 protected function cleanup()
 {
     parent::cleanup();
     if (!is_null($this->projectCode)) {
         $projectFilename = strtolower($this->projectCode);
         $stateFilename = strtolower($this->projectCode) . '.state';
         $lfmergePaths = SendReceiveCommands::getLFMergePaths();
         foreach ($lfmergePaths as $key => $path) {
             if (!is_null($path)) {
                 if ($key == "workPath") {
                     FileUtilities::removeFolderAndAllContents($lfmergePaths->workPath . DIRECTORY_SEPARATOR . $projectFilename);
                 }
                 if (file_exists($path . DIRECTORY_SEPARATOR . $projectFilename)) {
                     unlink($path . DIRECTORY_SEPARATOR . $projectFilename);
                 }
                 if (file_exists($path . DIRECTORY_SEPARATOR . $stateFilename)) {
                     unlink($path . DIRECTORY_SEPARATOR . $stateFilename);
                 }
             }
         }
     }
 }
 public function sendReceive_notification_sendRequest($projectCode)
 {
     return SendReceiveCommands::notificationSendRequest($projectCode);
 }
        }
    }
    FileUtilities::removeFolderAndAllContents($otherAssetsFolderPath);
}
// cleanup LfMerge 'syncqueue', 'webwork' and 'state' folders
if ($testProject->appName == LexProjectModel::LEXICON_APP) {
    $syncQueuePath = SendReceiveCommands::getLFMergePaths()->syncQueuePath;
    foreach (glob("{$syncQueuePath}/*") as $file) {
        if (is_file($file)) {
            unlink($file);
        }
    }
    $workPath = SendReceiveCommands::getLFMergePaths()->workPath;
    FileUtilities::removeFolderAndAllContents($workPath . DIRECTORY_SEPARATOR . $constants['srProjectCode']);
    FileUtilities::removeFolderAndAllContents($workPath . DIRECTORY_SEPARATOR . 'mock-id4');
    $stateFilePath = SendReceiveCommands::getLFMergePaths()->statePath . DIRECTORY_SEPARATOR . 'mock-id4.state';
    if (is_file($stateFilePath)) {
        unlink($stateFilePath);
    }
}
// cleanup mocked uploaded zip import (jpg file)
$tmpFilePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $constants['testMockJpgImportFile']['name'];
@unlink($tmpFilePath);
// cleanup mocked uploaded zip import (zip file)
$tmpFilePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $constants['testMockZipImportFile']['name'];
@unlink($tmpFilePath);
// cleanup mock uploaded audio (png file)
$tmpFilePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $constants['testMockPngUploadFile']['name'];
@unlink($tmpFilePath);
// cleanup mock uploaded audio (mp3 file)
$tmpFilePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $constants['testMockMp3UploadFile']['name'];
 public function testNotificationSendRequest_HasSendReceiveAndHasUncommittedEntry_Notified()
 {
     self::$environ->clean();
     $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE);
     $project->sendReceiveProjectIdentifier = 'sr_id';
     $project->sendReceiveProject = new SendReceiveProjectModel('sr_name', '', 'manager');
     $project->write();
     $tmpTestPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'notifiedTest';
     $lfmergePaths = SendReceiveCommands::getLFMergePaths(true, $tmpTestPath);
     $projectStatePath = $lfmergePaths->statePath . DIRECTORY_SEPARATOR . strtolower($project->projectCode) . '.state';
     FileUtilities::createAllFolders($tmpTestPath);
     FileUtilities::createAllFolders($lfmergePaths->sendQueuePath);
     FileUtilities::createAllFolders($lfmergePaths->statePath);
     file_put_contents($projectStatePath, '{"state": "SENDING", "uncommittedEditCount": 1}');
     $mockPidFilePath = sys_get_temp_dir() . '/mockLFMerge.pid';
     $mockCommand = 'php ' . __DIR__ . '/mockLFMergeExe.php';
     $isNotified = SendReceiveCommands::notificationSendRequest($project->projectCode, $lfmergePaths->statePath, $lfmergePaths->sendQueuePath, $mockPidFilePath, $mockCommand);
     $queueFileNames = scandir($lfmergePaths->sendQueuePath);
     $this->assertTrue($isNotified);
     $this->assertCount(3, $queueFileNames);
     FileUtilities::removeFolderAndAllContents($tmpTestPath);
 }
 /**
  * @param string $projectId
  * @param string $userId
  * @param null $lastFetchTime
  * @param int $offset
  * @throws \Exception
  * @return array
  */
 public static function encode($projectId, $userId, $lastFetchTime = null, $offset = 0)
 {
     $data = array();
     $project = new LexProjectModel($projectId);
     if ($lastFetchTime) {
         $entriesModel = new LexEntryListModel($project, $lastFetchTime);
         $entriesModel->readAsModels();
         $commentsModel = new LexCommentListModel($project, $lastFetchTime);
         $commentsModel->readAsModels();
     } else {
         $entriesModel = new LexEntryListModel($project, null, self::MAX_ENTRIES_PER_REQUEST, $offset);
         $entriesModel->readAsModels();
         $commentsModel = new LexCommentListModel($project, null, self::MAX_ENTRIES_PER_REQUEST, $offset);
         $commentsModel->readAsModels();
         $data['itemTotalCount'] = $entriesModel->totalCount > $commentsModel->totalCount ? $entriesModel->totalCount : $commentsModel->totalCount;
         $data['itemCount'] = $entriesModel->count > $commentsModel->count ? $entriesModel->count : $commentsModel->count;
         $data['offset'] = $offset;
     }
     $entries = LexDbeDtoEntriesEncoder::encode($entriesModel);
     $entries = $entries['entries'];
     $encodedComments = LexDbeDtoCommentsEncoder::encode($commentsModel);
     $data['comments'] = $encodedComments['entries'];
     $votes = new UserGenericVoteModel($userId, $projectId, 'lexCommentPlusOne');
     $votesDto = array();
     foreach ($votes->votes as $vote) {
         $votesDto[$vote->ref->id] = true;
     }
     $data['commentsUserPlusOne'] = $votesDto;
     if (!is_null($lastFetchTime)) {
         $deletedEntriesModel = new LexDeletedEntryListModel($project, $lastFetchTime);
         $deletedEntriesModel->read();
         $data['deletedEntryIds'] = array_map(function ($e) {
             return $e['id'];
         }, $deletedEntriesModel->entries);
         $deletedCommentsModel = new LexDeletedCommentListModel($project, $lastFetchTime);
         $deletedCommentsModel->read();
         $data['deletedCommentIds'] = array_map(function ($c) {
             return $c['id'];
         }, $deletedCommentsModel->entries);
     }
     $lexemeInputSystems = $project->config->entry->fields[LexConfig::LEXEME]->inputSystems;
     usort($entries, function ($a, $b) use($lexemeInputSystems) {
         $lexeme1Value = '';
         if (array_key_exists(LexConfig::LEXEME, $a)) {
             $lexeme1 = $a[LexConfig::LEXEME];
             foreach ($lexemeInputSystems as $ws) {
                 if (array_key_exists($ws, $lexeme1) && $lexeme1[$ws]['value'] != '') {
                     $lexeme1Value = $lexeme1[$ws]['value'];
                     // '\P{xx} matches all characters without the Unicode property XX. L is the Unicode property "letter".
                     $lexeme1Value = preg_replace('/^\\P{L}+/', '', $lexeme1Value);
                     // Strip non-letter characters from front of word for sorting
                     break;
                 }
             }
         }
         $lexeme2Value = '';
         if (array_key_exists(LexConfig::LEXEME, $b)) {
             $lexeme2 = $b[LexConfig::LEXEME];
             foreach ($lexemeInputSystems as $ws) {
                 if (array_key_exists($ws, $lexeme2) && $lexeme2[$ws]['value'] != '') {
                     $lexeme2Value = $lexeme2[$ws]['value'];
                     $lexeme2Value = preg_replace('/^\\P{L}+/', '', $lexeme2Value);
                     // Strip non-letter characters from front of word for sorting
                     break;
                 }
             }
         }
         return strtolower($lexeme1Value) > strtolower($lexeme2Value) ? 1 : -1;
     });
     $data['entries'] = $entries;
     $data['timeOnServer'] = time();
     // for offline syncing
     if ($project->hasSendReceive()) {
         $data['sendReceive'] = array();
         $data['sendReceive']['status'] = SendReceiveCommands::getProjectStatus($projectId);
     }
     return $data;
 }