/** * Return the json array for a given locale, sourceCatalog, xliffPath and package. * The json will be cached. * * @param Locale $locale The locale * @throws \TYPO3\Flow\I18n\Exception * @return \TYPO3\Flow\Error\Result */ 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; }
/** * Creates a Doctrine ODM DocumentManager * * @return \Doctrine\ODM\CouchDB\DocumentManager */ public function create() { if (isset($this->documentManager)) { return $this->documentManager; } $httpClient = new \Doctrine\CouchDB\HTTP\SocketClient($this->settings['host'], $this->settings['port'], $this->settings['username'], $this->settings['password'], $this->settings['ip']); $reader = new \Doctrine\Common\Annotations\AnnotationReader(); $metaDriver = new \Doctrine\ODM\CouchDB\Mapping\Driver\AnnotationDriver($reader); $config = new \Doctrine\ODM\CouchDB\Configuration(); $config->setMetadataDriverImpl($metaDriver); $packages = $this->packageManager->getActivePackages(); foreach ($packages as $package) { $designDocumentRootPath = \TYPO3\Flow\Utility\Files::concatenatePaths(array($package->getPackagePath(), 'Migrations/CouchDB/DesignDocuments')); if (is_dir($designDocumentRootPath)) { $packageDesignDocumentFolders = glob($designDocumentRootPath . '/*'); foreach ($packageDesignDocumentFolders as $packageDesignDocumentFolder) { if (is_dir($packageDesignDocumentFolder)) { $designDocumentName = strtolower(basename($packageDesignDocumentFolder)); $config->addDesignDocument($designDocumentName, 'Radmiraal\\CouchDB\\View\\Migration', array('packageKey' => $package->getPackageKey(), 'path' => $packageDesignDocumentFolder)); } } } } $proxyDirectory = \TYPO3\Flow\Utility\Files::concatenatePaths(array($this->environment->getPathToTemporaryDirectory(), 'DoctrineODM/Proxies')); \TYPO3\Flow\Utility\Files::createDirectoryRecursively($proxyDirectory); $config->setProxyDir($proxyDirectory); $config->setProxyNamespace('TYPO3\\Flow\\Persistence\\DoctrineODM\\Proxies'); $config->setAutoGenerateProxyClasses(TRUE); $couchClient = new \Doctrine\CouchDB\CouchDBClient($httpClient, $this->settings['databaseName']); $this->documentManager = \Doctrine\ODM\CouchDB\DocumentManager::create($couchClient, $config); return $this->documentManager; }
/** * Import sites content * * This command allows for importing one or more sites or partial content from an XML source. The format must * be identical to that produced by the export command. * * If a filename is specified, this command expects the corresponding file to contain the XML structure. The * filename php://stdin can be used to read from standard input. * * If a package key is specified, this command expects a Sites.xml file to be located in the private resources * directory of the given package (Resources/Private/Content/Sites.xml). * * @param string $packageKey Package key specifying the package containing the sites content * @param string $filename relative path and filename to the XML file containing the sites content * @return void */ public function importCommand($packageKey = null, $filename = null) { $exceedingArguments = $this->request->getExceedingArguments(); if (isset($exceedingArguments[0]) && $packageKey === null && $filename === null) { if (file_exists($exceedingArguments[0])) { $filename = $exceedingArguments[0]; } elseif ($this->packageManager->isPackageAvailable($exceedingArguments[0])) { $packageKey = $exceedingArguments[0]; } } if ($packageKey === null && $filename === null) { $this->outputLine('You have to specify either "--package-key" or "--filename"'); $this->quit(1); } $site = null; if ($filename !== null) { try { $site = $this->siteImportService->importFromFile($filename); } catch (\Exception $exception) { $this->systemLogger->logException($exception); $this->outputLine('Error: During the import of the file "%s" an exception occurred: %s, see log for further information.', array($filename, $exception->getMessage())); $this->quit(1); } } else { try { $site = $this->siteImportService->importFromPackage($packageKey); } catch (\Exception $exception) { $this->systemLogger->logException($exception); $this->outputLine('Error: During the import of the "Sites.xml" from the package "%s" an exception occurred: %s, see log for further information.', array($packageKey, $exception->getMessage())); $this->quit(1); } } $this->outputLine('Import of site "%s" finished.', array($site->getName())); }
/** * Checks the syntax of the given $packageKey and quits with an error message if it's not valid * * @param string $packageKey * @return void */ protected function validatePackageKey($packageKey) { if (!$this->packageManager->isPackageKeyValid($packageKey)) { $this->outputLine('Package key "%s" is not valid. Only UpperCamelCase with alphanumeric characters in the format <VendorName>.<PackageKey>, please!', array($packageKey)); exit(1); } }
/** * Set the routes configuration for the Neos setup and configures the routing component * to skip initialisation, which would overwrite the specific settings again. * * @param ComponentContext $componentContext * @return void */ public function handle(ComponentContext $componentContext) { $configurationSource = $this->objectManager->get('TYPO3\\Flow\\Configuration\\Source\\YamlSource'); $routesConfiguration = $configurationSource->load($this->packageManager->getPackage('TYPO3.Setup')->getConfigurationPath() . ConfigurationManager::CONFIGURATION_TYPE_ROUTES); $this->router->setRoutesConfiguration($routesConfiguration); $componentContext->setParameter('TYPO3\\Flow\\Mvc\\Routing\\RoutingComponent', 'skipRouterInitialization', TRUE); }
/** * @param $patchId * @return \TYPO3\Flow\Package\PackageInterface */ public function getPatchTargetPackage($patchId) { $details = $this->requestGerritAPI(sprintf($this->gerritApiPattern, $patchId, 'detail')); $projectParts = explode('/', $details['project']); $packageName = $projectParts[1]; $package = $this->packageManager->getPackage($packageName); return $package; }
/** * @param string $packageName * @return bool */ protected function isPackageActiveByName($packageName) { $foundPackage = false; foreach ($this->packageManager->getActivePackages() as $key => $package) { if (property_exists($package->getComposerManifest(), 'name') == true && $package->getComposerManifest()->name == $packageName) { $foundPackage = true; break; } } return $foundPackage; }
/** * Resolve view object. Falls back to TYPO3.Ice package templates * if current package does not contain a template for current request. * * @return \TYPO3\Flow\Mvc\View\ViewInterface the resolved view */ public function resolveView() { $view = parent::resolveView(); if (!$view->canRender($this->controllerContext) && $this->request->getFormat() === 'html') { $templateFileName = \TYPO3\Flow\Utility\Files::concatenatePaths(array($this->packageManager->getPackage('TYPO3.Ice')->getPackagePath(), 'Resources', 'Private', 'Templates', 'Standard', 'Index.html')); // Fallback to TYPO3.Ice template if file exists if (file_exists($templateFileName)) { $view->setTemplatePathAndFilename($templateFileName); } } return $view; }
/** * Executes this task * * @param \TYPO3\Surf\Domain\Model\Node $node * @param \TYPO3\Surf\Domain\Model\Application $application * @param \TYPO3\Surf\Domain\Model\Deployment $deployment * @param array $options * @return void * @throws \TYPO3\Surf\Exception\TaskExecutionException */ public function execute(Node $node, Application $application, Deployment $deployment, array $options = array()) { $this->hosting = $application->getOption('hosting'); $this->username = $options['username']; $this->hostname = $node->getHostname(); $this->deployment = $deployment; $this->resourcePath = $this->packageManager->getPackage('Famelo.Surf.SharedHosting')->getResourcesPath() . 'Private/' . $this->hosting; $this->temporaryPath = FLOW_PATH_ROOT . '/Data/Temporary/Deployment/' . $this->hosting; if (!is_dir($this->temporaryPath)) { \TYPO3\Flow\Utility\Files::createDirectoryRecursively($this->temporaryPath); } }
/** * Kickstart a new site package * * This command generates a new site package with basic TypoScript and Sites.xml * * @param string $packageKey The packageKey for your site * @param string $siteName The siteName of your site * @return string */ public function siteCommand($packageKey, $siteName) { if (!$this->packageManager->isPackageKeyValid($packageKey)) { $this->outputLine('Package key "%s" is not valid. Only UpperCamelCase with alphanumeric characters and underscore, please!', array($packageKey)); $this->quit(1); } if ($this->packageManager->isPackageAvailable($packageKey)) { $this->outputLine('Package "%s" already exists.', array($packageKey)); $this->quit(1); } $generatedFiles = $this->generatorService->generateSitePackage($packageKey, $siteName); $this->outputLine(implode(PHP_EOL, $generatedFiles)); }
/** * Kickstart a new site package * * This command generates a new site package with basic TypoScript and Sites.xml * * @param string $packageKey The packageKey for your site * @param string $siteName The siteName of your site * @return string */ public function siteCommand($packageKey, $siteName) { if (!$this->packageManager->isPackageKeyValid($packageKey)) { $this->outputLine('Package key "%s" is not valid. Only UpperCamelCase in the format "Vendor.PackageKey", please!', array($packageKey)); $this->quit(1); } if ($this->packageManager->isPackageAvailable($packageKey)) { $this->outputLine('Package "%s" already exists.', array($packageKey)); $this->quit(1); } $generatedFiles = $this->generatorService->generateSitePackage($packageKey, $siteName); $this->outputLine(implode(PHP_EOL, $generatedFiles)); }
/** * Create a new subsite * * @return void */ public function newMultiSiteAction() { $sitePackages = $this->packageManager->getFilteredPackages('available', null, 'typo3-flow-site'); $host = $this->request->getHttpRequest()->getBaseUri()->getHost(); $possibleDomains = []; $hostParts = explode('.', $host); while (count($hostParts) > 1) { $possibleDomain = implode('.', $hostParts); $possibleDomains[$possibleDomain] = $possibleDomain; array_shift($hostParts); } $this->view->assignMultiple(array('sitePackages' => $sitePackages, 'possibleDomains' => $possibleDomains)); }
/** * Fetches the site with the given name and exports it into XML in the given package. * * @param array<Site> $sites * @param boolean $tidy Whether to export formatted XML * @param string $packageKey Package key where the export output should be saved to * @param string $nodeTypeFilter Filter the node type of the nodes, allows complex expressions (e.g. "TYPO3.Neos:Page", "!TYPO3.Neos:Page,TYPO3.Neos:Text") * @return void * @throws NeosException */ public function exportToPackage(array $sites, $tidy = false, $packageKey, $nodeTypeFilter = null) { if (!$this->packageManager->isPackageActive($packageKey)) { throw new NeosException(sprintf('Error: Package "%s" is not active.', $packageKey), 1404375719); } $contentPathAndFilename = sprintf('resource://%s/Private/Content/Sites.xml', $packageKey); $this->resourcesPath = Files::concatenatePaths(array(dirname($contentPathAndFilename), 'Resources')); Files::createDirectoryRecursively($this->resourcesPath); $this->xmlWriter = new \XMLWriter(); $this->xmlWriter->openUri($contentPathAndFilename); $this->xmlWriter->setIndent($tidy); $this->exportSites($sites, $nodeTypeFilter); $this->xmlWriter->flush(); }
/** * Convert (and optionally filter) code coverage data generated by functional tests, * such that file references inside point not to the code cache inside Data/Temporary/...., * but to the Classes/ directory of the packages. * * <b>Example Usage:</b> * phpunit -c Build/BuildEssentials/FunctionalTests.xml --coverage-php Build/Reports/RawFunctionalTestCoverageReport.php * ./flow codeCoverage:convert Build/Reports/RawFunctionalTestCoverageReport.php Build/Reports/FunctionalTestCoverageReport.php --packages 'Your.Packages,Separated.By.Comma' * * The "--packages" argument is optional; but using it results in a huge speed boost; * as only the classes from the specified packages are included in the coverage result. * * @param string $codeCoverageFile Path to the code coverage file generated with "--coverage-php" of phpunit. * @param string $outFile Path to the converted code coverage file * @param string $packages The comma-separated list of packages to filter for. These packages must be installed here. * @param string $context The Flow context which has been used during the functional test run. Only needs to be modified if tests are ran in a special context. */ public function convertCommand($codeCoverageFile, $outFile, $packages = '*', $context = 'Testing') { // Load $packages which should be taken into account while conversion $packageKeys = $packages; if ($packageKeys === '*') { $packages = $this->packageManager->getActivePackages(); } else { $packages = array(); foreach (\TYPO3\Flow\Utility\Arrays::trimExplode(',', $packageKeys) as $packageKey) { $packages[] = $this->packageManager->getPackage($packageKey); } } // For all $packages which should be used, build up a "cache-file-name" -> "real-file-name" mapping. $reverseIndexOfCacheFileNamesToClassFiles = array(); foreach ($packages as $package) { /* @var $package \TYPO3\Flow\Package\PackageInterface */ foreach ($package->getClassFiles() as $className => $fileName) { $cacheFileName = str_replace('\\', '_', $className); $reverseIndexOfCacheFileNamesToClassFiles[$cacheFileName] = $package->getPackagePath() . $fileName; } } // Modify the coverage report /* @var $coverage \Php_CodeCoverage */ $coverage = unserialize(file_get_contents($codeCoverageFile)); $coverageData = $coverage->getData(); $baseDirectoryLength = strlen(FLOW_PATH_ROOT . 'Data/Temporary/' . $context . '/Cache/Code/Flow_Object_Classes/'); $adjustedCoverageData = array(); foreach ($coverageData as $fullCacheFileName => $coverageDataForFile) { $shortCacheFileName = substr($fullCacheFileName, $baseDirectoryLength, -4); if (isset($reverseIndexOfCacheFileNamesToClassFiles[$shortCacheFileName])) { $classFileInPackage = $reverseIndexOfCacheFileNamesToClassFiles[$shortCacheFileName]; $numberOfLinesOfFile = count(file($classFileInPackage)); if (isset($adjustedCoverageData[$classFileInPackage])) { throw new \Sandstorm\Fuzzer\Exception('Coverage data already found for class file "' . $classFileInPackage . '". This should never happen; so we do not override it. It is probably a bug in Fuzzer.', 1367238729); } $adjustedCoverageData[$classFileInPackage] = array(); foreach ($coverageDataForFile as $lineNumber => $coveredBy) { if ($lineNumber <= $numberOfLinesOfFile) { $adjustedCoverageData[$classFileInPackage][$lineNumber] = $coveredBy; } } } } // Save the new coverage report $adjustedCoverage = new PhpunitCodeCoverage(); $adjustedCoverage->setData($adjustedCoverageData); $adjustedCoverage->setTests($coverage->getTests()); file_put_contents($outFile, serialize($adjustedCoverage)); }
/** * Update global Piwik settings * * @param array $piwik * @return void */ public function updateAction(array $piwik) { $configurationPath = $this->packageManager->getPackage('Portachtzig.Neos.Piwik')->getConfigurationPath(); $settings = $this->configurationSource->load($configurationPath . ConfigurationManager::CONFIGURATION_TYPE_SETTINGS); $piwik['host'] = preg_replace("(^https?://)", "", $piwik['host']); $settings = Arrays::setValueByPath($settings, 'Portachtzig.Neos.Piwik.host', $piwik['host']); $settings = Arrays::setValueByPath($settings, 'Portachtzig.Neos.Piwik.protocol', $piwik['protocol']); $settings = Arrays::setValueByPath($settings, 'Portachtzig.Neos.Piwik.token_auth', $piwik['token_auth']); if (array_key_exists('idSite', $piwik)) { $settings = Arrays::setValueByPath($settings, 'Portachtzig.Neos.Piwik.idSite', $piwik['idSite']); } $this->configurationSource->save($configurationPath . ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, $settings); $this->configurationManager->flushConfigurationCache(); $this->redirect('index'); }
/** * Index action * * @return void */ public function indexAction() { $this->view->assign('flowPathRoot', realpath(FLOW_PATH_ROOT)); $this->view->assign('flowPathWeb', realpath(FLOW_PATH_WEB)); $this->view->assign('isMyPackageActive', $this->packageManager->isPackageActive('MyCompany.MyPackage')); $baseUri = $this->request->getHttpRequest()->getBaseUri(); $this->view->assign('baseUri', $baseUri); $this->view->assign('isWindows', DIRECTORY_SEPARATOR !== '/'); $flowPackage = $this->packageManager->getPackage('TYPO3.Flow'); $version = $flowPackage->getPackageMetaData()->getVersion(); $this->view->assign('version', $version); $activePackages = $this->packageManager->getActivePackages(); $this->view->assign('activePackages', $activePackages); $this->view->assign('notDevelopmentContext', !$this->objectManager->getContext()->isDevelopment()); }
/** * Finds all Locale objects representing locales available in the * Flow installation. This is done by scanning all Private and Public * resource files of all active packages, in order to find localized files. * * Localized files have a locale identifier added before their extension * (or at the end of filename, if no extension exists). For example, a * localized file for foobar.png, can be foobar.en.png, fobar.en_GB.png, etc. * * Just one localized resource file causes the corresponding locale to be * regarded as available (installed, supported). * * Note: result of this method invocation is cached * * @return void */ protected function generateAvailableLocalesCollectionByScanningFilesystem() { /** @var PackageInterface $activePackage */ foreach ($this->packageManager->getActivePackages() as $activePackage) { $packageResourcesPath = $activePackage->getResourcesPath(); if (!is_dir($packageResourcesPath)) { continue; } $directories = array(Files::getNormalizedPath($packageResourcesPath)); while ($directories !== array()) { $currentDirectory = array_pop($directories); if ($handle = opendir($currentDirectory)) { while (false !== ($filename = readdir($handle))) { if ($filename[0] === '.') { continue; } $pathAndFilename = Files::concatenatePaths(array($currentDirectory, $filename)); if (is_dir($pathAndFilename)) { array_push($directories, Files::getNormalizedPath($pathAndFilename)); } else { $localeIdentifier = Utility::extractLocaleTagFromFilename($filename); if ($localeIdentifier !== false) { $this->localeCollection->addLocale(new Locale($localeIdentifier)); } } } closedir($handle); } } } }
/** * Flush all caches * * The flush command flushes all caches (including code caches) which have been * registered with Flow's Cache Manager. It also removes any session data. * * If fatal errors caused by a package prevent the compile time bootstrap * from running, the removal of any temporary data can be forced by specifying * the option <b>--force</b>. * * This command does not remove the precompiled data provided by frozen * packages unless the <b>--force</b> option is used. * * @param boolean $force Force flushing of any temporary data * @return void * @see typo3.flow:cache:warmup * @see typo3.flow:package:freeze * @see typo3.flow:package:refreeze */ public function flushCommand($force = false) { // Internal note: the $force option is evaluated early in the Flow // bootstrap in order to reliably flush the temporary data before any // other code can cause fatal errors. $this->cacheManager->flushCaches(); $this->outputLine('Flushed all caches for "' . $this->bootstrap->getContext() . '" context.'); if ($this->lockManager->isSiteLocked()) { $this->lockManager->unlockSite(); } $frozenPackages = array(); foreach (array_keys($this->packageManager->getActivePackages()) as $packageKey) { if ($this->packageManager->isPackageFrozen($packageKey)) { $frozenPackages[] = $packageKey; } } if ($frozenPackages !== array()) { $this->outputFormatted(PHP_EOL . 'Please note that the following package' . (count($frozenPackages) === 1 ? ' is' : 's are') . ' currently frozen: ' . PHP_EOL); $this->outputFormatted(implode(PHP_EOL, $frozenPackages) . PHP_EOL, array(), 2); $message = 'As code and configuration changes in these packages are not detected, the application may respond '; $message .= 'unexpectedly if modifications were done anyway or the remaining code relies on these changes.' . PHP_EOL . PHP_EOL; $message .= 'You may call <b>package:refreeze all</b> in order to refresh frozen packages or use the <b>--force</b> '; $message .= 'option of this <b>cache:flush</b> command to flush caches if Flow becomes unresponsive.' . PHP_EOL; $this->outputFormatted($message, array($frozenPackages)); } $this->sendAndExit(0); }
/** * 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 \TYPO3\Flow\Resource\Exception * @throws \InvalidArgumentException */ 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 = parse_url($requestedPath); if (!is_array($uriParts) || !isset($uriParts['host'])) { return FALSE; } if (preg_match('/^[0-9a-f]{40}$/i', $uriParts['host']) === 1) { $resourcePath = $this->resourceManager->getPersistentResourcesStorageBaseUri() . $uriParts['host']; if ($checkForExistence === FALSE || file_exists($resourcePath)) { return $resourcePath; } else { return FALSE; } } if (!$this->packageManager->isPackageAvailable($uriParts['host'])) { throw new \TYPO3\Flow\Resource\Exception(sprintf('Invalid resource URI "%s": Package "%s" is not available.', $requestedPath, $uriParts['host']), 1309269952); } $package = $this->packageManager->getPackage($uriParts['host']); $resourcePath = \TYPO3\Flow\Utility\Files::concatenatePaths(array($package->getResourcesPath(), $uriParts['path'])); if ($checkForExistence === FALSE || file_exists($resourcePath)) { return $resourcePath; } return FALSE; }
/** * Generate additional folders for site packages. * * @param string $packageKey * @throws \TYPO3\Flow\Utility\Exception */ 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))); } }
private function getNamespaceBaseDirectory($packageKey) { $package = $this->packageManager->getPackage($packageKey); if ($package->getAutoloadType() === Package::AUTOLOADER_TYPE_PSR4) { // WORKAROUND to support PSR4 properly return Files::getNormalizedPath($package->getClassesPath()); } else { return $package->getClassesNamespaceEntryPath(); } }
/** * Rescan package availability and recreates the PackageStates configuration. */ public function rescanCommand() { $packageStates = $this->packageManager->rescanPackages(); $this->outputLine('The following packages are registered and will be loaded in this order:'); $this->outputLine(''); foreach ($packageStates['packages'] as $composerName => $packageState) { $this->outputLine($composerName); } $this->outputLine(''); $this->outputLine('Package rescan successful.'); }
/** * Imports one or multiple sites from the XML file at $pathAndFilename * * @param string $pathAndFilename * @return Site The imported site * @throws UnknownPackageException|InvalidPackageStateException|NeosException */ public function importFromFile($pathAndFilename) { /** @var Site $importedSite */ $site = NULL; $this->eventEmittingService->withoutEventLog(function () use($pathAndFilename, &$site) { $xmlReader = new \XMLReader(); $xmlReader->open($pathAndFilename, NULL, LIBXML_PARSEHUGE); if ($this->workspaceRepository->findOneByName('live') === NULL) { $this->workspaceRepository->add(new Workspace('live')); } $rootNode = $this->contextFactory->create()->getRootNode(); $this->persistenceManager->persistAll(); $sitesNode = $rootNode->getNode('/sites'); if ($sitesNode === NULL) { $sitesNode = $rootNode->createSingleNode('sites'); } while ($xmlReader->read()) { if ($xmlReader->nodeType != \XMLReader::ELEMENT || $xmlReader->name !== 'site') { continue; } $isLegacyFormat = $xmlReader->getAttribute('nodeName') !== NULL && $xmlReader->getAttribute('state') === NULL && $xmlReader->getAttribute('siteResourcesPackageKey') === NULL; if ($isLegacyFormat) { $site = $this->legacySiteImportService->importSitesFromFile($pathAndFilename); return; } $site = $this->getSiteByNodeName($xmlReader->getAttribute('siteNodeName')); $site->setName($xmlReader->getAttribute('name')); $site->setState((int) $xmlReader->getAttribute('state')); $siteResourcesPackageKey = $xmlReader->getAttribute('siteResourcesPackageKey'); if (!$this->packageManager->isPackageAvailable($siteResourcesPackageKey)) { throw new UnknownPackageException(sprintf('Package "%s" specified in the XML as site resources package does not exist.', $siteResourcesPackageKey), 1303891443); } if (!$this->packageManager->isPackageActive($siteResourcesPackageKey)) { throw new InvalidPackageStateException(sprintf('Package "%s" specified in the XML as site resources package is not active.', $siteResourcesPackageKey), 1303898135); } $site->setSiteResourcesPackageKey($siteResourcesPackageKey); $rootNode = $this->contextFactory->create()->getRootNode(); // We fetch the workspace to be sure it's known to the persistence manager and persist all // so the workspace and site node are persisted before we import any nodes to it. $rootNode->getContext()->getWorkspace(); $this->persistenceManager->persistAll(); $sitesNode = $rootNode->getNode('/sites'); if ($sitesNode === NULL) { $sitesNode = $rootNode->createNode('sites'); } $this->nodeImportService->import($xmlReader, $sitesNode->getPath(), dirname($pathAndFilename) . '/Resources'); } }); if ($site === NULL) { throw new NeosException(sprintf('The XML file did not contain a valid site node.'), 1418999522); } $this->emitSiteImported($site); return $site; }
/** * If site packages already exist and are active, we will deactivate them in order to prevent * interactions with the newly created or imported package (like Content Dimensions being used). * * @param string $activePackageKey Package key of one package which should stay active * @return array deactivated site packages */ protected function deactivateAllOtherSitePackages($activePackageKey) { $sitePackagesToDeactivate = $this->packageManager->getFilteredPackages('active', null, 'typo3-flow-site'); $deactivatedSitePackages = array(); foreach (array_keys($sitePackagesToDeactivate) as $packageKey) { if ($packageKey !== $activePackageKey) { $this->packageManager->deactivatePackage($packageKey); $deactivatedSitePackages[] = $packageKey; } } return $deactivatedSitePackages; }
/** * @param string $packageKey * @return Error|Message */ protected function freezePackage($packageKey) { try { $this->packageManager->freezePackage($packageKey); $message = new Message('Package %s has been frozen', 1343231689, array($packageKey)); } catch (\LogicException $exception) { $message = new Error($exception->getMessage(), 1343231690); } catch (UnknownPackageException $exception) { $message = new Error($exception->getMessage(), 1343231691); } return $message; }
/** * @test */ public function openResolves40CharacterLongPackageKeysUsingThePackageManager() { $packageKey = 'Some.PackageKey.Containing.40.Characters'; mkdir('vfs://Foo/Some/'); file_put_contents('vfs://Foo/Some/Path', 'fixture'); $this->mockPackageManager->expects($this->once())->method('isPackageAvailable')->with($packageKey)->will($this->returnValue(TRUE)); $mockPackage = $this->getMockBuilder(PackageInterface::class)->getMock(); $mockPackage->expects($this->any())->method('getResourcesPath')->will($this->returnValue('vfs://Foo')); $this->mockPackageManager->expects($this->once())->method('getPackage')->with($packageKey)->will($this->returnValue($mockPackage)); $openedPathAndFilename = ''; $this->assertTrue($this->resourceStreamWrapper->open('resource://' . $packageKey . '/Some/Path', 'r', 0, $openedPathAndFilename)); }
/** * 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 = array(); $packages = $this->packageManager->getActivePackages(); foreach ($packages as $packageKey => $package) { /** @var PackageInterface $package */ $publicResourcesPath = Files::concatenatePaths(array($package->getResourcesPath(), 'Public')); if (is_dir($publicResourcesPath)) { $paths[$packageKey] = $publicResourcesPath; } } return $paths; }
/** * @return void */ protected function displayHelpIndex() { $context = $this->bootstrap->getContext(); $this->outputLine('<b>TYPO3 Flow %s ("%s" context)</b>', array($this->packageManager->getPackage('TYPO3.Flow')->getPackageMetaData()->getVersion() ?: FLOW_VERSION_BRANCH, $context)); $this->outputLine('<i>usage: %s <command identifier></i>', array($this->getFlowInvocationString())); $this->outputLine(); $this->outputLine('The following commands are currently available:'); $this->displayShortHelpForCommands($this->commandManager->getAvailableCommands()); $this->outputLine('* = compile time command'); $this->outputLine(); $this->outputLine('See "%s help <commandidentifier>" for more information about a specific command.', array($this->getFlowInvocationString())); $this->outputLine(); }
/** * Returns an array of packages that are available for translation. * * The list includes basically every active package * - minus the ones that are excluded in the configuration * - minus the ones that don't have the needed translation files * * @return array all the available packages */ protected function getAvailablePackages() { $allPackages = $this->packageManager->getActivePackages(); // make sure the packages of the framework are excluded depending on our settings $packages = array(); $packagesToExclude = \TYPO3\Flow\Utility\Arrays::trimExplode(',', $this->settings['packagesToExclude']); foreach ($allPackages as $package) { if (!in_array($package->getPackageKey(), $packagesToExclude) && $this->hasXliffFilesInDefaultDirectories($package)) { $packages[] = $package; } } return $packages; }
/** * 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 \TYPO3\Flow\Error\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 = array(); $activePackages = $this->packageManager->getActivePackages(); foreach ($activePackages as $package) { $packageKey = $package->getPackageKey(); $packageSchemaPath = \TYPO3\Flow\Utility\Files::concatenatePaths(array($package->getResourcesPath(), 'Private/Schema')); if (is_dir($packageSchemaPath)) { $packageSchemaFiles = \TYPO3\Flow\Utility\Files::readDirectoryRecursively($packageSchemaPath, '.schema.yaml'); foreach ($packageSchemaFiles 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[] = array('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 = \TYPO3\Flow\Utility\Arrays::getValueByPath($configuration, $schemaFileInfo['path']); } else { $data = $configuration; } if (empty($data)) { $result->addNotice(new Notice('No configuration found, skipping schema "%s".', 1364985445, array(substr($schemaFileInfo['file'], strlen(FLOW_PATH_ROOT))))); } else { $parsedSchema = \Symfony\Component\Yaml\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; }