/** * Detects if the package contains a package file and returns the path and classname. * * @param string $packageKey The package key * @param string $absolutePackagePath Absolute path to the package * @return array The path to the package file and classname for this package or an empty array if none was found. * @throws Exception\CorruptPackageException * @throws Exception\InvalidPackagePathException */ public function detectFlowPackageFilePath($packageKey, $absolutePackagePath) { if (!is_dir($absolutePackagePath)) { throw new Exception\InvalidPackagePathException(sprintf('The given package path "%s" is not a readable directory.', $absolutePackagePath), 1445904440); } $composerManifest = ComposerUtility::getComposerManifest($absolutePackagePath); if (!ComposerUtility::isFlowPackageType(isset($composerManifest['type']) ? $composerManifest['type'] : '')) { return []; } $possiblePackageClassPaths = [Files::concatenatePaths(['Classes', 'Package.php']), Files::concatenatePaths(['Classes', str_replace('.', '/', $packageKey), 'Package.php'])]; $foundPackageClassPaths = array_filter($possiblePackageClassPaths, function ($packageClassPathAndFilename) use($absolutePackagePath) { $absolutePackageClassPath = Files::concatenatePaths([$absolutePackagePath, $packageClassPathAndFilename]); return is_file($absolutePackageClassPath); }); if ($foundPackageClassPaths === []) { return []; } if (count($foundPackageClassPaths) > 1) { throw new Exception\CorruptPackageException(sprintf('The package "%s" contains multiple possible "Package.php" files. Please make sure that only one "Package.php" exists in the autoload root(s) of your Flow package.', $packageKey), 1457454840); } $packageClassPathAndFilename = reset($foundPackageClassPaths); $absolutePackageClassPath = Files::concatenatePaths([$absolutePackagePath, $packageClassPathAndFilename]); $packageClassContents = file_get_contents($absolutePackageClassPath); $packageClassName = (new PhpAnalyzer($packageClassContents))->extractFullyQualifiedClassName(); if ($packageClassName === null) { throw new Exception\CorruptPackageException(sprintf('The package "%s" does not contain a valid package class. Check if the file "%s" really contains a class.', $packageKey, $packageClassPathAndFilename), 1327587091); } return ['className' => $packageClassName, 'pathAndFilename' => $packageClassPathAndFilename]; }
/** * Builds a temporary directory to work on. * @return void */ protected function prepareTemporaryDirectory() { $this->temporaryDirectory = Files::concatenatePaths(array(FLOW_PATH_DATA, 'Temporary', 'Testing', str_replace('\\', '_', __CLASS__))); if (!file_exists($this->temporaryDirectory)) { Files::createDirectoryRecursively($this->temporaryDirectory); } }
/** * @test */ public function getPathToTemporaryDirectoryReturnsAnExistingPath() { $environment = new Environment(new ApplicationContext('Testing')); $environment->setTemporaryDirectoryBase(Files::concatenatePaths([sys_get_temp_dir(), 'FlowEnvironmentTest'])); $path = $environment->getPathToTemporaryDirectory(); $this->assertTrue(file_exists($path), 'The temporary path does not exist.'); }
/** * @return void */ protected function writeComposerManifest() { $composerJsonFilename = Files::concatenatePaths(array($this->targetPackageData['path'], 'composer.json')); if (file_exists($composerJsonFilename)) { return; } $manifest = array(); $nameParts = explode('.', $this->targetPackageData['packageKey']); $vendor = array_shift($nameParts); $manifest['name'] = strtolower($vendor . '/' . implode('-', $nameParts)); switch ($this->targetPackageData['category']) { case 'Application': $manifest['type'] = 'typo3-flow-package'; break; default: $manifest['type'] = strtolower('typo3-flow-' . $this->targetPackageData['category']); } $manifest['description'] = $this->targetPackageData['meta']['description']; $manifest['version'] = $this->targetPackageData['meta']['version']; $manifest['require'] = array('typo3/flow' => '*'); $manifest['autoload'] = array('psr-0' => array(str_replace('.', '\\', $this->targetPackageData['packageKey']) => 'Classes')); if (defined('JSON_PRETTY_PRINT')) { file_put_contents($composerJsonFilename, json_encode($manifest, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); } else { file_put_contents($composerJsonFilename, json_encode($manifest)); } }
/** * @test */ public function modelIsReturnedCorrectlyForLocaleImplicatingChaining() { $localeImplementingChaining = new I18n\Locale('de_DE'); $cldrModel = $this->cldrRepository->getModelForLocale($localeImplementingChaining); $this->assertAttributeContains(Files::concatenatePaths([$this->cldrBasePath, 'main/root.xml']), 'sourcePaths', $cldrModel); $this->assertAttributeContains(Files::concatenatePaths([$this->cldrBasePath, 'main/de_DE.xml']), 'sourcePaths', $cldrModel); $this->assertAttributeContains(Files::concatenatePaths([$this->cldrBasePath, 'main/de.xml']), 'sourcePaths', $cldrModel); }
/** * @param string $subject * @param boolean $exclusiveLock TRUE to, acquire an exclusive (write) lock, FALSE for a shared (read) lock. * @return void * @throws LockNotAcquiredException */ public function acquire($subject, $exclusiveLock) { $this->lockFileName = Utility\Files::concatenatePaths([$this->temporaryDirectory, md5($subject)]); $aquiredLock = false; $i = 0; while ($aquiredLock === false) { $aquiredLock = $this->tryToAcquireLock($exclusiveLock); $i++; if ($i > 10000) { throw new LockNotAcquiredException(sprintf('After 10000 attempts a lock could not be aquired for subject "%s".', $subject), 1449829188); } } }
/** * Will return an array with all available packages. * * The data for each entry will be an array with the key, full path to * the package (index 'path') and a category (the packages subfolder, * index 'category'). The array is indexed by package key. * * @param string $packagesPath * @return array */ public static function getPackagesData($packagesPath) { $packagesData = array(); $packagesDirectoryIterator = new \DirectoryIterator($packagesPath); foreach ($packagesDirectoryIterator as $categoryFileInfo) { $category = $categoryFileInfo->getFilename(); if (!$categoryFileInfo->isDir() || $category[0] === '.' || $category === 'Libraries') { continue; } $categoryDirectoryIterator = new \DirectoryIterator($categoryFileInfo->getPathname()); foreach ($categoryDirectoryIterator as $packageFileInfo) { $packageKey = $packageFileInfo->getFilename(); if (!$packageFileInfo->isDir() || $packageKey[0] === '.') { continue; } $meta = self::readPackageMetaData(Files::concatenatePaths(array($packageFileInfo->getPathname(), 'Meta/Package.xml'))); $composerManifest = self::readComposerManifest(Files::concatenatePaths(array($packageFileInfo->getPathname(), 'composer.json'))); $packagesData[$packageKey] = array('packageKey' => $packageKey, 'category' => $category, 'path' => $packageFileInfo->getPathname(), 'meta' => $meta, 'composerManifest' => $composerManifest); } } return $packagesData; }
/** * Helper function to get the base path for key storage. * * @return string */ protected function getPath() { return Utility\Files::concatenatePaths([FLOW_PATH_DATA, 'Persistent', 'FileBasedSimpleKeyService']); }
/** * Generate a new migration * * If $diffAgainstCurrent is TRUE (the default), it generates a migration file * with the diff between current DB structure and the found mapping metadata. * * Otherwise an empty migration skeleton is generated. * * Only includes tables/sequences matching the $filterExpression regexp when * diffing models and existing schema. Include delimiters in the expression! * The use of * * --filter-expression '/^acme_com/' * * would only create a migration touching tables starting with "acme_com". * * Note: A filter-expression will overrule any filter configured through the * Neos.Flow.persistence.doctrine.migrations.ignoredTables setting * * @param boolean $diffAgainstCurrent Whether to base the migration on the current schema structure * @param string $filterExpression Only include tables/sequences matching the filter expression regexp * @return void * @see neos.flow:doctrine:migrate * @see neos.flow:doctrine:migrationstatus * @see neos.flow:doctrine:migrationexecute * @see neos.flow:doctrine:migrationversion */ public function migrationGenerateCommand($diffAgainstCurrent = true, $filterExpression = null) { // "driver" is used only for Doctrine, thus we (mis-)use it here // additionally, when no host is set, skip this step, assuming no DB is needed if (!$this->isDatabaseConfigured()) { $this->outputLine('Doctrine migration generation has been SKIPPED, the driver and host backend options are not set in /Configuration/Settings.yaml.'); $this->quit(1); } // use default filter expression from settings if ($filterExpression === null) { $ignoredTables = array_keys(array_filter($this->settings['doctrine']['migrations']['ignoredTables'])); if ($ignoredTables !== array()) { $filterExpression = sprintf('/^(?!%s$).*$/xs', implode('$|', $ignoredTables)); } } list($status, $migrationClassPathAndFilename) = $this->doctrineService->generateMigration($diffAgainstCurrent, $filterExpression); $this->outputLine('<info>%s</info>', [$status]); $this->outputLine(); if ($migrationClassPathAndFilename) { $choices = ['Don\'t Move']; $packages = [null]; /** @var Package $package */ foreach ($this->packageManager->getAvailablePackages() as $package) { $type = $package->getComposerManifest('type'); if ($type === null || strpos($type, 'typo3-') !== 0 && strpos($type, 'neos-') !== 0) { continue; } $choices[] = $package->getPackageKey(); $packages[] = $package; } $selectedPackageIndex = (int) $this->output->select('Do you want to move the migration to one of these packages?', $choices, 0); $this->outputLine(); if ($selectedPackageIndex !== 0) { /** @var Package $selectedPackage */ $selectedPackage = $packages[$selectedPackageIndex]; $targetPathAndFilename = Files::concatenatePaths([$selectedPackage->getPackagePath(), 'Migrations', $this->doctrineService->getDatabasePlatformName(), basename($migrationClassPathAndFilename)]); Files::createDirectoryRecursively(dirname($targetPathAndFilename)); rename($migrationClassPathAndFilename, $targetPathAndFilename); $this->outputLine('The migration was moved to: <comment>%s</comment>', [substr($targetPathAndFilename, strlen(FLOW_PATH_PACKAGES))]); $this->outputLine(); $this->outputLine('Next Steps:'); } else { $this->outputLine('Next Steps:'); $this->outputLine(sprintf('- Move <comment>%s</comment> to YourPackage/<comment>Migrations/%s/</comment>', $migrationClassPathAndFilename, $this->doctrineService->getDatabasePlatformName())); } $this->outputLine('- Review and adjust the generated migration.'); $this->outputLine('- (optional) execute the migration using <comment>%s doctrine:migrate</comment>', [$this->getFlowInvocationString()]); } }
/** * @param PackageInterface $package * @return array */ protected function getPrimaryNamespaceAndEntryPath(PackageInterface $package) { $autoloadConfigurations = $package->getComposerManifest('autoload'); $firstAutoloadType = null; $firstAutoloadConfiguration = null; foreach ($autoloadConfigurations as $autoloadType => $autoloadConfiguration) { if (ClassLoader::isAutoloadTypeWithPredictableClassPath($autoloadType)) { $firstAutoloadType = $autoloadType; $firstAutoloadConfiguration = $autoloadConfiguration; break; } } $autoloadPaths = reset($firstAutoloadConfiguration); $firstAutoloadPath = is_array($autoloadPaths) ? reset($autoloadPaths) : $autoloadPaths; $namespace = key($firstAutoloadConfiguration); $autoloadPathPostfix = ''; if ($firstAutoloadType === ClassLoader::MAPPING_TYPE_PSR0) { $autoloadPathPostfix = str_replace('\\', '/', trim($namespace, '\\')); } return [$namespace, Files::concatenatePaths([$package->getPackagePath(), $firstAutoloadPath, $autoloadPathPostfix]), $firstAutoloadType]; }
/** * Initializes the Configuration Manager, the Flow settings and the Environment service * * @param Bootstrap $bootstrap * @return void * @throws FlowException */ public static function initializeConfiguration(Bootstrap $bootstrap) { $context = $bootstrap->getContext(); $environment = new Environment($context); $environment->setTemporaryDirectoryBase(FLOW_PATH_TEMPORARY_BASE); $bootstrap->setEarlyInstance(Environment::class, $environment); $packageManager = $bootstrap->getEarlyInstance(PackageManagerInterface::class); $configurationManager = new ConfigurationManager($context); $configurationManager->setTemporaryDirectoryPath($environment->getPathToTemporaryDirectory()); $configurationManager->injectConfigurationSource(new YamlSource()); $configurationManager->setPackages($packageManager->getActivePackages()); $configurationManager->loadConfigurationCache(); $settings = $configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'Neos.Flow'); $lockManager = new LockManager($settings['utility']['lockStrategyClassName'], ['lockDirectory' => Files::concatenatePaths([$environment->getPathToTemporaryDirectory(), 'Lock'])]); Lock::setLockManager($lockManager); $packageManager->injectSettings($settings); $bootstrap->getSignalSlotDispatcher()->dispatch(ConfigurationManager::class, 'configurationManagerReady', [$configurationManager]); $bootstrap->setEarlyInstance(ConfigurationManager::class, $configurationManager); }
/** * Write a composer manifest for the package. * * @param string $manifestPath * @param string $packageKey * @param array $composerManifestData * @return array the manifest data written */ public static function writeComposerManifest($manifestPath, $packageKey, array $composerManifestData = []) { $manifest = ['description' => '']; if ($composerManifestData !== null) { $manifest = array_merge($manifest, $composerManifestData); } if (!isset($manifest['name']) || empty($manifest['name'])) { $manifest['name'] = static::getComposerPackageNameFromPackageKey($packageKey); } if (!isset($manifest['require']) || empty($manifest['require'])) { $manifest['require'] = array('typo3/flow' => '*'); } if (!isset($manifest['autoload'])) { $namespace = str_replace('.', '\\', $packageKey) . '\\'; $manifest['autoload'] = array('psr-4' => array($namespace => PackageInterface::DIRECTORY_CLASSES)); } $manifest['extra']['neos']['package-key'] = $packageKey; if (defined('JSON_PRETTY_PRINT')) { file_put_contents(Files::concatenatePaths(array($manifestPath, 'composer.json')), json_encode($manifest, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); } else { file_put_contents(Files::concatenatePaths(array($manifestPath, 'composer.json')), json_encode($manifest)); } return $manifest; }
/** * Returns absolute paths to CLDR files connected in hierarchy * * For given locale, many CLDR files have to be merged in order to get full * set of CLDR data. For example, for 'en_GB' locale, files 'root', 'en', * and 'en_GB' should be merged. * * @param I18n\Locale $locale A locale * @param string $directoryPath Relative path to existing CLDR directory which contains one file per locale (see 'main' directory in CLDR for example) * @return array<string> Absolute paths to CLDR files in hierarchy */ protected function findLocaleChain(I18n\Locale $locale, $directoryPath) { $filesInHierarchy = [Files::concatenatePaths([$directoryPath, (string) $locale . '.xml'])]; $localeIdentifier = (string) $locale; while ($localeIdentifier = substr($localeIdentifier, 0, (int) strrpos($localeIdentifier, '_'))) { $possibleFilename = Files::concatenatePaths([$directoryPath, $localeIdentifier . '.xml']); if (file_exists($possibleFilename)) { array_unshift($filesInHierarchy, $possibleFilename); } } array_unshift($filesInHierarchy, Files::concatenatePaths([$directoryPath, 'root.xml'])); return $filesInHierarchy; }
/** * Removes the existing password and starts over by generating a new one. * * @param integer $step The requested setup step * @return void * @Flow\SkipCsrfProtection */ public function generateNewPasswordAction($step = 0) { $existingPasswordFile = Files::concatenatePaths([FLOW_PATH_DATA, 'Persistent', 'FileBasedSimpleKeyService', $this->keyName]); if (file_exists($existingPasswordFile)) { unlink($existingPasswordFile); $this->addFlashMessage('A new password has been generated.', 'Password reset'); } $this->redirect('login', null, null, ['step' => $step]); }
/** * Returns the absolute path and filename of the form with the specified $persistenceIdentifier * Note: This (intentionally) does not check whether the file actually exists * * @param string $persistenceIdentifier * @return string the absolute path and filename of the form with the specified $persistenceIdentifier */ protected function getFormPathAndFilename($persistenceIdentifier) { $formFileName = sprintf('%s.yaml', $persistenceIdentifier); return \Neos\Utility\Files::concatenatePaths(array($this->savePath, $formFileName)); }
/** * Initializes the Configuration Manager, the Flow settings and the Environment service * * @param Bootstrap $bootstrap * @return void * @throws FlowException */ public static function initializeConfiguration(Bootstrap $bootstrap) { $context = $bootstrap->getContext(); $packageManager = $bootstrap->getEarlyInstance(PackageManagerInterface::class); $configurationManager = new ConfigurationManager($context); $configurationManager->injectConfigurationSource(new YamlSource()); $configurationManager->loadConfigurationCache(); $configurationManager->setPackages($packageManager->getActivePackages()); $settings = $configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'Neos.Flow'); $environment = new Environment($context); if (isset($settings['utility']['environment']['temporaryDirectoryBase'])) { $defaultTemporaryDirectoryBase = FLOW_PATH_DATA . '/Temporary'; if (FLOW_PATH_TEMPORARY_BASE !== $defaultTemporaryDirectoryBase) { throw new FlowException(sprintf('It seems like the PHP default temporary base path has been changed from "%s" to "%s" via the FLOW_PATH_TEMPORARY_BASE environment variable. If that variable is present, the Neos.Flow.utility.environment.temporaryDirectoryBase setting must not be specified!', $defaultTemporaryDirectoryBase, FLOW_PATH_TEMPORARY_BASE), 1447707261); } $environment->setTemporaryDirectoryBase($settings['utility']['environment']['temporaryDirectoryBase']); } else { $environment->setTemporaryDirectoryBase(FLOW_PATH_TEMPORARY_BASE); } $configurationManager->setTemporaryDirectoryPath($environment->getPathToTemporaryDirectory()); $lockManager = new LockManager($settings['utility']['lockStrategyClassName'], ['lockDirectory' => Files::concatenatePaths([$environment->getPathToTemporaryDirectory(), 'Lock'])]); Lock::setLockManager($lockManager); $packageManager->injectSettings($settings); $bootstrap->getSignalSlotDispatcher()->dispatch(ConfigurationManager::class, 'configurationManagerReady', [$configurationManager]); $bootstrap->setEarlyInstance(ConfigurationManager::class, $configurationManager); $bootstrap->setEarlyInstance(Environment::class, $environment); }
/** * Evaluates the absolute path and filename of the resource file specified * by the given path. * * @param string $requestedPath * @param boolean $checkForExistence Whether a (non-hash) path should be checked for existence before being returned * @return mixed The full path and filename or FALSE if the file doesn't exist * @throws \InvalidArgumentException|ResourceException */ protected function evaluateResourcePath($requestedPath, $checkForExistence = true) { if (substr($requestedPath, 0, strlen(self::SCHEME)) !== self::SCHEME) { throw new \InvalidArgumentException('The ' . __CLASS__ . ' only supports the \'' . self::SCHEME . '\' scheme.', 1256052544); } $uriParts = Functions::parse_url($requestedPath); if (!is_array($uriParts) || !isset($uriParts['host'])) { return false; } if (preg_match('/^[0-9a-f]{40}$/i', $uriParts['host']) === 1) { $resource = $this->resourceManager->getResourceBySha1($uriParts['host']); return $this->resourceManager->getStreamByResource($resource); } if (!$this->packageManager->isPackageAvailable($uriParts['host'])) { throw new ResourceException(sprintf('Invalid resource URI "%s": Package "%s" is not available.', $requestedPath, $uriParts['host']), 1309269952); } $package = $this->packageManager->getPackage($uriParts['host']); $resourceUri = Files::concatenatePaths([$package->getResourcesPath(), $uriParts['path']]); if ($checkForExistence === false || file_exists($resourceUri)) { return $resourceUri; } return false; }
/** * Returns a XliffModel instance representing desired XLIFF file. * * Will return existing instance if a model for given $sourceName was already * requested before. Returns FALSE when $sourceName doesn't point to existing * file. * * @param string $packageKey Key of the package containing the source file * @param string $sourceName Relative path to existing CLDR file * @param I18n\Locale $locale Locale object * @return XliffModel New or existing instance * @throws I18n\Exception */ protected function getModel($packageKey, $sourceName, I18n\Locale $locale) { $sourcePath = Files::concatenatePaths(['resource://' . $packageKey, $this->xliffBasePath]); list($sourcePath, $foundLocale) = $this->localizationService->getXliffFilenameAndPath($sourcePath, $sourceName, $locale); if ($sourcePath === false) { throw new I18n\Exception('No XLIFF file is available for ' . $packageKey . '::' . $sourceName . '::' . $locale . ' in the locale chain.', 1334759591); } if (isset($this->models[$sourcePath])) { return $this->models[$sourcePath]; } return $this->models[$sourcePath] = new XliffModel($sourcePath, $foundLocale); }
/** * @param Configuration $configuration * @param string $up * @param string $down * @return string * @throws \RuntimeException */ protected function writeMigrationClassToFile(Configuration $configuration, $up, $down) { $namespace = $configuration->getMigrationsNamespace(); $className = 'Version' . date('YmdHis'); $up = $up === null ? '' : "\n " . implode("\n ", explode("\n", $up)); $down = $down === null ? '' : "\n " . implode("\n ", explode("\n", $down)); $path = Files::concatenatePaths([$configuration->getMigrationsDirectory(), $className . '.php']); try { Files::createDirectoryRecursively(dirname($path)); } catch (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; use Doctrine\\DBAL\\Schema\\Schema; /** * Auto-generated Migration: Please modify to your needs! This block will be used as the migration description if getDescription() is not used. */ class {$className} extends AbstractMigration { /** * @return string */ public function getDescription() { return ''; } /** * @param Schema \$schema * @return void */ public function up(Schema \$schema) { // this up() migration is autogenerated, please modify it to your needs{$up} } /** * @param Schema \$schema * @return void */ public function down(Schema \$schema) { // this down() migration is autogenerated, please modify it to your needs{$down} } } EOT; file_put_contents($path, $code); return $path; }
/** * @param string $autoloadType * @param string $autoloadNamespace * @param string $autoloadPath * @return string */ protected function normalizeAutoloadPath($autoloadType, $autoloadNamespace, $autoloadPath) { $normalizedAutoloadPath = $autoloadPath; if ($autoloadType === ClassLoader::MAPPING_TYPE_PSR0) { $normalizedAutoloadPath = Files::concatenatePaths([$autoloadPath, str_replace('\\', '/', $autoloadNamespace)]) . '/'; } if ($autoloadType === ClassLoader::MAPPING_TYPE_PSR4) { $normalizedAutoloadPath = rtrim($normalizedAutoloadPath, '/') . '/'; } return $normalizedAutoloadPath; }
/** * Creates a dummy class file inside $package's path * and requires it for propagation * * @param PackageInterface $package * @return object The dummy object of the class which was created */ protected function createDummyObjectForPackage(PackageInterface $package) { $namespaces = $package->getNamespaces(); $dummyClassName = 'Someclass' . md5(uniqid(mt_rand(), true)); $fullyQualifiedClassName = '\\' . reset($namespaces) . '\\' . $dummyClassName; $dummyClassFilePath = Files::concatenatePaths([$package->getPackagePath(), PackageInterface::DIRECTORY_CLASSES, $dummyClassName . '.php']); file_put_contents($dummyClassFilePath, '<?php namespace ' . reset($namespaces) . '; class ' . $dummyClassName . ' {}'); require $dummyClassFilePath; return new $fullyQualifiedClassName(); }
/** * Factory method which creates an EntityManager. * * @return EntityManager * @throws InvalidConfigurationException */ public function create() { $config = new Configuration(); $config->setClassMetadataFactoryName(Mapping\ClassMetadataFactory::class); $this->applySecondLevelCacheSettingsToConfiguration($this->settings['doctrine']['secondLevelCache'], $config); $cache = new CacheAdapter(); // must use ObjectManager in compile phase... $cache->setCache($this->objectManager->get(CacheManager::class)->getCache('Flow_Persistence_Doctrine')); $config->setMetadataCacheImpl($cache); $config->setQueryCacheImpl($cache); $resultCache = new CacheAdapter(); // must use ObjectManager in compile phase... $resultCache->setCache($this->objectManager->get(CacheManager::class)->getCache('Flow_Persistence_Doctrine_Results')); $config->setResultCacheImpl($resultCache); if (is_string($this->settings['doctrine']['sqlLogger']) && class_exists($this->settings['doctrine']['sqlLogger'])) { $configuredSqlLogger = $this->settings['doctrine']['sqlLogger']; $sqlLoggerInstance = new $configuredSqlLogger(); if ($sqlLoggerInstance instanceof SQLLogger) { $config->setSQLLogger($sqlLoggerInstance); } else { throw new InvalidConfigurationException(sprintf('Neos.Flow.persistence.doctrine.sqlLogger must point to a \\Doctrine\\DBAL\\Logging\\SQLLogger implementation, %s given.', get_class($sqlLoggerInstance)), 1426150388); } } $eventManager = $this->buildEventManager(); $flowAnnotationDriver = $this->objectManager->get(FlowAnnotationDriver::class); $config->setMetadataDriverImpl($flowAnnotationDriver); $proxyDirectory = Files::concatenatePaths([$this->environment->getPathToTemporaryDirectory(), 'Doctrine/Proxies']); Files::createDirectoryRecursively($proxyDirectory); $config->setProxyDir($proxyDirectory); $config->setProxyNamespace('Neos\\Flow\\Persistence\\Doctrine\\Proxies'); $config->setAutoGenerateProxyClasses(false); // Set default host to 127.0.0.1 if there is no host configured but a dbname if (empty($this->settings['backendOptions']['host']) && !empty($this->settings['backendOptions']['dbname'])) { $this->settings['backendOptions']['host'] = '127.0.0.1'; } // The following code tries to connect first, if that succeeds, all is well. If not, the platform is fetched directly from the // driver - without version checks to the database server (to which no connection can be made) - and is added to the config // which is then used to create a new connection. This connection will then return the platform directly, without trying to // detect the version it runs on, which fails if no connection can be made. But the platform is used even if no connection can // be made, which was no problem with Doctrine DBAL 2.3. And then came version-aware drivers and platforms... $connection = DriverManager::getConnection($this->settings['backendOptions'], $config, $eventManager); try { $connection->connect(); } catch (ConnectionException $exception) { $settings = $this->settings['backendOptions']; $settings['platform'] = $connection->getDriver()->getDatabasePlatform(); $connection = DriverManager::getConnection($settings, $config, $eventManager); } $entityManager = EntityManager::create($connection, $config, $eventManager); $flowAnnotationDriver->setEntityManager($entityManager); if (isset($this->settings['doctrine']['dbal']['mappingTypes']) && is_array($this->settings['doctrine']['dbal']['mappingTypes'])) { foreach ($this->settings['doctrine']['dbal']['mappingTypes'] as $typeName => $typeConfiguration) { Type::addType($typeName, $typeConfiguration['className']); $entityManager->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping($typeConfiguration['dbType'], $typeName); } } if (isset($this->settings['doctrine']['filters']) && is_array($this->settings['doctrine']['filters'])) { foreach ($this->settings['doctrine']['filters'] as $filterName => $filterClass) { $config->addFilter($filterName, $filterClass); $entityManager->getFilters()->enable($filterName); } } if (isset($this->settings['doctrine']['dql']) && is_array($this->settings['doctrine']['dql'])) { $this->applyDqlSettingsToConfiguration($this->settings['doctrine']['dql'], $config); } return $entityManager; }
/** * Fetches the site with the given name and exports it as XML into the given file. * * @param array<Site> $sites * @param boolean $tidy Whether to export formatted XML * @param string $pathAndFilename Path to where the export output should be saved to * @param string $nodeTypeFilter Filter the node type of the nodes, allows complex expressions (e.g. "Neos.Neos:Page", "!Neos.Neos:Page,Neos.Neos:Text") * @return void */ public function exportToFile(array $sites, $tidy = false, $pathAndFilename, $nodeTypeFilter = null) { $this->resourcesPath = Files::concatenatePaths(array(dirname($pathAndFilename), 'Resources')); Files::createDirectoryRecursively($this->resourcesPath); $this->xmlWriter = new \XMLWriter(); $this->xmlWriter->openUri($pathAndFilename); $this->xmlWriter->setIndent($tidy); $this->exportSites($sites, $nodeTypeFilter); $this->xmlWriter->flush(); }
/** * Return the json array for a given locale, sourceCatalog, xliffPath and package. * The json will be cached. * * @param Locale $locale The locale * @return Result * @throws Exception */ public function getCachedJson(Locale $locale) { $cacheIdentifier = md5($locale); if ($this->xliffToJsonTranslationsCache->has($cacheIdentifier)) { $json = $this->xliffToJsonTranslationsCache->get($cacheIdentifier); } else { $labels = []; $localeChain = $this->localizationService->getLocaleChain($locale); foreach ($this->packagesRegisteredForAutoInclusion as $packageKey => $sourcesToBeIncluded) { if (!is_array($sourcesToBeIncluded)) { continue; } $translationBasePath = Files::concatenatePaths([$this->packageManager->getPackage($packageKey)->getResourcesPath(), $this->xliffBasePath]); // We merge labels in the chain from the worst choice to best choice foreach (array_reverse($localeChain) as $allowedLocale) { $localeSourcePath = Files::getNormalizedPath(Files::concatenatePaths([$translationBasePath, $allowedLocale])); foreach ($sourcesToBeIncluded as $sourceName) { foreach (glob($localeSourcePath . $sourceName . '.xlf') as $xliffPathAndFilename) { $xliffPathInfo = pathinfo($xliffPathAndFilename); $sourceName = str_replace($localeSourcePath, '', $xliffPathInfo['dirname'] . '/' . $xliffPathInfo['filename']); $labels = Arrays::arrayMergeRecursiveOverrule($labels, $this->parseXliffToArray($xliffPathAndFilename, $packageKey, $sourceName)); } } } } $json = json_encode($labels); $this->xliffToJsonTranslationsCache->set($cacheIdentifier, $json); } return $json; }
/** * Generate additional folders for site packages. * * @param string $packageKey */ protected function generateAdditionalFolders($packageKey) { $resourcesPath = $this->packageManager->getPackage($packageKey)->getResourcesPath(); $publicResourcesPath = Files::concatenatePaths(array($resourcesPath, 'Public')); foreach (array('Images', 'JavaScript', 'Styles') as $publicResourceFolder) { Files::createDirectoryRecursively(Files::concatenatePaths(array($publicResourcesPath, $publicResourceFolder))); } }
/** * @param string $driver * @return array Not supported image format */ protected function findUnsupportedImageFormats($driver) { $this->imagineFactory->injectSettings(array('driver' => ucfirst($driver))); $imagine = $this->imagineFactory->create(); $unsupportedFormats = array(); foreach (array('jpg', 'gif', 'png') as $imageFormat) { $imagePath = Files::concatenatePaths(array($this->packageManager->getPackage('Neos.Neos')->getResourcesPath(), 'Private/Installer/TestImages/Test.' . $imageFormat)); try { $imagine->open($imagePath); } catch (\Exception $exception) { $unsupportedFormats[] = sprintf('"%s"', $imageFormat); } } return $unsupportedFormats; }
/** * @param string $packageKey * @return string|null */ protected function getPackagePrivateResourcesPath($packageKey) { if (!$this->packageManager->isPackageActive($packageKey)) { return null; } $packageResourcesPath = $this->packageManager->getPackage($packageKey)->getResourcesPath(); return Files::concatenatePaths([$packageResourcesPath, 'Private']); }
/** * Returns the absolute paths of public resources directories of all active packages. * This method is used directly by the FileSystemSymlinkTarget. * * @return array<string> */ public function getPublicResourcePaths() { $paths = []; $packages = $this->packageManager->getActivePackages(); foreach ($packages as $packageKey => $package) { /** @var PackageInterface $package */ $publicResourcesPath = Files::concatenatePaths([$package->getResourcesPath(), 'Public']); if (is_dir($publicResourcesPath)) { $paths[$packageKey] = $publicResourcesPath; } } return $paths; }
/** * Applies all registered moveFile operations. * * @return void */ protected function applyFileOperations() { foreach ($this->operations['moveFile'] as $operation) { $oldPath = Files::concatenatePaths(array($this->targetPackageData['path'] . '/' . $operation[0])); $newPath = Files::concatenatePaths(array($this->targetPackageData['path'] . '/' . $operation[1])); if (substr($oldPath, -1) === '*') { $oldPath = substr($oldPath, 0, -1); if (!file_exists($oldPath)) { continue; } if (!file_exists($newPath)) { Files::createDirectoryRecursively($newPath); } if (!is_dir($newPath)) { continue; } foreach (Files::getRecursiveDirectoryGenerator($this->targetPackageData['path'], null, true) as $pathAndFilename) { if (substr_compare($pathAndFilename, $oldPath, 0, strlen($oldPath)) === 0) { $relativePathAndFilename = substr($pathAndFilename, strlen($oldPath)); if (!is_dir(dirname(Files::concatenatePaths(array($newPath, $relativePathAndFilename))))) { Files::createDirectoryRecursively(dirname(Files::concatenatePaths(array($newPath, $relativePathAndFilename)))); } Git::move($pathAndFilename, Files::concatenatePaths(array($newPath, $relativePathAndFilename))); } } } else { $oldPath = Files::concatenatePaths(array($this->targetPackageData['path'] . '/' . $operation[0])); $newPath = Files::concatenatePaths(array($this->targetPackageData['path'] . '/' . $operation[1])); Git::move($oldPath, $newPath); } } foreach ($this->operations['deleteFile'] as $operation) { $filename = Files::concatenatePaths(array($this->targetPackageData['path'] . '/' . $operation[0])); if (file_exists($filename)) { Git::remove($filename); } } }
/** * Validate a single configuration type * * @param string $configurationType the configuration typr to validate * @param string $path configuration path to validate, or NULL. * @param array $loadedSchemaFiles will be filled with a list of loaded schema files * @return \Neos\Error\Messages\Result * @throws Exception\SchemaValidationException */ protected function validateSingleType($configurationType, $path, &$loadedSchemaFiles) { $availableConfigurationTypes = $this->configurationManager->getAvailableConfigurationTypes(); if (in_array($configurationType, $availableConfigurationTypes) === false) { throw new Exception\SchemaValidationException('The configuration type "' . $configurationType . '" was not found. Only the following configuration types are supported: "' . implode('", "', $availableConfigurationTypes) . '"', 1364984886); } $configuration = $this->configurationManager->getConfiguration($configurationType); // find schema files for the given type and path $schemaFileInfos = []; $activePackages = $this->packageManager->getActivePackages(); foreach ($activePackages as $package) { $packageKey = $package->getPackageKey(); $packageSchemaPath = Files::concatenatePaths([$package->getResourcesPath(), 'Private/Schema']); if (is_dir($packageSchemaPath)) { foreach (Files::getRecursiveDirectoryGenerator($packageSchemaPath, '.schema.yaml') as $schemaFile) { $schemaName = substr($schemaFile, strlen($packageSchemaPath) + 1, -strlen('.schema.yaml')); $schemaNameParts = explode('.', str_replace('/', '.', $schemaName), 2); $schemaType = $schemaNameParts[0]; $schemaPath = isset($schemaNameParts[1]) ? $schemaNameParts[1] : null; if ($schemaType === $configurationType && ($path === null || strpos($schemaPath, $path) === 0)) { $schemaFileInfos[] = ['file' => $schemaFile, 'name' => $schemaName, 'path' => $schemaPath, 'packageKey' => $packageKey]; } } } } if (count($schemaFileInfos) === 0) { throw new Exception\SchemaValidationException('No schema files found for configuration type "' . $configurationType . '"' . ($path !== null ? ' and path "' . $path . '".' : '.'), 1364985056); } $result = new Result(); foreach ($schemaFileInfos as $schemaFileInfo) { $loadedSchemaFiles[] = $schemaFileInfo['file']; if ($schemaFileInfo['path'] !== null) { $data = Arrays::getValueByPath($configuration, $schemaFileInfo['path']); } else { $data = $configuration; } if (empty($data)) { $result->addNotice(new Notice('No configuration found, skipping schema "%s".', 1364985445, [substr($schemaFileInfo['file'], strlen(FLOW_PATH_ROOT))])); } else { $parsedSchema = Yaml::parse($schemaFileInfo['file']); $validationResultForSingleSchema = $this->schemaValidator->validate($data, $parsedSchema); if ($schemaFileInfo['path'] !== null) { $result->forProperty($schemaFileInfo['path'])->merge($validationResultForSingleSchema); } else { $result->merge($validationResultForSingleSchema); } } } return $result; }