/**
  * 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);
             }
         }
     }
 }