diff --git a/src/Maker/MakeCrud.php b/src/Maker/MakeCrud.php index 4ecd8fa3a..e2a6ea53b 100644 --- a/src/Maker/MakeCrud.php +++ b/src/Maker/MakeCrud.php @@ -119,6 +119,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $repositoryClassName = $repositoryClassDetails->getFullName(); $repositoryVars = [ + 'repository_full_class_name' => $repositoryClassName, 'repository_class_name' => $repositoryClassDetails->getShortName(), 'repository_var' => lcfirst($this->inflector->singularize($repositoryClassDetails->getShortName())), ]; diff --git a/src/Resources/skeleton/crud/controller/Controller.tpl.php b/src/Resources/skeleton/crud/controller/Controller.tpl.php index 19f2fb011..2842a0c02 100644 --- a/src/Resources/skeleton/crud/controller/Controller.tpl.php +++ b/src/Resources/skeleton/crud/controller/Controller.tpl.php @@ -47,7 +47,8 @@ public function new(Request $request, EntityManagerInterface $entityManager): Re repositoryHasAddRemoveMethods($repository_full_class_name)) { ?> if ($form->isSubmitted() && $form->isValid()) { - $->add($); + $->add($, true); + return $this->redirectToRoute('_index', [], Response::HTTP_SEE_OTHER); } @@ -92,7 +93,8 @@ public function edit(Request $request, $repositoryHasAddRemoveMethods($repository_full_class_name)) { ?> if ($form->isSubmitted() && $form->isValid()) { - $->add($); + $->add($, true); + return $this->redirectToRoute('_index', [], Response::HTTP_SEE_OTHER); } @@ -125,7 +127,7 @@ public function delete(Request $request, $repositoryHasAddRemoveMethods($repository_full_class_name)) { ?> if ($this->isCsrfTokenValid('delete'.$->get(), $request->request->get('_token'))) { - $->remove($); + $->remove($, true); } if ($this->isCsrfTokenValid('delete'.$->get(), $request->request->get('_token'))) { diff --git a/tests/Maker/MakeCrudTest.php b/tests/Maker/MakeCrudTest.php index 4717c0340..abb5a249b 100644 --- a/tests/Maker/MakeCrudTest.php +++ b/tests/Maker/MakeCrudTest.php @@ -18,6 +18,8 @@ class MakeCrudTest extends MakerTestCase { + use TestHelpersTrait; + protected function getMakerClass(): string { return MakeCrud::class; @@ -28,7 +30,7 @@ public function getTestDetails(): \Generator yield 'it_generates_basic_crud' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { $runner->copy( - 'make-crud/SweetFood.php', + $this->getFixturePath('SweetFood.php', $runner), 'src/Entity/SweetFood.php' ); @@ -48,7 +50,7 @@ public function getTestDetails(): \Generator yield 'it_generates_crud_with_custom_controller' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { $runner->copy( - 'make-crud/SweetFood.php', + $this->getFixturePath('SweetFood.php', $runner), 'src/Entity/SweetFood.php' ); @@ -74,7 +76,7 @@ public function getTestDetails(): \Generator ); $runner->copy( - 'make-crud/SweetFood-custom-namespace.php', + $this->getFixturePath('SweetFood-custom-namespace.php', $runner), 'src/Entity/SweetFood.php' ); @@ -94,7 +96,7 @@ public function getTestDetails(): \Generator yield 'it_generates_crud_using_custom_repository' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { $runner->copy( - 'make-crud/SweetFood.php', + $this->getFixturePath('SweetFoodCustomRepository.php', $runner), 'src/Entity/SweetFood.php' ); $runner->copy( @@ -112,13 +114,18 @@ public function getTestDetails(): \Generator $this->assertStringContainsString('created: src/Form/SweetFoodType.php', $output); $this->runCrudTest($runner, 'it_generates_basic_crud.php'); + + self::assertFileEquals( + sprintf('%s/fixtures/%s', \dirname(__DIR__), $this->getFixturePath('expected/WithCustomRepository.php', $runner)), + $runner->getPath('src/Controller/SweetFoodController.php') + ); }), ]; yield 'it_generates_crud_with_no_base_template' => [$this->createMakerTest() ->run(function (MakerTestRunner $runner) { $runner->copy( - 'make-crud/SweetFood.php', + $this->getFixturePath('SweetFood.php', $runner), 'src/Entity/SweetFood.php' ); @@ -138,6 +145,14 @@ public function getTestDetails(): \Generator ]; } + // @legacy - remove when annotations are no longer supported + private function getFixturePath(string $sourceName, MakerTestRunner $runner): string + { + $path = $this->useAttributes($runner) ? 'make-crud' : 'make-crud/legacy'; + + return sprintf('%s/%s', $path, $sourceName); + } + private function runCrudTest(MakerTestRunner $runner, string $filename): void { $runner->copy( diff --git a/tests/Maker/MakeEntityTest.php b/tests/Maker/MakeEntityTest.php index d71896371..b4a2c8750 100644 --- a/tests/Maker/MakeEntityTest.php +++ b/tests/Maker/MakeEntityTest.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\MakerBundle\Tests\Maker; -use Doctrine\ORM\Mapping\Driver\AttributeReader; use Symfony\Bundle\MakerBundle\Maker\MakeEntity; use Symfony\Bundle\MakerBundle\Test\MakerTestCase; use Symfony\Bundle\MakerBundle\Test\MakerTestDetails; @@ -21,6 +20,8 @@ class MakeEntityTest extends MakerTestCase { + use TestHelpersTrait; + protected function getMakerClass(): string { return MakeEntity::class; @@ -671,13 +672,6 @@ private function changeToXmlMapping(MakerTestRunner $runner): void ); } - private function useAttributes(MakerTestRunner $runner): bool - { - return \PHP_VERSION_ID >= 80000 - && $runner->doesClassExist(AttributeReader::class) - && $runner->getSymfonyVersion() >= 50200; - } - private function copyEntity(MakerTestRunner $runner, string $filename): void { $entityClassName = substr( diff --git a/tests/Maker/TestHelpersTrait.php b/tests/Maker/TestHelpersTrait.php new file mode 100644 index 000000000..eac266d03 --- /dev/null +++ b/tests/Maker/TestHelpersTrait.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\MakerBundle\Tests\Maker; + +use Doctrine\ORM\Mapping\Driver\AttributeReader; +use Symfony\Bundle\MakerBundle\Test\MakerTestRunner; + +/** + * @author Jesse Rushlow + * + * @internal + */ +trait TestHelpersTrait +{ + // @legacy - remove when annotations are no longer supported + protected function useAttributes(MakerTestRunner $runner): bool + { + return \PHP_VERSION_ID >= 80000 + && $runner->doesClassExist(AttributeReader::class); + } +} diff --git a/tests/fixtures/make-crud/SweetFood-custom-namespace.php b/tests/fixtures/make-crud/SweetFood-custom-namespace.php index e29011735..650ebfd0b 100644 --- a/tests/fixtures/make-crud/SweetFood-custom-namespace.php +++ b/tests/fixtures/make-crud/SweetFood-custom-namespace.php @@ -4,21 +4,15 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ +#[ORM\Entity()] class SweetFood { - /** - * @ORM\Column(name="id", type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** - * @ORM\Column(name="title", type="string", length=255) - */ + #[ORM\Column(type: 'string', length: 255)] private $title; public function getId() @@ -26,19 +20,15 @@ public function getId() return $this->id; } - /** - * @return mixed - */ - public function getTitle() + public function getTitle(): string { return $this->title; } - /** - * @param mixed $title - */ - public function setTitle($title) + public function setTitle(string $title): self { $this->title = $title; + + return $this; } } diff --git a/tests/fixtures/make-crud/SweetFood.php b/tests/fixtures/make-crud/SweetFood.php index 66590eaf7..dadafd158 100644 --- a/tests/fixtures/make-crud/SweetFood.php +++ b/tests/fixtures/make-crud/SweetFood.php @@ -4,21 +4,15 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity() - */ +#[ORM\Entity()] class SweetFood { - /** - * @ORM\Column(name="id", type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: 'integer')] private $id; - /** - * @ORM\Column(name="title", type="string", length=255) - */ + #[ORM\Column(type: 'string', length: 255)] private $title; public function getId() @@ -26,19 +20,15 @@ public function getId() return $this->id; } - /** - * @return mixed - */ - public function getTitle() + public function getTitle(): string { return $this->title; } - /** - * @param mixed $title - */ - public function setTitle($title) + public function setTitle(string $title): self { $this->title = $title; + + return $this; } } diff --git a/tests/fixtures/make-crud/SweetFoodCustomRepository.php b/tests/fixtures/make-crud/SweetFoodCustomRepository.php new file mode 100644 index 000000000..c0474333f --- /dev/null +++ b/tests/fixtures/make-crud/SweetFoodCustomRepository.php @@ -0,0 +1,35 @@ +id; + } + + public function getTitle(): string + { + return $this->title; + } + + public function setTitle(string $title): self + { + $this->title = $title; + + return $this; + } +} diff --git a/tests/fixtures/make-crud/SweetFoodRepository.php b/tests/fixtures/make-crud/SweetFoodRepository.php index 2207f239e..71e7e0a45 100644 --- a/tests/fixtures/make-crud/SweetFoodRepository.php +++ b/tests/fixtures/make-crud/SweetFoodRepository.php @@ -7,6 +7,8 @@ use Doctrine\Persistence\ManagerRegistry; /** + * @extends ServiceEntityRepository + * * @method SweetFood|null find($id, $lockMode = null, $lockVersion = null) * @method SweetFood|null findOneBy(array $criteria, array $orderBy = null) * @method SweetFood[] findAll() @@ -19,16 +21,21 @@ public function __construct(ManagerRegistry $registry) parent::__construct($registry, SweetFood::class); } - /* - public function findBySomething($value) + public function add(SweetFood $entity, bool $flush = false): void { - return $this->createQueryBuilder('t') - ->where('t.something = :value')->setParameter('value', $value) - ->orderBy('t.id', 'ASC') - ->setMaxResults(10) - ->getQuery() - ->getResult() - ; + ($em = $this->getEntityManager())->persist($entity); + + if ($flush) { + $em->flush(); + } + } + + public function remove(SweetFood $entity, bool $flush = false): void + { + ($em = $this->getEntityManager())->remove($entity); + + if ($flush) { + $em->flush(); + } } - */ } diff --git a/tests/fixtures/make-crud/expected/WithCustomRepository.php b/tests/fixtures/make-crud/expected/WithCustomRepository.php new file mode 100644 index 000000000..725c38a89 --- /dev/null +++ b/tests/fixtures/make-crud/expected/WithCustomRepository.php @@ -0,0 +1,78 @@ +render('sweet_food/index.html.twig', [ + 'sweet_foods' => $sweetFoodRepository->findAll(), + ]); + } + + #[Route('/new', name: 'app_sweet_food_new', methods: ['GET', 'POST'])] + public function new(Request $request, SweetFoodRepository $sweetFoodRepository): Response + { + $sweetFood = new SweetFood(); + $form = $this->createForm(SweetFoodType::class, $sweetFood); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $sweetFoodRepository->add($sweetFood, true); + + return $this->redirectToRoute('app_sweet_food_index', [], Response::HTTP_SEE_OTHER); + } + + return $this->renderForm('sweet_food/new.html.twig', [ + 'sweet_food' => $sweetFood, + 'form' => $form, + ]); + } + + #[Route('/{id}', name: 'app_sweet_food_show', methods: ['GET'])] + public function show(SweetFood $sweetFood): Response + { + return $this->render('sweet_food/show.html.twig', [ + 'sweet_food' => $sweetFood, + ]); + } + + #[Route('/{id}/edit', name: 'app_sweet_food_edit', methods: ['GET', 'POST'])] + public function edit(Request $request, SweetFood $sweetFood, SweetFoodRepository $sweetFoodRepository): Response + { + $form = $this->createForm(SweetFoodType::class, $sweetFood); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $sweetFoodRepository->add($sweetFood, true); + + return $this->redirectToRoute('app_sweet_food_index', [], Response::HTTP_SEE_OTHER); + } + + return $this->renderForm('sweet_food/edit.html.twig', [ + 'sweet_food' => $sweetFood, + 'form' => $form, + ]); + } + + #[Route('/{id}', name: 'app_sweet_food_delete', methods: ['POST'])] + public function delete(Request $request, SweetFood $sweetFood, SweetFoodRepository $sweetFoodRepository): Response + { + if ($this->isCsrfTokenValid('delete'.$sweetFood->getId(), $request->request->get('_token'))) { + $sweetFoodRepository->remove($sweetFood, true); + } + + return $this->redirectToRoute('app_sweet_food_index', [], Response::HTTP_SEE_OTHER); + } +} diff --git a/tests/fixtures/make-crud/legacy/SweetFood-custom-namespace.php b/tests/fixtures/make-crud/legacy/SweetFood-custom-namespace.php new file mode 100644 index 000000000..e29011735 --- /dev/null +++ b/tests/fixtures/make-crud/legacy/SweetFood-custom-namespace.php @@ -0,0 +1,44 @@ +id; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param mixed $title + */ + public function setTitle($title) + { + $this->title = $title; + } +} diff --git a/tests/fixtures/make-crud/legacy/SweetFood.php b/tests/fixtures/make-crud/legacy/SweetFood.php new file mode 100644 index 000000000..66590eaf7 --- /dev/null +++ b/tests/fixtures/make-crud/legacy/SweetFood.php @@ -0,0 +1,44 @@ +id; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param mixed $title + */ + public function setTitle($title) + { + $this->title = $title; + } +} diff --git a/tests/fixtures/make-crud/legacy/SweetFoodCustomRepository.php b/tests/fixtures/make-crud/legacy/SweetFoodCustomRepository.php new file mode 100644 index 000000000..2d27b6854 --- /dev/null +++ b/tests/fixtures/make-crud/legacy/SweetFoodCustomRepository.php @@ -0,0 +1,45 @@ +id; + } + + /** + * @return mixed + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param mixed $title + */ + public function setTitle($title) + { + $this->title = $title; + } +} diff --git a/tests/fixtures/make-crud/legacy/SweetFoodRepository.php b/tests/fixtures/make-crud/legacy/SweetFoodRepository.php new file mode 100644 index 000000000..71e7e0a45 --- /dev/null +++ b/tests/fixtures/make-crud/legacy/SweetFoodRepository.php @@ -0,0 +1,41 @@ + + * + * @method SweetFood|null find($id, $lockMode = null, $lockVersion = null) + * @method SweetFood|null findOneBy(array $criteria, array $orderBy = null) + * @method SweetFood[] findAll() + * @method SweetFood[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class SweetFoodRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, SweetFood::class); + } + + public function add(SweetFood $entity, bool $flush = false): void + { + ($em = $this->getEntityManager())->persist($entity); + + if ($flush) { + $em->flush(); + } + } + + public function remove(SweetFood $entity, bool $flush = false): void + { + ($em = $this->getEntityManager())->remove($entity); + + if ($flush) { + $em->flush(); + } + } +} diff --git a/tests/fixtures/make-crud/legacy/expected/WithCustomRepository.php b/tests/fixtures/make-crud/legacy/expected/WithCustomRepository.php new file mode 100644 index 000000000..53e90a985 --- /dev/null +++ b/tests/fixtures/make-crud/legacy/expected/WithCustomRepository.php @@ -0,0 +1,90 @@ +render('sweet_food/index.html.twig', [ + 'sweet_foods' => $sweetFoodRepository->findAll(), + ]); + } + + /** + * @Route("/new", name="app_sweet_food_new", methods={"GET", "POST"}) + */ + public function new(Request $request, SweetFoodRepository $sweetFoodRepository): Response + { + $sweetFood = new SweetFood(); + $form = $this->createForm(SweetFoodType::class, $sweetFood); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $sweetFoodRepository->add($sweetFood, true); + + return $this->redirectToRoute('app_sweet_food_index', [], Response::HTTP_SEE_OTHER); + } + + return $this->renderForm('sweet_food/new.html.twig', [ + 'sweet_food' => $sweetFood, + 'form' => $form, + ]); + } + + /** + * @Route("/{id}", name="app_sweet_food_show", methods={"GET"}) + */ + public function show(SweetFood $sweetFood): Response + { + return $this->render('sweet_food/show.html.twig', [ + 'sweet_food' => $sweetFood, + ]); + } + + /** + * @Route("/{id}/edit", name="app_sweet_food_edit", methods={"GET", "POST"}) + */ + public function edit(Request $request, SweetFood $sweetFood, SweetFoodRepository $sweetFoodRepository): Response + { + $form = $this->createForm(SweetFoodType::class, $sweetFood); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $sweetFoodRepository->add($sweetFood, true); + + return $this->redirectToRoute('app_sweet_food_index', [], Response::HTTP_SEE_OTHER); + } + + return $this->renderForm('sweet_food/edit.html.twig', [ + 'sweet_food' => $sweetFood, + 'form' => $form, + ]); + } + + /** + * @Route("/{id}", name="app_sweet_food_delete", methods={"POST"}) + */ + public function delete(Request $request, SweetFood $sweetFood, SweetFoodRepository $sweetFoodRepository): Response + { + if ($this->isCsrfTokenValid('delete'.$sweetFood->getId(), $request->request->get('_token'))) { + $sweetFoodRepository->remove($sweetFood, true); + } + + return $this->redirectToRoute('app_sweet_food_index', [], Response::HTTP_SEE_OTHER); + } +}