/** * Import a LIFT file * * @param string $projectId * @param string $mediaType * @param string $tmpFilePath * @throws \Exception * @return UploadResponse */ public static function importLiftFile($projectId, $mediaType, $tmpFilePath) { if ($mediaType != 'import-lift') { throw new \Exception("Unsupported upload type."); } if (!$tmpFilePath) { throw new \Exception("Upload controller did not move the uploaded file."); } $file = $_FILES['file']; $fileName = $file['name']; $mergeRule = $_POST['mergeRule']; $skipSameModTime = $_POST['skipSameModTime']; $deleteMatchingEntry = $_POST['deleteMatchingEntry']; $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); $allowedTypes = array("text/xml", "application/xml"); $response = new UploadResponse(); if (in_array(strtolower($fileType), $allowedTypes) && in_array(strtolower($fileExt), self::$allowedLiftExtensions)) { // make the folders if they don't exist $project = new LexProjectModel($projectId); $project->createAssetsFolders(); $folderPath = $project->getAssetsFolderPath(); $importer = LiftImport::get()->merge($tmpFilePath, $project, $mergeRule, $skipSameModTime, $deleteMatchingEntry); $project->write(); $moveOk = true; if (!$project->liftFilePath || $mergeRule != LiftMergeRule::IMPORT_LOSES) { // cleanup previous files of any allowed extension $cleanupFiles = glob($folderPath . '/*[' . implode(', ', self::$allowedLiftExtensions) . ']'); foreach ($cleanupFiles as $cleanupFile) { @unlink($cleanupFile); } // move uploaded LIFT file from tmp location to assets $filePath = $folderPath . DIRECTORY_SEPARATOR . $fileName; $project->liftFilePath = $filePath; $project->write(); $moveOk = copy($tmpFilePath, $filePath); @unlink($tmpFilePath); } // construct server response if ($moveOk && $tmpFilePath) { $data = new ImportResult(); $data->path = $project->getAssetsRelativePath(); $data->fileName = $fileName; $data->stats = $importer->stats; $data->importErrors = $importer->getReport()->toFormattedString(); $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(", ", self::$allowedLiftExtensions); $data = new ErrorResult(); $data->errorType = 'UserMessage'; if (count(self::$allowedLiftExtensions) < 1) { $data->errorMessage = "{$fileName} of type: {$fileType} is not an allowed LIFT file. No LIFT file formats are currently enabled, contact your Site Administrator."; } elseif (count(self::$allowedLiftExtensions) == 1) { $data->errorMessage = "{$fileName} of type: {$fileType} is not an allowed LIFT file. Ensure the file is a {$allowedExtensionsStr}."; } else { $data->errorMessage = "{$fileName} of type: {$fileType} is not an allowed LIFT file. Ensure the file is one of the following types: {$allowedExtensionsStr}."; } $response->result = false; } $response->data = $data; return $response; }
/** * * @param string $zipFilePath * @param LexProjectModel $projectModel * @param string $mergeRule (use LiftMergeRule const) * @param boolean $skipSameModTime * @param boolean $deleteMatchingEntry * @throws \Exception * @return LiftImport */ public function importZip($zipFilePath, $projectModel, $mergeRule = LiftMergeRule::IMPORT_WINS, $skipSameModTime = false, $deleteMatchingEntry = false) { $assetsFolderPath = $projectModel->getAssetsFolderPath(); $extractFolderPath = $assetsFolderPath . '/initialUpload_' . mt_rand(); $this->report = new ImportErrorReport(); $zipNodeError = new ZipImportNodeError(ZipImportNodeError::FILE, basename($zipFilePath)); try { self::extractZip($zipFilePath, $extractFolderPath); // Now find the .lift file in the uploaded zip $dirIter = new \RecursiveDirectoryIterator($extractFolderPath); $iterIter = new \RecursiveIteratorIterator($dirIter); $liftIter = new \RegexIterator($iterIter, '/\\.lift$/', \RegexIterator::MATCH); $liftFilePaths = array(); foreach ($liftIter as $file) { $liftFilePaths[] = $file->getPathname(); } if (empty($liftFilePaths)) { throw new \Exception("Uploaded file does not contain any LIFT data"); } if (count($liftFilePaths) > 1) { foreach (array_slice($liftFilePaths, 1) as $filename) { $zipNodeError->addUnhandledLiftFile(basename($filename)); } } // Import subfolders foreach (glob($extractFolderPath . '/*', GLOB_ONLYDIR) as $folderPath) { $folderName = basename($folderPath); switch ($folderName) { case 'pictures': case 'audio': case 'others': case 'WritingSystems': $assetsPath = $assetsFolderPath . "/" . $folderName; if (file_exists($folderPath) && is_dir($folderPath)) { FileUtilities::copyFolderTree($folderPath, $assetsPath); } break; default: $zipNodeError->addUnhandledSubfolder($folderName); } } // Import first .lift file (only). $this->liftFilePath = $liftFilePaths[0]; $this->merge($this->liftFilePath, $projectModel, $mergeRule, $skipSameModTime, $deleteMatchingEntry); if ($zipNodeError->hasError()) { error_log($zipNodeError->toString() . "\n"); } foreach ($this->report->nodeErrors as $subnodeError) { $zipNodeError->addSubnodeError($subnodeError); } $this->report = new ImportErrorReport(); $this->report->nodeErrors[] = $zipNodeError; } catch (\Exception $e) { if ($zipNodeError->hasError()) { error_log($zipNodeError->toString() . "\n"); } foreach ($this->report->nodeErrors as $subnodeError) { $zipNodeError->addSubnodeError($subnodeError); } $this->report = new ImportErrorReport(); $this->report->nodeErrors[] = $zipNodeError; throw new \Exception($e->getMessage(), $e->getCode()); } return $this; }
public function testCreateProject_NewSRProject_SRProjectWithLinks() { self::$environ = new LexiconMongoTestEnvironment(); self::$environ->clean(); $user1Id = self::$environ->createUser("user1name", "User1 Name", "*****@*****.**"); $user1 = new UserModel($user1Id); $srProject = array('identifier' => 'srIdentifier', 'name' => 'srName', 'repository' => 'http://public.languagedepot.org', 'role' => 'manager'); $projectId = ProjectCommands::createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE, LexProjectModel::LEXICON_APP, $user1->id->asString(), self::$environ->website, $srProject); $project = new LexProjectModel($projectId); $assetImagePath = $project->getImageFolderPath(); $assetAudioPath = $project->getAudioFolderPath(); $this->assertTrue($project->hasSendReceive()); $this->assertTrue(is_link($assetImagePath)); $this->assertTrue(is_link($assetAudioPath)); $projectWorkPath = $project->getSendReceiveWorkFolder(); FileUtilities::removeFolderAndAllContents($project->getAssetsFolderPath()); FileUtilities::removeFolderAndAllContents($projectWorkPath); }