Skip to content

Commit

Permalink
feature #113 Add make:crud & improve make:form commands (sadikoff, we…
Browse files Browse the repository at this point in the history
…averryan)

This PR was merged into the 1.0-dev branch.

Discussion
----------

Add make:crud & improve make:form commands

Hi all,

## Improved make:form command
Main improvement is that command works in two ways. First way simple, it just generates skeleton form class and user can do with it whatever he want. Second way is generation from entity class. Generator checks if entity exists and ask user if he wants to generate form from entity or user can use `--entity` flag if he knows that entity exists.
### Generation features:
- Simple skeleton form class
- Doctrine entity form class
### Examples:
**Simple class generation**
```bash
root@striX: ~/project_root# bin/console make:form

 The name of the form class (e.g. GentleElephantType):
 > SimpleForm

Enter the class or entity name that the new form will be bound to (empty for none):
 >

 created: src/Form/SimpleFormType.php

  Success!
```
**Entity form generation**
```bash
root@striX: ~/project_root# bin/console make:form

 The name of the form class (e.g. GentleElephantType):
 > EntityFormType

Enter the class or entity name that the new form will be bound to (empty for none):
 > Entity

 created: src/Form/EntityFormType.php

  Success!
```
Closes: #114

## New make:crud command
Want to introduce `make:crud` command it is similar to doctrine:generate:crud from SensioGeneratorBundle.

All you need to generate cool crud is Entity :)
### Features
- complete crud generation
### Example:
```bash
root@striX: ~/project_root# bin/console make:crud SweetFood

 created: src/Controller/SweetFoodController.php
 created: src/Form/SweetFoodType.php
 created: templates/sweet_food/_delete_form.html.twig
 created: templates/sweet_food/_form.html.twig
 created: templates/sweet_food/index.html.twig
 created: templates/sweet_food/show.html.twig
 created: templates/sweet_food/new.html.twig
 created: templates/sweet_food/edit.html.twig

  Success!

```
Closes: #3

Commits
-------

2683114 some improvements
2ec8ff0 fix form variables
0d9e637 added validation on arguments
ada7db0 fix phpcs
f740e2e fix variables to follow official recommendations
b3bf878 some make:form improvements + experiments
204f5aa final fix for skeleton templates
96d54a7 Merge branch 'master' of https://github.com/sadikoff/maker-bundle
38b2864 Merge remote-tracking branch 'upstream/master'
ee98865 making test name less specific so we can run only it
ba0438f phpcs fix
3d319bd some skeleton improvements
da37780 Merge remote-tracking branch 'upstream/master'
2ebff8c fix cs and improvements according to review request
772f0db fix make:form
44b7851 completed improvement of make:form command
db30634 added tests for crud testig
ad8a4fb fix tests on appveyor
e8eabd6 Merge remote-tracking branch 'upstream/master'
60c0005 php cs fix
404c38f update all to lastest bundle code
cc4b758 Merge remote-tracking branch 'upstream/master'
1b95509 add csrf dependency it's necessary for delete action in crud and for better security
52a20bb improve make:crud command to use make:form logic for form generation
e24b22c fix to use with php 7.0
7555a3a improved make:form command
4045695 removed unnecessary code
7ed6b8b improved tests
3787739 cs fix
71d2e90 some code refactoring + testing new GeneratorHelper to simplify skeleton templates
6f1c296 array style fix
96f2af2 Merge remote-tracking branch 'upstream/master'
ab0a0dc Merge remote-tracking branch 'upstream/master'
422d31b Merge branch 'master' of https://github.com/sadikoff/maker-bundle
ff9a08d some fixes
42047a6 fix Token parameter name in delete action
5157e0a fix interception of /new url by show action
7783313 fix fobpot.io cs
31d9e81 fix templates generation with date fields in entity
1b0f17a test remove some phpdoc comments to pass travis.ci
207d8be add exception if entity doesn't exists
478b457 fix fabpot.io cs 3
791241d fix fabpot.io cs 2
9961f43 fix fabpot.io cs
f189efd fix tests
8c98b45 trying tests 2
08d4bc5 trying tests
8e9bd67 fix skeleton according to community recommendations
e9f91ef add MakeCrud class to makers.xml
6cdda8f final fix fabpot.ci CS
4c0b639 fix fabpot.ci CS
bf9a5c1 make:crud command initial commit
  • Loading branch information
