├── Resources ├── doc │ └── index.rst ├── views │ └── Default │ │ └── index.html.twig ├── skeleton │ ├── crud │ │ ├── actions │ │ │ ├── admin_delete.php.twig │ │ │ ├── admin_new.php.twig │ │ │ ├── admin_edit.php.twig │ │ │ ├── admin_show.php.twig │ │ │ ├── admin_index.php.twig │ │ │ └── admin_manage.php.twig │ │ ├── views │ │ │ ├── others │ │ │ │ ├── actions.html.twig.twig │ │ │ │ └── record_actions.html.twig.twig │ │ │ ├── edit.html.twig.twig │ │ │ ├── new.html.twig.twig │ │ │ ├── show.html.twig.twig │ │ │ └── index.html.twig.twig │ │ ├── tests │ │ │ └── test.php.twig │ │ └── controller.php.twig │ └── bundle │ │ ├── TransactionalService.php.twig │ │ └── BaseRepository.php.twig ├── config │ ├── routing.yml │ └── services.yml └── translations │ └── messages.fr.xlf ├── DarkwoodGeneratorBundle.php ├── Controller └── DefaultController.php ├── README.md ├── Tests └── Controller │ └── DefaultControllerTest.php ├── composer.json ├── DependencyInjection ├── Configuration.php └── DarkwoodGeneratorExtension.php ├── LICENSE ├── Command ├── GenerateBundleCommand.php ├── GenerateDoctrineEntityCommand.php └── GenerateDoctrineCrudCommand.php └── Generator ├── BundleGenerator.php ├── DoctrineEntityGenerator.php └── DoctrineCrudGenerator.php /Resources/doc/index.rst: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Resources/views/Default/index.html.twig: -------------------------------------------------------------------------------- 1 | Hello {{ name }}! 2 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/actions/admin_delete.php.twig: -------------------------------------------------------------------------------- 1 | {% extends 'crud/actions/delete.php.twig' %} -------------------------------------------------------------------------------- /Resources/config/routing.yml: -------------------------------------------------------------------------------- 1 | darkwood_generator_homepage: 2 | pattern: /hello/{name} 3 | defaults: { _controller: DarkwoodGeneratorBundle:Default:index } 4 | -------------------------------------------------------------------------------- /Resources/config/services.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # darkwood_generator.example.class: Darkwood\GeneratorBundle\Example 3 | 4 | services: 5 | # darkwood_generator.example: 6 | # class: %darkwood_generator.example.class% 7 | # arguments: [@service_id, "plain_value", %parameter%] 8 | -------------------------------------------------------------------------------- /DarkwoodGeneratorBundle.php: -------------------------------------------------------------------------------- 1 | setCreated(new \DateTime()); 6 | {% endblock method_body %} 7 | 8 | {% block method_return %} 9 | return $this->manage($entity); 10 | {% endblock method_return %} 11 | 12 | -------------------------------------------------------------------------------- /Controller/DefaultController.php: -------------------------------------------------------------------------------- 1 | render('DarkwoodGeneratorBundle:Default:index.html.twig', array('name' => $name)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/views/others/actions.html.twig.twig: -------------------------------------------------------------------------------- 1 | 2 | 13 | -------------------------------------------------------------------------------- /Resources/translations/messages.fr.xlf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Symfony2 is great 7 | J'aime Symfony2 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DarkwoodGeneratorBundle 2 | ===================== 3 | 4 | The `DarkwoodGeneratorBundle` extends the default Symfony2 command line 5 | interface by providing new interactive and intuitive commands for generating 6 | code skeletons like bundles, form classes, or CRUD controllers based on a 7 | Doctrine 2 schema. 8 | 9 | More information in the official 10 | [documentation](http://symfony.com/doc/current/bundles/SensioGeneratorBundle/index.html). 11 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/views/edit.html.twig.twig: -------------------------------------------------------------------------------- 1 | {% block extends %} 2 | {{ "{% extends '::base.html.twig' %}" }} 3 | {% endblock extends %} 4 | 5 | {% block body %} 6 | {{ "{% block body -%}" }} 7 |

{{ entity }} edit

8 | 9 | {{ '{{ form(edit_form) }}' }} 10 | 11 | {% set hide_edit, hide_delete = true, false %} 12 | {% include 'crud/views/others/record_actions.html.twig.twig' %} 13 | {{ "{% endblock %}" }} 14 | {% endblock body %} 15 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/views/new.html.twig.twig: -------------------------------------------------------------------------------- 1 | {% block extends %} 2 | {{ "{% extends '::base.html.twig' %}" }} 3 | {% endblock extends %} 4 | 5 | {% block body %} 6 | {{ "{% block body -%}" }} 7 |

{{ entity }} creation

