Write a composer manifest for the package.
/** * @test */ public function packageStatesConfigurationContainsRelativePaths() { $packageKeys = ['RobertLemke.Flow.NothingElse' . md5(uniqid(mt_rand(), true)), 'Neos.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, ['updateShortcuts', 'emitPackageStatesUpdated'], [], '', false); $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/'); $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php'); $packageFactory = new PackageFactory($packageManager); $this->inject($packageManager, 'packageFactory', $packageFactory); $packageManager->_set('packages', []); $actualPackageStatesConfiguration = $packageManager->rescanPackages(); $expectedPackageStatesConfiguration = []; foreach ($packageKeys as $packageKey) { $composerName = ComposerUtility::getComposerPackageNameFromPackageKey($packageKey); $expectedPackageStatesConfiguration[$composerName] = ['state' => 'active', 'packagePath' => 'Application/' . $packageKey . '/', 'composerName' => $composerName, 'packageClassInformation' => [], 'packageKey' => $packageKey, 'autoloadConfiguration' => []]; } $this->assertEquals($expectedPackageStatesConfiguration, $actualPackageStatesConfiguration['packages']); }
/** * Create a package, given the package key * * @param string $packageKey The package key of the new package * @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. * @param string $packagesPath If specified, the package will be created in this path, otherwise the default "Application" directory is used * @return PackageInterface The newly created package * * @throws Exception\PackageKeyAlreadyExistsException * @throws Exception\InvalidPackageKeyException * @throws Exception\PackageKeyAlreadyExistsException * @api */ public function createPackage($packageKey, array $manifest = [], $packagesPath = 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); } 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_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]; }