weaverryan committed Mar 14, 2018
2 parents 6d59659 + 2683114 commit fb18b88
Show file tree
Hide file tree
Showing 26 changed files with 1,195 additions and 20 deletions.
54 changes: 54 additions & 0 deletions src/Doctrine/DoctrineEntityDetails.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

/*
* This file is part of the Symfony MakerBundle package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\MakerBundle\Doctrine;

/**
* @author Sadicov Vladimir <[email protected]>
*
* @internal
*/
final class DoctrineEntityDetails
{
private $repositoryClass;

private $identifier;
private $displayFields;
private $formFields;

public function __construct($repositoryClass, $identifier, $displayFields, $formFields)
{
$this->repositoryClass = $repositoryClass;
$this->identifier = $identifier;
$this->displayFields = $displayFields;
$this->formFields = $formFields;
}

public function getRepositoryClass()
{
return $this->repositoryClass;
}

public function getIdentifier()
{
return $this->identifier;
}

public function getDisplayFields()
{
return $this->displayFields;
}

public function getFormFields()
{
return $this->formFields;
}
}
100 changes: 100 additions & 0 deletions src/Doctrine/DoctrineEntityHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

/*
* This file is part of the Symfony MakerBundle package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\MakerBundle\Doctrine;

use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Symfony\Bundle\MakerBundle\Util\ClassNameDetails;

/**
* @author Sadicov Vladimir <[email protected]>
*
* @internal
*/
final class DoctrineEntityHelper
{
private $metadataFactory;

public function __construct(ManagerRegistry $registry = null)
{
$this->metadataFactory = null !== $registry ? new DoctrineMetadataFactory($registry) : null;
}

private function isDoctrineInstalled(): bool
{
return null !== $this->metadataFactory;
}

public function getEntitiesForAutocomplete(): array
{
$entities = [];

if ($this->isDoctrineInstalled()) {
$allMetadata = $this->metadataFactory->getAllMetadata();
/** @var ClassMetadataInfo $metadata */
foreach ($allMetadata as $metadata) {
$entityClassDetails = new ClassNameDetails($metadata->name, 'App\\Entity');
$entities[] = $entityClassDetails->getRelativeName();
}
}

return $entities;
}

/**
* @param string $entityClassName
*
* @return null|DoctrineEntityDetails
*
* @throws \Exception
*/
public function createDoctrineDetails(string $entityClassName)
{
$metadata = $this->getEntityMetadata($entityClassName);

if (null !== $metadata) {
return new DoctrineEntityDetails(
$metadata->customRepositoryClassName,
$metadata->identifier[0],
$metadata->fieldMappings,
$this->getFormFieldsFromEntity($metadata)
);
}

return null;
}

public function getFormFieldsFromEntity(ClassMetadataInfo $metadata): array
{
$fields = (array) $metadata->fieldNames;
// Remove the primary key field if it's not managed manually
if (!$metadata->isIdentifierNatural()) {
$fields = array_diff($fields, $metadata->identifier);
}
foreach ($metadata->associationMappings as $fieldName => $relation) {
if (ClassMetadataInfo::ONE_TO_MANY !== $relation['type']) {
$fields[] = $fieldName;
}
}

return $fields;
}

public function getEntityMetadata($entityClassName)
{
if (null === $this->metadataFactory) {
throw new \Exception('Somehow the doctrine service is missing. Is DoctrineBundle installed?');
}

return $this->metadataFactory->getMetadataForClass($entityClassName);
}
}
93 changes: 93 additions & 0 deletions src/Doctrine/DoctrineMetadataFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