8 | 9 | {{ '{{ form(form) }}' }} 10 | 11 | {% set hide_edit, hide_delete = true, true %} 12 | {% include 'crud/views/others/record_actions.html.twig.twig' %} 13 | {{ "{% endblock %}" }} 14 | {% endblock body %} 15 | -------------------------------------------------------------------------------- /Tests/Controller/DefaultControllerTest.php: -------------------------------------------------------------------------------- 1 | request('GET', '/hello/Fabien'); 14 | 15 | $this->assertTrue($crawler->filter('html:contains("Hello Fabien")')->count() > 0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/views/others/record_actions.html.twig.twig: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/actions/admin_edit.php.twig: -------------------------------------------------------------------------------- 1 | {% extends 'crud/actions/edit.php.twig' %} 2 | 3 | {% block method_body %} 4 | $em = $this->getDoctrine()->getManager(); 5 | 6 | $entity = $em->getRepository('{{ bundle }}:{{ entity }}')->find($id); 7 | 8 | if (!$entity) { 9 | throw $this->createNotFoundException('Unable to find {{ entity }} entity.'); 10 | } 11 | $entity->setCreated(new \DateTime()); 12 | {% endblock method_body %} 13 | 14 | {% block method_return %} 15 | return $this->manage($entity); 16 | {% endblock method_return %} 17 | 18 | {% block form %}{% endblock %} -------------------------------------------------------------------------------- /Resources/skeleton/crud/tests/test.php.twig: -------------------------------------------------------------------------------- 1 | getDoctrine()->getManager(); 5 | 6 | $entity = $em->getRepository('{{ bundle }}:{{ entity }}')->find($id); 7 | 8 | if (!$entity) { 9 | throw $this->createNotFoundException('Unable to find {{ entity }} entity.'); 10 | } 11 | {% endblock method_body %} 12 | 13 | {% block method_return %} 14 | {% if 'annotation' == format %} 15 | return array( 16 | 'entity' => $entity, 17 | ); 18 | {% else %} 19 | return $this->render('{{ bundle }}:{{ entity|replace({'\\': '/'}) }}:show.html.twig', array( 20 | 'entity' => $entity, 21 | )); 22 | {% endif %} 23 | {% endblock method_return %} 24 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "darkwood/generator-bundle", 3 | "description": "This bundle generates code for you", 4 | "keywords": [], 5 | "type": "symfony-bundle", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Mathieu Ledru", 10 | "email": "matyo91@gmail.com" 11 | } 12 | ], 13 | "require": { 14 | "symfony/framework-bundle": "~2.2", 15 | "symfony/console": "~2.0" 16 | }, 17 | "require-dev": { 18 | "symfony/doctrine-bridge": "~2.2", 19 | "doctrine/orm": "~2.2,>=2.2.3", 20 | "twig/twig": "~1.11" 21 | }, 22 | "autoload": { 23 | "psr-0": { "Darkwood\\GeneratorBundle": "" } 24 | }, 25 | "target-dir": "Darkwood/GeneratorBundle", 26 | "minimum-stability": "dev", 27 | "extra": { 28 | "branch-alias": { 29 | "dev-master": "2.3.x-dev" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | root('darkwood_generator'); 22 | 23 | // Here you should define the parameters that are allowed to 24 | // configure your bundle. See the documentation linked above for 25 | // more information on that topic. 26 | 27 | return $treeBuilder; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/views/show.html.twig.twig: -------------------------------------------------------------------------------- 1 | {% block extends %} 2 | {{ "{% extends '::base.html.twig' %}" }} 3 | {% endblock extends %} 4 | 5 | {% block body %} 6 | {{ "{% block body -%}" }} 7 |

{{ entity }}

8 | 9 | 10 | 11 | {%- for field, metadata in fields %} 12 | 13 | 14 | 15 | 16 | {%- if metadata.type in ['date', 'datetime'] %} 17 | 18 | 19 | 20 | {%- else %} 21 | 22 | 23 | 24 | {%- endif %} 25 | 26 | 27 | 28 | {%- endfor %} 29 | 30 | 31 |
{{ field|capitalize }}{{ '{{ entity.' ~ field|replace({'_': ''}) ~ '|date(\'Y-m-d H:i:s\') }}' }}{{ '{{ entity.' ~ field|replace({'_': ''}) ~ ' }}' }}
32 | 33 | {% set hide_edit, hide_delete = false, false %} 34 | {% include 'crud/views/others/record_actions.html.twig.twig' %} 35 | {{ "{% endblock %}" }} 36 | {% endblock body %} 37 | -------------------------------------------------------------------------------- /DependencyInjection/DarkwoodGeneratorExtension.php: -------------------------------------------------------------------------------- 1 | processConfiguration($configuration, $configs); 24 | 25 | $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 26 | $loader->load('services.yml'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2013 Mathieu Ledru 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Command/GenerateBundleCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Darkwood\GeneratorBundle\Command; 13 | 14 | use Sensio\Bundle\GeneratorBundle\Command\GenerateBundleCommand as BaseCommand; 15 | use Darkwood\GeneratorBundle\Generator\BundleGenerator; 16 | use Symfony\Component\HttpKernel\Bundle\BundleInterface; 17 | 18 | /** 19 | * Generates bundles. 20 | * 21 | * @author Mathieu Ledru 22 | */ 23 | class GenerateBundleCommand extends BaseCommand 24 | { 25 | /** 26 | * @see Command 27 | */ 28 | protected function configure() 29 | { 30 | parent::configure(); 31 | 32 | $this->setName('darkwood:generate:bundle'); 33 | } 34 | 35 | protected function createGenerator() 36 | { 37 | return new BundleGenerator($this->getContainer()->get('filesystem')); 38 | } 39 | 40 | protected function getSkeletonDirs(BundleInterface $bundle = null) 41 | { 42 | $skeletonDirs = parent::getSkeletonDirs($bundle); 43 | 44 | array_splice($skeletonDirs, -2, 0, array( 45 | __DIR__.'/../Resources/skeleton', 46 | __DIR__.'/../Resources', 47 | )); 48 | 49 | return $skeletonDirs; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/TransactionalService.php.twig: -------------------------------------------------------------------------------- 1 | em; 26 | } 27 | 28 | /** 29 | * Setter of the Entity Manager 30 | * 31 | * @param EntityManager $em the Entity Manager 32 | */ 33 | public function setEntityManager($em) 34 | { 35 | $this->em = $em; 36 | } 37 | 38 | /** 39 | * Add a repository to this service 40 | * 41 | * @param integer $key Key 42 | * @param string $class Class 43 | * 44 | * @return void 45 | */ 46 | public function addRepository($key, $class) 47 | { 48 | $this->$key = $this->em->getRepository($class); 49 | } 50 | 51 | /** 52 | * Add a service to this service 53 | * 54 | * @param integer $key Key 55 | * @param string $class Class 56 | * 57 | * @return void 58 | */ 59 | public function addService($key, $service) 60 | { 61 | $this->$key = $service; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/actions/admin_index.php.twig: -------------------------------------------------------------------------------- 1 | {% extends 'crud/actions/index.php.twig' %} 2 | 3 | {% block method_body %} 4 | $searchQuery = array(); 5 | 6 | $formSearch = $this->createForm(new {{ entity_class }}SearchType()); 7 | $formSearch->add('submit', 'submit', array('label' => 'Find')); 8 | if ('POST' === $this->get('request')->getMethod()) { 9 | 10 | $formSearch->handleRequest($this->get('request')); 11 | 12 | if ($formSearch->isValid()) { 13 | $searchQuery = array_merge($searchQuery, $formSearch->getData()->getSearchData()); 14 | } 15 | } 16 | 17 | $query = $this->get('{{ bundleService }}.{{ entityLink }}')->searchQuery($searchQuery); 18 | 19 | $paginator = $this->get('knp_paginator'); 20 | $entities = $paginator->paginate( 21 | $query, 22 | $this->get('request')->query->get('page', 1), 23 | 10 24 | ); 25 | {% endblock method_body %} 26 | 27 | {% block method_return %} 28 | {% if 'annotation' == format %} 29 | return array( 30 | 'entities' => $entities, 31 | 'formSearch' => $formSearch->createView(), 32 | ); 33 | {% else %} 34 | return $this->render('{{ bundle }}:{{ entity|replace({'\\': '/'}) }}:index.html.twig', array( 35 | 'entities' => $entities, 36 | 'formSearch' => $formSearch->createView(), 37 | )); 38 | {% endif %} 39 | {% endblock method_return %} 40 | -------------------------------------------------------------------------------- /Command/GenerateDoctrineEntityCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Darkwood\GeneratorBundle\Command; 13 | 14 | use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineEntityCommand as BaseCommand; 15 | use Darkwood\GeneratorBundle\Generator\DoctrineEntityGenerator; 16 | use Symfony\Component\HttpKernel\Bundle\BundleInterface; 17 | 18 | /** 19 | * Generates a CRUD for a Doctrine entity. 20 | * 21 | * @author Matheu Ledru 22 | */ 23 | class GenerateDoctrineEntityCommand extends BaseCommand 24 | { 25 | protected function configure() 26 | { 27 | parent::configure(); 28 | 29 | $this->setName('darkwood:generate:doctrine:entity'); 30 | } 31 | 32 | protected function createGenerator() 33 | { 34 | return new DoctrineEntityGenerator($this->getContainer()->get('filesystem'), $this->getContainer()->get('doctrine')); 35 | } 36 | 37 | protected function getSkeletonDirs(BundleInterface $bundle = null) 38 | { 39 | $skeletonDirs = parent::getSkeletonDirs($bundle); 40 | 41 | array_splice($skeletonDirs, -2, 0, array( 42 | __DIR__.'/../Resources/skeleton', 43 | __DIR__.'/../Resources', 44 | )); 45 | 46 | return $skeletonDirs; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Generator/BundleGenerator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Darkwood\GeneratorBundle\Generator; 13 | 14 | use Sensio\Bundle\GeneratorBundle\Generator\BundleGenerator as BaseGenerator; 15 | use Symfony\Component\DependencyInjection\Container; 16 | 17 | /** 18 | * Generates a bundle. 19 | * 20 | * @author Matheu Ledru 21 | */ 22 | class BundleGenerator extends BaseGenerator 23 | { 24 | public function generate($namespace, $bundle, $dir, $format, $structure) 25 | { 26 | parent::generate($namespace, $bundle, $dir, $format, $structure); 27 | 28 | if (preg_match('/CoreBundle$/', $bundle)) { 29 | //Core bundle 30 | 31 | $dir .= '/'.strtr($namespace, '\\', '/'); 32 | 33 | $basename = substr($bundle, 0, -6); 34 | $parameters = array( 35 | 'namespace' => $namespace, 36 | 'bundle' => $bundle, 37 | 'format' => $format, 38 | 'bundle_basename' => $basename, 39 | 'extension_alias' => Container::underscore($basename), 40 | ); 41 | 42 | $this->renderFile('bundle/BaseRepository.php.twig', $dir.'/Repository/BaseRepository.php', $parameters); 43 | $this->renderFile('bundle/TransactionalService.php.twig', $dir.'/Services/TransactionalService.php', $parameters); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/actions/admin_manage.php.twig: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates a form to create a {{ entity }} entity. 3 | * 4 | * @param \{{ namespace }}\Entity\{{ entity }} $entity The entity 5 | * 6 | * @return \Symfony\Component\Form\Form The form 7 | */ 8 | private function manage({{ entity }} $entity) 9 | { 10 | $mode = $entity->getId() ? 'edit' : 'new'; 11 | 12 | $form = $this->createForm(new {{ entity }}Type(), $entity, array( 13 | 'action' => ($mode === 'new') ? $this->generateUrl('{{ route_name_prefix }}_new') : $this->generateUrl('{{ route_name_prefix }}_edit', array('id' => $entity->getId())), 14 | )); 15 | 16 | $form->add('submit', 'submit', array('label' => $mode === 'new' ? 'Create' : 'Update')); 17 | 18 | if ('POST' === $this->getRequest()->getMethod()) { 19 | $request = $this->getRequest(); 20 | 21 | $form->handleRequest($request); 22 | 23 | if ($form->isValid()) { 24 | /** @var \{{ namespace }}\Services\{{ entity }}Service $entityService */ 25 | $entityService = $this->get('{{ bundleService }}.{{ entityLink }}'); 26 | $entityService->save($entity); 27 | 28 | return $this->redirect($this->generateUrl('{{ route_name_prefix }}_edit', array('id' => $entity->getId()))); 29 | } 30 | } 31 | 32 | $params = array('entity' => $entity); 33 | if ($mode === 'new') { 34 | $params['form'] = $form->createView(); 35 | } else { 36 | $deleteForm = $this->createDeleteForm($entity->getId()); 37 | 38 | $params['edit_form'] = $form->createView(); 39 | $params['delete_form'] = $deleteForm->createView(); 40 | } 41 | 42 | return $this->render('{{ bundle }}:{{ entity|replace({'\\': '/'}) }}'.$mode.'.html.twig', $params); 43 | } -------------------------------------------------------------------------------- /Resources/skeleton/crud/views/index.html.twig.twig: -------------------------------------------------------------------------------- 1 | {% block extends %} 2 | {{ "{% extends '::base.html.twig' %}" }} 3 | {% endblock extends %} 4 | 5 | {% block body %} 6 | {{ "{% block body -%}" }} 7 |

{{ entity }} list

8 | 9 | 10 | 11 | 12 | {%- for field, metadata in fields %} 13 | 14 | 15 | 16 | {%- endfor %} 17 | 18 | 19 | 20 | 21 | 22 | {{ '{% for entity in entities %}' }} 23 | 24 | 25 | {%- for field, metadata in fields %} 26 | {%- if loop.first and ('show' in actions) %} 27 | 28 | 29 | 30 | {%- elseif metadata.type in ['date', 'datetime'] %} 31 | 32 | 33 | 34 | {%- else %} 35 | 36 | 37 | 38 | {%- endif %} 39 | 40 | {%- if loop.last %} 41 | 42 | 45 | 46 | {%- endif %} 47 | {%- endfor %} 48 | 49 | 50 | {{ '{% endfor %}' }} 51 | 52 |
{{ field|capitalize }}Actions
{{ '{{ entity.' ~ field|replace({'_': ''}) ~ ' }}' }}{{ '{% if entity.' ~ field|replace({'_': ''}) ~ ' %}{{ entity.' ~ field|replace({'_': ''}) ~ '|date(\'Y-m-d H:i:s\') }}{% endif %}' }}{{ '{{ entity.' ~ field|replace({'_': ''}) ~ ' }}' }} 43 | {%- include "crud/views/others/actions.html.twig.twig" %} 44 |
53 | 54 | {% if 'new' in actions %} 55 | 62 | {% endif %} 63 | {{ "{% endblock %}" }} 64 | {% endblock body %} 65 | -------------------------------------------------------------------------------- /Resources/skeleton/crud/controller.php.twig: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Darkwood\GeneratorBundle\Generator; 13 | 14 | use Sensio\Bundle\GeneratorBundle\Generator\DoctrineEntityGenerator as BaseGenerator; 15 | use Symfony\Component\Filesystem\Filesystem; 16 | use Symfony\Component\HttpKernel\Bundle\BundleInterface; 17 | use Symfony\Bridge\Doctrine\RegistryInterface; 18 | use Doctrine\ORM\Mapping\ClassMetadataInfo; 19 | use Doctrine\ORM\Tools\Export\ClassMetadataExporter; 20 | 21 | /** 22 | * Generates a CRUD controller. 23 | * 24 | * @author Matheu Ledru 25 | */ 26 | class DoctrineEntityGenerator extends BaseGenerator 27 | { 28 | private $filesystem; 29 | private $registry; 30 | 31 | public function __construct(Filesystem $filesystem, RegistryInterface $registry) 32 | { 33 | parent::__construct($filesystem, $registry); 34 | 35 | $this->filesystem = $filesystem; 36 | $this->registry = $registry; 37 | } 38 | 39 | public function generate(BundleInterface $bundle, $entity, $format, array $fields, $withRepository) 40 | { 41 | // configure the bundle (needed if the bundle does not contain any Entities yet) 42 | $config = $this->registry->getManager(null)->getConfiguration(); 43 | $config->setEntityNamespaces(array_merge( 44 | array($bundle->getName() => $bundle->getNamespace().'\\Entity'), 45 | $config->getEntityNamespaces() 46 | )); 47 | 48 | $entityClass = $this->registry->getAliasNamespace($bundle->getName()).'\\'.$entity; 49 | $entityPath = $bundle->getPath().'/Entity/'.str_replace('\\', '/', $entity).'.php'; 50 | if (file_exists($entityPath)) { 51 | throw new \RuntimeException(sprintf('Entity "%s" already exists.', $entityClass)); 52 | } 53 | 54 | $class = new ClassMetadataInfo($entityClass); 55 | if ($withRepository) { 56 | $repositoryClassName = preg_replace('/Entity$/', 'Repository', $this->registry->getAliasNamespace($bundle->getName())).'\\'.$entity; 57 | $class->customRepositoryClassName = $repositoryClassName.'Repository'; 58 | } 59 | $class->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true)); 60 | $class->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); 61 | foreach ($fields as $field) { 62 | $class->mapField($field); 63 | } 64 | 65 | $entityGenerator = $this->getEntityGenerator(); 66 | if ('annotation' === $format) { 67 | $entityGenerator->setGenerateAnnotations(true); 68 | $entityCode = $entityGenerator->generateEntityClass($class); 69 | $mappingPath = $mappingCode = false; 70 | } else { 71 | $cme = new ClassMetadataExporter(); 72 | $exporter = $cme->getExporter('yml' == $format ? 'yaml' : $format); 73 | $mappingPath = $bundle->getPath().'/Resources/config/doctrine/'.str_replace('\\', '.', $entity).'.orm.'.$format; 74 | 75 | if (file_exists($mappingPath)) { 76 | throw new \RuntimeException(sprintf('Cannot generate entity when mapping "%s" already exists.', $mappingPath)); 77 | } 78 | 79 | $mappingCode = $exporter->exportClassMetadata($class); 80 | $entityGenerator->setGenerateAnnotations(false); 81 | $entityCode = $entityGenerator->generateEntityClass($class); 82 | } 83 | 84 | $this->filesystem->mkdir(dirname($entityPath)); 85 | file_put_contents($entityPath, $entityCode); 86 | 87 | if ($mappingPath) { 88 | $this->filesystem->mkdir(dirname($mappingPath)); 89 | file_put_contents($mappingPath, $mappingCode); 90 | } 91 | 92 | if ($withRepository) { 93 | $path = $bundle->getPath().str_repeat('/..', substr_count(get_class($bundle), '\\')); 94 | $this->getRepositoryGenerator()->writeEntityRepositoryClass($class->customRepositoryClassName, $path); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/BaseRepository.php.twig: -------------------------------------------------------------------------------- 1 | _em->getClassMetadata(get_class($entity)); 34 | $identifiersNames = $classMetadata->getIdentifier(); 35 | /* if there's only one id, got to pass it outside an array */ 36 | $identenfiers = array(); 37 | if (1 == count($identifiersNames)) { 38 | $identenfiers = 39 | $classMetadata->getFieldValue($entity, $identifiersNames[0]); 40 | } else { 41 | foreach ($identifiersNames as $identifierName) { 42 | array_push($identenfiers, $classMetadata->getFieldValue($entity, $identifierName)); 43 | } 44 | } 45 | 46 | return $this->_em->find(get_class($entity), $identenfiers); 47 | } 48 | 49 | /** 50 | * Inserts an entity 51 | * 52 | * @param Entity $entity The entity to insert 53 | * 54 | * @throws ExistingObjectException An ExistingObjectException if the entity already 55 | * exists 56 | * @throws PDOException PDO Exception 57 | */ 58 | public function insert($entity) 59 | { 60 | try { 61 | $this->_em->persist($entity); 62 | $this->_em->flush($entity); 63 | } catch (\PDOException $pdoe) { 64 | switch ($pdoe->getCode()) { 65 | case self::PDO_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION: 66 | case self::PDO_EXCEPTION_UNIQUE_VIOLATION: 67 | throw new ExistingObjectException(array('object' => $entity)); 68 | default: 69 | throw $pdoe; 70 | } 71 | } 72 | 73 | return $entity; 74 | } 75 | 76 | /** 77 | * Updates an entity 78 | * 79 | * @param Entity $entity The entity to update 80 | * 81 | * @throws NonExistingObjectException An NonExistingObjectException if the entity does 82 | * not exist 83 | * @throws ExistingObjectException An ExistingObjectException if the 84 | * entity is already exist in database 85 | */ 86 | public function update($entity) 87 | { 88 | $entity = $this->findById($entity); 89 | if (is_null($entity)) { 90 | throw new NonExistingObjectException(array('object' => $entity)); 91 | } 92 | 93 | try { 94 | $this->_em->flush($entity); 95 | } catch (\PDOException $pdoe) { 96 | switch ($pdoe->getCode()) { 97 | case self::PDO_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION: 98 | case self::PDO_EXCEPTION_UNIQUE_VIOLATION: 99 | throw new ExistingObjectException(array('object' => $entity)); 100 | default: 101 | throw $pdoe; 102 | } 103 | } 104 | } 105 | 106 | 107 | /** 108 | * Removes an entity 109 | * 110 | * @param Entity $entity The entity to remove 111 | * 112 | * @throws NonExistingObjectException An NonExistingObjectException if the entity does 113 | * not exist 114 | */ 115 | public function delete($entity) 116 | { 117 | $this->_em->remove($entity); 118 | $this->_em->flush(); 119 | } 120 | 121 | /** 122 | * Save an entity 123 | * 124 | * @param Entity $entity An entity that i want saved 125 | * 126 | * @return void 127 | */ 128 | public function save($entity) 129 | { 130 | $this->_em->persist($entity); 131 | $this->_em->flush(); 132 | 133 | return $entity; 134 | } 135 | 136 | /** 137 | * Find all in query 138 | * 139 | * @param array $parameters Parameters 140 | * 141 | * @return QueryBuilder 142 | */ 143 | public function queryFindAll($parameters = array()) 144 | { 145 | $qb = $this->createQueryBuilder('e') 146 | ->select(); 147 | 148 | foreach ($parameters as $parameter => $value) { 149 | $qb->andWhere('e.'.$parameter.' = '.$value); 150 | } 151 | 152 | return $qb; 153 | } 154 | 155 | /** 156 | * Find in query 157 | * 158 | * @param array $criteria Criteria 159 | * 160 | * @return QueryBuilder 161 | */ 162 | protected function queryFind(array $criteria) 163 | { 164 | $qb = $this->createQueryBuilder('e') 165 | ->select(); 166 | 167 | foreach ($criteria as $parameter => $value) { 168 | $qb->andWhere($qb->expr()->like('e.'.$filterBy, ':'.$filterBy)) 169 | ->setParameter($parameter, '%'.$value.'%'); 170 | } 171 | 172 | return $qb; 173 | } 174 | 175 | /** 176 | * Find all 177 | * 178 | * @param array $parameters Parameters 179 | * 180 | * @return Collection 181 | */ 182 | public function findAll($parameters = array()) 183 | { 184 | return $this->queryFindAll($parameters)->getQuery()->getResult(); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /Command/GenerateDoctrineCrudCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Darkwood\GeneratorBundle\Command; 13 | 14 | use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCrudCommand as BaseCommand; 15 | use Darkwood\GeneratorBundle\Generator\DoctrineCrudGenerator; 16 | use Symfony\Component\HttpKernel\Bundle\BundleInterface; 17 | use Symfony\Component\Console\Input\InputOption; 18 | use Symfony\Component\Console\Input\InputInterface; 19 | use Symfony\Component\Console\Output\OutputInterface; 20 | use Sensio\Bundle\GeneratorBundle\Command\Validators; 21 | 22 | /** 23 | * Generates a CRUD for a Doctrine entity. 24 | * 25 | * @author Matheu Ledru 26 | */ 27 | class GenerateDoctrineCrudCommand extends BaseCommand 28 | { 29 | protected function configure() 30 | { 31 | parent::configure(); 32 | 33 | $this->setName('darkwood:generate:doctrine:crud'); 34 | $this 35 | ->getDefinition() 36 | ->addOption(new InputOption('to-bundle', '', InputOption::VALUE_REQUIRED, 'The bundle where to put crud generation')); 37 | } 38 | 39 | protected function execute(InputInterface $input, OutputInterface $output) 40 | { 41 | $dialog = $this->getDialogHelper(); 42 | 43 | if ($input->isInteractive()) { 44 | if (!$dialog->askConfirmation($output, $dialog->getQuestion('Do you confirm generation', 'yes', '?'), true)) { 45 | $output->writeln('Command aborted'); 46 | 47 | return 1; 48 | } 49 | } 50 | 51 | $entity = Validators::validateEntityName($input->getOption('entity')); 52 | list($bundle, $entity) = $this->parseShortcutNotation($entity); 53 | 54 | $toBundle = Validators::validateBundleName($input->getOption('to-bundle')); 55 | $format = Validators::validateFormat($input->getOption('format')); 56 | $prefix = $this->getRoutePrefix($input, $entity); 57 | $withWrite = $input->getOption('with-write'); 58 | $forceOverwrite = $input->getOption('overwrite'); 59 | 60 | $dialog->writeSection($output, 'CRUD generation'); 61 | 62 | $entityClass = $this->getContainer()->get('doctrine')->getAliasNamespace($bundle).'\\'.$entity; 63 | $metadata = $this->getEntityMetadata($entityClass); 64 | $bundle = $this->getContainer()->get('kernel')->getBundle($bundle); 65 | $toBundle = $this->getContainer()->get('kernel')->getBundle($toBundle); 66 | 67 | $generator = $this->getGenerator($bundle); 68 | $generator->generateToBundle($bundle, $entity, $toBundle, $metadata[0], $format, $prefix, $withWrite, $forceOverwrite); 69 | 70 | $output->writeln('Generating the CRUD code: OK'); 71 | 72 | $errors = array(); 73 | $runner = $dialog->getRunner($output, $errors); 74 | 75 | // form 76 | if ($withWrite) { 77 | $this->generateForm($bundle, $entity, $metadata); 78 | $output->writeln('Generating the Form code: OK'); 79 | } 80 | 81 | // routing 82 | if ('annotation' != $format) { 83 | $runner($this->updateRouting($dialog, $input, $output, $bundle, $format, $entity, $prefix)); 84 | } 85 | 86 | $dialog->writeGeneratorSummary($output, $errors); 87 | } 88 | 89 | protected function interact(InputInterface $input, OutputInterface $output) 90 | { 91 | $dialog = $this->getDialogHelper(); 92 | $dialog->writeSection($output, 'Welcome to the Doctrine2 CRUD generator'); 93 | 94 | // namespace 95 | $output->writeln(array( 96 | '', 97 | 'This command helps you generate CRUD controllers and templates.', 98 | '', 99 | 'First, you need to give the entity for which you want to generate a CRUD.', 100 | 'You can give an entity that does not exist yet and the wizard will help', 101 | 'you defining it.', 102 | '', 103 | 'You must use the shortcut notation like AcmeBlogBundle:Post.', 104 | '', 105 | )); 106 | 107 | $entity = $dialog->askAndValidate($output, $dialog->getQuestion('The Entity shortcut name', $input->getOption('entity')), array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateEntityName'), false, $input->getOption('entity')); 108 | $input->setOption('entity', $entity); 109 | list($bundle, $entity) = $this->parseShortcutNotation($entity); 110 | 111 | // to-bundle 112 | $toBundle = $bundle; 113 | $output->writeln(array( 114 | '', 115 | 'Determine the bundle where to put the generated CRUD.', 116 | '', 117 | )); 118 | $toBundle = $dialog->askAndValidate($output, $dialog->getQuestion('Which bundle you want to put the crud generation', $toBundle), array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateBundleName'), false, $toBundle); 119 | $input->setOption('to-bundle', $toBundle); 120 | 121 | // write? 122 | $withWrite = $input->getOption('with-write') ?: false; 123 | $output->writeln(array( 124 | '', 125 | 'By default, the generator creates two actions: list and show.', 126 | 'You can also ask it to generate "write" actions: new, update, and delete.', 127 | '', 128 | )); 129 | $withWrite = $dialog->askConfirmation($output, $dialog->getQuestion('Do you want to generate the "write" actions', $withWrite ? 'yes' : 'no', '?'), $withWrite); 130 | $input->setOption('with-write', $withWrite); 131 | 132 | // format 133 | $format = $input->getOption('format'); 134 | $output->writeln(array( 135 | '', 136 | 'Determine the format to use for the generated CRUD.', 137 | '', 138 | )); 139 | $format = $dialog->askAndValidate($output, $dialog->getQuestion('Configuration format (yml, xml, php, or annotation)', $format), array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateFormat'), false, $format); 140 | $input->setOption('format', $format); 141 | 142 | // route prefix 143 | $prefix = $this->getRoutePrefix($input, $entity); 144 | $output->writeln(array( 145 | '', 146 | 'Determine the routes prefix (all the routes will be "mounted" under this', 147 | 'prefix: /prefix/, /prefix/new, ...).', 148 | '', 149 | )); 150 | $prefix = $dialog->ask($output, $dialog->getQuestion('Routes prefix', '/'.$prefix), '/'.$prefix); 151 | $input->setOption('route-prefix', $prefix); 152 | 153 | // summary 154 | $output->writeln(array( 155 | '', 156 | $this->getHelper('formatter')->formatBlock('Summary before generation', 'bg=blue;fg=white', true), 157 | '', 158 | sprintf("You are going to generate a CRUD controller for \"%s:%s\"", $bundle, $entity), 159 | sprintf("using the \"%s\" format.", $format), 160 | '', 161 | )); 162 | } 163 | 164 | protected function createGenerator($bundle = null) 165 | { 166 | return new DoctrineCrudGenerator($this->getContainer()->get('filesystem')); 167 | } 168 | 169 | protected function getSkeletonDirs(BundleInterface $bundle = null) 170 | { 171 | $skeletonDirs = parent::getSkeletonDirs($bundle); 172 | 173 | array_splice($skeletonDirs, -2, 0, array( 174 | __DIR__.'/../Resources/skeleton', 175 | __DIR__.'/../Resources', 176 | )); 177 | 178 | return $skeletonDirs; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /Generator/DoctrineCrudGenerator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Darkwood\GeneratorBundle\Generator; 13 | 14 | use Sensio\Bundle\GeneratorBundle\Command\Validators; 15 | use Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator as BaseGenerator; 16 | use Symfony\Component\DependencyInjection\Container; 17 | use Symfony\Component\HttpKernel\Bundle\BundleInterface; 18 | use Doctrine\ORM\Mapping\ClassMetadataInfo; 19 | 20 | /** 21 | * Generates a CRUD controller. 22 | * 23 | * @author Matheu Ledru 24 | */ 25 | class DoctrineCrudGenerator extends BaseGenerator 26 | { 27 | protected $entityLink; 28 | protected $bundleService; 29 | protected $toBundle; 30 | protected $toBundleService; 31 | protected $templatePrefix; 32 | 33 | protected function parseBundleNamespace($namespace) 34 | { 35 | $namespace = Validators::validateBundleNamespace($namespace); 36 | 37 | $pos = strpos($namespace, '\\'); 38 | 39 | return array(substr($namespace, 0, $pos), substr($namespace, $pos + 1)); 40 | } 41 | 42 | /** 43 | * Generate the CRUD controller. 44 | * 45 | * @param BundleInterface $bundle A bundle object 46 | * @param string $entity The entity relative class name 47 | * @param ClassMetadataInfo $metadata The entity class metadata 48 | * @param string $format The configuration format (xml, yaml, annotation) 49 | * @param string $routePrefix The route name prefix 50 | * @param array $needWriteActions Wether or not to generate write actions 51 | * 52 | * @throws \RuntimeException 53 | */ 54 | public function generateToBundle(BundleInterface $bundle, $entity, BundleInterface $toBundle, ClassMetadataInfo $metadata, $format, $routePrefix, $needWriteActions, $forceOverwrite) 55 | { 56 | $this->routePrefix = $routePrefix; 57 | $this->routeNamePrefix = str_replace('/', '_', $routePrefix); 58 | $this->actions = $needWriteActions ? array('index', 'show', 'new', 'edit', 'delete') : array('index', 'show'); 59 | 60 | if (count($metadata->identifier) > 1) { 61 | throw new \RuntimeException('The CRUD generator does not support entity classes with multiple primary keys.'); 62 | } 63 | 64 | if (!in_array('id', $metadata->identifier)) { 65 | throw new \RuntimeException('The CRUD generator expects the entity object has a primary key field named "id" with a getId() method.'); 66 | } 67 | 68 | $this->entity = $entity; 69 | $this->entityLink = Container::underscore(str_replace('\\', ':', $entity)); 70 | $this->bundle = $bundle; 71 | list($bundleNamespace, $bundleEntity) = $this->parseBundleNamespace($this->bundle->getNamespace()); 72 | $this->bundleService = lcfirst(Container::camelize(substr($bundleEntity, 0, -6))); 73 | $this->toBundle = $toBundle; 74 | list($toBundleNamespace, $toBundleEntity) = $this->parseBundleNamespace($this->toBundle->getNamespace()); 75 | $this->toBundleService = lcfirst(Container::camelize(substr($toBundleEntity, 0, -6))); 76 | $this->metadata = $metadata; 77 | $this->templatePrefix = (preg_match('/AdminBundle$/', $this->toBundle->getName())) ? 'admin_' : ''; 78 | $this->setFormat($format); 79 | 80 | $this->generateControllerClass($forceOverwrite); 81 | 82 | $dir = sprintf('%s/Resources/views/%s', $this->toBundle->getPath(), str_replace('\\', '/', $this->entity)); 83 | 84 | if (!file_exists($dir)) { 85 | $this->filesystem->mkdir($dir, 0777); 86 | } 87 | 88 | $this->generateIndexView($dir); 89 | 90 | if (in_array('show', $this->actions)) { 91 | $this->generateShowView($dir); 92 | } 93 | 94 | if (in_array('new', $this->actions)) { 95 | $this->generateNewView($dir); 96 | } 97 | 98 | if (in_array('edit', $this->actions)) { 99 | $this->generateEditView($dir); 100 | } 101 | 102 | $this->generateTestClass(); 103 | $this->generateConfiguration(); 104 | } 105 | 106 | /** 107 | * Sets the configuration format. 108 | * 109 | * @param string $format The configuration format 110 | */ 111 | private function setFormat($format) 112 | { 113 | switch ($format) { 114 | case 'yml': 115 | case 'xml': 116 | case 'php': 117 | case 'annotation': 118 | $this->format = $format; 119 | break; 120 | default: 121 | $this->format = 'yml'; 122 | break; 123 | } 124 | } 125 | 126 | /** 127 | * Generates the controller class only. 128 | * 129 | */ 130 | protected function generateControllerClass($forceOverwrite) 131 | { 132 | $dir = $this->toBundle->getPath(); 133 | 134 | $parts = explode('\\', $this->entity); 135 | $entityClass = array_pop($parts); 136 | $entityNamespace = implode('\\', $parts); 137 | 138 | $target = sprintf( 139 | '%s/Controller/%s/%sController.php', 140 | $dir, 141 | str_replace('\\', '/', $entityNamespace), 142 | $entityClass 143 | ); 144 | 145 | if (!$forceOverwrite && file_exists($target)) { 146 | throw new \RuntimeException('Unable to generate the controller as it already exists.'); 147 | } 148 | 149 | $this->renderFile('crud/controller.php.twig', $target, array( 150 | 'actions' => $this->actions, 151 | 'route_prefix' => $this->routePrefix, 152 | 'route_name_prefix' => $this->routeNamePrefix, 153 | 'template_prefix' => $this->templatePrefix, 154 | 'bundle' => $this->bundle->getName(), 155 | 'bundleService' => $this->bundleService, 156 | 'toBundle' => $this->toBundle->getName(), 157 | 'toBundleService' => $this->toBundleService, 158 | 'entity' => $this->entity, 159 | 'entityLink' => $this->entityLink, 160 | 'entity_class' => $entityClass, 161 | 'namespace' => $this->bundle->getNamespace(), 162 | 'toNamespace' => $this->toBundle->getNamespace(), 163 | 'entity_namespace' => $entityNamespace, 164 | 'format' => $this->format, 165 | )); 166 | } 167 | 168 | /** 169 | * Generates the functional test class only. 170 | * 171 | */ 172 | protected function generateTestClass() 173 | { 174 | $parts = explode('\\', $this->entity); 175 | $entityClass = array_pop($parts); 176 | $entityNamespace = implode('\\', $parts); 177 | 178 | $dir = $this->toBundle->getPath() .'/Tests/Controller'; 179 | $target = $dir .'/'. str_replace('\\', '/', $entityNamespace).'/'. $entityClass .'ControllerTest.php'; 180 | 181 | $this->renderFile('crud/tests/test.php.twig', $target, array( 182 | 'route_prefix' => $this->routePrefix, 183 | 'route_name_prefix' => $this->routeNamePrefix, 184 | 'entity' => $this->entity, 185 | 'bundle' => $this->bundle->getName(), 186 | 'entity_class' => $entityClass, 187 | 'namespace' => $this->bundle->getNamespace(), 188 | 'toNamespace' => $this->toBundle->getNamespace(), 189 | 'entity_namespace' => $entityNamespace, 190 | 'actions' => $this->actions, 191 | 'form_type_name' => strtolower(str_replace('\\', '_', $this->bundle->getNamespace()).($parts ? '_' : '').implode('_', $parts).'_'.$entityClass.'Type'), 192 | )); 193 | } 194 | 195 | /** 196 | * Generates the index.html.twig template in the final bundle. 197 | * 198 | * @param string $dir The path to the folder that hosts templates in the bundle 199 | */ 200 | protected function generateIndexView($dir) 201 | { 202 | $this->renderFile('crud/views/index.html.twig.twig', $dir.'/index.html.twig', array( 203 | 'bundle' => $this->bundle->getName(), 204 | 'toBundle' => $this->toBundle->getName(), 205 | 'entity' => $this->entity, 206 | 'fields' => $this->metadata->fieldMappings, 207 | 'actions' => $this->actions, 208 | 'record_actions' => $this->getRecordActions(), 209 | 'route_prefix' => $this->routePrefix, 210 | 'route_name_prefix' => $this->routeNamePrefix, 211 | )); 212 | } 213 | 214 | /** 215 | * Generates the show.html.twig template in the final bundle. 216 | * 217 | * @param string $dir The path to the folder that hosts templates in the bundle 218 | */ 219 | protected function generateShowView($dir) 220 | { 221 | $this->renderFile('crud/views/show.html.twig.twig', $dir.'/show.html.twig', array( 222 | 'bundle' => $this->bundle->getName(), 223 | 'toBundle' => $this->toBundle->getName(), 224 | 'entity' => $this->entity, 225 | 'fields' => $this->metadata->fieldMappings, 226 | 'actions' => $this->actions, 227 | 'route_prefix' => $this->routePrefix, 228 | 'route_name_prefix' => $this->routeNamePrefix, 229 | )); 230 | } 231 | 232 | /** 233 | * Generates the new.html.twig template in the final bundle. 234 | * 235 | * @param string $dir The path to the folder that hosts templates in the bundle 236 | */ 237 | protected function generateNewView($dir) 238 | { 239 | $this->renderFile('crud/views/new.html.twig.twig', $dir.'/new.html.twig', array( 240 | 'bundle' => $this->bundle->getName(), 241 | 'toBundle' => $this->toBundle->getName(), 242 | 'entity' => $this->entity, 243 | 'route_prefix' => $this->routePrefix, 244 | 'route_name_prefix' => $this->routeNamePrefix, 245 | 'actions' => $this->actions, 246 | )); 247 | } 248 | 249 | /** 250 | * Generates the edit.html.twig template in the final bundle. 251 | * 252 | * @param string $dir The path to the folder that hosts templates in the bundle 253 | */ 254 | protected function generateEditView($dir) 255 | { 256 | $this->renderFile('crud/views/edit.html.twig.twig', $dir.'/edit.html.twig', array( 257 | 'route_prefix' => $this->routePrefix, 258 | 'route_name_prefix' => $this->routeNamePrefix, 259 | 'entity' => $this->entity, 260 | 'bundle' => $this->bundle->getName(), 261 | 'toBundle' => $this->toBundle->getName(), 262 | 'actions' => $this->actions, 263 | )); 264 | } 265 | } 266 | --------------------------------------------------------------------------------