vendor/easycorp/easyadmin-bundle/src/Command/MakeAdminDashboardCommand.php line 27

Open in your IDE?
  1. <?php
  2. namespace EasyCorp\Bundle\EasyAdminBundle\Command;
  3. use EasyCorp\Bundle\EasyAdminBundle\Maker\ClassMaker;
  4. use Symfony\Component\Console\Command\Command;
  5. use Symfony\Component\Console\Input\InputInterface;
  6. use Symfony\Component\Console\Output\OutputInterface;
  7. use Symfony\Component\Console\Style\SymfonyStyle;
  8. use Symfony\Component\Filesystem\Filesystem;
  9. use Symfony\Component\HttpKernel\Kernel;
  10. use Symfony\Component\String\Slugger\AsciiSlugger;
  11. use function Symfony\Component\String\u;
  12. /**
  13. * Generates the PHP class needed to define a Dashboard controller.
  14. *
  15. * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  16. */
  17. class MakeAdminDashboardCommand extends Command
  18. {
  19. protected static $defaultName = 'make:admin:dashboard';
  20. protected static $defaultDescription = 'Creates a new EasyAdmin Dashboard class';
  21. private $classMaker;
  22. private $projectDir;
  23. public function __construct(ClassMaker $classMaker, string $projectDir, string $name = null)
  24. {
  25. parent::__construct($name);
  26. $this->classMaker = $classMaker;
  27. $this->projectDir = $projectDir;
  28. }
  29. protected function configure()
  30. {
  31. $this
  32. ->setDescription(self::$defaultDescription)
  33. ->setHelp($this->getCommandHelp())
  34. ;
  35. }
  36. /**
  37. * @return int
  38. */
  39. protected function execute(InputInterface $input, OutputInterface $output)
  40. {
  41. $io = new SymfonyStyle($input, $output);
  42. $fs = new Filesystem();
  43. $controllerClassName = $io->ask('Which class name do you prefer for your Dashboard controller?', 'DashboardController', static function (string $className) {
  44. return u($className)->ensureEnd('Controller')->toString();
  45. });
  46. $projectDir = $this->projectDir;
  47. $controllerDir = $io->ask(
  48. sprintf('In which directory of your project do you want to generate "%s"?', $controllerClassName),
  49. 'src/Controller/Admin/',
  50. static function (string $selectedDir) use ($fs, $projectDir) {
  51. $absoluteDir = u($selectedDir)->ensureStart($projectDir.\DIRECTORY_SEPARATOR);
  52. if (null !== $absoluteDir->indexOf('..')) {
  53. throw new \RuntimeException(sprintf('The given directory path can\'t contain ".." and must be relative to the project directory (which is "%s")', $projectDir));
  54. }
  55. $fs->mkdir($absoluteDir);
  56. if (!$fs->exists($absoluteDir)) {
  57. throw new \RuntimeException('The given directory does not exist and couldn\'t be created. Type in the path of an existing directory relative to your project root (e.g. src/Controller/Admin/)');
  58. }
  59. return $absoluteDir->after($projectDir.\DIRECTORY_SEPARATOR)->trimEnd(\DIRECTORY_SEPARATOR)->toString();
  60. }
  61. );
  62. $controllerFilePath = sprintf('%s/%s.php', u($controllerDir)->ensureStart($projectDir.\DIRECTORY_SEPARATOR), $controllerClassName);
  63. if ($fs->exists($controllerFilePath)) {
  64. throw new \RuntimeException(sprintf('The "%s.php" file already exists in the given "%s" directory. Use a different controller name or generate it in a different directory.', $controllerClassName, $controllerDir));
  65. }
  66. $guessedNamespace = u($controllerDir)->equalsTo('src')
  67. ? 'App'
  68. : u($controllerDir)->replace('/', ' ')->replace('\\', ' ')->replace('src ', 'app ')->title(true)->replace(' ', '\\')->trimEnd('\\');
  69. $generatedFilePath = $this->classMaker->make(sprintf('%s/%s.php', $controllerDir, $controllerClassName), 'dashboard.tpl', [
  70. 'namespace' => $guessedNamespace,
  71. 'site_title' => $this->getSiteTitle($this->projectDir),
  72. 'use_php_attributes' => $this->canUsePhpAttributes(),
  73. ]);
  74. $io = new SymfonyStyle($input, $output);
  75. $io->success('Your dashboard class has been successfully generated.');
  76. $io->text('Next steps:');
  77. $io->listing([
  78. sprintf('Configure your Dashboard at "%s"', $generatedFilePath),
  79. 'Run "make:admin:crud" to generate CRUD controllers and link them from the Dashboard.',
  80. ]);
  81. return 0;
  82. }
  83. private function getSiteTitle(string $projectDir): string
  84. {
  85. $guessedTitle = (new AsciiSlugger())
  86. ->slug(basename($projectDir), ' ')
  87. ->title(true)
  88. ->trim()
  89. ->toString();
  90. return empty($guessedTitle) ? 'EasyAdmin' : $guessedTitle;
  91. }
  92. private function canUsePhpAttributes(): bool
  93. {
  94. return Kernel::VERSION_ID >= 50200 && version_compare($this->phpVersionRequiredByProject(), '8.0', '>=');
  95. }
  96. /**
  97. * Based on Symfony\Bundle\MakerBundle\Util\PhpCompatUtil
  98. * https://github.com/symfony/maker-bundle/blob/main/src/Util/PhpCompatUtil.php
  99. * (c) Jesse Rushlow <jr@rushlow.dev>.
  100. */
  101. private function phpVersionRequiredByProject(): string
  102. {
  103. $composerLockPath = sprintf('%s/composer.lock', $this->projectDir);
  104. if (!file_exists($composerLockPath)) {
  105. return \PHP_VERSION;
  106. }
  107. $lockFileContents = json_decode(file_get_contents($composerLockPath), true);
  108. $phpVersionRequirement = $lockFileContents['platform-overrides']['php'] ?? $lockFileContents['platform']['php'] ?? \PHP_VERSION;
  109. // e.g. $phpVersionRequirement = '>=7.2.5', $phpVersion = '7.2.5'
  110. $phpVersion = preg_replace('/[^0-9\.]/', '', $phpVersionRequirement);
  111. return $phpVersion;
  112. }
  113. private function getCommandHelp()
  114. {
  115. return <<<'HELP'
  116. The <info>%command.name%</info> command creates a new EasyAdmin Dashboard class
  117. in your application. Follow the steps shown by the command to configure the
  118. name and location of the new class.
  119. This command never changes or overwrites an existing class, so you can run it
  120. safely as many times as needed to create multiple dashboards.
  121. HELP
  122. ;
  123. }
  124. }