vendor/sonata-project/admin-bundle/src/Command/GenerateAdminCommand.php line 35

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of the Sonata Project package.
  5.  *
  6.  * (c) Thomas Rabaix <[email protected]>
  7.  *
  8.  * For the full copyright and license information, please view the LICENSE
  9.  * file that was distributed with this source code.
  10.  */
  11. namespace Sonata\AdminBundle\Command;
  12. use Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle;
  13. use Sonata\AdminBundle\Admin\Pool;
  14. use Sonata\AdminBundle\Controller\CRUDController;
  15. use Sonata\AdminBundle\Generator\AdminGenerator;
  16. use Sonata\AdminBundle\Generator\ControllerGenerator;
  17. use Sonata\AdminBundle\Manipulator\ServicesManipulator;
  18. use Sonata\AdminBundle\Model\ModelManagerInterface;
  19. use Symfony\Bundle\FrameworkBundle\Console\Application;
  20. use Symfony\Component\Console\Input\InputArgument;
  21. use Symfony\Component\Console\Input\InputInterface;
  22. use Symfony\Component\Console\Input\InputOption;
  23. use Symfony\Component\Console\Output\OutputInterface;
  24. use Symfony\Component\DependencyInjection\Container;
  25. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  26. use Symfony\Component\HttpKernel\KernelInterface;
  27. @trigger_error(
  28.     'The '.__NAMESPACE__.'\GenerateAdminCommand class is deprecated since 3.55 in favor of Maker Bundle.'
  29.     .' Install symfony/maker-bundle and use $ bin/console make:sonata:admin instead',
  30.     E_USER_DEPRECATED
  31. );
  32. /**
  33.  * @final since sonata-project/admin-bundle 3.52
  34.  *
  35.  * Remove this class after dropping support symfony < 4.2.0
  36.  *
  37.  * @author Marek Stipek <[email protected]>
  38.  * @author Simon Cosandey <[email protected]>
  39.  */
  40. class GenerateAdminCommand extends QuestionableCommand
  41. {
  42.     protected static $defaultName 'sonata:admin:generate';
  43.     /**
  44.      * @var Pool
  45.      */
  46.     private $pool;
  47.     /**
  48.      * An array of model managers indexed by their service ids.
  49.      *
  50.      * @var ModelManagerInterface[]
  51.      */
  52.     private $managerTypes = [];
  53.     public function __construct(Pool $pool, array $managerTypes)
  54.     {
  55.         $this->pool $pool;
  56.         $this->managerTypes $managerTypes;
  57.         parent::__construct();
  58.     }
  59.     public function configure()
  60.     {
  61.         $this
  62.             ->setDescription('Generates an admin class based on the given model class')
  63.             ->addArgument('model'InputArgument::REQUIRED'The fully qualified model class')
  64.             ->addOption('bundle''b'InputOption::VALUE_OPTIONAL'The bundle name')
  65.             ->addOption('admin''a'InputOption::VALUE_OPTIONAL'The admin class basename')
  66.             ->addOption('controller''c'InputOption::VALUE_OPTIONAL'The controller class basename')
  67.             ->addOption('manager''m'InputOption::VALUE_OPTIONAL'The model manager type')
  68.             ->addOption('services''y'InputOption::VALUE_OPTIONAL'The services YAML file''services.yml')
  69.             ->addOption('id''i'InputOption::VALUE_OPTIONAL'The admin service ID')
  70.         ;
  71.     }
  72.     public function isEnabled()
  73.     {
  74.         return class_exists(SensioGeneratorBundle::class);
  75.     }
  76.     /**
  77.      * @param string $managerType
  78.      *
  79.      * @throws \InvalidArgumentException
  80.      *
  81.      * @return string
  82.      */
  83.     public function validateManagerType($managerType)
  84.     {
  85.         $managerTypes $this->getAvailableManagerTypes();
  86.         if (!isset($managerTypes[$managerType])) {
  87.             throw new \InvalidArgumentException(sprintf(
  88.                 'Invalid manager type "%s". Available manager types are "%s".',
  89.                 $managerType,
  90.                 implode('", "'array_keys($managerTypes))
  91.             ));
  92.         }
  93.         return $managerType;
  94.     }
  95.     protected function execute(InputInterface $inputOutputInterface $output)
  96.     {
  97.         $modelClass Validators::validateClass($input->getArgument('model'));
  98.         $modelClassBasename current(\array_slice(explode('\\'$modelClass), -1));
  99.         $bundle $this->getBundle($input->getOption('bundle') ?: $this->getBundleNameFromClass($modelClass));
  100.         $adminClassBasename $input->getOption('admin') ?: $modelClassBasename.'Admin';
  101.         $adminClassBasename Validators::validateAdminClassBasename($adminClassBasename);
  102.         $managerType $input->getOption('manager') ?: $this->getDefaultManagerType();
  103.         $modelManager $this->getModelManager($managerType);
  104.         $skeletonDirectory __DIR__.'/../Resources/skeleton';
  105.         $adminGenerator = new AdminGenerator($modelManager$skeletonDirectory);
  106.         try {
  107.             $adminGenerator->generate($bundle$adminClassBasename$modelClass);
  108.             $output->writeln(sprintf(
  109.                 '%sThe admin class "<info>%s</info>" has been generated under the file "<info>%s</info>".',
  110.                 PHP_EOL,
  111.                 $adminGenerator->getClass(),
  112.                 realpath($adminGenerator->getFile())
  113.             ));
  114.         } catch (\Exception $e) {
  115.             $this->writeError($output$e->getMessage());
  116.         }
  117.         $controllerName CRUDController::class;
  118.         if ($controllerClassBasename $input->getOption('controller')) {
  119.             $controllerClassBasename Validators::validateControllerClassBasename($controllerClassBasename);
  120.             $controllerGenerator = new ControllerGenerator($skeletonDirectory);
  121.             try {
  122.                 $controllerGenerator->generate($bundle$controllerClassBasename);
  123.                 $controllerName $controllerGenerator->getClass();
  124.                 $output->writeln(sprintf(
  125.                     '%sThe controller class "<info>%s</info>" has been generated under the file "<info>%s</info>".',
  126.                     PHP_EOL,
  127.                     $controllerName,
  128.                     realpath($controllerGenerator->getFile())
  129.                 ));
  130.             } catch (\Exception $e) {
  131.                 $this->writeError($output$e->getMessage());
  132.             }
  133.         }
  134.         if ($servicesFile $input->getOption('services')) {
  135.             $adminClass $adminGenerator->getClass();
  136.             $file sprintf('%s/Resources/config/%s'$bundle->getPath(), $servicesFile);
  137.             $servicesManipulator = new ServicesManipulator($file);
  138.             try {
  139.                 $id $input->getOption('id') ?: $this->getAdminServiceId($bundle->getName(), $adminClassBasename);
  140.                 $servicesManipulator->addResource($id$modelClass$adminClass$controllerName$managerType);
  141.                 $output->writeln(sprintf(
  142.                     '%sThe service "<info>%s</info>" has been appended to the file <info>"%s</info>".',
  143.                     PHP_EOL,
  144.                     $id,
  145.                     realpath($file)
  146.                 ));
  147.             } catch (\Exception $e) {
  148.                 $this->writeError($output$e->getMessage());
  149.             }
  150.         }
  151.         return 0;
  152.     }
  153.     protected function interact(InputInterface $inputOutputInterface $output)
  154.     {
  155.         $questionHelper $this->getQuestionHelper();
  156.         $questionHelper->writeSection($output'Welcome to the Sonata admin generator');
  157.         $modelClass $this->askAndValidate(
  158.             $input,
  159.             $output,
  160.             'The fully qualified model class',
  161.             $input->getArgument('model'),
  162.             'Sonata\AdminBundle\Command\Validators::validateClass'
  163.         );
  164.         $modelClassBasename current(\array_slice(explode('\\'$modelClass), -1));
  165.         $bundleName $this->askAndValidate(
  166.             $input,
  167.             $output,
  168.             'The bundle name',
  169.             $input->getOption('bundle') ?: $this->getBundleNameFromClass($modelClass),
  170.             'Sensio\Bundle\GeneratorBundle\Command\Validators::validateBundleName'
  171.         );
  172.         $adminClassBasename $this->askAndValidate(
  173.             $input,
  174.             $output,
  175.             'The admin class basename',
  176.             $input->getOption('admin') ?: $modelClassBasename.'Admin',
  177.             'Sonata\AdminBundle\Command\Validators::validateAdminClassBasename'
  178.         );
  179.         if (\count($this->getAvailableManagerTypes()) > 1) {
  180.             $managerType $this->askAndValidate(
  181.                 $input,
  182.                 $output,
  183.                 'The manager type',
  184.                 $input->getOption('manager') ?: $this->getDefaultManagerType(),
  185.                 [$this'validateManagerType']
  186.             );
  187.             $input->setOption('manager'$managerType);
  188.         }
  189.         if ($this->askConfirmation($input$output'Do you want to generate a controller''no''?')) {
  190.             $controllerClassBasename $this->askAndValidate(
  191.                 $input,
  192.                 $output,
  193.                 'The controller class basename',
  194.                 $input->getOption('controller') ?: $modelClassBasename.'AdminController',
  195.                 'Sonata\AdminBundle\Command\Validators::validateControllerClassBasename'
  196.             );
  197.             $input->setOption('controller'$controllerClassBasename);
  198.         }
  199.         if ($this->askConfirmation($input$output'Do you want to update the services YAML configuration file''yes''?')) {
  200.             $path $this->getBundle($bundleName)->getPath().'/Resources/config/';
  201.             $servicesFile $this->askAndValidate(
  202.                 $input,
  203.                 $output,
  204.                 'The services YAML configuration file',
  205.                 is_file($path.'admin.yml') ? 'admin.yml' 'services.yml',
  206.                 'Sonata\AdminBundle\Command\Validators::validateServicesFile'
  207.             );
  208.             $id $this->askAndValidate(
  209.                 $input,
  210.                 $output,
  211.                 'The admin service ID',
  212.                 $this->getAdminServiceId($bundleName$adminClassBasename),
  213.                 'Sonata\AdminBundle\Command\Validators::validateServiceId'
  214.             );
  215.             $input->setOption('services'$servicesFile);
  216.             $input->setOption('id'$id);
  217.         } else {
  218.             $input->setOption('services'false);
  219.         }
  220.         $input->setArgument('model'$modelClass);
  221.         $input->setOption('admin'$adminClassBasename);
  222.         $input->setOption('bundle'$bundleName);
  223.     }
  224.     /**
  225.      * @throws \InvalidArgumentException
  226.      */
  227.     private function getBundleNameFromClass(string $class): ?string
  228.     {
  229.         $application $this->getApplication();
  230.         /* @var $application Application */
  231.         foreach ($application->getKernel()->getBundles() as $bundle) {
  232.             if (=== strpos($class$bundle->getNamespace().'\\')) {
  233.                 return $bundle->getName();
  234.             }
  235.         }
  236.         return null;
  237.     }
  238.     private function getBundle(string $name): BundleInterface
  239.     {
  240.         return $this->getKernel()->getBundle($name);
  241.     }
  242.     private function writeError(OutputInterface $outputstring $message): void
  243.     {
  244.         $output->writeln(sprintf("\n<error>%s</error>"$message));
  245.     }
  246.     /**
  247.      * @throws \RuntimeException
  248.      */
  249.     private function getDefaultManagerType(): string
  250.     {
  251.         if (!$managerTypes $this->getAvailableManagerTypes()) {
  252.             throw new \RuntimeException('There are no model managers registered.');
  253.         }
  254.         return current(array_keys($managerTypes));
  255.     }
  256.     private function getModelManager(string $managerType): ModelManagerInterface
  257.     {
  258.         $modelManager $this->getAvailableManagerTypes()[$managerType];
  259.         \assert($modelManager instanceof ModelManagerInterface);
  260.         return $modelManager;
  261.     }
  262.     private function getAdminServiceId(string $bundleNamestring $adminClassBasename): string
  263.     {
  264.         $prefix 'Bundle' === substr($bundleName, -6) ? substr($bundleName0, -6) : $bundleName;
  265.         $suffix 'Admin' === substr($adminClassBasename, -5) ? substr($adminClassBasename0, -5) : $adminClassBasename;
  266.         $suffix str_replace('\\''.'$suffix);
  267.         return Container::underscore(sprintf(
  268.             '%s.admin.%s',
  269.             $prefix,
  270.             $suffix
  271.         ));
  272.     }
  273.     /**
  274.      * @return string[]
  275.      */
  276.     private function getAvailableManagerTypes(): array
  277.     {
  278.         $managerTypes = [];
  279.         foreach ($this->managerTypes as $id => $manager) {
  280.             $managerType substr($id21);
  281.             $managerTypes[$managerType] = $manager;
  282.         }
  283.         return $managerTypes;
  284.     }
  285.     private function getKernel(): KernelInterface
  286.     {
  287.         /* @var $application Application */
  288.         $application $this->getApplication();
  289.         return $application->getKernel();
  290.     }
  291. }