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 testInitializeNewProject_SendReceiveProjectAndExistingTargetFile_SourceFileMovedAndSymlinksCreated() { $project = self::$environ->createProject(SF_TESTPROJECT, SF_TESTPROJECTCODE); $project->sendReceiveProjectIdentifier = 'sr_id'; $project->sendReceiveProject = new SendReceiveProjectModel('sr_name', '', 'manager'); $project->write(); $this->assertTrue($project->hasSendReceive()); $projectWorkPath = $project->getSendReceiveWorkFolder(); $srImagePath = $projectWorkPath . DIRECTORY_SEPARATOR . 'LinkedFiles' . DIRECTORY_SEPARATOR . 'Pictures'; FileUtilities::createAllFolders($srImagePath); $srTestImageFilePath = $srImagePath . DIRECTORY_SEPARATOR . 'existingTargetImage.jpg'; touch($srTestImageFilePath); $this->assertTrue(file_exists($srTestImageFilePath)); $assetImagePath = $project->getImageFolderPath(); $filenameToMove = 'existingSourceImage.jpg'; $filePathToMove = $assetImagePath . DIRECTORY_SEPARATOR . $filenameToMove; touch($filePathToMove); $this->assertTrue(file_exists($filePathToMove)); $project->initializeNewProject(); $this->assertTrue(is_link($assetImagePath)); $this->assertTrue(file_exists($srTestImageFilePath)); $this->assertTrue(file_exists($filePathToMove)); $this->assertTrue(file_exists($srImagePath . DIRECTORY_SEPARATOR . $filenameToMove)); $assetAudioPath = $project->getAudioFolderPath(); $this->assertTrue(is_link($assetAudioPath)); $project->initializeNewProject(); $this->assertTrue(is_link($assetImagePath)); $this->assertTrue(file_exists($srTestImageFilePath)); $this->assertTrue(file_exists($filePathToMove)); $this->assertTrue(file_exists($srImagePath . DIRECTORY_SEPARATOR . $filenameToMove)); $this->assertTrue(is_link($assetAudioPath)); FileUtilities::removeFolderAndAllContents($project->getAssetsFolderPath()); FileUtilities::removeFolderAndAllContents($projectWorkPath); }
/** * Import a LIFT file * * @param string $projectId * @param string $mediaType * @param string $tmpFilePath * @throws \Exception * @return \Api\Model\Shared\Command\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 LexiconProjectModel($projectId); $folderPath = $project->getAssetsFolderPath(); FileUtilities::createAllFolders($folderPath); $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 . '/' . $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; }
/** * 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); } } } } }
/** * Cleanup test files and folders * * @param string $assetsFolderPath */ public function cleanupTestFiles($assetsFolderPath) { $this->cleanupTestUploadFiles(); FileUtilities::removeFolderAndAllContents($assetsFolderPath); }
/** * Add node as a custom field * * @param SimpleXMLElement $sxeNode * @param string $nodeId * @param string $customFieldNamePrefix * @param array $customFieldSpecs * @param LexiconFieldListConfigObj $levelConfig * @param LexEntryModel|Sense|Example $item */ private function addCustomField($sxeNode, $nodeId, $customFieldNamePrefix, $levelConfig, $item) { $fieldType = FileUtilities::replaceSpecialCharacters($nodeId); $customFieldSpecs = $this->getCustomFieldSpecs($fieldType); $customFieldName = $this->createCustomField($nodeId, $fieldType, $customFieldNamePrefix, $customFieldSpecs, $levelConfig); if ($customFieldSpecs['Type'] == 'ReferenceAtom') { $item->customFields[$customFieldName] = new LexiconField(); $item->customFields[$customFieldName]->value = (string) $sxeNode['value']; } elseif ($customFieldSpecs['Type'] == 'ReferenceCollection') { if (!array_key_exists($customFieldName, $item->customFields)) { $item->customFields[$customFieldName] = new LexiconMultiValueField(); } $item->customFields[$customFieldName]->value((string) $sxeNode['value']); } elseif ($customFieldSpecs['Type'] == 'OwningAtom') { $multiText = $this->readMultiText($sxeNode, $levelConfig->fields[$customFieldName]->inputSystems); $item->customFields[$customFieldName] = self::convertMultiParaMultiText($multiText); } else { $item->customFields[$customFieldName] = $this->readMultiText($sxeNode, $levelConfig->fields[$customFieldName]->inputSystems); } }
/** * @param string $zipFilePath * @param string $destDir * @throws \Exception */ public static function extractZip($zipFilePath, $destDir) { // Use absolute path for archive file $realpathResult = realpath($zipFilePath); if ($realpathResult) { $zipFilePath = $realpathResult; } else { throw new \Exception("Error receiving uploaded file"); } if (!file_exists($realpathResult)) { throw new \Exception("Error file '{$zipFilePath}' does not exist."); } $basename = basename($zipFilePath); $pathinfo = pathinfo($basename); $extension_1 = isset($pathinfo['extension']) ? $pathinfo['extension'] : 'NOEXT'; // Handle .tar.gz, .tar.bz2, etc. by checking if there's another extension "inside" the first one $basename_without_ext = $pathinfo['filename']; $pathinfo = pathinfo($basename_without_ext); $extension_2 = isset($pathinfo['extension']) ? $pathinfo['extension'] : 'NOEXT'; // $extension_2 will be 'tar' if the file was a .tar.gz, .tar.bz2, etc. if ($extension_2 == "tar") { // We don't handle tarball formats... yet. throw new \Exception("Sorry, the ." . $extension_2 . "." . $extension_1 . " format isn't allowed"); } switch ($extension_1) { case "zip": $cmd = 'unzip ' . escapeshellarg($zipFilePath) . " -d " . escapeshellarg($destDir); break; case "zipx": case "7z": $cmd = '7z x ' . escapeshellarg($zipFilePath) . " -o" . escapeshellarg($destDir); break; default: throw new \Exception("Sorry, the ." . $extension_1 . " format isn't allowed"); break; } FileUtilities::createAllFolders($destDir); $destFilesBeforeUnpacking = scandir($destDir); // ensure non-roman filesnames are returned $cmd = 'LANG="en_US.UTF-8" ' . $cmd; $output = array(); $retcode = 0; exec($cmd, $output, $retcode); if ($retcode) { if ($retcode != 1 || $retcode == 1 && strstr(end($output), 'failed setting times/attribs') == false) { throw new \Exception("Uncompressing archive file failed: " . print_r($output, true)); } } // If the .zip contained just one top-level folder with all contents below that folder, // "promote" the contents up one level so that $destDir contains all the .zip's contents. $destFilesAfterUnpacking = scandir($destDir); if (count($destFilesAfterUnpacking) == count($destFilesBeforeUnpacking) + 1) { $diff = array_values(array_diff($destFilesAfterUnpacking, $destFilesBeforeUnpacking)); $zipTopLevel = $diff[0]; if (is_dir($destDir . "/" . $zipTopLevel)) { FileUtilities::promoteDirContents($destDir . "/" . $zipTopLevel); } } }
$changeDatabase = false; // process xml into a php data structure, organized by language $xml = simplexml_load_file($xmlFilePath); $lang = $argv[2]; $version = $argv[3]; $projectCode = "semdom-{$lang}-{$semdomVersion}"; $projectName = "Semdom {$lang} Project"; $appName = LfProjectModel::SEMDOMTRANS_APP; $website = new Website($domain, Website::LANGUAGEFORGE); // if a previous project for that language and semantic domain version exists, DO NOT IMPORT $previousProject = new SemDomTransProjectModel(); $previousProject->readByProperties(array("languageIsoCode" => $lang, "semdomVersion" => $semdomVersion)); if ($previousProject->id->asString() == "") { $sourceProject = new SemDomTransProjectModel(); $sourceProject->readByCode("en"); $projectID = ProjectCommands::createProject($projectName, $projectCode, $appName, $userId, $website); $projectModel = new SemDomTransProjectModel($projectID); $newXmlFilePath = $projectModel->getAssetsFolderPath() . '/' . basename($xmlFilePath); FileUtilities::createAllFolders($projectModel->getAssetsFolderPath()); print "copying {$xmlFilePath} to {$newXmlFilePath}\n"; copy($xmlFilePath, $newXmlFilePath); $projectModel->xmlFilePath = $newXmlFilePath; $projectModel->languageIsoCode = $lang; $projectModel->semdomVersion = $semdomVersion; $projectModel->sourceLanguageProjectId = $sourceProject->id->asString(); $projectModel->write(); $importer = new SemDomXMLImporter($xmlFilePath, $projectModel, false, $isEnglish); $importer->run(); } else { echo "Project exists already" . "\n"; }
unlink($filePath); } } 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)
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); }
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); }
<?php require_once 'e2eTestConfig.php'; use Api\Model\Languageforge\Lexicon\LexiconProjectModel; use Api\Model\Languageforge\Lexicon\Command\LexUploadCommands; use Api\Model\ProjectModel; use Palaso\Utilities\FileUtilities; $constants = json_decode(file_get_contents(TestPath . '/testConstants.json'), true); // cleanup test assets folder $project = new ProjectModel(); $project->readByProperties(array('projectCode' => $constants['testProjectCode'])); $testProject = $project->getById($project->id->asString()); $assetsFolderPath = $testProject->getAssetsFolderPath(); FileUtilities::removeFolderAndAllContents($assetsFolderPath); // cleanup mocked uploaded zip import (jpg file) $tmpFilePath = sys_get_temp_dir() . '/' . $constants['testMockJpgImportFile']['name']; @unlink($tmpFilePath); // cleanup mocked uploaded zip import (zip file) $tmpFilePath = sys_get_temp_dir() . '/' . $constants['testMockZipImportFile']['name']; @unlink($tmpFilePath);
/** * @return string Full path of the projects assets folder */ public function getAssetsFolderPath() { $folderPath = APPPATH . $this->getAssetsRelativePath(); FileUtilities::createAllFolders($folderPath); return $folderPath; }
/** * 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; }
/** * Cleanup assets folder upon project deletion */ protected function cleanup() { FileUtilities::removeFolderAndAllContents($this->getAssetsFolderPath()); }
/** * @param string $projectCode * @param string $statePath * @param string $sendQueuePath * @param string $pidFilePath * @param string $command * @return bool true if notification file is created (or already exists) and LFMerge started, false otherwise * @throws \Exception */ public static function notificationSendRequest($projectCode, $statePath = null, $sendQueuePath = null, $pidFilePath = null, $command = null) { $project = new LexProjectModel(); if (!$project->readByProperty('projectCode', $projectCode)) { return false; } if (!$project->hasSendReceive()) { return false; } $status = self::getProjectStatus($project->id->asString(), $statePath); if (!$status || !array_key_exists('uncommittedEditCount', $status)) { return false; } if ($status['uncommittedEditCount'] <= 0) { return false; } if (is_null($sendQueuePath)) { $sendQueuePath = self::getLFMergePaths()->sendQueuePath; } $notificationFilePath = $sendQueuePath . '/' . $project->projectCode . '.notification'; if (!file_exists($notificationFilePath) || !is_file($notificationFilePath)) { FileUtilities::createAllFolders($sendQueuePath); if (file_put_contents($notificationFilePath, '') === false) { throw new \Exception('Cannot write to Send/Receive Send Queue. Contact the website administrator.'); } } return self::startLFMergeIfRequired($project->id->asString(), $pidFilePath, $command); }