Skip to content

Commit

Permalink
06 - Add an event registration to the website
Browse files Browse the repository at this point in the history
  • Loading branch information
wachterjohannes authored and niklasnatter committed Oct 17, 2022
1 parent 24ec20c commit 3534d84
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/Controller/Website/EventWebsiteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
namespace App\Controller\Website;

use App\Entity\Event;
use App\Form\EventRegistrationType;
use App\Repository\EventRegistrationRepository;
use App\Repository\EventRepository;
use Sulu\Bundle\WebsiteBundle\Resolver\TemplateAttributeResolverInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
Expand All @@ -18,6 +21,7 @@ class EventWebsiteController extends AbstractController
public function __construct(
private readonly EventRepository $eventRepository,
private readonly TemplateAttributeResolverInterface $templateAttributeResolver,
private readonly EventRegistrationRepository $eventRegistrationRepository,
) {
}

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

$registration = $this->eventRegistrationRepository->create($event);
$form = $this->createForm(EventRegistrationType::class, $registration);
$form->add(
'submit',
SubmitType::class,
[
'label' => 'Create',
],
);

$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$this->eventRegistrationRepository->save($registration);

return $this->redirectToRoute(
'app.event',
[
'id' => $event->getId(),
'success' => true,
],
);
}

return $this->render(
'events/index.html.twig',
$this->templateAttributeResolver->resolve(
[
'event' => $event,
'success' => $request->query->get('success'),
'form' => $form->createView(),
'content' => ['title' => $event->getTitle()],
],
),
Expand Down
100 changes: 100 additions & 0 deletions src/Entity/EventRegistration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);

namespace App\Entity;

use App\Repository\EventRegistrationRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

#[ORM\Entity(repositoryClass: EventRegistrationRepository::class)]
class EventRegistration
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: Types::INTEGER)]
private ?int $id = null;

#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
#[Assert\NotBlank]
private ?string $firstName = null;

#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
#[Assert\NotBlank]
private ?string $lastName = null;

#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
#[Assert\NotBlank]
#[Assert\Email]
private ?string $email = null;

#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
private ?string $message = null;

public function __construct(
#[ORM\ManyToOne(targetEntity: Event::class)]
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
private Event $event,
) {
}

public function getId(): ?int
{
return $this->id;
}

public function getEvent(): Event
{
return $this->event;
}

public function getFirstName(): ?string
{
return $this->firstName;
}

public function setFirstName(string $firstName): self
{
$this->firstName = $firstName;

return $this;
}

public function getLastName(): ?string
{
return $this->lastName;
}

public function setLastName(string $lastName): self
{
$this->lastName = $lastName;

return $this;
}

public function getEmail(): ?string
{
return $this->email;
}

public function setEmail(string $email): self
{
$this->email = $email;

return $this;
}

public function getMessage(): ?string
{
return $this->message;
}

public function setMessage(string $message): self
{
$this->message = $message;

return $this;
}
}
31 changes: 31 additions & 0 deletions src/Form/EventRegistrationType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace App\Form;

use App\Entity\EventRegistration;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class EventRegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('firstName')
->add('lastName')
->add('email')
->add('message');
}

public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(
[
'data_class' => EventRegistration::class,
],
);
}
}
32 changes: 32 additions & 0 deletions src/Repository/EventRegistrationRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace App\Repository;

use App\Entity\Event;
use App\Entity\EventRegistration;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
* @extends ServiceEntityRepository<EventRegistration>
*/
class EventRegistrationRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, EventRegistration::class);
}

public function create(Event $event): EventRegistration
{
return new EventRegistration($event);
}

public function save(EventRegistration $registration): void
{
$this->getEntityManager()->persist($registration);
$this->getEntityManager()->flush();
}
}
14 changes: 14 additions & 0 deletions templates/events/index.html.twig
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{% extends "base.html.twig" %}

{% form_theme form 'bootstrap_4_layout.html.twig' %}

{% block content %}
<section class="jumbotron text-center">
<div class="container">
Expand All @@ -12,6 +14,18 @@
{{ event.description|raw }}
</div>

<div class="container">
{% if success %}
<div class="success">
<b>Thanks for your registration.</b>
</div>
{% else %}
<h2>Register for this event:</h2>