/*
* This file is part of the Symfony MakerBundle package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\MakerBundle\Doctrine;

use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;

/**
* Simpler version of DoctrineBundle's DisconnectedMetadataFactory, to
* avoid PSR-4 issues.
*
* @internal
*
* @author Fabien Potencier <[email protected]>
* @author Ryan Weaver <[email protected]>
*/
final class DoctrineMetadataFactory
{
private $registry;

/**
* Constructor.
*
* @param ManagerRegistry $registry A ManagerRegistry instance
*/
public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
}

/**
* @param string $namespace
*
* @return array|ClassMetadata[]
*/
public function getMetadataForNamespace($namespace)
{
$metadata = [];
foreach ($this->getAllMetadata() as $m) {
if (0 === strpos($m->name, $namespace)) {
$metadata[] = $m;
}
}

return $metadata;
}

/**
* @param string $entity
*
* @return ClassMetadata|null
*/
public function getMetadataForClass(string $entity)
{
foreach ($this->registry->getManagers() as $em) {
$cmf = new DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);

if (!$cmf->isTransient($entity)) {
return $cmf->getMetadataFor($entity);
}
}

return null;
}

/**
* @return array
*/
public function getAllMetadata()
{
$metadata = [];
foreach ($this->registry->getManagers() as $em) {
$cmf = new DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);
foreach ($cmf->getAllMetadata() as $m) {
$metadata[] = $m;
}
}

return $metadata;
}
}
6 changes: 6 additions & 0 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
class Generator
{
private $fileManager;
private $twigHelper;
private $pendingOperations = [];
private $namespacePrefix;

public function __construct(FileManager $fileManager, $namespacePrefix)
{
$this->fileManager = $fileManager;
$this->twigHelper = new GeneratorTwigHelper($fileManager);
$this->namespacePrefix = rtrim($namespacePrefix, '\\');
}

Expand Down Expand Up @@ -60,6 +62,10 @@ public function generateClass(string $className, string $templateName, array $va
*/
public function generateFile(string $targetPath, string $templateName, array $variables)
{
$variables = array_merge($variables, [
'helper' => $this->twigHelper,
]);

$this->addOperation($targetPath, $templateName, $variables);
}

Expand Down
69 changes: 69 additions & 0 deletions src/GeneratorTwigHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/*
* This file is part of the Symfony MakerBundle package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\MakerBundle;

/**
* @author Sadicov Vladimir <[email protected]>
*/
final class GeneratorTwigHelper
{
private $fileManager;

public function __construct(FileManager $fileManager)
{
$this->fileManager = $fileManager;
}

public function getEntityFieldPrintCode($entity, $field): string
{
$printCode = $entity.'.'.$field['fieldName'];

switch ($field['type']) {
case 'datetime':
$printCode .= ' ? '.$printCode.'|date(\'Y-m-d H:i:s\') : \'\'';
break;
case 'date':
$printCode .= ' ? '.$printCode.'|date(\'Y-m-d\') : \'\'';
break;
case 'time':
$printCode .= ' ? '.$printCode.'|date(\'H:i:s\') : \'\'';
break;
case 'array':
$printCode .= ' ? '.$printCode.'|join(\', \') : \'\'';
break;
case 'boolean':
$printCode .= ' ? \'Yes\' : \'No\'';
break;
}

return $printCode;
}

public function getHeadPrintCode($title): string
{
if ($this->fileManager->fileExists('templates/base.html.twig')) {
return <<<TWIG
{% extends 'base.html.twig' %}
{% block title %}$title{% endblock %}
TWIG;
}

return <<<HTML
<!DOCTYPE html>
<title>$title</title>
HTML;
}
}
Loading

0 comments on commit fb18b88

Please sign in to comment.