diff --git a/config/forms/event_details.xml b/config/forms/event_details.xml index c30baef..2de73ca 100644 --- a/config/forms/event_details.xml +++ b/config/forms/event_details.xml @@ -24,7 +24,7 @@ - + app.location diff --git a/config/packages/sulu_admin.yaml b/config/packages/sulu_admin.yaml index a669187..d84555c 100644 --- a/config/packages/sulu_admin.yaml +++ b/config/packages/sulu_admin.yaml @@ -38,3 +38,17 @@ sulu_admin: icon: fa-calendar label: 'app.events' overlay_title: 'app.events' + + single_selection: + single_location_selection: + default_type: list_overlay + resource_key: locations + types: + list_overlay: + adapter: table + list_key: locations + display_properties: + - name + icon: fa-home + empty_text: 'app.location.no_selections' + overlay_title: 'app.locations' diff --git a/src/Controller/Admin/EventController.php b/src/Controller/Admin/EventController.php index f8a5100..3b641ce 100644 --- a/src/Controller/Admin/EventController.php +++ b/src/Controller/Admin/EventController.php @@ -7,6 +7,7 @@ use App\Common\DoctrineListRepresentationFactory; use App\Entity\Event; use App\Repository\EventRepository; +use App\Repository\LocationRepository; use Sulu\Bundle\MediaBundle\Entity\MediaRepositoryInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -31,14 +32,21 @@ class EventController extends AbstractController */ private $doctrineListRepresentationFactory; + /** + * @var LocationRepository + */ + private $locationRepository; + public function __construct( EventRepository $repository, MediaRepositoryInterface $mediaRepository, DoctrineListRepresentationFactory $doctrineListRepresentationFactory, + LocationRepository $locationRepository ) { $this->eventRepository = $repository; $this->mediaRepository = $mediaRepository; $this->doctrineListRepresentationFactory = $doctrineListRepresentationFactory; + $this->locationRepository = $locationRepository; } /** @@ -139,6 +147,7 @@ protected function getDataForEntity(Event $entity): array $image = $entity->getImage(); $startDate = $entity->getStartDate(); $endDate = $entity->getEndDate(); + $location = $entity->getLocation(); return [ 'id' => $entity->getId(), @@ -151,7 +160,7 @@ protected function getDataForEntity(Event $entity): array 'description' => $entity->getDescription(), 'startDate' => $startDate ? $startDate->format('c') : null, 'endDate' => $endDate ? $endDate->format('c') : null, - 'location' => $entity->getLocation(), + 'locationId' => $location ? $location->getId() : null, ]; } @@ -168,7 +177,7 @@ protected function mapDataToEntity(array $data, Event $entity): void $entity->setDescription($data['description'] ?? ''); $entity->setStartDate($data['startDate'] ? new \DateTimeImmutable($data['startDate']) : null); $entity->setEndDate($data['endDate'] ? new \DateTimeImmutable($data['endDate']) : null); - $entity->setLocation($data['location'] ?? null); + $entity->setLocation($data['locationId'] ? $this->locationRepository->findById((int) $data['locationId']) : null); } protected function load(int $id, Request $request): ?Event diff --git a/src/DataFixtures/ORM/AppFixtures.php b/src/DataFixtures/ORM/AppFixtures.php index 727b5c4..c156957 100644 --- a/src/DataFixtures/ORM/AppFixtures.php +++ b/src/DataFixtures/ORM/AppFixtures.php @@ -5,6 +5,7 @@ namespace App\DataFixtures\ORM; use App\Entity\Event; +use App\Entity\Location; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Persistence\ObjectManager; @@ -56,7 +57,8 @@ public function load(ObjectManager $manager): void */ private function loadEvents(ObjectManager $manager, array $images): void { - $repository = $manager->getRepository(Event::class); + $eventRepository = $manager->getRepository(Event::class); + $locationRepository = $manager->getRepository(Location::class); $data = [ [ @@ -132,18 +134,30 @@ private function loadEvents(ObjectManager $manager, array $images): void ]; foreach ($data as $item) { - $event = $repository->create(self::LOCALE); + $location = null; + if ($item['location']) { + $location = $locationRepository->create(); + $location->setName($item['location']); + $location->setStreet(''); + $location->setNumber(''); + $location->setCity(''); + $location->setCountryCode(''); + $location->setPostalCode(''); + $locationRepository->save($location); + } + + $event = $eventRepository->create(self::LOCALE); $event->setTitle($item['title']); $event->setImage($images[$item['image']] ?? null); - $event->setLocation($item['location']); + $event->setLocation($location); $event->setTeaser($item['teaser']); $event->setDescription('

' . $item['description'] . '

'); $event->setStartDate(new \DateTimeImmutable($item['startDate'])); $event->setEndDate(new \DateTimeImmutable($item['endDate'])); $event->setEnabled($item['enabled']); - $repository->save($event); + $eventRepository->save($event); } } diff --git a/src/Entity/Event.php b/src/Entity/Event.php index 0924e60..37ad951 100644 --- a/src/Entity/Event.php +++ b/src/Entity/Event.php @@ -47,9 +47,10 @@ class Event private $endDate; /** - * @var string|null + * @var Location|null * - * @ORM\Column(type="string", nullable=true) + * @ORM\ManyToOne(targetEntity="App\Entity\Location") + * @ORM\JoinColumn(onDelete="SET NULL") */ private $location; @@ -119,12 +120,12 @@ public function setEndDate(?\DateTimeImmutable $endDate): self return $this; } - public function getLocation(): ?string + public function getLocation(): ?Location { return $this->location; } - public function setLocation(?string $location): self + public function setLocation(?Location $location): self { $this->location = $location; diff --git a/tests/Functional/Controller/Admin/EventControllerTest.php b/tests/Functional/Controller/Admin/EventControllerTest.php index e6a3625..0ac25f9 100644 --- a/tests/Functional/Controller/Admin/EventControllerTest.php +++ b/tests/Functional/Controller/Admin/EventControllerTest.php @@ -5,6 +5,7 @@ namespace App\Tests\Functional\Controller\Admin; use App\Tests\Functional\Traits\EventTrait; +use App\Tests\Functional\Traits\LocationTrait; use Sulu\Bundle\TestBundle\Testing\SuluTestCase; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Component\HttpFoundation\Response; @@ -12,6 +13,7 @@ class EventControllerTest extends SuluTestCase { use EventTrait; + use LocationTrait; /** * @var KernelBrowser @@ -64,6 +66,8 @@ public function testGet(): void public function testPost(): void { + $location = $this->createLocation('Sulu HQ'); + $this->client->jsonRequest( 'POST', '/admin/api/events?locale=de', @@ -73,7 +77,7 @@ public function testPost(): void 'startDate' => '2019-01-01 12:00', 'endDate' => '2019-01-02 12:00', 'description' => 'Sulu is really awesome', - 'location' => 'Dornbirn', + 'locationId' => $location->getId(), ] ); @@ -90,7 +94,7 @@ public function testPost(): void $this->assertSame('2019-01-01T12:00:00+00:00', $result['startDate']); $this->assertSame('2019-01-02T12:00:00+00:00', $result['endDate']); $this->assertSame('Sulu is really awesome', $result['description']); - $this->assertSame('Dornbirn', $result['location']); + $this->assertSame($location->getId(), $result['locationId']); $result = $this->findEventById($result['id'], 'de'); @@ -103,7 +107,8 @@ public function testPost(): void $this->assertNotNull($result->getEndDate()); $this->assertSame('2019-01-02T12:00:00+00:00', $result->getEndDate()->format('c')); $this->assertSame('Sulu is really awesome', $result->getDescription()); - $this->assertSame('Dornbirn', $result->getLocation()); + $this->assertNotNull($result->getLocation()); + $this->assertSame($location->getId(), $result->getLocation()->getId()); } public function testPostNullValues(): void @@ -134,7 +139,7 @@ public function testPostNullValues(): void $this->assertNull($result['startDate']); $this->assertNull($result['endDate']); $this->assertSame($result['description'], ''); - $this->assertNull($result['location']); + $this->assertNull($result['locationId']); $result = $this->findEventById($result['id'], 'de'); @@ -151,6 +156,7 @@ public function testPostNullValues(): void public function testPut(): void { $event = $this->createEvent('Symfony', 'de'); + $location = $this->createLocation('Sulu HQ'); $this->client->jsonRequest( 'PUT', @@ -161,7 +167,7 @@ public function testPut(): void 'startDate' => '2019-01-01 12:00', 'endDate' => '2019-01-02 12:00', 'description' => 'Symfony Live is really awesome', - 'location' => 'Dornbirn', + 'locationId' => $location->getId(), ] ); @@ -178,7 +184,7 @@ public function testPut(): void $this->assertSame('2019-01-01T12:00:00+00:00', $result['startDate']); $this->assertSame('2019-01-02T12:00:00+00:00', $result['endDate']); $this->assertSame('Symfony Live is really awesome', $result['description']); - $this->assertSame('Dornbirn', $result['location']); + $this->assertSame($location->getId(), $result['locationId']); $result = $this->findEventById($result['id'], 'de'); @@ -191,7 +197,8 @@ public function testPut(): void $this->assertNotNull($result->getEndDate()); $this->assertSame('2019-01-02T12:00:00+00:00', $result->getEndDate()->format('c')); $this->assertSame('Symfony Live is really awesome', $result->getDescription()); - $this->assertSame('Dornbirn', $result->getLocation()); + $this->assertNotNull($result->getLocation()); + $this->assertSame($location->getId(), $result->getLocation()->getId()); } public function testPutNullValues(): void @@ -224,7 +231,7 @@ public function testPutNullValues(): void $this->assertNull($result['startDate']); $this->assertNull($result['endDate']); $this->assertSame($result['description'], ''); - $this->assertNull($result['location']); + $this->assertNull($result['locationId']); $result = $this->findEventById($result['id'], 'de'); diff --git a/tests/Unit/Entity/EventTest.php b/tests/Unit/Entity/EventTest.php index c8144c0..f5d6933 100644 --- a/tests/Unit/Entity/EventTest.php +++ b/tests/Unit/Entity/EventTest.php @@ -6,11 +6,18 @@ use App\Entity\Event; use App\Entity\EventTranslation; +use App\Entity\Location; use PHPUnit\Framework\TestCase; +use Prophecy\Prophecy\ObjectProphecy; use Sulu\Bundle\MediaBundle\Entity\MediaInterface; class EventTest extends TestCase { + /** + * @var Location|ObjectProphecy + */ + private $location; + /** * @var Event */ @@ -18,6 +25,8 @@ class EventTest extends TestCase protected function setUp(): void { + $this->location = $this->prophesize(Location::class); + $this->event = new Event(); $this->event->setLocale('de'); } @@ -51,9 +60,12 @@ public function testEndDate(): void public function testLocation(): void { + $this->location->getId()->willReturn(42); + $this->assertNull($this->event->getLocation()); - $this->assertSame($this->event, $this->event->setLocation('Amsterdam')); - $this->assertSame('Amsterdam', $this->event->getLocation()); + $this->assertSame($this->event, $this->event->setLocation($this->location->reveal())); + $this->assertNotNull($this->event->getLocation()); + $this->assertSame($this->location->reveal(), $this->event->getLocation()); } public function testImage(): void diff --git a/translations/admin.de.json b/translations/admin.de.json index ac72ae7..071d38b 100644 --- a/translations/admin.de.json +++ b/translations/admin.de.json @@ -8,5 +8,6 @@ "app.enable_event": "Veranstaltungen aktivieren", "app.enabled": "Aktiviert", "app.location": "Standort", - "app.locations": "Standorte" + "app.locations": "Standorte", + "app.location.no_selections": "Kein Standord ausgewählt" } diff --git a/translations/admin.en.json b/translations/admin.en.json index b073ae1..52a386b 100644 --- a/translations/admin.en.json +++ b/translations/admin.en.json @@ -8,5 +8,6 @@ "app.enable_event": "Enable event", "app.enabled": "Enabled", "app.location": "Location", - "app.locations": "Locations" + "app.locations": "Locations", + "app.location.no_selections": "No location selected" }