/**
  * Create a package, given the package key
  *
  * @param string $packageKey The package key of the new package
  * @param \TYPO3\Flow\Package\MetaData $packageMetaData If specified, this package meta object is used for writing the Package.xml file, otherwise a rudimentary Package.xml file is created
  * @param string $packagesPath If specified, the package will be created in this path, otherwise the default "Application" directory is used
  * @param string $packageType
  * @param array $manifest A composer manifest as associative array. This is a preparation for the signature change in Flow 4.0. If you use this argument, then $packageMetaData and $packageType will be ignored.
  * @return PackageInterface The newly created package
  *
  * @throws Exception\InvalidPackageKeyException
  * @throws Exception\PackageKeyAlreadyExistsException
  * @api
  * @deprecated The method signature of this method will change with Flow 4.0, the method itself will stay.
  * @see \TYPO3\Flow\Package\PackageManagerInterface::createPackage
  */
 public function createPackage($packageKey, \TYPO3\Flow\Package\MetaData $packageMetaData = null, $packagesPath = null, $packageType = 'neos-package', array $manifest = null)
 {
     if (!$this->isPackageKeyValid($packageKey)) {
         throw new Exception\InvalidPackageKeyException('The package key "' . $packageKey . '" is invalid', 1220722210);
     }
     if ($this->isPackageAvailable($packageKey)) {
         throw new Exception\PackageKeyAlreadyExistsException('The package key "' . $packageKey . '" already exists', 1220722873);
     }
     // TODO: This if and the method used can be removed for Flow 4.0 together with the MetaData classes.
     if ($manifest === null) {
         $manifest = $this->generateManifestFromMetaDataAndType($packageType, $packageMetaData);
     }
     if ($packagesPath === null) {
         $packagesPath = 'Application';
         $packageType = isset($manifest['type']) ? $manifest['type'] : PackageInterface::DEFAULT_COMPOSER_TYPE;
         if (is_array($this->settings['package']['packagesPathByType']) && isset($this->settings['package']['packagesPathByType'][$packageType])) {
             $packagesPath = $this->settings['package']['packagesPathByType'][$packageType];
         }
         $packagesPath = Files::getUnixStylePath(Files::concatenatePaths([$this->packagesBasePath, $packagesPath]));
     }
     $packagePath = Files::concatenatePaths([$packagesPath, $packageKey]) . '/';
     Files::createDirectoryRecursively($packagePath);
     foreach ([PackageInterface::DIRECTORY_CLASSES, PackageInterface::DIRECTORY_CONFIGURATION, PackageInterface::DIRECTORY_DOCUMENTATION, PackageInterface::DIRECTORY_RESOURCES, PackageInterface::DIRECTORY_TESTS_UNIT, PackageInterface::DIRECTORY_TESTS_FUNCTIONAL] as $path) {
         Files::createDirectoryRecursively(Files::concatenatePaths([$packagePath, $path]));
     }
     $manifest = ComposerUtility::writeComposerManifest($packagePath, $packageKey, $manifest);
     $refreshedPackageStatesConfiguration = $this->rescanPackages(false);
     $this->packageStatesConfiguration = $refreshedPackageStatesConfiguration;
     $this->registerPackageFromStateConfiguration($manifest['name'], $this->packageStatesConfiguration['packages'][$manifest['name']]);
     return $this->packages[$packageKey];
 }
 /**
  * @test
  */
 public function packageStatesConfigurationContainsRelativePaths()
 {
     $packageKeys = array('RobertLemke.Flow.NothingElse' . md5(uniqid(mt_rand(), true)), 'TYPO3.Flow' . md5(uniqid(mt_rand(), true)), 'TYPO3.YetAnotherTestPackage' . md5(uniqid(mt_rand(), true)));
     foreach ($packageKeys as $packageKey) {
         $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
         mkdir($packagePath, 0770, true);
         mkdir($packagePath . 'Classes');
         ComposerUtility::writeComposerManifest($packagePath, $packageKey, ['type' => 'flow-test', 'autoload' => []]);
     }
     $packageManager = $this->getAccessibleMock(PackageManager::class, array('updateShortcuts', 'emitPackageStatesUpdated'), array(), '', false);
     $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
     $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
     $packageFactory = new \TYPO3\Flow\Package\PackageFactory($packageManager);
     $this->inject($packageManager, 'packageFactory', $packageFactory);
     $packageManager->_set('packages', array());
     $actualPackageStatesConfiguration = $packageManager->rescanPackages();
     $expectedPackageStatesConfiguration = array();
     foreach ($packageKeys as $packageKey) {
         $composerName = ComposerUtility::getComposerPackageNameFromPackageKey($packageKey);
         $expectedPackageStatesConfiguration[$composerName] = array('state' => 'active', 'packagePath' => 'Application/' . $packageKey . '/', 'composerName' => $composerName, 'packageClassInformation' => array(), 'packageKey' => $packageKey, 'autoloadConfiguration' => []);
     }
     $this->assertEquals($expectedPackageStatesConfiguration, $actualPackageStatesConfiguration['packages']);
 }