diff --git a/.env.test b/.env.test index d048686..2d25a38 100644 --- a/.env.test +++ b/.env.test @@ -3,3 +3,4 @@ KERNEL_CLASS='App\Kernel' APP_SECRET='$ecretf0rt3st' SYMFONY_DEPRECATIONS_HELPER=999999 PANTHER_APP_ENV=panther +DATABASE_URL=sqlite:///%kernel.project_dir%/var/test.db \ No newline at end of file diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index ac234ab..39b6839 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -19,5 +19,11 @@ jobs: - name: Build webpack run: yarn encore prod + - name: Create database + run: bin/console doctrine:database:create --env test + + - name: Create database schema + run: bin/console doctrine:schema:create --env test + - name: Run test suite run: bin/phpunit diff --git a/composer.json b/composer.json index 2ccc090..746c1a2 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "symfony/yaml": "5.0.*" }, "require-dev": { + "dama/doctrine-test-bundle": "^6.3", "doctrine/doctrine-fixtures-bundle": "^3.3", "easycorp/easy-log-handler": "^1.0.7", "friendsofphp/php-cs-fixer": "^2.16", diff --git a/composer.lock b/composer.lock index 46bb123..aec48f7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e8fada79453fd8b0ecc332e62942ddc4", + "content-hash": "9291532147be5655a18a248f4baa363d", "packages": [ { "name": "basster/lazy-response-bundle", @@ -5419,6 +5419,63 @@ ], "time": "2019-11-06T16:40:04+00:00" }, + { + "name": "dama/doctrine-test-bundle", + "version": "v6.3.2", + "source": { + "type": "git", + "url": "https://github.com/dmaicher/doctrine-test-bundle.git", + "reference": "06932e828b4e8ed8655b9b64ae30428e048b616e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dmaicher/doctrine-test-bundle/zipball/06932e828b4e8ed8655b9b64ae30428e048b616e", + "reference": "06932e828b4e8ed8655b9b64ae30428e048b616e", + "shasum": "" + }, + "require": { + "doctrine/dbal": "^2.9,>=2.9.3", + "doctrine/doctrine-bundle": "^1.11 || ^2.0", + "php": "^7.1", + "symfony/framework-bundle": "^3.4 || ^4.3 || ^5.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "symfony/phpunit-bridge": "^4.3 || ^5.0", + "symfony/yaml": "^3.4 || ^4.3 || ^5.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "7.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "DAMA\\DoctrineTestBundle\\": "src/DAMA/DoctrineTestBundle" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David Maicher", + "email": "mail@dmaicher.de" + } + ], + "description": "Symfony bundle to isolate doctrine database tests and improve test performance", + "keywords": [ + "doctrine", + "isolation", + "performance", + "symfony", + "tests" + ], + "time": "2020-03-02T20:42:23+00:00" + }, { "name": "doctrine/data-fixtures", "version": "1.4.2", @@ -6360,23 +6417,23 @@ }, { "name": "symfony/phpunit-bridge", - "version": "v5.0.4", + "version": "v5.0.5", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "38959f0ef4cea3e003f94c670bca89b2f4d932c5" + "reference": "b8fee53045a55ccbb9209e453bf6fdcf74381959" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/38959f0ef4cea3e003f94c670bca89b2f4d932c5", - "reference": "38959f0ef4cea3e003f94c670bca89b2f4d932c5", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/b8fee53045a55ccbb9209e453bf6fdcf74381959", + "reference": "b8fee53045a55ccbb9209e453bf6fdcf74381959", "shasum": "" }, "require": { "php": ">=5.5.9" }, "conflict": { - "phpunit/phpunit": "<5.4.3" + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0|<6.4,>=6.0" }, "suggest": { "symfony/error-handler": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" @@ -6421,7 +6478,7 @@ ], "description": "Symfony PHPUnit Bridge", "homepage": "https://symfony.com", - "time": "2020-01-31T09:56:42+00:00" + "time": "2020-02-24T15:05:31+00:00" }, { "name": "symfony/process", @@ -6579,5 +6636,6 @@ "ext-ctype": "*", "ext-iconv": "*" }, - "platform-dev": [] + "platform-dev": [], + "plugin-api-version": "1.1.0" } diff --git a/config/bundles.php b/config/bundles.php index 2d23c6a..917925f 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -14,4 +14,5 @@ Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], + DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true], ]; diff --git a/config/packages/test/dama_doctrine_test_bundle.yaml b/config/packages/test/dama_doctrine_test_bundle.yaml new file mode 100644 index 0000000..80b0091 --- /dev/null +++ b/config/packages/test/dama_doctrine_test_bundle.yaml @@ -0,0 +1,4 @@ +dama_doctrine_test: + enable_static_connection: true + enable_static_meta_data_cache: true + enable_static_query_cache: true diff --git a/docker-compose.yaml b/docker-compose.yaml index 35dfa4e..4537299 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -9,9 +9,15 @@ services: MYSQL_ROOT_PASSWORD: password ports: - 3306:3306 + volumes: + - dbdata:/var/lib/mysql mailhog: image: mailhog/mailhog ports: - 1025:1025 - - 8025:8025 \ No newline at end of file + - 8025:8025 + +volumes: + dbdata: + driver: local diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d6e204f..5dfff55 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -12,7 +12,7 @@ - + @@ -30,6 +30,10 @@ + + + + diff --git a/src/Action/HomeAction.php b/src/Action/HomeAction.php index 9181d15..23ed828 100644 --- a/src/Action/HomeAction.php +++ b/src/Action/HomeAction.php @@ -4,6 +4,7 @@ namespace App\Action; +use App\Repository\AppointmentRepository; use Basster\LazyResponseBundle\Response\TemplateResponse; use Symfony\Component\Routing\Annotation\Route; @@ -12,8 +13,10 @@ final class HomeAction /** * @Route("/", name="app_home") */ - public function __invoke(): TemplateResponse + public function __invoke(AppointmentRepository $appointmentRepository): TemplateResponse { - return new TemplateResponse('home.html.twig'); + return new TemplateResponse('home.html.twig', [ + 'appointments' => $appointmentRepository->findAll(), + ]); } } diff --git a/src/DataFixtures/AppointmentFixtures.php b/src/DataFixtures/AppointmentFixtures.php index c238c2f..92a52c0 100644 --- a/src/DataFixtures/AppointmentFixtures.php +++ b/src/DataFixtures/AppointmentFixtures.php @@ -5,17 +5,25 @@ namespace App\DataFixtures; use App\Entity\Appointment; +use App\Entity\Attribute; use DateTimeImmutable; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\DependentFixtureInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\Persistence\ObjectManager; -class AppointmentFixtures extends Fixture implements DependentFixtureInterface +final class AppointmentFixtures extends Fixture implements DependentFixtureInterface { + public const PHPUGHB_3 = 'appointment:phpughb3'; + public function load(ObjectManager $manager): void { /** @var \App\Entity\Talk $talk */ $talk = $this->getReference(TalkFixtures::TALK_SOLID); + /** @var \App\Entity\Location $teamNeusta */ + $teamNeusta = $this->getReference(LocationFixtures::TEAM_NEUSTA); + $ticketsType = $this->getReference(AttributeFixtures::TYPE_TICKETS); + + $ticketsAttr = new Attribute($ticketsType, 'Anmelden', 'https://www.eventbrite.de/e/php-usergroup-bremen-phpughb-iii-tickets-93670576215'); $appointment = new Appointment( '#PHPUGHB III', @@ -23,12 +31,15 @@ public function load(ObjectManager $manager): void DateTimeImmutable::createFromFormat('Y-m-d H:i', '2020-03-11 18:30') ); $appointment->addTalk($talk); + $appointment->setLocation($teamNeusta); + $appointment->addAttribute($ticketsAttr); $manager->persist($appointment); + $manager->persist($ticketsAttr); $manager->flush(); - $this->addReference('appointment:phpughb3', $appointment); + $this->addReference(self::PHPUGHB_3, $appointment); } /** @@ -36,6 +47,10 @@ public function load(ObjectManager $manager): void */ public function getDependencies(): array { - return [TalkFixtures::class]; + return [ + TalkFixtures::class, + LocationFixtures::class, + AttributeFixtures::class, + ]; } } diff --git a/src/DataFixtures/AttributeFixtures.php b/src/DataFixtures/AttributeFixtures.php new file mode 100644 index 0000000..4524e1d --- /dev/null +++ b/src/DataFixtures/AttributeFixtures.php @@ -0,0 +1,42 @@ +persist($twitterType); + $manager->persist($youtubeType); + $manager->persist($latLngType); + $manager->persist($ticketsType); + $manager->flush(); + + $this->addReference(self::TYPE_TWITTER, $twitterType); + $this->addReference(self::TYPE_YOUTUBE, $youtubeType); + $this->addReference(self::TYPE_LATLNG, $latLngType); + $this->addReference(self::TYPE_TICKETS, $ticketsType); + } +} diff --git a/src/DataFixtures/LocationFixtures.php b/src/DataFixtures/LocationFixtures.php new file mode 100644 index 0000000..f83ef77 --- /dev/null +++ b/src/DataFixtures/LocationFixtures.php @@ -0,0 +1,47 @@ +getReference(AttributeFixtures::TYPE_LATLNG); + + $teamNeusta = new Location('team neusta', 'Konsul-Smidt-Str.', '24', '28217', 'Bremen'); + $tnLatLng = new Attribute($latLngType, '8.7742443,53.090925'); + $teamNeusta->addAttribute($tnLatLng); + + $manager->persist($teamNeusta); + $manager->persist($tnLatLng); + $manager->flush(); + + $this->setReference(self::TEAM_NEUSTA, $teamNeusta); + } + + /** + * {@inheritdoc} + */ + public function getDependencies(): array + { + return [ + AttributeFixtures::class, + ]; + } +} diff --git a/src/DataFixtures/SpeakerFixture.php b/src/DataFixtures/SpeakerFixture.php new file mode 100644 index 0000000..c7785f9 --- /dev/null +++ b/src/DataFixtures/SpeakerFixture.php @@ -0,0 +1,64 @@ +getReference(AttributeFixtures::TYPE_TWITTER); + + $ole = new Speaker('Ole', 'Rößner'); + $oleTwitter = new Attribute($twitterType, 'djbasster'); + + $ole->addAttribute($oleTwitter); + $ole->linkUser($this->getReference(UserFixture::USER_OLE)); + + $denis = new Speaker('Denis', 'Brumann'); + $denisTwitter = new Attribute($twitterType, 'dbrumann'); + + $stephan = new Speaker('Stephan', 'Hochdörfer'); + $stephanTwitter = new Attribute($twitterType, 'shochdoerfer'); + + $manager->persist($ole); + $manager->persist($oleTwitter); + $manager->persist($denis); + $manager->persist($denisTwitter); + $manager->persist($stephan); + $manager->persist($stephanTwitter); + $manager->flush(); + + $this->setReference(self::OLE, $ole); + $this->setReference(self::DENIS, $denis); + $this->setReference(self::STEPHAN, $stephan); + } + + /** + * {@inheritdoc} + */ + public function getDependencies(): array + { + return [ + AttributeFixtures::class, + UserFixture::class, + ]; + } +} diff --git a/src/DataFixtures/TalkFixtures.php b/src/DataFixtures/TalkFixtures.php index bb960f2..c9eeed5 100644 --- a/src/DataFixtures/TalkFixtures.php +++ b/src/DataFixtures/TalkFixtures.php @@ -5,41 +5,40 @@ namespace App\DataFixtures; use App\Entity\Attribute; -use App\Entity\AttributeType; -use App\Entity\Speaker; use App\Entity\Talk; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\DependentFixtureInterface; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\Persistence\ObjectManager; -class TalkFixtures extends Fixture implements DependentFixtureInterface +final class TalkFixtures extends Fixture implements DependentFixtureInterface { - public const SPEAKER_OLE = 'speaker:Ole'; public const TALK_SOLID = 'talk:SOLIDe Symfony Apps'; + public const TALK_IMPORTS = 'talk:Imports like a pro'; + public const TALK_DISCO = 'talk:Disco - A fresh look at DI'; public function load(ObjectManager $manager): void { - /** @var \App\Entity\User $oleUser */ - $oleUser = $this->getReference(UserFixture::USER_OLE); - - $twitterType = new AttributeType('twitter', 'twitter'); - $twitterAttr = new Attribute($twitterType, 'djbasster'); - - $speaker = new Speaker('Ole', 'Rößner'); - $speaker->addAttribute($twitterAttr); - $speaker->linkUser($oleUser); - - $talk = new Talk('SOLIDe Symfony Apps', $speaker); - - $manager->persist($twitterType); - $manager->persist($twitterAttr); - $manager->persist($speaker); - $manager->persist($talk); + $solid = new Talk('SOLIDe Symfony Apps', $this->getReference(SpeakerFixture::OLE)); + $imports = new Talk('Imports like a pro', $this->getReference(SpeakerFixture::DENIS)); + $disco = new Talk('Disco - A fresh look at DI', $this->getReference(SpeakerFixture::STEPHAN)); + + $importsVideo = new Attribute( + $this->getReference(AttributeFixtures::TYPE_YOUTUBE), + 'Ansehen', + 'https://youtu.be/tgb5kybJISM' + ); + $imports->addAttribute($importsVideo); + + $manager->persist($solid); + $manager->persist($imports); + $manager->persist($importsVideo); + $manager->persist($disco); $manager->flush(); - $this->addReference(self::SPEAKER_OLE, $speaker); - $this->addReference(self::TALK_SOLID, $talk); + $this->addReference(self::TALK_SOLID, $solid); + $this->addReference(self::TALK_IMPORTS, $imports); + $this->addReference(self::TALK_DISCO, $disco); } /** @@ -47,6 +46,6 @@ public function load(ObjectManager $manager): void */ public function getDependencies(): array { - return [UserFixture::class]; + return [SpeakerFixture::class]; } } diff --git a/src/DataFixtures/UserFixture.php b/src/DataFixtures/UserFixture.php index e4f9076..3ffb0ac 100644 --- a/src/DataFixtures/UserFixture.php +++ b/src/DataFixtures/UserFixture.php @@ -6,9 +6,9 @@ use App\Entity\User; use Doctrine\Bundle\FixturesBundle\Fixture; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\Persistence\ObjectManager; -class UserFixture extends Fixture +final class UserFixture extends Fixture { public const USER_OLE = 'user:Ole'; diff --git a/src/Domain/Attribute/Exception/MissingAttributeTypeException.php b/src/Domain/Attribute/Exception/MissingAttributeTypeException.php new file mode 100644 index 0000000..f90e53d --- /dev/null +++ b/src/Domain/Attribute/Exception/MissingAttributeTypeException.php @@ -0,0 +1,19 @@ +title = $title; $this->text = $text; $this->dateTime = $dateTime; $this->talks = new ArrayCollection(); + $this->initAttributes(); } public function getTitle(): string @@ -73,4 +79,22 @@ public function addTalk(Talk $talk): void $this->talks->add($talk); $talk->setAppointment($this); } + + public function getLocation(): ?Location + { + return $this->location; + } + + public function setLocation(?Location $location): void + { + $this->location = $location; + } + + /** + * @return \Doctrine\Common\Collections\ArrayCollection|\Doctrine\Common\Collections\Collection + */ + public function getTalks() + { + return $this->talks; + } } diff --git a/src/Entity/Attribute.php b/src/Entity/Attribute.php index 3f6803a..fed3412 100644 --- a/src/Entity/Attribute.php +++ b/src/Entity/Attribute.php @@ -52,4 +52,14 @@ public function getType(): AttributeType { return $this->type; } + + public function getValue(): string + { + return $this->value; + } + + public function getUrl(): ?string + { + return $this->url; + } } diff --git a/src/Entity/AttributeAware.php b/src/Entity/AttributeAware.php new file mode 100644 index 0000000..c636079 --- /dev/null +++ b/src/Entity/AttributeAware.php @@ -0,0 +1,26 @@ +attributes; + } + + public function addAttribute(Attribute $attribute): void + { + if (!$this->attributes->contains($attribute)) { + $this->attributes[] = $attribute; + } + } + + public function removeAttribute(Attribute $attribute): void + { + if ($this->attributes->contains($attribute)) { + $this->attributes->removeElement($attribute); + } + } + + /** {@inheritdoc} */ + public function getAttribute(string $type): Attribute + { + foreach ($this->attributes as $attribute) { + if (strcasecmp($attribute->getType()->getTitle(), $type) === 0) { + return $attribute; + } + } + + throw new MissingAttributeTypeException($type); + } + + public function hasAttribute(string $type): bool + { + try { + $this->getAttribute($type); + + return true; + } catch (MissingAttributeTypeException $ex) { + return false; + } + } + + private function initAttributes(): void + { + $this->attributes = new ArrayCollection(); + } +} diff --git a/src/Entity/AttributeType.php b/src/Entity/AttributeType.php index feacb9d..79ab2ba 100644 --- a/src/Entity/AttributeType.php +++ b/src/Entity/AttributeType.php @@ -20,10 +20,10 @@ class AttributeType private ?int $id = null; /** - * @ORM\Column(type="string", length=10) + * @ORM\Column(type="string", length=50) * * @Assert\NotBlank - * @Assert\Length(max="10") + * @Assert\Length(max="50") */ private string $faIcon; @@ -40,4 +40,14 @@ public function __construct(string $faIcon, string $title) $this->faIcon = $faIcon; $this->title = $title; } + + public function getTitle(): string + { + return $this->title; + } + + public function getFaIcon(): string + { + return $this->faIcon; + } } diff --git a/src/Entity/Location.php b/src/Entity/Location.php new file mode 100644 index 0000000..dd2ccbe --- /dev/null +++ b/src/Entity/Location.php @@ -0,0 +1,141 @@ +name = $name; + $this->street = $street; + $this->streetNumber = $streetNumber; + $this->zipCode = $zipCode; + $this->city = $city; + $this->appointments = new ArrayCollection(); + $this->initAttributes(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function getStreet(): ?string + { + return $this->street; + } + + public function setStreet(string $street): void + { + $this->street = $street; + } + + public function getStreetNumber(): ?string + { + return $this->streetNumber; + } + + public function setStreetNumber(?string $streetNumber): void + { + $this->streetNumber = $streetNumber; + } + + public function getZipCode(): ?string + { + return $this->zipCode; + } + + public function setZipCode(string $zipCode): void + { + $this->zipCode = $zipCode; + } + + public function getCity(): ?string + { + return $this->city; + } + + public function setCity(string $city): void + { + $this->city = $city; + } + + /** + * @return Collection|Appointment[] + */ + public function getAppointments(): Collection + { + return $this->appointments; + } +} diff --git a/src/Entity/Speaker.php b/src/Entity/Speaker.php index a968a1a..272e0f0 100644 --- a/src/Entity/Speaker.php +++ b/src/Entity/Speaker.php @@ -12,8 +12,10 @@ /** * @ORM\Entity() */ -class Speaker +class Speaker implements AttributeAware { + use AttributeTrait; + /** * @ORM\Id() * @ORM\GeneratedValue() @@ -41,17 +43,12 @@ class Speaker */ private Collection $talks; - /** - * @ORM\ManyToMany(targetEntity="App\Entity\Attribute") - */ - private Collection $attributes; - public function __construct(string $firstname, string $lastname) { $this->firstname = $firstname; $this->lastname = $lastname; $this->talks = new ArrayCollection(); - $this->attributes = new ArrayCollection(); + $this->initAttributes(); } public function getId(): ?int @@ -97,26 +94,4 @@ public function addTalk(Talk $talk): void $this->talks[] = $talk; } } - - /** - * @return Collection|Attribute[] - */ - public function getAttributes(): Collection - { - return clone $this->attributes; - } - - public function addAttribute(Attribute $attribute): void - { - if (!$this->attributes->contains($attribute)) { - $this->attributes[] = $attribute; - } - } - - public function removeAttribute(Attribute $attribute): void - { - if ($this->attributes->contains($attribute)) { - $this->attributes->removeElement($attribute); - } - } } diff --git a/src/Entity/Talk.php b/src/Entity/Talk.php index 1790b17..00779f8 100644 --- a/src/Entity/Talk.php +++ b/src/Entity/Talk.php @@ -4,8 +4,6 @@ namespace App\Entity; -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Constraints as Assert; @@ -15,8 +13,10 @@ * * @UniqueEntity(fields={"title"}) */ -class Talk +class Talk implements AttributeAware { + use AttributeTrait; + /** * @ORM\Column(type="integer", unique=true) * @ORM\Id @@ -43,17 +43,12 @@ class Talk */ private Speaker $speaker; - /** - * @ORM\ManyToMany(targetEntity="App\Entity\Attribute") - */ - private Collection $attributes; - public function __construct(string $title, Speaker $speaker) { $this->title = $title; $this->speaker = $speaker; $speaker->addTalk($this); - $this->attributes = new ArrayCollection(); + $this->initAttributes(); } public function getSpeaker(): ?Speaker @@ -66,25 +61,8 @@ public function setAppointment(Appointment $appointment): void $this->appointment = $appointment; } - /** - * @return Collection|Attribute[] - */ - public function getAttributes(): Collection - { - return clone $this->attributes; - } - - public function addAttribute(Attribute $attribute): void - { - if (!$this->attributes->contains($attribute)) { - $this->attributes[] = $attribute; - } - } - - public function removeAttribute(Attribute $attribute): void + public function getTitle(): string { - if ($this->attributes->contains($attribute)) { - $this->attributes->removeElement($attribute); - } + return $this->title; } } diff --git a/src/Repository/AppointmentRepository.php b/src/Repository/AppointmentRepository.php new file mode 100644 index 0000000..a8cb1c0 --- /dev/null +++ b/src/Repository/AppointmentRepository.php @@ -0,0 +1,25 @@ +findBy([], ['dateTime' => 'desc']); + } +} diff --git a/symfony.lock b/symfony.lock index 8647c23..0aa054e 100644 --- a/symfony.lock +++ b/symfony.lock @@ -17,6 +17,18 @@ "composer/xdebug-handler": { "version": "1.4.0" }, + "dama/doctrine-test-bundle": { + "version": "4.0", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "master", + "version": "4.0", + "ref": "56eaa387b5e48ebcc7c95a893b47dfa1ad51449c" + }, + "files": [ + "config/packages/test/dama_doctrine_test_bundle.yaml" + ] + }, "doctrine/annotations": { "version": "1.0", "recipe": { diff --git a/templates/home.html.twig b/templates/home.html.twig index 7bc927d..78bcdf7 100644 --- a/templates/home.html.twig +++ b/templates/home.html.twig @@ -5,30 +5,43 @@ {% endblock %} {% block content %} -
- Card image cap -
-

