/
home
/
obinna
/
html
/
boazapp
/
vendor
/
symfony
/
maker-bundle
/
src
/
Upload File
HOME
<?php /* * This file is part of the Symfony MakerBundle package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bundle\MakerBundle; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException; use Symfony\Bundle\MakerBundle\Util\ClassNameDetails; use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil; use Symfony\Bundle\MakerBundle\Util\TemplateComponentGenerator; /** * @author Javier Eguiluz <javier.eguiluz@gmail.com> * @author Ryan Weaver <weaverryan@gmail.com> */ class Generator { private $fileManager; private $twigHelper; private $pendingOperations = []; private $namespacePrefix; private $phpCompatUtil; private $templateComponentGenerator; public function __construct(FileManager $fileManager, string $namespacePrefix, PhpCompatUtil $phpCompatUtil = null, TemplateComponentGenerator $templateComponentGenerator = null) { $this->fileManager = $fileManager; $this->twigHelper = new GeneratorTwigHelper($fileManager); $this->namespacePrefix = trim($namespacePrefix, '\\'); if (null === $phpCompatUtil) { $phpCompatUtil = new PhpCompatUtil($fileManager); trigger_deprecation('symfony/maker-bundle', '1.25', 'Initializing Generator without providing an instance of PhpCompatUtil is deprecated.'); } $this->phpCompatUtil = $phpCompatUtil; $this->templateComponentGenerator = $templateComponentGenerator; } /** * Generate a new file for a class from a template. * * @param string $className The fully-qualified class name * @param string $templateName Template name in Resources/skeleton to use * @param array $variables Array of variables to pass to the template * * @return string The path where the file will be created * * @throws \Exception */ public function generateClass(string $className, string $templateName, array $variables = []): string { $targetPath = $this->fileManager->getRelativePathForFutureClass($className); if (null === $targetPath) { throw new \LogicException(sprintf('Could not determine where to locate the new class "%s", maybe try with a full namespace like "\\My\\Full\\Namespace\\%s"', $className, Str::getShortClassName($className))); } $variables = array_merge($variables, [ 'class_name' => Str::getShortClassName($className), 'namespace' => Str::getNamespace($className), ]); $this->addOperation($targetPath, $templateName, $variables); return $targetPath; } /** * Generate a normal file from a template. */ public function generateFile(string $targetPath, string $templateName, array $variables = []) { $variables = array_merge($variables, [ 'helper' => $this->twigHelper, ]); $this->addOperation($targetPath, $templateName, $variables); } public function dumpFile(string $targetPath, string $contents) { $this->pendingOperations[$targetPath] = [ 'contents' => $contents, ]; } public function getFileContentsForPendingOperation(string $targetPath): string { if (!isset($this->pendingOperations[$targetPath])) { throw new RuntimeCommandException(sprintf('File "%s" is not in the Generator\'s pending operations', $targetPath)); } $templatePath = $this->pendingOperations[$targetPath]['template']; $parameters = $this->pendingOperations[$targetPath]['variables']; $templateParameters = array_merge($parameters, [ 'relative_path' => $this->fileManager->relativizePath($targetPath), ]); return $this->fileManager->parseTemplate($templatePath, $templateParameters); } /** * Creates a helper object to get data about a class name. * * Examples: * * // App\Entity\FeaturedProduct * $gen->createClassNameDetails('FeaturedProduct', 'Entity'); * $gen->createClassNameDetails('featured product', 'Entity'); * * // App\Controller\FooController * $gen->createClassNameDetails('foo', 'Controller', 'Controller'); * * // App\Controller\Admin\FooController * $gen->createClassNameDetails('Foo\\Admin', 'Controller', 'Controller'); * * // App\Controller\Security\Voter\CoolController * $gen->createClassNameDetails('Cool', 'Security\Voter', 'Voter'); * * // Full class names can also be passed. Imagine the user has an autoload * // rule where Cool\Stuff lives in a "lib/" directory * // Cool\Stuff\BalloonController * $gen->createClassNameDetails('Cool\\Stuff\\Balloon', 'Controller', 'Controller'); * * @param string $name The short "name" that will be turned into the class name * @param string $namespacePrefix Recommended namespace where this class should live, but *without* the "App\\" part * @param string $suffix Optional suffix to guarantee is on the end of the class */ public function createClassNameDetails(string $name, string $namespacePrefix, string $suffix = '', string $validationErrorMessage = ''): ClassNameDetails { $fullNamespacePrefix = $this->namespacePrefix.'\\'.$namespacePrefix; if ('\\' === $name[0]) { // class is already "absolute" - leave it alone (but strip opening \) $className = substr($name, 1); } else { $className = rtrim($fullNamespacePrefix, '\\').'\\'.Str::asClassName($name, $suffix); } Validator::validateClassName($className, $validationErrorMessage); // if this is a custom class, we may be completely different than the namespace prefix // the best way can do, is find the PSR4 prefix and use that if (0 !== strpos($className, $fullNamespacePrefix)) { $fullNamespacePrefix = $this->fileManager->getNamespacePrefixForClass($className); } return new ClassNameDetails($className, $fullNamespacePrefix, $suffix); } public function getRootDirectory(): string { return $this->fileManager->getRootDirectory(); } private function addOperation(string $targetPath, string $templateName, array $variables) { if ($this->fileManager->fileExists($targetPath)) { throw new RuntimeCommandException(sprintf('The file "%s" can\'t be generated because it already exists.', $this->fileManager->relativizePath($targetPath))); } $variables['relative_path'] = $this->fileManager->relativizePath($targetPath); $variables['use_attributes'] = $this->phpCompatUtil->canUseAttributes(); $variables['use_typed_properties'] = $this->phpCompatUtil->canUseTypedProperties(); $variables['use_union_types'] = $this->phpCompatUtil->canUseUnionTypes(); $templatePath = $templateName; if (!file_exists($templatePath)) { $templatePath = __DIR__.'/Resources/skeleton/'.$templateName; if (!file_exists($templatePath)) { throw new \Exception(sprintf('Cannot find template "%s"', $templateName)); } } $this->pendingOperations[$targetPath] = [ 'template' => $templatePath, 'variables' => $variables, ]; } public function hasPendingOperations(): bool { return !empty($this->pendingOperations); } /** * Actually writes and file changes that are pending. */ public function writeChanges() { foreach ($this->pendingOperations as $targetPath => $templateData) { if (isset($templateData['contents'])) { $this->fileManager->dumpFile($targetPath, $templateData['contents']); continue; } $this->fileManager->dumpFile( $targetPath, $this->getFileContentsForPendingOperation($targetPath, $templateData) ); } $this->pendingOperations = []; } public function getRootNamespace(): string { return $this->namespacePrefix; } public function generateController(string $controllerClassName, string $controllerTemplatePath, array $parameters = []): string { return $this->generateClass( $controllerClassName, $controllerTemplatePath, $parameters + [ 'generator' => $this->templateComponentGenerator, 'parent_class_name' => static::getControllerBaseClass()->getShortName(), ] ); } /** * Generate a template file. */ public function generateTemplate(string $targetPath, string $templateName, array $variables = []) { $this->generateFile( $this->fileManager->getPathForTemplate($targetPath), $templateName, $variables ); } public static function getControllerBaseClass(): ClassNameDetails { // @legacy Support for Controller::class can be dropped when FrameworkBundle minimum supported version is >=4.1 $class = method_exists(AbstractController::class, 'getParameter') ? AbstractController::class : Controller::class; return new ClassNameDetails($class, '\\'); } }