%PDF- %PDF-
Direktori : /home/emtnaeewxm/www/vendor/sensio/generator-bundle/Command/ |
Current File : /home/emtnaeewxm/www/vendor/sensio/generator-bundle/Command/GenerateBundleCommand.php |
<?php /* * This file is part of the Symfony 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 Sensio\Bundle\GeneratorBundle\Command; use Sensio\Bundle\GeneratorBundle\Manipulator\ConfigurationManipulator; use Sensio\Bundle\GeneratorBundle\Model\Bundle; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\HttpKernel\KernelInterface; use Sensio\Bundle\GeneratorBundle\Generator\BundleGenerator; use Sensio\Bundle\GeneratorBundle\Manipulator\KernelManipulator; use Sensio\Bundle\GeneratorBundle\Manipulator\RoutingManipulator; /** * Generates bundles. * * @author Fabien Potencier <fabien@symfony.com> */ class GenerateBundleCommand extends GeneratorCommand { /** * @see Command */ protected function configure() { $this ->setName('generate:bundle') ->setDescription('Generates a bundle') ->setDefinition(array( new InputOption('namespace', '', InputOption::VALUE_REQUIRED, 'The namespace of the bundle to create'), new InputOption('dir', '', InputOption::VALUE_REQUIRED, 'The directory where to create the bundle', 'src/'), new InputOption('bundle-name', '', InputOption::VALUE_REQUIRED, 'The optional bundle name'), new InputOption('format', '', InputOption::VALUE_REQUIRED, 'Use the format for configuration files (php, xml, yml, or annotation)'), new InputOption('shared', '', InputOption::VALUE_NONE, 'Are you planning on sharing this bundle across multiple applications?'), )) ->setHelp(<<<EOT The <info>%command.name%</info> command helps you generates new bundles. By default, the command interacts with the developer to tweak the generation. Any passed option will be used as a default value for the interaction (<comment>--namespace</comment> is the only one needed if you follow the conventions): <info>php %command.full_name% --namespace=Acme/BlogBundle</info> Note that you can use <comment>/</comment> instead of <comment>\\ </comment>for the namespace delimiter to avoid any problems. If you want to disable any user interaction, use <comment>--no-interaction</comment> but don't forget to pass all needed options: <info>php %command.full_name% --namespace=Acme/BlogBundle --dir=src [--bundle-name=...] --no-interaction</info> Note that the bundle namespace must end with "Bundle". EOT ) ; } /** * @see Command * * @throws \InvalidArgumentException When namespace doesn't end with Bundle * @throws \RuntimeException When bundle can't be executed */ protected function execute(InputInterface $input, OutputInterface $output) { $questionHelper = $this->getQuestionHelper(); $bundle = $this->createBundleObject($input); $questionHelper->writeSection($output, 'Bundle generation'); /** @var BundleGenerator $generator */ $generator = $this->getGenerator(); $output->writeln(sprintf( '> Generating a sample bundle skeleton into <info>%s</info>', $this->makePathRelative($bundle->getTargetDirectory()) )); $generator->generateBundle($bundle); $errors = array(); $runner = $questionHelper->getRunner($output, $errors); // check that the namespace is already autoloaded $runner($this->checkAutoloader($output, $bundle)); // register the bundle in the Kernel class $runner($this->updateKernel($output, $this->getContainer()->get('kernel'), $bundle)); // routing importing $runner($this->updateRouting($output, $bundle)); if (!$bundle->shouldGenerateDependencyInjectionDirectory()) { // we need to import their services.yml manually! $runner($this->updateConfiguration($output, $bundle)); } $questionHelper->writeGeneratorSummary($output, $errors); } protected function interact(InputInterface $input, OutputInterface $output) { $questionHelper = $this->getQuestionHelper(); $questionHelper->writeSection($output, 'Welcome to the Symfony bundle generator!'); /* * shared option */ $shared = $input->getOption('shared'); // ask, but use $shared as the default $question = new ConfirmationQuestion($questionHelper->getQuestion( 'Are you planning on sharing this bundle across multiple applications?', $shared ? 'yes' : 'no' ), $shared); $shared = $questionHelper->ask($input, $output, $question); $input->setOption('shared', $shared); /* * namespace option */ $namespace = $input->getOption('namespace'); $output->writeln(array( '', 'Your application code must be written in <comment>bundles</comment>. This command helps', 'you generate them easily.', '', )); $askForBundleName = true; if ($shared) { // a shared bundle, so it should probably have a vendor namespace $output->writeln(array( 'Each bundle is hosted under a namespace (like <comment>Acme/BlogBundle</comment>).', 'The namespace should begin with a "vendor" name like your company name, your', 'project name, or your client name, followed by one or more optional category', 'sub-namespaces, and it should end with the bundle name itself', '(which must have <comment>Bundle</comment> as a suffix).', '', 'See http://symfony.com/doc/current/cookbook/bundles/best_practices.html#bundle-name for more', 'details on bundle naming conventions.', '', 'Use <comment>/</comment> instead of <comment>\\ </comment>for the namespace delimiter to avoid any problems.', '', )); $question = new Question($questionHelper->getQuestion( 'Bundle namespace', $namespace ), $namespace); $question->setValidator(function ($answer) { return Validators::validateBundleNamespace($answer, true); }); $namespace = $questionHelper->ask($input, $output, $question); } else { // a simple application bundle $output->writeln(array( 'Give your bundle a descriptive name, like <comment>BlogBundle</comment>.', )); $question = new Question($questionHelper->getQuestion( 'Bundle name', $namespace ), $namespace); $question->setValidator(function ($inputNamespace) { return Validators::validateBundleNamespace($inputNamespace, false); }); $namespace = $questionHelper->ask($input, $output, $question); if (strpos($namespace, '\\') === false) { // this is a bundle name (FooBundle) not a namespace (Acme\FooBundle) // so this is the bundle name (and it is also the namespace) $input->setOption('bundle-name', $namespace); $askForBundleName = false; } } $input->setOption('namespace', $namespace); /* * bundle-name option */ if ($askForBundleName) { $bundle = $input->getOption('bundle-name'); // no bundle yet? Get a default from the namespace if (!$bundle) { $bundle = strtr($namespace, array('\\Bundle\\' => '', '\\' => '')); } $output->writeln(array( '', 'In your code, a bundle is often referenced by its name. It can be the', 'concatenation of all namespace parts but it\'s really up to you to come', 'up with a unique name (a good practice is to start with the vendor name).', 'Based on the namespace, we suggest <comment>'.$bundle.'</comment>.', '', )); $question = new Question($questionHelper->getQuestion( 'Bundle name', $bundle ), $bundle); $question->setValidator( array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateBundleName') ); $bundle = $questionHelper->ask($input, $output, $question); $input->setOption('bundle-name', $bundle); } /* * dir option */ // defaults to src/ in the option $dir = $input->getOption('dir'); $output->writeln(array( '', 'Bundles are usually generated into the <info>src/</info> directory. Unless you\'re', 'doing something custom, hit enter to keep this default!', '', )); $question = new Question($questionHelper->getQuestion( 'Target Directory', $dir ), $dir); $dir = $questionHelper->ask($input, $output, $question); $input->setOption('dir', $dir); /* * format option */ $format = $input->getOption('format'); if (!$format) { $format = $shared ? 'xml' : 'annotation'; } $output->writeln(array( '', 'What format do you want to use for your generated configuration?', '', )); $question = new Question($questionHelper->getQuestion( 'Configuration format (annotation, yml, xml, php)', $format ), $format); $question->setValidator(function ($format) { return Validators::validateFormat($format); }); $question->setAutocompleterValues(array('annotation', 'yml', 'xml', 'php')); $format = $questionHelper->ask($input, $output, $question); $input->setOption('format', $format); } protected function checkAutoloader(OutputInterface $output, Bundle $bundle) { $output->writeln('> Checking that the bundle is autoloaded'); if (!class_exists($bundle->getBundleClassName())) { return array( '- Edit the <comment>composer.json</comment> file and register the bundle', ' namespace in the "autoload" section:', '', ); } } protected function updateKernel(OutputInterface $output, KernelInterface $kernel, Bundle $bundle) { $kernelManipulator = new KernelManipulator($kernel); $output->writeln(sprintf( '> Enabling the bundle inside <info>%s</info>', $this->makePathRelative($kernelManipulator->getFilename()) )); try { $ret = $kernelManipulator->addBundle($bundle->getBundleClassName()); if (!$ret) { $reflected = new \ReflectionObject($kernel); return array( sprintf('- Edit <comment>%s</comment>', $reflected->getFilename()), ' and add the following bundle in the <comment>AppKernel::registerBundles()</comment> method:', '', sprintf(' <comment>new %s(),</comment>', $bundle->getBundleClassName()), '', ); } } catch (\RuntimeException $e) { return array( sprintf('Bundle <comment>%s</comment> is already defined in <comment>AppKernel::registerBundles()</comment>.', $bundle->getBundleClassName()), '', ); } } protected function updateRouting(OutputInterface $output, Bundle $bundle) { $targetRoutingPath = $this->getContainer()->getParameter('kernel.root_dir').'/config/routing.yml'; $output->writeln(sprintf( '> Importing the bundle\'s routes from the <info>%s</info> file', $this->makePathRelative($targetRoutingPath) )); $routing = new RoutingManipulator($targetRoutingPath); try { $ret = $routing->addResource($bundle->getName(), $bundle->getConfigurationFormat()); if (!$ret) { if ('annotation' === $bundle->getConfigurationFormat()) { $help = sprintf(" <comment>resource: \"@%s/Controller/\"</comment>\n <comment>type: annotation</comment>\n", $bundle->getName()); } else { $help = sprintf(" <comment>resource: \"@%s/Resources/config/routing.%s\"</comment>\n", $bundle->getName(), $bundle->getConfigurationFormat()); } $help .= " <comment>prefix: /</comment>\n"; return array( '- Import the bundle\'s routing resource in the app\'s main routing file:', '', sprintf(' <comment>%s:</comment>', $bundle->getName()), $help, '', ); } } catch (\RuntimeException $e) { return array( sprintf('Bundle <comment>%s</comment> is already imported.', $bundle->getName()), '', ); } } protected function updateConfiguration(OutputInterface $output, Bundle $bundle) { $targetConfigurationPath = $this->getContainer()->getParameter('kernel.root_dir').'/config/config.yml'; $output->writeln(sprintf( '> Importing the bundle\'s %s from the <info>%s</info> file', $bundle->getServicesConfigurationFilename(), $this->makePathRelative($targetConfigurationPath) )); $manipulator = new ConfigurationManipulator($targetConfigurationPath); try { $manipulator->addResource($bundle); } catch (\RuntimeException $e) { return array( sprintf('- Import the bundle\'s "%s" resource in the app\'s main configuration file:', $bundle->getServicesConfigurationFilename()), '', $manipulator->getImportCode($bundle), '', ); } } /** * Creates the Bundle object based on the user's (non-interactive) input. * * @param InputInterface $input * * @return Bundle */ protected function createBundleObject(InputInterface $input) { foreach (array('namespace', 'dir') as $option) { if (null === $input->getOption($option)) { throw new \RuntimeException(sprintf('The "%s" option must be provided.', $option)); } } $shared = $input->getOption('shared'); $namespace = Validators::validateBundleNamespace($input->getOption('namespace'), $shared); if (!$bundleName = $input->getOption('bundle-name')) { $bundleName = strtr($namespace, array('\\' => '')); } $bundleName = Validators::validateBundleName($bundleName); $dir = $input->getOption('dir'); if (null === $input->getOption('format')) { $input->setOption('format', 'annotation'); } $format = Validators::validateFormat($input->getOption('format')); // an assumption that the kernel root dir is in a directory (like app/) $projectRootDirectory = $this->getContainer()->getParameter('kernel.root_dir').'/..'; if (!$this->getContainer()->get('filesystem')->isAbsolutePath($dir)) { $dir = $projectRootDirectory.'/'.$dir; } // add trailing / if necessary $dir = '/' === substr($dir, -1, 1) ? $dir : $dir.'/'; $bundle = new Bundle( $namespace, $bundleName, $dir, $format, $shared ); // not shared - put the tests in the root if (!$shared) { $testsDir = $projectRootDirectory.'/tests/'.$bundleName; $bundle->setTestsDirectory($testsDir); } return $bundle; } protected function createGenerator() { return new BundleGenerator($this->getContainer()->get('filesystem')); } }