/** * @test */ public function getLanguagesScansFormatDirectoryAndReturnsLanguagesAsStrings() { $formatPath = \vfsStream::url('testDirectory') . '/'; \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($formatPath . 'en'); $format = new \TYPO3\FLOW3\Package\Documentation\Format('DocBook', $formatPath); $availableLanguages = $format->getAvailableLanguages(); $this->assertEquals(array('en'), $availableLanguages); }
/** * @test */ public function getDocumentationFormatsScansDocumentationDirectoryAndReturnsDocumentationFormatObjectsIndexedByFormatName() { $documentationPath = \vfsStream::url('testDirectory') . '/'; $mockPackage = $this->getMock('TYPO3\\FLOW3\\Package\\PackageInterface'); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($documentationPath . 'DocBook/en'); $documentation = new \TYPO3\FLOW3\Package\Documentation($mockPackage, 'Manual', $documentationPath); $documentationFormats = $documentation->getDocumentationFormats(); $this->assertEquals('DocBook', $documentationFormats['DocBook']->getFormatName()); }
/** */ public function setUp() { \vfsStreamWrapper::register(); \vfsStreamWrapper::setRoot(new \vfsStreamDirectory('Foo')); $temporaryDirectoryBase = realpath(sys_get_temp_dir()) . '/' . str_replace('\\', '_', __CLASS__); $this->temporaryDirectoryPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($temporaryDirectoryBase, 'FLOW3PrivateResourcesPublishingAspectTestTemporaryDirectory')); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($this->temporaryDirectoryPath); $this->publishPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($temporaryDirectoryBase, 'FLOW3PrivateResourcesPublishingAspectTestPublishDirectory')); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($this->publishPath); }
/** * Loads all files in $sourcePath, transforms and stores them in $targetPath * * @param string $sourcePath Absolute path of the source file directory * @param string $targetPath Absolute path of the target file directory * @return void * @author Bastian Waidelich <*****@*****.**> */ public function processFiles($sourcePath, $targetPath) { $this->setSourcePath($sourcePath); $this->setTargetPath($targetPath); if ($this->emptyTargetPath) { \TYPO3\FLOW3\Utility\Files::emptyDirectoryRecursively($this->targetPath); } $this->findSourceFilenames(); $codeProcessor = $this->objectManager->get($this->codeProcessorClassName); $codeProcessor->setExtensionKey($this->extensionKey); $unusedReplacePairs = $this->replacePairs; foreach ($this->sourceFilenames as $sourceFilename) { $classCode = \TYPO3\FLOW3\Utility\Files::getFileContents($sourceFilename); $relativeFilePath = substr($sourceFilename, strlen($this->sourcePath) + 1); if (!$this->shouldFileBeProcessed($relativeFilePath)) { continue; } $targetFilename = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($this->targetPath, $relativeFilePath)); $targetFilename = $this->renameTargetFilename($targetFilename); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively(dirname($targetFilename)); $codeProcessor->setClassCode($classCode); $fileSpecificReplacePairs = array(); $unusedFileSpecificReplacePairs = array(); if (isset($this->fileSpecificReplacePairs[$relativeFilePath]) && is_array($this->fileSpecificReplacePairs[$relativeFilePath])) { $fileSpecificReplacePairs = $this->fileSpecificReplacePairs[$relativeFilePath]; $unusedFileSpecificReplacePairs = $fileSpecificReplacePairs; } file_put_contents($targetFilename, $codeProcessor->processCode($this->replacePairs, $fileSpecificReplacePairs, $unusedReplacePairs, $unusedFileSpecificReplacePairs)); if (count($unusedFileSpecificReplacePairs)) { /*\TYPO3\FLOW3\var_dump( $unusedFileSpecificReplacePairs, 'Unused file specific replace pairs' );*/ //echo '--- Unused file specific replace pairs: ' . $relativeFilePath . chr(10); //var_dump($unusedFileSpecificReplacePairs); } } // Additional classes if (count($unusedReplacePairs)) { /*\TYPO3\FLOW3\var_dump( $unusedReplacePairs, 'Unused replace pairs' );*/ //echo '--- Unused replace pairs: ' . chr(10); //var_dump($unusedReplacePairs); } }
/** * Sets a reference to the cache frontend which uses this backend and * initializes the default cache directory. * * @param \TYPO3\FLOW3\Cache\Frontend\FrontendInterface $cache The cache frontend * @return void * @throws \TYPO3\FLOW3\Cache\Exception */ public function setCache(FrontendInterface $cache) { parent::setCache($cache); $codeOrData = $cache instanceof PhpFrontend ? 'Code' : 'Data'; $cacheDirectory = $this->environment->getPathToTemporaryDirectory() . 'Cache/' . $codeOrData . '/' . $this->cacheIdentifier . '/'; if (!is_writable($cacheDirectory)) { try { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($cacheDirectory); } catch (\TYPO3\FLOW3\Utility\Exception $exception) { throw new \TYPO3\FLOW3\Cache\Exception('The cache directory "' . $cacheDirectory . '" could not be created.', 1264426237); } } if (!is_dir($cacheDirectory) && !is_link($cacheDirectory)) { throw new \TYPO3\FLOW3\Cache\Exception('The cache directory "' . $cacheDirectory . '" does not exist.', 1203965199); } if (!is_writable($cacheDirectory)) { throw new \TYPO3\FLOW3\Cache\Exception('The cache directory "' . $cacheDirectory . '" is not writable.', 1203965200); } $this->cacheDirectory = $cacheDirectory; $this->cacheEntryFileExtension = $cache instanceof PhpFrontend ? '.php' : ''; if (strlen($this->cacheDirectory) + 23 > $this->environment->getMaximumPathLength()) { throw new \TYPO3\FLOW3\Cache\Exception('The length of the temporary cache path "' . $this->cacheDirectory . '" exceeds the maximum path length of ' . ($this->environment->getMaximumPathLength() - 23) . '. Please consider setting the temporaryDirectoryBase option to a shorter path. ', 1248710426); } }
/** * Persists a key to the file system * * @param string $name * @param string $password * @return void * @throws \TYPO3\FLOW3\Security\Exception */ protected function persistKey($name, $password) { $hashedPassword = $this->hashService->hashPassword($password, $this->passwordHashingStrategy); $keyPathAndFilename = $this->getKeyPathAndFilename($name); if (!is_dir($this->getPath())) { Files::createDirectoryRecursively($this->getPath()); } $result = file_put_contents($keyPathAndFilename, $hashedPassword); if ($result === FALSE) { throw new \TYPO3\FLOW3\Security\Exception(sprintf('The key could not be stored ("%s").', $keyPathAndFilename), 1305812921); } }
/** * Initializes the PHP session according to the settings provided. * * @return void */ public function initializeObject() { if (!empty($this->settings['session']['PhpSession']['name'])) { session_name($this->settings['session']['PhpSession']['name']); } $cookieParameters = session_get_cookie_params(); if (!empty($this->settings['session']['PhpSession']['cookie']['domain'])) { $cookieParameters['domain'] = $this->settings['session']['PhpSession']['cookie']['domain']; } if (!empty($this->settings['session']['PhpSession']['cookie']['lifetime'])) { $cookieParameters['lifetime'] = $this->settings['session']['PhpSession']['cookie']['lifetime']; } if (!empty($this->settings['session']['PhpSession']['cookie']['path'])) { $cookieParameters['path'] = $this->settings['session']['PhpSession']['cookie']['path']; } if (!empty($this->settings['session']['PhpSession']['cookie']['secure'])) { $cookieParameters['secure'] = $this->settings['session']['PhpSession']['cookie']['secure']; } if (!empty($this->settings['session']['PhpSession']['cookie']['httponly'])) { $cookieParameters['httponly'] = $this->settings['session']['PhpSession']['cookie']['httponly']; } session_set_cookie_params($cookieParameters['lifetime'], $cookieParameters['path'], $cookieParameters['domain'], $cookieParameters['secure'], $cookieParameters['httponly']); if (empty($this->settings['session']['PhpSession']['savePath'])) { $sessionsPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($this->environment->getPathToTemporaryDirectory(), 'Sessions')); } else { $sessionsPath = $this->settings['session']['PhpSession']['savePath']; } if (!file_exists($sessionsPath)) { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($sessionsPath); } session_save_path($sessionsPath); }
/** * Saves the current configuration into a cache file and creates a cache inclusion script * in the context's Configuration directory. * * @return void * @throws \TYPO3\FLOW3\Configuration\Exception */ protected function saveConfigurationCache() { $configurationCachePath = $this->environment->getPathToTemporaryDirectory() . 'Configuration/'; if (!file_exists($configurationCachePath)) { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($configurationCachePath); } $cachePathAndFilename = $configurationCachePath . str_replace('/', '_', (string) $this->context) . 'Configurations.php'; $flow3RootPath = FLOW3_PATH_ROOT; $includeCachedConfigurationsCode = <<<EOD <?php if (FLOW3_PATH_ROOT !== '{$flow3RootPath}' || !file_exists('{$cachePathAndFilename}')) { \tunlink(__FILE__); \treturn array(); } return require '{$cachePathAndFilename}'; ?> EOD; file_put_contents($cachePathAndFilename, '<?php return ' . var_export($this->configurations, TRUE) . '?>'); if (!is_dir(dirname($this->includeCachedConfigurationsPathAndFilename)) && !is_link(dirname($this->includeCachedConfigurationsPathAndFilename))) { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively(dirname($this->includeCachedConfigurationsPathAndFilename)); } file_put_contents($this->includeCachedConfigurationsPathAndFilename, $includeCachedConfigurationsCode); if (!file_exists($this->includeCachedConfigurationsPathAndFilename)) { throw new \TYPO3\FLOW3\Configuration\Exception(sprintf('Could not write configuration cache file "%s". Check file permissions for the parent directory.', $this->includeCachedConfigurationsPathAndFilename), 1323339284); } }
/** * Factory method which creates an EntityManager. * * @return \Doctrine\ORM\EntityManager */ public function create() { $config = new \Doctrine\ORM\Configuration(); $config->setClassMetadataFactoryName('TYPO3\\FLOW3\\Persistence\\Doctrine\\Mapping\\ClassMetadataFactory'); if (class_exists($this->settings['doctrine']['cacheImplementation'])) { // safeguard against apc being disabled in CLI... if ($this->settings['doctrine']['cacheImplementation'] !== 'Doctrine\\Common\\Cache\\ApcCache' || function_exists('apc_fetch')) { $cache = new $this->settings['doctrine']['cacheImplementation'](); $config->setMetadataCacheImpl($cache); $config->setQueryCacheImpl($cache); } } if (class_exists($this->settings['doctrine']['sqlLogger'])) { $config->setSQLLogger(new $this->settings['doctrine']['sqlLogger']()); } // must use ObjectManager in compile phase... $flow3AnnotationDriver = $this->objectManager->get('TYPO3\\FLOW3\\Persistence\\Doctrine\\Mapping\\Driver\\Flow3AnnotationDriver'); $config->setMetadataDriverImpl($flow3AnnotationDriver); $proxyDirectory = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($this->environment->getPathToTemporaryDirectory(), 'Doctrine/Proxies')); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($proxyDirectory); $config->setProxyDir($proxyDirectory); $config->setProxyNamespace('TYPO3\\FLOW3\\Persistence\\Doctrine\\Proxies'); $config->setAutoGenerateProxyClasses(FALSE); $entityManager = \Doctrine\ORM\EntityManager::create($this->settings['backendOptions'], $config); $flow3AnnotationDriver->setEntityManager($entityManager); return $entityManager; }
/** * Returns the publish path and filename to be used to publish the specified persistent resource * * @FLOW3\Around("method(TYPO3\FLOW3\Resource\Publishing\FileSystemPublishingTarget->buildPersistentResourcePublishPathAndFilename()) && setting(TYPO3.FLOW3.security.enable)") * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return mixed Result of the target method */ public function rewritePersistentResourcePublishPathAndFilenameForPrivateResources(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $resource = $joinPoint->getMethodArgument('resource'); $configuration = $resource->getPublishingConfiguration(); $returnFilename = $joinPoint->getMethodArgument('returnFilename'); if ($configuration === NULL || $configuration instanceof \TYPO3\FLOW3\Security\Authorization\Resource\SecurityPublishingConfiguration === FALSE) { return $joinPoint->getAdviceChain()->proceed($joinPoint); } $publishingPath = FALSE; $allowedRoles = $configuration->getAllowedRoles(); if (count(array_intersect($allowedRoles, $this->securityContext->getRoles())) > 0) { $publishingPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($joinPoint->getProxy()->getResourcesPublishingPath(), 'Persistent/', $this->session->getID())) . '/'; $filename = $resource->getResourcePointer()->getHash() . '.' . $resource->getFileExtension(); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($publishingPath); $this->accessRestrictionPublisher->publishAccessRestrictionsForPath($publishingPath); if ($this->settings['resource']['publishing']['fileSystem']['mirrorMode'] === 'link') { foreach ($allowedRoles as $role) { $roleDirectory = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($this->environment->getPathToTemporaryDirectory(), 'PrivateResourcePublishing/', $role)); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($roleDirectory); if (file_exists($publishingPath . $role)) { if (\TYPO3\FLOW3\Utility\Files::is_link(\TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))) && realpath(\TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))) === $roleDirectory) { continue; } unlink($publishingPath . $role); symlink($roleDirectory, \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))); } else { symlink($roleDirectory, \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $role))); } } $publishingPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $allowedRoles[0])) . '/'; } if ($returnFilename === TRUE) { $publishingPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($publishingPath, $filename)); } } return $publishingPath; }
/** * Stores the current reflection data related to classes of the specified package * in the PrecompiledReflectionData directory for the current context. * * This method is used by the package manager. * * @param string $packageKey * @return void */ public function freezePackageReflection($packageKey) { $package = $this->packageManager->getPackage($packageKey); $packageNamespace = $package->getPackageNamespace() . '\\'; $packageNamespaceLength = strlen($packageNamespace); $reflectionData = array('classReflectionData' => $this->classReflectionData, 'classSchemata' => $this->classSchemata, 'annotatedClasses' => $this->annotatedClasses, 'classesByMethodAnnotations' => $this->classesByMethodAnnotations); foreach (array_keys($reflectionData['classReflectionData']) as $className) { if (substr($className, 0, $packageNamespaceLength) !== $packageNamespace) { unset($reflectionData['classReflectionData'][$className]); } } foreach (array_keys($reflectionData['classSchemata']) as $className) { if (substr($className, 0, $packageNamespaceLength) !== $packageNamespace) { unset($reflectionData['classSchemata'][$className]); } } foreach (array_keys($reflectionData['annotatedClasses']) as $className) { if (substr($className, 0, $packageNamespaceLength) !== $packageNamespace) { unset($reflectionData['annotatedClasses'][$className]); } } if (isset($reflectionData['classesByMethodAnnotations'])) { foreach ($reflectionData['classesByMethodAnnotations'] as $annotationClassName => $classNames) { foreach ($classNames as $index => $className) { if (substr($className, 0, $packageNamespaceLength) !== $packageNamespace) { unset($reflectionData['classesByMethodAnnotations'][$annotationClassName][$index]); } } } } $precompiledReflectionStoragePath = $this->getPrecompiledReflectionStoragePath(); if (!is_dir($precompiledReflectionStoragePath)) { Files::createDirectoryRecursively($precompiledReflectionStoragePath); } $pathAndFilename = $precompiledReflectionStoragePath . $packageKey . '.dat'; file_put_contents($pathAndFilename, extension_loaded('igbinary') ? igbinary_serialize($reflectionData) : serialize($reflectionData)); }
/** * Import a package from a remote location * * Imports the specified package from a remote git repository. The imported package will not be activated automatically. * Currently only packages located at forge.typo3.org are supported. Note that the git binary must be available. * * @param string $packageKey The package key of the package to import. * @return \TYPO3\FLOW3\Package\PackageInterface The imported package * @throws \TYPO3\FLOW3\Package\Exception\PackageKeyAlreadyExistsException * @throws \TYPO3\FLOW3\Package\Exception\PackageRepositoryException */ public function importPackage($packageKey) { if ($this->isPackageAvailable($packageKey)) { throw new \TYPO3\FLOW3\Package\Exception\PackageKeyAlreadyExistsException('The package already exists.', 1315223754); } exec($this->settings['package']['git']['gitBinary'] . ' --version', $output, $result); if ($result !== 0) { throw new \TYPO3\FLOW3\Package\Exception\PackageRepositoryException('Could not execute the git command line tool. Make sure to configure the right path in TYPO3:FLOW3:package:git:gitBinary.', 1315223755); } unset($output); $packagesPath = Files::getUnixStylePath(Files::concatenatePaths(array($this->packagesBasePath, 'Application'))); $packagePath = Files::concatenatePaths(array($packagesPath, $packageKey)) . '/'; Files::createDirectoryRecursively($packagePath); $gitCommand = ' clone --recursive git://git.typo3.org/FLOW3/Packages/' . $packageKey . '.git ' . $packagePath; exec($this->settings['package']['git']['gitBinary'] . $gitCommand, $output, $result); if ($result !== 0) { throw new \TYPO3\FLOW3\Package\Exception\PackageRepositoryException('Could not clone the remote package.' . PHP_EOL . 'git ' . $gitCommand, 1315223852); } $package = new Package($packageKey, $packagePath); $this->packageStatesConfiguration['packages'][$packageKey]['state'] = 'inactive'; $this->packageStatesConfiguration['packages'][$packageKey]['packagePath'] = substr($package->getPackagePath(), strlen($this->packagesBasePath)); $this->sortAndSavePackageStates(); return $package; }
/** * Connect to the database * * @return void * @throws \TYPO3\FLOW3\Persistence\Exception if the connection cannot be established */ protected function connect() { try { $splitdsn = explode(':', $this->dataSourceName, 2); $this->pdoDriver = $splitdsn[0]; if ($this->pdoDriver === 'sqlite' && !file_exists($splitdsn[1])) { if (!file_exists(dirname($splitdsn[1]))) { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively(dirname($splitdsn[1])); } $this->databaseHandle = new \PDO($this->dataSourceName, $this->username, $this->password); $this->createCacheTables(); } else { $this->databaseHandle = new \PDO($this->dataSourceName, $this->username, $this->password); } $this->databaseHandle->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); if ($this->pdoDriver === 'mysql') { $this->databaseHandle->exec('SET SESSION sql_mode=\'ANSI\';'); } } catch (\PDOException $e) { throw new \TYPO3\FLOW3\Persistence\Exception('Could not connect to cache table with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(), 1334736164); } }
/** * @param \Doctrine\DBAL\Migrations\Configuration\Configuration $configuration * @param string $up * @param string $down * @return string * @throws \RuntimeException */ protected function writeMigrationClassToFile(\Doctrine\DBAL\Migrations\Configuration\Configuration $configuration, $up, $down) { $namespace = $configuration->getMigrationsNamespace(); $className = 'Version' . date('YmdHis'); $up = $up === NULL ? '' : "\n\t\t" . implode("\n\t\t", explode("\n", $up)); $down = $down === NULL ? '' : "\n\t\t" . implode("\n\t\t", explode("\n", $down)); $path = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array($configuration->getMigrationsDirectory(), $className . '.php')); try { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively(dirname($path)); } catch (\TYPO3\FLOW3\Utility\Exception $exception) { throw new \RuntimeException(sprintf('Migration target directory "%s" does not exist.', dirname($path)), 1303298536, $exception); } $code = <<<EOT <?php namespace {$namespace}; use Doctrine\\DBAL\\Migrations\\AbstractMigration, \tDoctrine\\DBAL\\Schema\\Schema; /** * Auto-generated Migration: Please modify to your need! */ class {$className} extends AbstractMigration { \t/** \t * @param Schema \$schema \t * @return void \t */ \tpublic function up(Schema \$schema) { \t\t\t// this up() migration is autogenerated, please modify it to your needs{$up} \t} \t/** \t * @param Schema \$schema \t * @return void \t */ \tpublic function down(Schema \$schema) { \t\t\t// this down() migration is autogenerated, please modify it to your needs{$down} \t} } ?> EOT; file_put_contents($path, $code); return $path; }
/** * @test */ public function unlinkProperlyRemovesSymlinksPointingToDirectories() { $targetPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array(dirname(tempnam($this->temporaryDirectory, '')), 'FLOW3FilesTestDirectory')); if (!is_dir($targetPath)) { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($targetPath); } $linkPath = \TYPO3\FLOW3\Utility\Files::concatenatePaths(array(dirname(tempnam($this->temporaryDirectory, '')), 'FLOW3FilesTestDirectoryLink')); if (is_dir($linkPath)) { \TYPO3\FLOW3\Utility\Files::removeDirectoryRecursively($linkPath); } symlink($targetPath, $linkPath); $this->assertTrue(\TYPO3\FLOW3\Utility\Files::unlink($linkPath)); $this->assertTrue(file_exists($targetPath)); $this->assertFalse(file_exists($linkPath)); }
/** * Carries out all actions necessary to prepare the logging backend, such as opening * the log file or opening a database connection. * * @return void * @throws \TYPO3\FLOW3\Log\Exception\CouldNotOpenResourceException * @api */ public function open() { $this->severityLabels = array(LOG_EMERG => 'EMERGENCY', LOG_ALERT => 'ALERT ', LOG_CRIT => 'CRITICAL ', LOG_ERR => 'ERROR ', LOG_WARNING => 'WARNING ', LOG_NOTICE => 'NOTICE ', LOG_INFO => 'INFO ', LOG_DEBUG => 'DEBUG '); if (file_exists($this->logFileUrl) && $this->maximumLogFileSize > 0 && filesize($this->logFileUrl) > $this->maximumLogFileSize) { $this->rotateLogFile(); } if (file_exists($this->logFileUrl)) { $this->fileHandle = fopen($this->logFileUrl, 'ab'); } else { $logPath = dirname($this->logFileUrl); if (!is_dir($logPath) && !is_link($logPath)) { if ($this->createParentDirectories === FALSE) { throw new \TYPO3\FLOW3\Log\Exception\CouldNotOpenResourceException('Could not open log file "' . $this->logFileUrl . '" for write access because the parent directory does not exist.', 1243931200); } \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($logPath); } $this->fileHandle = fopen($this->logFileUrl, 'ab'); if ($this->fileHandle === FALSE) { throw new \TYPO3\FLOW3\Log\Exception\CouldNotOpenResourceException('Could not open log file "' . $this->logFileUrl . '" for write access.', 1243588980); } $streamMeta = stream_get_meta_data($this->fileHandle); if ($streamMeta['wrapper_type'] === 'plainfile') { fclose($this->fileHandle); chmod($this->logFileUrl, 0666); $this->fileHandle = fopen($this->logFileUrl, 'ab'); } } if ($this->fileHandle === FALSE) { throw new \TYPO3\FLOW3\Log\Exception\CouldNotOpenResourceException('Could not open log file "' . $this->logFileUrl . '" for write access.', 1229448440); } }
/** * Depending on the settings of this publishing target copies the specified file * or creates a symbolic link. * * @param string $sourcePathAndFilename * @param string $targetPathAndFilename * @param boolean $createDirectoriesIfNecessary * @return void * @throws \TYPO3\FLOW3\Resource\Exception */ protected function mirrorFile($sourcePathAndFilename, $targetPathAndFilename, $createDirectoriesIfNecessary = FALSE) { if ($createDirectoriesIfNecessary === TRUE) { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively(dirname($targetPathAndFilename)); } switch ($this->settings['resource']['publishing']['fileSystem']['mirrorMode']) { case 'copy': copy($sourcePathAndFilename, $targetPathAndFilename); touch($targetPathAndFilename, filemtime($sourcePathAndFilename)); break; case 'link': if (file_exists($targetPathAndFilename)) { if (\TYPO3\FLOW3\Utility\Files::is_link($targetPathAndFilename) && $this->realpath($targetPathAndFilename) === $this->realpath($sourcePathAndFilename)) { break; } unlink($targetPathAndFilename); symlink($sourcePathAndFilename, $targetPathAndFilename); } else { symlink($sourcePathAndFilename, $targetPathAndFilename); } break; default: throw new \TYPO3\FLOW3\Resource\Exception('An invalid mirror mode (' . $this->settings['resource']['publishing']['fileSystem']['mirrorMode'] . ') has been configured.', 1256133400); } if (!file_exists($targetPathAndFilename)) { throw new \TYPO3\FLOW3\Resource\Exception('The resource "' . $sourcePathAndFilename . '" could not be mirrored.', 1207255453); } }
/** * Creates FLOW3's temporary directory - or at least asserts that it exists and is * writable. * * For each FLOW3 Application Context, we create an extra temporary folder, * and for nested contexts, the folders are prefixed with "SubContext" to * avoid ambiguity, and look like: Data/Temporary/Production/SubContextLive * * @param string $temporaryDirectoryBase Full path to the base for the temporary directory * @return string The full path to the temporary directory * @throws \TYPO3\FLOW3\Utility\Exception if the temporary directory could not be created or is not writable */ protected function createTemporaryDirectory($temporaryDirectoryBase) { $temporaryDirectoryBase = \TYPO3\FLOW3\Utility\Files::getUnixStylePath($temporaryDirectoryBase); if (substr($temporaryDirectoryBase, -1, 1) !== '/') { $temporaryDirectoryBase .= '/'; } $temporaryDirectory = $temporaryDirectoryBase . str_replace('/', '/SubContext', (string) $this->context) . '/'; if (!is_dir($temporaryDirectory) && !is_link($temporaryDirectory)) { try { \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($temporaryDirectory); } catch (\TYPO3\FLOW3\Error\Exception $exception) { throw new \TYPO3\FLOW3\Utility\Exception('The temporary directory "' . $temporaryDirectory . '" could not be created. Please make sure permissions are correct for this path or define another temporary directory in your Settings.yaml with the path "TYPO3.FLOW3.utility.environment.temporaryDirectoryBase".', 1335382361); } } if (!is_writable($temporaryDirectory)) { throw new \TYPO3\FLOW3\Utility\Exception('The temporary directory "' . $temporaryDirectory . '" is not writable. Please make this directory writable or define another temporary directory in your Settings.yaml with the path "TYPO3.FLOW3.utility.environment.temporaryDirectoryBase".', 1216287176); } return $temporaryDirectory; }
/** * Check for implementations of TYPO3\FLOW3\Resource\Streams\StreamWrapperInterface and * register them. * * @return void */ public function initialize() { $streamWrapperClassNames = $this->reflectionService->getAllImplementationClassNamesForInterface('TYPO3\\FLOW3\\Resource\\Streams\\StreamWrapperInterface'); foreach ($streamWrapperClassNames as $streamWrapperClassName) { $scheme = $streamWrapperClassName::getScheme(); if (in_array($scheme, stream_get_wrappers())) { stream_wrapper_unregister($scheme); } stream_wrapper_register($scheme, '\\TYPO3\\FLOW3\\Resource\\Streams\\StreamWrapperAdapter'); \TYPO3\FLOW3\Resource\Streams\StreamWrapperAdapter::registerStreamWrapper($scheme, $streamWrapperClassName); } // For now this URI is hardcoded, but might be manageable in the future // if additional persistent resources storages are supported. $this->persistentResourcesStorageBaseUri = FLOW3_PATH_DATA . 'Persistent/Resources/'; \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively($this->persistentResourcesStorageBaseUri); $this->importedResources = new \SplObjectStorage(); }
/** * @test */ public function publishStaticResourcesDoesNotMirrorAFileIfItAlreadyExistsAndTheModificationTimeIsEqualOrNewer() { mkdir('vfs://Foo/Sources'); file_put_contents('vfs://Foo/Sources/file1.txt', 1); file_put_contents('vfs://Foo/Sources/file2.txt', 1); file_put_contents('vfs://Foo/Sources/file3.txt', 1); \TYPO3\FLOW3\Utility\Files::createDirectoryRecursively('vfs://Foo/Web/_Resources/Static/Bar'); file_put_contents('vfs://Foo/Web/_Resources/Static/Bar/file2.txt', 1); \vfsStreamWrapper::getRoot()->getChild('Web/_Resources/Static/Bar/file2.txt')->lastModified(time() - 5); file_put_contents('vfs://Foo/Web/_Resources/Static/Bar/file3.txt', 1); $mirrorFileCallback = function ($sourcePathAndFilename, $targetPathAndFilename) { if ($sourcePathAndFilename === 'vfs://Foo/Sources/file3.txt') { throw new \Exception('file3.txt should not have been mirrored.'); } }; $publishingTarget = $this->getAccessibleMock('TYPO3\\FLOW3\\Resource\\Publishing\\FileSystemPublishingTarget', array('mirrorFile', 'realpath')); $publishingTarget->expects($this->any())->method('realpath')->will($this->returnCallback(function ($path) { return $path; })); $publishingTarget->_set('resourcesPublishingPath', 'vfs://Foo/Web/_Resources/'); $publishingTarget->expects($this->exactly(2))->method('mirrorFile')->will($this->returnCallback($mirrorFileCallback)); $result = $publishingTarget->publishStaticResources('vfs://Foo/Sources', 'Bar'); $this->assertTrue($result); }