Am 23.10.2019 | Wesertower @ hmmh

-
-

Sponsoren

- -
-

Talks

-
Imports like a Pro
-
Denis Brumann
- - -
-
Disco - A fresh look at DI
-
Stephan Hochdörfer
- -
Leider kein Mittschnitt vorhanden
-
-

Teilnahme

- Der Eintritt ist Frei! Wenn ihr uns bei der Planung helfen wollt, dann meldet euch bitte hier an: -
- Anmelden + {% for appointment in appointments %} +
+ Card image cap +
+

Am {{ appointment.dateTime | date('d.m.Y') }} + | {{ appointment.location.name }}

+
+

Sponsoren

+ +
+

Talks

+ {% for talk in appointment.talks %} +
{{ talk.title }}
+
{{ talk.speaker.fullname }}
+ {% if talk.speaker.hasAttribute('twitter') %} + {% set twitterHandle = talk.speaker.getAttribute('twitter').value %} + + {% endif %} + {% for talkAttr in talk.attributes %} + + {% endfor %} +
+ {% endfor %} +
+ {% if appointment.hasAttribute('tickets') %} + {% set tickets = appointment.getAttribute('tickets') %} +

Teilnahme

+ Der Eintritt ist Frei! Wenn ihr uns bei der Planung helfen wollt, dann meldet euch bitte hier an: +
+ {{ tickets.value }} + + {% endif %} +
+
-
-
-{% endblock %} \ No newline at end of file + {% endfor %} +{% endblock %} diff --git a/tests/Unit/Entity/AttributeAwareTest.php b/tests/Unit/Entity/AttributeAwareTest.php new file mode 100644 index 0000000..2224ff6 --- /dev/null +++ b/tests/Unit/Entity/AttributeAwareTest.php @@ -0,0 +1,55 @@ +expectException(MissingAttributeTypeException::class); + + $appointment = new Appointment('Test Appointment'); + $appointment->getAttribute('ticket'); + } + + /** + * @test + */ + public function getAttribute(): void + { + $twitterType = new AttributeType('twitter', 'twitter'); + $twitterAttr = new Attribute($twitterType, 'phpughb'); + + $appointment = new Appointment('Test Appointment'); + $appointment->addAttribute($twitterAttr); + + static::assertSame($twitterAttr, $appointment->getAttribute('twitter')); + } + + /** + * @test + */ + public function hasAttribute(): void + { + $appointment = new Appointment('Test Appointment'); + static::assertFalse($appointment->hasAttribute('twitter')); + } +}