/**
  * @return void
  */
 public function up()
 {
     $affectedFiles = array();
     foreach (Files::getRecursiveDirectoryGenerator($this->targetPackageData['path'], null, true) as $pathAndFilename) {
         if (substr($pathAndFilename, -13) !== 'Converter.php') {
             continue;
         }
         $fileContents = file_get_contents($pathAndFilename);
         if (preg_match('/public\\s+function\\s+canConvertFrom\\s*\\(/', $fileContents) === 1) {
             $affectedFiles[] = substr($pathAndFilename, strlen($this->targetPackageData['path']) + 1);
         }
     }
     if ($affectedFiles !== array()) {
         $this->showWarning('Following TypeConverters implement the canConvertFrom() method. The element type of the $targetType argument is no longer cut off, so it might be "array<Some/Element/Type>" instead of just "array" for example. Make sure that this is not an issue or add' . PHP_EOL . '  $targetType = TypeHandling::truncateElementType($targetType);' . PHP_EOL . 'to the beginning of this method body if you\'re not sure:' . PHP_EOL . PHP_EOL . '* ' . implode(PHP_EOL . '* ', $affectedFiles));
     }
 }
 /**
  * Return all Objects stored in this storage filtered by the given directory / filename pattern
  *
  * @param string $pattern A glob compatible directory / filename pattern
  * @param callable $callback Function called after each object
  * @return \Generator<StorageObject>
  */
 public function getObjectsByPathPattern($pattern, callable $callback = null)
 {
     $directories = [];
     if (strpos($pattern, '/') !== false) {
         list($packageKeyPattern, $directoryPattern) = explode('/', $pattern, 2);
     } else {
         $packageKeyPattern = $pattern;
         $directoryPattern = '*';
     }
     // $packageKeyPattern can be used in a future implementation to filter by package key
     $packages = $this->packageManager->getActivePackages();
     foreach ($packages as $packageKey => $package) {
         /** @var PackageInterface $package */
         if ($directoryPattern === '*') {
             $directories[$packageKey][] = $package->getPackagePath();
         } else {
             $directories[$packageKey] = glob($package->getPackagePath() . $directoryPattern, GLOB_ONLYDIR);
         }
     }
     $iteration = 0;
     foreach ($directories as $packageKey => $packageDirectories) {
         foreach ($packageDirectories as $directoryPath) {
             foreach (Files::getRecursiveDirectoryGenerator($directoryPath) as $resourcePathAndFilename) {
                 $pathInfo = UnicodeFunctions::pathinfo($resourcePathAndFilename);
                 $object = new Object();
                 $object->setFilename($pathInfo['basename']);
                 $object->setSha1(sha1_file($resourcePathAndFilename));
                 $object->setMd5(md5_file($resourcePathAndFilename));
                 $object->setFileSize(filesize($resourcePathAndFilename));
                 if (isset($pathInfo['dirname'])) {
                     list(, $path) = explode('/', str_replace($packages[$packageKey]->getResourcesPath(), '', $pathInfo['dirname']), 2);
                     $object->setRelativePublicationPath($packageKey . '/' . $path . '/');
                 }
                 $object->setStream(function () use($resourcePathAndFilename) {
                     return fopen($resourcePathAndFilename, 'r');
                 });
                 (yield $object);
                 if (is_callable($callback)) {
                     call_user_func($callback, $iteration, $object);
                 }
                 $iteration++;
             }
         }
     }
 }
 /**
  * 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 \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 = [];
     $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;
 }
 /**
  * Look for code migration files in the given package path and register them
  * for further action.
  *
  * @param string $packagePath
  * @return void
  */
 protected function registerMigrationFiles($packagePath)
 {
     $packagePath = rtrim($packagePath, '/');
     $packageKey = substr($packagePath, strrpos($packagePath, '/') + 1);
     $migrationsDirectory = Files::concatenatePaths(array($packagePath, 'Migrations/Code'));
     if (!is_dir($migrationsDirectory)) {
         return;
     }
     foreach (Files::getRecursiveDirectoryGenerator($migrationsDirectory, '.php') as $filenameAndPath) {
         /** @noinspection PhpIncludeInspection */
         require_once $filenameAndPath;
         $baseFilename = basename($filenameAndPath, '.php');
         $className = '\\TYPO3\\Flow\\Core\\Migrations\\' . $baseFilename;
         /** @var AbstractMigration $migration */
         $migration = new $className($this, $packageKey);
         $this->migrations[$migration->getVersionNumber()] = $migration;
     }
 }