{{ form(form) }}
{% endif %}
</div>

{% if event.image %}
<div class="container">
{% set image = sulu_resolve_media(event.image, app.request.locale) %}
Expand Down
35 changes: 35 additions & 0 deletions tests/Functional/Controller/Website/EventWebsiteControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

namespace App\Tests\Functional\Controller\Website;

use App\Tests\Functional\Traits\EventRegistrationTrait;
use App\Tests\Functional\Traits\EventTrait;
use Sulu\Bundle\TestBundle\Testing\SuluTestCase;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Component\HttpFoundation\Response;

class EventWebsiteControllerTest extends SuluTestCase
{
use EventRegistrationTrait;
use EventTrait;

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

$this->assertStringContainsString('Sulu is awesome', $crawler->filter('h1')->html());
}

public function testRegister(): void
{
$event = $this->createEvent('Sulu is awesome', 'en');

$crawler = $this->client->request('GET', '/en/event/' . $event->getId());

$response = $this->client->getResponse();
$this->assertInstanceOf(Response::class, $response);
$this->assertHttpStatusCode(200, $response);

$form = $crawler->filter('#event_registration_submit')->form(
[
'event_registration[firstName]' => 'Max',
'event_registration[lastName]' => 'Mustermann',
'event_registration[email]' => '[email protected]',
'event_registration[message]' => 'I would love to see this.',
],
);

$this->client->submit($form);
$crawler = $this->client->followRedirect();

$this->assertStringContainsString('Thanks for your registration', $crawler->filter('.success')->html());

$registrations = $this->findEventRegistrations($event);

$this->assertCount(1, $registrations);
$this->assertSame('Max', $registrations[0]->getFirstName());
$this->assertSame('Mustermann', $registrations[0]->getLastName());
$this->assertSame('[email protected]', $registrations[0]->getEmail());
$this->assertSame('I would love to see this.', $registrations[0]->getMessage());
}
}
28 changes: 28 additions & 0 deletions tests/Functional/Traits/EventRegistrationTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace App\Tests\Functional\Traits;

use App\Entity\Event;
use App\Entity\EventRegistration;
use App\Repository\EventRegistrationRepository;
use Doctrine\ORM\EntityManagerInterface;

trait EventRegistrationTrait
{
/**
* @return EventRegistration[]
*/
public function findEventRegistrations(Event $event): array
{
return $this->getEventRegistrationRepository()->findBy(['event' => $event]);
}

protected function getEventRegistrationRepository(): EventRegistrationRepository
{
return static::getEntityManager()->getRepository(EventRegistration::class);
}

abstract protected static function getEntityManager(): EntityManagerInterface;
}
53 changes: 53 additions & 0 deletions tests/Unit/Entity/EventRegistrationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace App\Tests\Unit\Entity;

use App\Entity\Event;
use App\Entity\EventRegistration;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;

class EventRegistrationTest extends TestCase
{
use ProphecyTrait;

/**
* @var ObjectProphecy<Event>
*/
private ObjectProphecy $event;

private EventRegistration $eventRegistration;

protected function setUp(): void
{
$this->event = $this->prophesize(Event::class);
$this->eventRegistration = new EventRegistration($this->event->reveal());
}

public function testFirstName(): void
{
$this->assertSame($this->eventRegistration, $this->eventRegistration->setFirstName('Max'));
$this->assertSame('Max', $this->eventRegistration->getFirstName());
}

public function testGetLastName(): void
{
$this->assertSame($this->eventRegistration, $this->eventRegistration->setLastName('Mustermann'));
$this->assertSame('Mustermann', $this->eventRegistration->getLastName());
}

public function testGetEmail(): void
{
$this->assertSame($this->eventRegistration, $this->eventRegistration->setEmail('[email protected]'));
$this->assertSame('[email protected]', $this->eventRegistration->getEmail());
}

public function testGetMessage(): void
{
$this->assertSame($this->eventRegistration, $this->eventRegistration->setMessage('I would live to see this.'));
$this->assertSame('I would live to see this.', $this->eventRegistration->getMessage());
}
}

0 comments on commit 3534d84

Please sign in to comment.