%PDF- %PDF-
| Direktori : /home/e/m/t/emtnaeewxm/www/vendor/sensio/generator-bundle/Command/ |
| Current File : /home/e/m/t/emtnaeewxm/www/vendor/sensio/generator-bundle/Command/GenerateControllerCommand.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\RoutingManipulator;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\Question;
use Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper;
use Sensio\Bundle\GeneratorBundle\Generator\ControllerGenerator;
/**
* Generates controllers.
*
* @author Wouter J <wouter@wouterj.nl>
*/
class GenerateControllerCommand extends GeneratorCommand
{
/**
* @see Command
*/
public function configure()
{
$this
->setName('generate:controller')
->setDescription('Generates a controller')
->setDefinition(array(
new InputOption('controller', '', InputOption::VALUE_REQUIRED, 'The name of the controller to create'),
new InputOption('route-format', '', InputOption::VALUE_REQUIRED, 'The format that is used for the routing (yml, xml, php, annotation)', 'annotation'),
new InputOption('template-format', '', InputOption::VALUE_REQUIRED, 'The format that is used for templating (twig, php)', 'twig'),
new InputOption('actions', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The actions in the controller'),
))
->setHelp(<<<EOT
The <info>%command.name%</info> command helps you generates new controllers
inside 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>--controller</comment> is the only one needed if you follow the conventions):
<info>php %command.full_name% --controller=AcmeBlogBundle:Post</info>
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% --controller=AcmeBlogBundle:Post --no-interaction</info>
Every generated file is based on a template. There are default templates but they can
be overridden by placing custom templates in one of the following locations, by order of priority:
<info>BUNDLE_PATH/Resources/SensioGeneratorBundle/skeleton/controller
APP_PATH/Resources/SensioGeneratorBundle/skeleton/controller</info>
You can check https://github.com/sensio/SensioGeneratorBundle/tree/master/Resources/skeleton
in order to know the file structure of the skeleton
EOT
)
;
}
public function execute(InputInterface $input, OutputInterface $output)
{
$questionHelper = $this->getQuestionHelper();
if ($input->isInteractive()) {
$question = new ConfirmationQuestion($questionHelper->getQuestion('Do you confirm generation', 'yes', '?'), true);
if (!$questionHelper->ask($input, $output, $question)) {
$output->writeln('<error>Command aborted</error>');
return 1;
}
}
if (null === $input->getOption('controller')) {
throw new \RuntimeException('The controller option must be provided.');
}
list($bundle, $controller) = $this->parseShortcutNotation($input->getOption('controller'));
if (is_string($bundle)) {
$bundle = Validators::validateBundleName($bundle);
try {
$bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
} catch (\Exception $e) {
$output->writeln(sprintf('<bg=red>Bundle "%s" does not exist.</>', $bundle));
}
}
$questionHelper->writeSection($output, 'Controller generation');
$routingFormat = $input->getOption('route-format');
/** @var ControllerGenerator $generator */
$generator = $this->getGenerator($bundle);
$generator->generate(
$bundle,
$controller,
$routingFormat,
$input->getOption('template-format'),
$this->parseActions($input->getOption('actions'))
);
if ('annotations' === $routingFormat) {
$this->tryUpdateAnnotationRouting($bundle, $controller);
}
$output->writeln('Generating the bundle code: <info>OK</info>');
$questionHelper->writeGeneratorSummary($output, array());
}
public function interact(InputInterface $input, OutputInterface $output)
{
$questionHelper = $this->getQuestionHelper();
$questionHelper->writeSection($output, 'Welcome to the Symfony controller generator');
// namespace
$output->writeln(array(
'',
'Every page, and even sections of a page, are rendered by a <comment>controller</comment>.',
'This command helps you generate them easily.',
'',
'First, you need to give the controller name you want to generate.',
'You must use the shortcut notation like <comment>AcmeBlogBundle:Post</comment>',
'',
));
$bundleNames = array_keys($this->getContainer()->get('kernel')->getBundles());
while (true) {
$question = new Question($questionHelper->getQuestion('Controller name', $input->getOption('controller')), $input->getOption('controller'));
$question->setAutocompleterValues($bundleNames);
$question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateControllerName'));
$controller = $questionHelper->ask($input, $output, $question);
list($bundle, $controller) = $this->parseShortcutNotation($controller);
try {
$b = $this->getContainer()->get('kernel')->getBundle($bundle);
if (!file_exists($b->getPath().'/Controller/'.$controller.'Controller.php')) {
break;
}
$output->writeln(sprintf('<bg=red>Controller "%s:%s" already exists.</>', $bundle, $controller));
} catch (\Exception $e) {
$output->writeln(sprintf('<bg=red>Bundle "%s" does not exist.</>', $bundle));
}
}
$input->setOption('controller', $bundle.':'.$controller);
// routing format
$defaultFormat = (null !== $input->getOption('route-format') ? $input->getOption('route-format') : 'annotation');
$output->writeln(array(
'',
'Determine the format to use for the routing.',
'',
));
$question = new Question($questionHelper->getQuestion('Routing format (php, xml, yml, annotation)', $defaultFormat), $defaultFormat);
$question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateFormat'));
$routeFormat = $questionHelper->ask($input, $output, $question);
$input->setOption('route-format', $routeFormat);
// templating format
$validateTemplateFormat = function ($format) {
if (!in_array($format, array('twig', 'php'))) {
throw new \InvalidArgumentException(sprintf('The template format must be twig or php, "%s" given', $format));
}
return $format;
};
$defaultFormat = (null !== $input->getOption('template-format') ? $input->getOption('template-format') : 'twig');
$output->writeln(array(
'',
'Determine the format to use for templating.',
'',
));
$question = new Question($questionHelper->getQuestion('Template format (twig, php)', $defaultFormat), $defaultFormat);
$question->setValidator($validateTemplateFormat);
$templateFormat = $questionHelper->ask($input, $output, $question);
$input->setOption('template-format', $templateFormat);
// actions
$input->setOption('actions', $this->addActions($input, $output, $questionHelper));
// summary
$questionHelper->writeSection($output, 'Summary before generation');
$output->writeln(array(
sprintf('You are going to generate a "<info>%s:%s</info>" controller', $bundle, $controller),
sprintf('using the "<info>%s</info>" format for the routing and the "<info>%s</info>" format', $routeFormat, $templateFormat),
'for templating',
));
}
public function addActions(InputInterface $input, OutputInterface $output, QuestionHelper $questionHelper)
{
$output->writeln(array(
'',
'Instead of starting with a blank controller, you can add some actions now. An action',
'is a PHP function or method that executes, for example, when a given route is matched.',
'Actions should be suffixed by <comment>Action</comment>.',
'',
));
$templateNameValidator = function ($name) {
if ('default' == $name) {
return $name;
}
if (2 != substr_count($name, ':')) {
throw new \InvalidArgumentException(sprintf('Template name "%s" does not have 2 colons', $name));
}
return $name;
};
$actions = $this->parseActions($input->getOption('actions'));
while (true) {
// name
$output->writeln('');
$question = new Question($questionHelper->getQuestion('New action name (press <return> to stop adding actions)', null), null);
$question->setValidator(function ($name) use ($actions) {
if (null == $name) {
return $name;
}
if (isset($actions[$name])) {
throw new \InvalidArgumentException(sprintf('Action "%s" is already defined', $name));
}
if ('Action' != substr($name, -6)) {
throw new \InvalidArgumentException(sprintf('Name "%s" is not suffixed by Action', $name));
}
return $name;
});
$actionName = $questionHelper->ask($input, $output, $question);
if (!$actionName) {
break;
}
// route
$question = new Question($questionHelper->getQuestion('Action route', '/'.substr($actionName, 0, -6)), '/'.substr($actionName, 0, -6));
$route = $questionHelper->ask($input, $output, $question);
$placeholders = $this->getPlaceholdersFromRoute($route);
// template
$defaultTemplate = $input->getOption('controller').':'.
strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr(substr($actionName, 0, -6), '_', '.')))
.'.html.'.$input->getOption('template-format');
$question = new Question($questionHelper->getQuestion('Template name (optional)', $defaultTemplate), $defaultTemplate);
$template = $questionHelper->ask($input, $output, $question);
// adding action
$actions[$actionName] = array(
'name' => $actionName,
'route' => $route,
'placeholders' => $placeholders,
'template' => $template,
);
}
return $actions;
}
public function parseActions($actions)
{
if (empty($actions) || $actions !== array_values($actions)) {
return $actions;
}
// '$actions' can be an array with just 1 element defining several actions
// separated by white spaces: $actions = array('... ... ...');
if (1 === count($actions)) {
$actions = explode(' ', $actions[0]);
}
$parsedActions = array();
foreach ($actions as $action) {
$data = explode(':', $action);
// name
if (!isset($data[0])) {
throw new \InvalidArgumentException('An action must have a name');
}
$name = array_shift($data);
// route
$route = (isset($data[0]) && '' != $data[0]) ? array_shift($data) : '/'.substr($name, 0, -6);
if ($route) {
$placeholders = $this->getPlaceholdersFromRoute($route);
} else {
$placeholders = array();
}
// template
$template = (0 < count($data) && '' != $data[0]) ? implode(':', $data) : 'default';
$parsedActions[$name] = array(
'name' => $name,
'route' => $route,
'placeholders' => $placeholders,
'template' => $template,
);
}
return $parsedActions;
}
public function getPlaceholdersFromRoute($route)
{
preg_match_all('/{(.*?)}/', $route, $placeholders);
$placeholders = $placeholders[1];
return $placeholders;
}
public function parseShortcutNotation($shortcut)
{
$entity = str_replace('/', '\\', $shortcut);
if (false === $pos = strpos($entity, ':')) {
throw new \InvalidArgumentException(sprintf('The controller name must contain a : ("%s" given, expecting something like AcmeBlogBundle:Post)', $entity));
}
return array(substr($entity, 0, $pos), substr($entity, $pos + 1));
}
protected function createGenerator()
{
return new ControllerGenerator($this->getContainer()->get('filesystem'));
}
private function tryUpdateAnnotationRouting($bundleName, $controller)
{
$routing = new RoutingManipulator($this->getContainer()->getParameter('kernel.root_dir').'/config/routing.yml');
if ($routing->hasResourceInAnnotation($bundleName)) {
return;
}
$routing->addAnnotationController($bundleName, $controller);
}
}