Permalink
Browse files

Make controller generation compatible w/ Symfony 2.3 and add autocomp…

…letion-support

- Fix crud-generation in symfony 2.3.x
- Fix auto-completion for entities
- Name generator templates consistently
- Make detection of bundles in "src" directory more stable and cross-platform compatible
- Look for overridden templates in the "HydraBundle" folder not "SensioGeneratorBundle"
- Restore the original URL prefix and route name handling
- Do not automatically create "Resources/views/" directory - it's not needed

This closes PR #2, thanks to Benjamin for his contributions.
  • Loading branch information...
benbender authored and lanthaler committed Nov 11, 2013
1 parent b0e0336 commit 9cf6f739312c859b8a1dc8ab46e3c64fa5d94849
@@ -9,17 +9,15 @@
namespace ML\HydraBundle\Command;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCrudCommand as SensioCrudCommand;
use Sensio\Bundle\GeneratorBundle\Command\Validators;
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineFormGenerator;
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator as SensioDoctrineCrudGenerator;
use Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper;
use Sensio\Bundle\GeneratorBundle\Manipulator\RoutingManipulator;
use ML\HydraBundle\Generator\DoctrineCrudGenerator;
/**
@@ -92,7 +90,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$metadata = $this->getEntityMetadata($entityClass);
$bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
$generator = $this->getGenerator();
$generator = $this->getGenerator($bundle);
$generator->generate($bundle, $entity, $metadata[0], $format, $prefix, $withWrite, $forceOverwrite);
$output->writeln('Generating the CRUD code: <info>OK</info>');
@@ -121,7 +119,34 @@ protected function interact(InputInterface $input, OutputInterface $output)
'',
));
$entity = $dialog->askAndValidate($output, $dialog->getQuestion('The Entity shortcut name', $input->getOption('entity')), array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateEntityName'), false, $input->getOption('entity'));
$entityNames = array();
$srcDir = realpath($this->getContainer()->get('kernel')->getRootDir() . '/../src/') . DIRECTORY_SEPARATOR;
foreach ($this->getContainer()->get('kernel')->getBundles() as $bundleName => $bundle) {
$finder = Finder::create();
$entityDir = $bundle->getPath() . DIRECTORY_SEPARATOR . 'Entity' . DIRECTORY_SEPARATOR;
if (file_exists($entityDir) && (0 === strncmp($entityDir, $srcDir, strlen($srcDir)))) {
$finder
->files()
->in($entityDir)
->notName('*Repository')
->getIterator()
;
foreach ($finder as $file) {
$entityNames[] = sprintf('%s:%s', $bundleName, str_replace(array($entityDir, '.php'), '', $file->getRealPath()));
}
}
}
$entity = $dialog->askAndValidate(
$output,
$dialog->getQuestion('The Entity shortcut name', $input->getOption('entity')),
array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateEntityName'),
false,
$input->getOption('entity'), $entityNames
);
$input->setOption('entity', $entity);
list($bundle, $entity) = $this->parseShortcutNotation($entity);
@@ -162,12 +187,26 @@ protected function interact(InputInterface $input, OutputInterface $output)
));
}
protected function getGenerator($bundle = null)
protected function createGenerator($bundle = null)
{
if (null === $this->generator) {
$this->generator = new DoctrineCrudGenerator($this->getContainer()->get('filesystem'), __DIR__.'/../Resources/skeleton/crud');
return new DoctrineCrudGenerator($this->getContainer()->get('filesystem'));
}
protected function getSkeletonDirs(BundleInterface $bundle = null)
{
$skeletonDirs = array();
if (isset($bundle) && is_dir($dir = $bundle->getPath().'/Resources/HydraBundle/skeleton')) {
$skeletonDirs[] = $dir;
}
return $this->generator;
if (is_dir($dir = $this->getContainer()->get('kernel')->getRootdir().'/Resources/HydraBundle/skeleton')) {
$skeletonDirs[] = $dir;
}
$skeletonDirs[] = __DIR__.'/../Resources/skeleton';
$skeletonDirs[] = __DIR__.'/../Resources';
return $skeletonDirs;
}
}
@@ -11,15 +11,15 @@
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator as SensioDoctrineCrudGenerator;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* Generates a CRUD controller.
*
* @author Markus Lanthaler <mail@markus-lanthaler.com>
*/
class DoctrineCrudGenerator extends
\Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator
class DoctrineCrudGenerator extends SensioDoctrineCrudGenerator
{
/**
* Generate the CRUD controller.
@@ -33,28 +33,13 @@ class DoctrineCrudGenerator extends
*
* @throws \RuntimeException
*/
public function generate(BundleInterface $bundle, $entity, ClassMetadataInfo $metadata, $format, $routePrefix, $needWriteActions)
public function generate(BundleInterface $bundle, $entity, ClassMetadataInfo $metadata, $format, $routePrefix, $needWriteActions, $forceOverwrite)
{
// Remove trailing "/"
if ('/' === $routePrefix[strlen($routePrefix) - 1]) {
$routePrefix = substr($routePrefix, 0, -1);
}
if (count($metadata->identifier) > 1) {
throw new \RuntimeException('The CRUD generator does not support entity classes with multiple primary keys.');
}
if (!in_array('id', $metadata->identifier)) {
throw new \RuntimeException('The CRUD generator expects the entity object has a primary key field named "id" with a getId() method.');
}
$parts = explode('\\', $entity);
$this->entity = $entity;
$this->entityClass = array_pop($parts);
$this->entityNamespace = implode('\\', $parts);
$this->bundle = $bundle;
$this->metadata = $metadata;
$this->format = 'annotation';
$this->routePrefix = $routePrefix;
// Convert camel-cased class name to underscores
@@ -63,68 +48,27 @@ public function generate(BundleInterface $bundle, $entity, ClassMetadataInfo $me
function ($match) {
return $match[1] . '_' . strtolower($match[2]);
},
$this->entityClass));
substr($entity, strrpos($entity, '\\'))
));
$this->actions = $needWriteActions ?
array('collection_get', 'collection_post', 'entity_get', 'entity_put', 'entity_delete')
$this->actions = $needWriteActions
? array('collection_get', 'collection_post', 'entity_get', 'entity_put', 'entity_delete')
: array('collection_get', 'entity_get');
$this->generateControllerClass();
$this->generateTestClass();
}
/**
* Generates the controller class only.
*
*/
private function generateControllerClass()
{
$dir = $this->bundle->getPath();
$target = sprintf(
'%s/Controller/%s/%sController.php',
$dir,
str_replace('\\', '/', $this->entityNamespace),
$this->entityClass
);
if (file_exists($target)) {
throw new \RuntimeException('Unable to generate the controller as it already exists.');
if (count($metadata->identifier) > 1) {
throw new \RuntimeException('The CRUD generator does not support entity classes with multiple primary keys.');
}
$this->renderFile($this->skeletonDir, 'controller.php', $target, array(
'actions' => $this->actions,
'route_prefix' => $this->routePrefix,
'route_name_prefix' => $this->routeNamePrefix,
'dir' => $this->skeletonDir,
'bundle' => $this->bundle->getName(),
'entity' => $this->entity,
'entity_class' => $this->entityClass,
'namespace' => $this->bundle->getNamespace(),
'entity_namespace' => $this->entityNamespace,
'format' => $this->format,
));
}
if (!in_array('id', $metadata->identifier)) {
throw new \RuntimeException('The CRUD generator expects the entity object has a primary key field named "id" with a getId() method.');
}
/**
* Generates the functional test class only.
*
*/
private function generateTestClass()
{
$dir = $this->bundle->getPath() .'/Tests/Controller';
$target = $dir .'/'. str_replace('\\', '/', $this->entityNamespace).'/'. $this->entityClass .'ControllerTest.php';
$this->entity = $entity;
$this->bundle = $bundle;
$this->metadata = $metadata;
$this->format = 'annotation';
$this->renderFile($this->skeletonDir, 'tests/test.php', $target, array(
'route_prefix' => $this->routePrefix,
'route_name_prefix' => $this->routeNamePrefix,
'entity' => $this->entity,
'entity_class' => $this->entityClass,
'namespace' => $this->bundle->getNamespace(),
'entity_namespace' => $this->entityNamespace,
'actions' => $this->actions,
'dir' => $this->skeletonDir,
));
$this->generateControllerClass($forceOverwrite);
$this->generateTestClass();
}
}
@@ -27,22 +27,22 @@ class {{ entity_class }}Controller extends HydraController
{
{%- if 'collection_get' in actions %}
{%- include 'actions/collection_get.php' %}
{%- include 'crud/actions/collection_get.php.twig' %}
{%- endif %}
{%- if 'collection_post' in actions %}
{%- include 'actions/collection_post.php' %}
{%- include 'crud/actions/collection_post.php.twig' %}
{%- endif %}
{%- if 'entity_get' in actions %}
{%- include 'actions/entity_get.php' %}
{%- include 'crud/actions/entity_get.php.twig' %}
{%- endif %}
{%- if 'entity_put' in actions %}
{%- include 'actions/entity_put.php' %}
{%- include 'crud/actions/entity_put.php.twig' %}
{%- endif %}
{%- if 'entity_delete' in actions %}
{%- include 'actions/entity_delete.php' %}
{%- include 'crud/actions/entity_delete.php.twig' %}
{%- endif %}
}
@@ -10,9 +10,9 @@ class {{ entity_class }}ControllerTest extends WebTestCase
/*
{%- if 'new' in actions %}
{%- include 'tests/others/full_scenario.php' -%}
{%- include 'crud/tests/others/full_scenario.php.twig' -%}
{%- else %}
{%- include 'tests/others/short_scenario.php' -%}
{%- include 'crud/tests/others/short_scenario.php.twig' -%}
{%- endif %}
*/

0 comments on commit 9cf6f73

Please sign in to comment.