/** * Sanitize a path, ensuring it is absolute and * if a directory, suffixed by a trailing slash. * * @param string $path * @return string */ protected function sanitizePath($path) { if (empty($path)) { return ''; } $path = Files::getUnixStylePath($path); if (is_dir($path)) { $path = Files::getNormalizedPath($path); } return $path; }
/** * Constructor * * @param string $packageKey Key of this package * @param string $composerName * @param string $packagePath Absolute path to the location of the package's composer manifest * @param array $autoloadConfiguration * @throws Exception\InvalidPackageKeyException */ public function __construct($packageKey, $composerName, $packagePath, array $autoloadConfiguration = []) { $this->autoloadConfiguration = $autoloadConfiguration; $this->packagePath = Files::getNormalizedPath($packagePath); $this->packageKey = $packageKey; $this->composerName = $composerName; }
/** * @test */ public function detectChangesDetectsDeletedFilesOfMonitoredDirectoriesIfPatternIsMatched() { $testPath = vfsStream::url('testDirectory'); // Initially known files per path $knownDirectoriesAndFiles = [Files::getNormalizedPath($testPath) => [$testPath . '/NodeTypes.foo.yaml' => 1]]; // Outcome of the change dection per file $changeDetectionResult = [$testPath . '/NodeTypes.foo.yaml' => ChangeDetectionStrategyInterface::STATUS_DELETED]; // Expected emitted changes for files $expectedEmittedChanges = [$testPath . '/NodeTypes.foo.yaml' => ChangeDetectionStrategyInterface::STATUS_DELETED]; $fileMonitor = $this->setUpFileMonitorForDetection($changeDetectionResult, $expectedEmittedChanges, $knownDirectoriesAndFiles); $fileMonitor->monitorDirectory($testPath, 'NodeTypes(\\..+)?\\.yaml'); $fileMonitor->detectChanges(); }
/** * Read a monitored directory recursively, taking into account filename patterns * * @param string $path The path of a monitored directory * @param string $filenamePattern * @return \Generator<string> A generator returning filenames with full path */ protected function readMonitoredDirectoryRecursively($path, $filenamePattern) { $directories = [Files::getNormalizedPath($path)]; while ($directories !== []) { $currentDirectory = array_pop($directories); if (is_file($currentDirectory . '.flowFileMonitorIgnore')) { continue; } if ($handle = opendir($currentDirectory)) { while (false !== ($filename = readdir($handle))) { if ($filename[0] === '.') { continue; } $pathAndFilename = $currentDirectory . $filename; if (is_dir($pathAndFilename)) { array_push($directories, $pathAndFilename . DIRECTORY_SEPARATOR); } elseif ($filenamePattern === null || preg_match('|' . $filenamePattern . '|', $filename) === 1) { (yield $pathAndFilename); } } closedir($handle); } } }
/** * 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; }
/** * Tries to remove a possibly existing namespace to class path map entry. * * @param string $namespace A namespace mapped to a class path. * @param string $classPath The class path to be removed. * @param string $mappingType The mapping type for this mapping entry. Currently one of self::MAPPING_TYPE_PSR0 or self::MAPPING_TYPE_PSR4 will work. Defaults to self::MAPPING_TYPE_PSR0 * @return void */ protected function removeNamespaceMapEntry($namespace, $classPath, $mappingType = self::MAPPING_TYPE_PSR0) { $unifiedClassPath = Files::getNormalizedPath($classPath); $entryIdentifier = md5($unifiedClassPath . '-' . $mappingType); $currentArray =& $this->packageNamespaces; foreach (explode('\\', rtrim($namespace, '\\')) as $namespacePart) { if (!isset($currentArray[$namespacePart])) { return; } $currentArray =& $currentArray[$namespacePart]; } if (!isset($currentArray['_pathData'])) { return; } if (isset($currentArray['_pathData'][$entryIdentifier])) { unset($currentArray['_pathData'][$entryIdentifier]); if (empty($currentArray['_pathData'])) { unset($currentArray['_pathData']); } } }
/** * Collects the manifest data for all packages in the given package states array * * @param array $packageStates * @return array */ protected function collectPackageManifestData(array $packageStates) { return array_map(function ($packageState) { return ComposerUtility::getComposerManifest(Files::getNormalizedPath(Files::concatenatePaths([$this->packagesBasePath, $packageState['packagePath']]))); }, $packageStates['packages']); }
/** * 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() { $whitelistPaths = array_keys(array_filter((array) $this->settings['scan']['includePaths'])); if ($whitelistPaths === []) { return; } $blacklistPattern = $this->getScanBlacklistPattern(); /** @var PackageInterface $activePackage */ foreach ($this->packageManager->getActivePackages() as $activePackage) { $packageResourcesPath = Files::getNormalizedPath($activePackage->getResourcesPath()); if (!is_dir($packageResourcesPath)) { continue; } $directories = []; foreach ($whitelistPaths as $path) { $scanPath = Files::concatenatePaths(array($packageResourcesPath, $path)); if (is_dir($scanPath)) { array_push($directories, Files::getNormalizedPath($scanPath)); } } while ($directories !== []) { $currentDirectory = array_pop($directories); $relativeDirectory = '/' . str_replace($packageResourcesPath, '', $currentDirectory); if ($blacklistPattern !== '' && preg_match($blacklistPattern, $relativeDirectory) === 1) { continue; } if ($handle = opendir($currentDirectory)) { while (false !== ($filename = readdir($handle))) { if ($filename[0] === '.') { continue; } $pathAndFilename = Files::concatenatePaths([$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); } } } }