Skip to content

Commit 7784d3e

Browse files
wachterjohannesniklasnatter
authored andcommitted
06 - Add an event registration to the website
1 parent 9f5b1e2 commit 7784d3e

File tree

8 files changed

+323
-0
lines changed

8 files changed

+323
-0
lines changed

src/Controller/Website/EventWebsiteController.php

+30
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
namespace App\Controller\Website;
66

77
use App\Entity\Event;
8+
use App\Form\EventRegistrationType;
9+
use App\Repository\EventRegistrationRepository;
810
use App\Repository\EventRepository;
911
use Sulu\Bundle\WebsiteBundle\Resolver\TemplateAttributeResolverInterface;
1012
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
13+
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
1114
use Symfony\Component\HttpFoundation\Request;
1215
use Symfony\Component\HttpFoundation\Response;
1316
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -18,6 +21,7 @@ class EventWebsiteController extends AbstractController
1821
public function __construct(
1922
private readonly EventRepository $eventRepository,
2023
private readonly TemplateAttributeResolverInterface $templateAttributeResolver,
24+
private readonly EventRegistrationRepository $eventRegistrationRepository,
2125
) {
2226
}
2327

@@ -29,11 +33,37 @@ public function indexAction(int $id, Request $request): Response
2933
throw new NotFoundHttpException();
3034
}
3135

