/** * Detects if the package contains a package file and returns the path and classname. * * @param string $packageKey The package key * @param string $absolutePackagePath Absolute path to the package * @return array The path to the package file and classname for this package or an empty array if none was found. * @throws Exception\CorruptPackageException * @throws InvalidPackagePathException */ public function detectFlowPackageFilePath($packageKey, $absolutePackagePath) { if (!is_dir($absolutePackagePath)) { throw new InvalidPackagePathException(sprintf('The given package path "%s" is not a readable directory.', $absolutePackagePath), 1445904440); } $composerManifest = ComposerUtility::getComposerManifest($absolutePackagePath); if (!ComposerUtility::isFlowPackageType(isset($composerManifest['type']) ? $composerManifest['type'] : '')) { return []; } $possiblePackageClassPaths = [Files::concatenatePaths(['Classes', 'Package.php']), Files::concatenatePaths(['Classes', str_replace('.', '/', $packageKey), 'Package.php'])]; $foundPackageClassPaths = array_filter($possiblePackageClassPaths, function ($packageClassPathAndFilename) use($absolutePackagePath) { $absolutePackageClassPath = Files::concatenatePaths([$absolutePackagePath, $packageClassPathAndFilename]); return is_file($absolutePackageClassPath); }); if ($foundPackageClassPaths === []) { return []; } if (count($foundPackageClassPaths) > 1) { throw new Exception\CorruptPackageException(sprintf('The package "%s" contains multiple possible "Package.php" files. Please make sure that only one "Package.php" exists in the autoload root(s) of your Flow package.', $packageKey), 1457454840); } $packageClassPathAndFilename = reset($foundPackageClassPaths); $absolutePackageClassPath = Files::concatenatePaths([$absolutePackagePath, $packageClassPathAndFilename]); $packageClassContents = file_get_contents($absolutePackageClassPath); $packageClassName = (new PhpAnalyzer($packageClassContents))->extractFullyQualifiedClassName(); if ($packageClassName === null) { throw new Exception\CorruptPackageException(sprintf('The package "%s" does not contain a valid package class. Check if the file "%s" really contains a class.', $packageKey, $packageClassPathAndFilename), 1327587091); } return ['className' => $packageClassName, 'pathAndFilename' => $packageClassPathAndFilename]; }
/** * Create a new package * * This command creates a new package which contains only the mandatory * directories and files. * * @Flow\FlushesCaches * @param string $packageKey The package key of the package to create * @param string $packageType The package type of the package to create * @return string * @see typo3.kickstart:kickstart:package */ public function createCommand($packageKey, $packageType = PackageInterface::DEFAULT_COMPOSER_TYPE) { if (!$this->packageManager->isPackageKeyValid($packageKey)) { $this->outputLine('The package key "%s" is not valid.', [$packageKey]); $this->quit(1); } if ($this->packageManager->isPackageAvailable($packageKey)) { $this->outputLine('The package "%s" already exists.', [$packageKey]); $this->quit(1); } if (!ComposerUtility::isFlowPackageType($packageType)) { $this->outputLine('The package must be a Flow package, but "%s" is not a valid Flow package type.', [$packageType]); $this->quit(1); } $package = $this->packageManager->createPackage($packageKey, null, null, null, ['type' => $packageType]); $this->outputLine('Created new package "' . $packageKey . '" at "' . $package->getPackagePath() . '".'); }
/** * Derive a flow package key from the given information. * The order of importance is: * * - package install path * - first found autoload namespace * - composer name * * @param string $composerName * @param string $packageType * @param string $packagePath * @param string $autoloadNamespace * @return string */ protected function derivePackageKey($composerName, $packageType = null, $packagePath = null, $autoloadNamespace = null) { $packageKey = ''; if ($packageType !== null && ComposerUtility::isFlowPackageType($packageType)) { $lastSegmentOfPackagePath = substr(trim($packagePath, '/'), strrpos(trim($packagePath, '/'), '/') + 1); if (strpos($lastSegmentOfPackagePath, '.') !== false) { $packageKey = $lastSegmentOfPackagePath; } } if ($autoloadNamespace !== null && ($packageKey === null || $this->isPackageKeyValid($packageKey) === false)) { $packageKey = str_replace('\\', '.', $autoloadNamespace); } if ($packageKey === null || $this->isPackageKeyValid($packageKey) === false) { $packageKey = str_replace('/', '.', $composerName); } $packageKey = trim($packageKey, '.'); $packageKey = preg_replace('/[^A-Za-z0-9.]/', '', $packageKey); return $packageKey; }
/** * Traverses through all class files of the active packages and registers collects the class names as * "all available class names". If the respective Flow settings say so, also function test classes * are registered. * * For performance reasons this function ignores classes whose name ends with "Exception". * * @param array $packages A list of packages to consider * @return array A list of class names which were discovered in the given packages * * @throws \TYPO3\Flow\Configuration\Exception\InvalidConfigurationTypeException */ protected function registerClassFiles(array $packages) { $includeClassesConfiguration = array(); if (isset($this->allSettings['TYPO3']['Flow']['object']['includeClasses'])) { if (!is_array($this->allSettings['TYPO3']['Flow']['object']['includeClasses'])) { throw new \TYPO3\Flow\Configuration\Exception\InvalidConfigurationTypeException('The setting "TYPO3.Flow.object.includeClasses" is invalid, it must be an array if set. Check the syntax in the YAML file.', 1422357285); } $includeClassesConfiguration = $this->allSettings['TYPO3']['Flow']['object']['includeClasses']; } $availableClassNames = array('' => array('DateTime')); /** @var \TYPO3\Flow\Package\Package $package */ foreach ($packages as $packageKey => $package) { if ($package->isObjectManagementEnabled() && (ComposerUtility::isFlowPackageType($package->getComposerManifest('type')) || isset($includeClassesConfiguration[$packageKey]))) { foreach ($package->getClassFiles() as $fullClassName => $path) { if (substr($fullClassName, -9, 9) !== 'Exception') { $availableClassNames[$packageKey][] = $fullClassName; } } if (isset($this->allSettings['TYPO3']['Flow']['object']['registerFunctionalTestClasses']) && $this->allSettings['TYPO3']['Flow']['object']['registerFunctionalTestClasses'] === true) { foreach ($package->getFunctionalTestsClassFiles() as $fullClassName => $path) { if (substr($fullClassName, -9, 9) !== 'Exception') { $availableClassNames[$packageKey][] = $fullClassName; } } } if (isset($availableClassNames[$packageKey]) && is_array($availableClassNames[$packageKey])) { $availableClassNames[$packageKey] = array_unique($availableClassNames[$packageKey]); } } } return $this->filterClassNamesFromConfiguration($availableClassNames, $includeClassesConfiguration); }