vendor/pimcore/pimcore/bundles/GeneratorBundle/Command/BaseGenerateBundleCommand.php line 23

Open in your IDE?
  1. <?php
  2. namespace Pimcore\Bundle\GeneratorBundle\Command;
  3. use Pimcore\Bundle\GeneratorBundle\Generator\BundleGenerator;
  4. use Pimcore\Bundle\GeneratorBundle\Manipulator\ConfigurationManipulator;
  5. use Pimcore\Bundle\GeneratorBundle\Manipulator\KernelManipulator;
  6. use Pimcore\Bundle\GeneratorBundle\Manipulator\RoutingManipulator;
  7. use Pimcore\Bundle\GeneratorBundle\Model\Bundle;
  8. use Symfony\Component\Console\Input\InputInterface;
  9. use Symfony\Component\Console\Input\InputOption;
  10. use Symfony\Component\Console\Output\OutputInterface;
  11. use Symfony\Component\Console\Question\ConfirmationQuestion;
  12. use Symfony\Component\Console\Question\Question;
  13. use Symfony\Component\HttpKernel\KernelInterface;
  14. /**
  15.  * @deprecated
  16.  * Generates bundles.
  17.  *
  18.  * The following class is copied from \Sensio\Bundle\GeneratorBundle\Command\GenerateBundleCommand
  19.  */
  20. class BaseGenerateBundleCommand extends BaseGeneratorCommand
  21. {
  22.     /**
  23.      * @see Command
  24.      */
  25.     protected function configure()
  26.     {
  27.         $this
  28.             ->setName('generate:bundle')
  29.             ->setDescription('Generates a bundle')
  30.             ->setDefinition([
  31.                 new InputOption('namespace'''InputOption::VALUE_REQUIRED'The namespace of the bundle to create'),
  32.                 new InputOption('dir'''InputOption::VALUE_REQUIRED'The directory where to create the bundle''src/'),
  33.                 new InputOption('bundle-name'''InputOption::VALUE_REQUIRED'The optional bundle name'),
  34.                 new InputOption('format'''InputOption::VALUE_REQUIRED'Use the format for configuration files (php, xml, yml, or annotation)'),
  35.                 new InputOption('shared'''InputOption::VALUE_NONE'Are you planning on sharing this bundle across multiple applications?'),
  36.             ])
  37.             ->setHelp(<<<EOT
  38. The <info>%command.name%</info> command helps you generates new bundles.
  39. By default, the command interacts with the developer to tweak the generation.
  40. Any passed option will be used as a default value for the interaction
  41. (<comment>--namespace</comment> is the only one needed if you follow the
  42. conventions):
  43. <info>php %command.full_name% --namespace=Acme/BlogBundle</info>
  44. Note that you can use <comment>/</comment> instead of <comment>\\ </comment>for the namespace delimiter to avoid any
  45. problems.
  46. If you want to disable any user interaction, use <comment>--no-interaction</comment> but don't forget to pass all needed options:
  47. <info>php %command.full_name% --namespace=Acme/BlogBundle --dir=src [--bundle-name=...] --no-interaction</info>
  48. Note that the bundle namespace must end with "Bundle".
  49. EOT
  50.             )
  51.         ;
  52.     }
  53.     /**
  54.      * @see Command
  55.      *
  56.      * @throws \InvalidArgumentException When namespace doesn't end with Bundle
  57.      * @throws \RuntimeException         When bundle can't be executed
  58.      *
  59.      * @return int
  60.      */
  61.     protected function execute(InputInterface $inputOutputInterface $output)
  62.     {
  63.         $questionHelper $this->getQuestionHelper();
  64.         $bundle $this->createBundleObject($input);
  65.         $questionHelper->writeSection($output'Bundle generation');
  66.         /** @var BundleGenerator $generator */
  67.         $generator $this->getGenerator();
  68.         $output->writeln(sprintf(
  69.             '> Generating a sample bundle skeleton into <info>%s</info>',
  70.             $this->makePathRelative($bundle->getTargetDirectory())
  71.         ));
  72.         $generator->generateBundle($bundle);
  73.         $errors = [];
  74.         $runner $questionHelper->getRunner($output$errors);
  75.         // check that the namespace is already autoloaded
  76.         $runner($this->checkAutoloader($output$bundle));
  77.         // register the bundle in the Kernel class
  78.         $runner($this->updateKernel($output$this->getContainer()->get('kernel'), $bundle));
  79.         // routing importing
  80.         $runner($this->updateRouting($output$bundle));
  81.         if (!$bundle->shouldGenerateDependencyInjectionDirectory()) {
  82.             // we need to import their services.yml manually!
  83.             $runner($this->updateConfiguration($output$bundle));
  84.         }
  85.         $questionHelper->writeGeneratorSummary($output$errors);
  86.         return 0;
  87.     }
  88.     protected function interact(InputInterface $inputOutputInterface $output)
  89.     {
  90.         $questionHelper $this->getQuestionHelper();
  91.         $questionHelper->writeSection($output'Welcome to the Symfony bundle generator!');
  92.         /*
  93.          * shared option
  94.          */
  95.         $shared $input->getOption('shared');
  96.         // ask, but use $shared as the default
  97.         $question = new ConfirmationQuestion($questionHelper->getQuestion(
  98.             'Are you planning on sharing this bundle across multiple applications?',
  99.             $shared 'yes' 'no'
  100.         ), $shared);
  101.         $shared $questionHelper->ask($input$output$question);
  102.         $input->setOption('shared'$shared);
  103.         /*
  104.          * namespace option
  105.          */
  106.         $namespace $input->getOption('namespace');
  107.         $output->writeln([
  108.             '',
  109.             'Your application code must be written in <comment>bundles</comment>. This command helps',
  110.             'you generate them easily.',
  111.             '',
  112.         ]);
  113.         $askForBundleName true;
  114.         if ($shared) {
  115.             // a shared bundle, so it should probably have a vendor namespace
  116.             $output->writeln([
  117.                 'Each bundle is hosted under a namespace (like <comment>Acme/BlogBundle</comment>).',
  118.                 'The namespace should begin with a "vendor" name like your company name, your',
  119.                 'project name, or your client name, followed by one or more optional category',
  120.                 'sub-namespaces, and it should end with the bundle name itself',
  121.                 '(which must have <comment>Bundle</comment> as a suffix).',
  122.                 '',
  123.                 'See http://symfony.com/doc/current/cookbook/bundles/best_practices.html#bundle-name for more',
  124.                 'details on bundle naming conventions.',
  125.                 '',
  126.                 'Use <comment>/</comment> instead of <comment>\\ </comment>for the namespace delimiter to avoid any problems.',
  127.                 '',
  128.             ]);
  129.             $question = new Question($questionHelper->getQuestion(
  130.                 'Bundle namespace',
  131.                 $namespace
  132.             ), $namespace);
  133.             $question->setValidator(function ($answer) {
  134.                 return Validators::validateBundleNamespace($answertrue);
  135.             });
  136.             $namespace $questionHelper->ask($input$output$question);
  137.         } else {
  138.             // a simple application bundle
  139.             $output->writeln([
  140.                 'Give your bundle a descriptive name, like <comment>BlogBundle</comment>.',
  141.             ]);
  142.             $question = new Question($questionHelper->getQuestion(
  143.                 'Bundle name',
  144.                 $namespace
  145.             ), $namespace);
  146.             $question->setValidator(function ($inputNamespace) {
  147.                 return Validators::validateBundleNamespace($inputNamespacefalse);
  148.             });
  149.             $namespace $questionHelper->ask($input$output$question);
  150.             if (strpos($namespace'\\') === false) {
  151.                 // this is a bundle name (FooBundle) not a namespace (Acme\FooBundle)
  152.                 // so this is the bundle name (and it is also the namespace)
  153.                 $input->setOption('bundle-name'$namespace);
  154.                 $askForBundleName false;
  155.             }
  156.         }
  157.         $input->setOption('namespace'$namespace);
  158.         /*
  159.          * bundle-name option
  160.          */
  161.         if ($askForBundleName) {
  162.             $bundle $input->getOption('bundle-name');
  163.             // no bundle yet? Get a default from the namespace
  164.             if (!$bundle) {
  165.                 $bundle strtr($namespace, ['\\Bundle\\' => '''\\' => '']);
  166.             }
  167.             $output->writeln([
  168.                 '',
  169.                 'In your code, a bundle is often referenced by its name. It can be the',
  170.                 'concatenation of all namespace parts but it\'s really up to you to come',
  171.                 'up with a unique name (a good practice is to start with the vendor name).',
  172.                 'Based on the namespace, we suggest <comment>'.$bundle.'</comment>.',
  173.                 '',
  174.             ]);
  175.             $question = new Question($questionHelper->getQuestion(
  176.                 'Bundle name',
  177.                 $bundle
  178.             ), $bundle);
  179.             $question->setValidator(
  180.                 ['Pimcore\Bundle\GeneratorBundle\Command\Validators''validateBundleName']
  181.             );
  182.             $bundle $questionHelper->ask($input$output$question);
  183.             $input->setOption('bundle-name'$bundle);
  184.         }
  185.         /*
  186.          * dir option
  187.          */
  188.         // defaults to src/ in the option
  189.         $dir $input->getOption('dir');
  190.         $output->writeln([
  191.             '',
  192.             'Bundles are usually generated into the <info>src/</info> directory. Unless you\'re',
  193.             'doing something custom, hit enter to keep this default!',
  194.             '',
  195.         ]);
  196.         $question = new Question($questionHelper->getQuestion(
  197.             'Target Directory',
  198.             $dir
  199.         ), $dir);
  200.         $dir $questionHelper->ask($input$output$question);
  201.         $input->setOption('dir'$dir);
  202.         /*
  203.          * format option
  204.          */
  205.         $format $input->getOption('format');
  206.         if (!$format) {
  207.             $format $shared 'xml' 'annotation';
  208.         }
  209.         $output->writeln([
  210.             '',
  211.             'What format do you want to use for your generated configuration?',
  212.             '',
  213.         ]);
  214.         $question = new Question($questionHelper->getQuestion(
  215.             'Configuration format (annotation, yml, xml, php)',
  216.             $format
  217.         ), $format);
  218.         $question->setValidator(function ($format) {
  219.             return Validators::validateFormat($format);
  220.         });
  221.         $question->setAutocompleterValues(['annotation''yml''xml''php']);
  222.         $format $questionHelper->ask($input$output$question);
  223.         $input->setOption('format'$format);
  224.     }
  225.     protected function checkAutoloader(OutputInterface $outputBundle $bundle)
  226.     {
  227.         $output->writeln('> Checking that the bundle is autoloaded');
  228.         if (!class_exists($bundle->getBundleClassName())) {
  229.             return [
  230.                 '- Edit the <comment>composer.json</comment> file and register the bundle',
  231.                 '  namespace in the "autoload" section:',
  232.                 '',
  233.             ];
  234.         }
  235.     }
  236.     protected function updateKernel(OutputInterface $outputKernelInterface $kernelBundle $bundle)
  237.     {
  238.         $kernelManipulator = new KernelManipulator($kernel);
  239.         $output->writeln(sprintf(
  240.             '> Enabling the bundle inside <info>%s</info>',
  241.             $this->makePathRelative($kernelManipulator->getFilename())
  242.         ));
  243.         try {
  244.             $ret $kernelManipulator->addBundle($bundle->getBundleClassName());
  245.             if (!$ret) {
  246.                 $reflected = new \ReflectionObject($kernel);
  247.                 return [
  248.                     sprintf('- Edit <comment>%s</comment>'$reflected->getFilename()),
  249.                     '  and add the following bundle in the <comment>AppKernel::registerBundles()</comment> method:',
  250.                     '',
  251.                     sprintf('    <comment>new %s(),</comment>'$bundle->getBundleClassName()),
  252.                     '',
  253.                 ];
  254.             }
  255.         } catch (\RuntimeException $e) {
  256.             return [
  257.                 sprintf('Bundle <comment>%s</comment> is already defined in <comment>AppKernel::registerBundles()</comment>.'$bundle->getBundleClassName()),
  258.                 '',
  259.             ];
  260.         }
  261.     }
  262.     protected function updateRouting(OutputInterface $outputBundle $bundle)
  263.     {
  264.         $targetRoutingPath $this->getContainer()->getParameter('kernel.root_dir').'/config/routing.yml';
  265.         $output->writeln(sprintf(
  266.             '> Importing the bundle\'s routes from the <info>%s</info> file',
  267.             $this->makePathRelative($targetRoutingPath)
  268.         ));
  269.         $routing = new RoutingManipulator($targetRoutingPath);
  270.         try {
  271.             $ret $routing->addResource($bundle->getName(), $bundle->getConfigurationFormat());
  272.             if (!$ret) {
  273.                 if ('annotation' === $bundle->getConfigurationFormat()) {
  274.                     $help sprintf("        <comment>resource: \"@%s/Controller/\"</comment>\n        <comment>type:     annotation</comment>\n"$bundle->getName());
  275.                 } else {
  276.                     $help sprintf("        <comment>resource: \"@%s/Resources/config/routing.%s\"</comment>\n"$bundle->getName(), $bundle->getConfigurationFormat());
  277.                 }
  278.                 $help .= "        <comment>prefix:   /</comment>\n";
  279.                 return [
  280.                     '- Import the bundle\'s routing resource in the app\'s main routing file:',
  281.                     '',
  282.                     sprintf('    <comment>%s:</comment>'$bundle->getName()),
  283.                     $help,
  284.                     '',
  285.                 ];
  286.             }
  287.         } catch (\RuntimeException $e) {
  288.             return [
  289.                 sprintf('Bundle <comment>%s</comment> is already imported.'$bundle->getName()),
  290.                 '',
  291.             ];
  292.         }
  293.     }
  294.     protected function updateConfiguration(OutputInterface $outputBundle $bundle)
  295.     {
  296.         $targetConfigurationPath $this->getContainer()->getParameter('kernel.root_dir').'/config/config.yml';
  297.         $output->writeln(sprintf(
  298.             '> Importing the bundle\'s %s from the <info>%s</info> file',
  299.             $bundle->getServicesConfigurationFilename(),
  300.             $this->makePathRelative($targetConfigurationPath)
  301.         ));
  302.         $manipulator = new ConfigurationManipulator($targetConfigurationPath);
  303.         try {
  304.             $manipulator->addResource($bundle);
  305.         } catch (\RuntimeException $e) {
  306.             return [
  307.                 sprintf('- Import the bundle\'s "%s" resource in the app\'s main configuration file:'$bundle->getServicesConfigurationFilename()),
  308.                 '',
  309.                 $manipulator->getImportCode($bundle),
  310.                 '',
  311.             ];
  312.         }
  313.     }
  314.     /**
  315.      * Creates the Bundle object based on the user's (non-interactive) input.
  316.      *
  317.      * @param InputInterface $input
  318.      *
  319.      * @return Bundle
  320.      */
  321.     protected function createBundleObject(InputInterface $input)
  322.     {
  323.         foreach (['namespace''dir'] as $option) {
  324.             if (null === $input->getOption($option)) {
  325.                 throw new \RuntimeException(sprintf('The "%s" option must be provided.'$option));
  326.             }
  327.         }
  328.         $shared $input->getOption('shared');
  329.         $namespace Validators::validateBundleNamespace($input->getOption('namespace'), $shared);
  330.         if (!$bundleName $input->getOption('bundle-name')) {
  331.             $bundleName strtr($namespace, ['\\' => '']);
  332.         }
  333.         $bundleName Validators::validateBundleName($bundleName);
  334.         $dir $input->getOption('dir');
  335.         if (null === $input->getOption('format')) {
  336.             $input->setOption('format''annotation');
  337.         }
  338.         $format Validators::validateFormat($input->getOption('format'));
  339.         // an assumption that the kernel root dir is in a directory (like app/)
  340.         $projectRootDirectory $this->getContainer()->getParameter('kernel.root_dir').'/..';
  341.         if (!$this->getContainer()->get('filesystem')->isAbsolutePath($dir)) {
  342.             $dir $projectRootDirectory.'/'.$dir;
  343.         }
  344.         // add trailing / if necessary
  345.         $dir '/' === substr($dir, -11) ? $dir $dir.'/';
  346.         $bundle = new Bundle(
  347.             $namespace,
  348.             $bundleName,
  349.             $dir,
  350.             $format,
  351.             $shared
  352.         );
  353.         // not shared - put the tests in the root
  354.         if (!$shared) {
  355.             $testsDir $projectRootDirectory.'/tests/'.$bundleName;
  356.             $bundle->setTestsDirectory($testsDir);
  357.         }
  358.         return $bundle;
  359.     }
  360.     protected function createGenerator()
  361.     {
  362.         return new BundleGenerator();
  363.     }
  364. }