36+
$registration = $this->eventRegistrationRepository->create($event);
37+
$form = $this->createForm(EventRegistrationType::class, $registration);
38+
$form->add(
39+
'submit',
40+
SubmitType::class,
41+
[
42+
'label' => 'Create',
43+
],
44+
);
45+
46+
$form->handleRequest($request);
47+
48+
if ($form->isSubmitted() && $form->isValid()) {
49+
$this->eventRegistrationRepository->save($registration);
50+
51+
return $this->redirectToRoute(
52+
'app.event',
53+
[
54+
'id' => $event->getId(),
55+
'success' => true,
56+
],
57+
);
58+
}
59+
3260
return $this->render(
3361
'events/index.html.twig',
3462
$this->templateAttributeResolver->resolve(
3563
[
3664
'event' => $event,
65+
'success' => $request->query->get('success'),
66+
'form' => $form->createView(),
3767
'content' => ['title' => $event->getTitle()],
3868
],
3969
),

src/Entity/EventRegistration.php

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity;
6+
7+
use App\Repository\EventRegistrationRepository;
8+
use Doctrine\DBAL\Types\Types;
9+
use Doctrine\ORM\Mapping as ORM;
10+
use Symfony\Component\Validator\Constraints as Assert;
11+
12+
#[ORM\Entity(repositoryClass: EventRegistrationRepository::class)]
13+
class EventRegistration
14+
{
15+
#[ORM\Id]
16+
#[ORM\GeneratedValue]
17+
#[ORM\Column(type: Types::INTEGER)]
18+
private ?int $id = null;
19+
20+
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
21+
#[Assert\NotBlank]
22+
private ?string $firstName = null;
23+
24+
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
25+
#[Assert\NotBlank]
26+
private ?string $lastName = null;
27+
28+
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
29+
#[Assert\NotBlank]
30+
#[Assert\Email]
31+
private ?string $email = null;
32+
33+
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
34+
private ?string $message = null;
35+
36+
public function __construct(
37+
#[ORM\ManyToOne(targetEntity: Event::class)]
38+
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
39+
private Event $event,
40+
) {
41+
}
42+
43+
public function getId(): ?int
44+
{
45+
return $this->id;
46+
}
47+
48+
public function getEvent(): Event
49+
{
50+
return $this->event;
51+
}
52+
53+
public function getFirstName(): ?string
54+
{
55+
return $this->firstName;
56+
}
57+
58+
public function setFirstName(string $firstName): self
59+
{
60+
$this->firstName = $firstName;
61+
62+
return $this;
63+
}
64+
65+
public function getLastName(): ?string
66+
{
67+
return $this->lastName;
68+
}
69+
70+
public function setLastName(string $lastName): self
71+
{
72+
$this->lastName = $lastName;
73+
74+
return $this;
75+
}
76+
77+
public function getEmail(): ?string
78+
{
79+
return $this->email;
80+
}
81+
82+
public function setEmail(string $email): self
83+
{
84+
$this->email = $email;
85+
86+
return $this;
87+
}
88+
89+
public function getMessage(): ?string
90+
{
91+
return $this->message;
92+
}
93+
94+
public function setMessage(string $message): self
95+
{
96+
$this->message = $message;
97+
98+
return $this;
99+
}
100+
}

src/Form/EventRegistrationType.php

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Form;
6+
7+
use App\Entity\EventRegistration;
8+
use Symfony\Component\Form\AbstractType;
9+
use Symfony\Component\Form\FormBuilderInterface;
10+
use Symfony\Component\OptionsResolver\OptionsResolver;
11+
12+
class EventRegistrationType extends AbstractType
13+
{
14+
public function buildForm(FormBuilderInterface $builder, array $options): void
15+
{
16+
$builder
17+
->add('firstName')
18+
->add('lastName')
19+
->add('email')
20+
->add('message');
21+
}
22+
23+
public function configureOptions(OptionsResolver $resolver): void
24+
{
25+
$resolver->setDefaults(
26+
[
27+
'data_class' => EventRegistration::class,
28+
],
29+
);
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Repository;
6+
7+
use App\Entity\Event;
8+
use App\Entity\EventRegistration;
9+
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
10+
use Doctrine\Persistence\ManagerRegistry;
11+
12+
/**
13+
* @extends ServiceEntityRepository<EventRegistration>
14+
*/
15+
class EventRegistrationRepository extends ServiceEntityRepository
16+
{
17+
public function __construct(ManagerRegistry $registry)
18+
{
19+
parent::__construct($registry, EventRegistration::class);
20+
}
21+
22+
public function create(Event $event): EventRegistration
23+
{
24+
return new EventRegistration($event);
25+
}
26+
27+
public function save(EventRegistration $registration): void
28+
{
29+
$this->getEntityManager()->persist($registration);
30+
$this->getEntityManager()->flush();
31+
}
32+
}

templates/events/index.html.twig

+14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{% extends "base.html.twig" %}
22

3+
{% form_theme form 'bootstrap_4_layout.html.twig' %}
4+
35
{% block content %}
46
<section class="jumbotron text-center">
57
<div class="container">
@@ -12,6 +14,18 @@
1214
{{ event.description|raw }}
1315
</div>
1416

17+
<div class="container">
18+
{% if success %}
19+
<div class="success">
20+
<b>Thanks for your registration.</b>
21+
</div>
22+
{% else %}
23+
<h2>Register for this event:</h2>
24+
25+
{{ form(form) }}
26+
{% endif %}
27+
</div>
28+
1529
{% if event.image %}
1630
<div class="container">
1731
{% set image = sulu_resolve_media(event.image, app.request.locale) %}

tests/Functional/Controller/Website/EventWebsiteControllerTest.php

+35
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44

55
namespace App\Tests\Functional\Controller\Website;
66

7+
use App\Tests\Functional\Traits\EventRegistrationTrait;
78
use App\Tests\Functional\Traits\EventTrait;
89
use Sulu\Bundle\TestBundle\Testing\SuluTestCase;
910
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
1011
use Symfony\Component\HttpFoundation\Response;
1112

1213
class EventWebsiteControllerTest extends SuluTestCase
1314
{
15+
use EventRegistrationTrait;
1416
use EventTrait;
1517

1618
private KernelBrowser $client;
@@ -34,4 +36,37 @@ public function testIndexAction(): void
3436

3537
$this->assertStringContainsString('Sulu is awesome', $crawler->filter('h1')->html());
3638
}
39+
40+
public function testRegister(): void
41+
{
42+
$event = $this->createEvent('Sulu is awesome', 'en');
43+
44+
$crawler = $this->client->request('GET', '/en/event/' . $event->getId());
45+
46+
$response = $this->client->getResponse();
47+
$this->assertInstanceOf(Response::class, $response);
48+
$this->assertHttpStatusCode(200, $response);
49+
50+
$form = $crawler->filter('#event_registration_submit')->form(
51+
[
52+
'event_registration[firstName]' => 'Max',
53+
'event_registration[lastName]' => 'Mustermann',
54+
'event_registration[email]' => '[email protected]',
55+
'event_registration[message]' => 'I would love to see this.',
56+
],
57+
);
58+
59+
$this->client->submit($form);
60+
$crawler = $this->client->followRedirect();
61+
62+
$this->assertStringContainsString('Thanks for your registration', $crawler->filter('.success')->html());
63+
64+
$registrations = $this->findEventRegistrations($event);
65+
66+
$this->assertCount(1, $registrations);
67+
$this->assertSame('Max', $registrations[0]->getFirstName());
68+
$this->assertSame('Mustermann', $registrations[0]->getLastName());
69+
$this->assertSame('[email protected]', $registrations[0]->getEmail());
70+
$this->assertSame('I would love to see this.', $registrations[0]->getMessage());
71+
}
3772
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Tests\Functional\Traits;
6+
7+
use App\Entity\Event;
8+
use App\Entity\EventRegistration;
9+
use App\Repository\EventRegistrationRepository;
10+
use Doctrine\ORM\EntityManagerInterface;
11+
12+
trait EventRegistrationTrait
13+
{
14+
/**
15+
* @return EventRegistration[]
16+
*/
17+
public function findEventRegistrations(Event $event): array
18+
{
19+
return $this->getEventRegistrationRepository()->findBy(['event' => $event]);
20+
}
21+
22+
protected function getEventRegistrationRepository(): EventRegistrationRepository
23+
{
24+
return static::getEntityManager()->getRepository(EventRegistration::class);
25+
}
26+
27+
abstract protected static function getEntityManager(): EntityManagerInterface;
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Tests\Unit\Entity;
6+
7+
use App\Entity\Event;
8+
use App\Entity\EventRegistration;
9+
use PHPUnit\Framework\TestCase;
10+
use Prophecy\PhpUnit\ProphecyTrait;
11+
use Prophecy\Prophecy\ObjectProphecy;
12+
13+
class EventRegistrationTest extends TestCase
14+
{
15+
use ProphecyTrait;
16+
17+
/**
18+
* @var ObjectProphecy<Event>
19+
*/
20+
private ObjectProphecy $event;
21+
22+
private EventRegistration $eventRegistration;
23+
24+
protected function setUp(): void
25+
{
26+
$this->event = $this->prophesize(Event::class);
27+
$this->eventRegistration = new EventRegistration($this->event->reveal());
28+
}
29+
30+
public function testFirstName(): void
31+
{
32+
$this->assertSame($this->eventRegistration, $this->eventRegistration->setFirstName('Max'));
33+
$this->assertSame('Max', $this->eventRegistration->getFirstName());
34+
}
35+
36+
public function testGetLastName(): void
37+
{
38+
$this->assertSame($this->eventRegistration, $this->eventRegistration->setLastName('Mustermann'));
39+
$this->assertSame('Mustermann', $this->eventRegistration->getLastName());
40+
}
41+
42+
public function testGetEmail(): void
43+
{
44+
$this->assertSame($this->eventRegistration, $this->eventRegistration->setEmail('[email protected]'));
45+
$this->assertSame('[email protected]', $this->eventRegistration->getEmail());
46+
}
47+
48+
public function testGetMessage(): void
49+
{
50+
$this->assertSame($this->eventRegistration, $this->eventRegistration->setMessage('I would live to see this.'));
51+
$this->assertSame('I would live to see this.', $this->eventRegistration->getMessage());
52+
}
53+
}

0 commit comments

Comments
 (0)