Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Refactoring the Domain, Guided by Tests v2

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

Refactoring the Domain, Guided by Tests v2

Avatar for pelshoff

pelshoff

April 26, 2018

More Decks by pelshoff

Other Decks in Programming

Transcript

  1. 1. final class Meeting { 2. private $meetingId; 3. private

    $title; 4. private $description; 5. private $code; 6. private $duration; 7. private $isPublished; 8. private $subTitle; 9. private $program; 10. 11. public function __construct(UuidInterface $meetingId, string $title, string 12. $description, string $code, MeetingDuration $duration, bool $isPublished, 13. string $subTitle, Program $program) { 14. $this->meetingId = $meetingId; 15. $this->title = $title; 16. $this->description = $description; 17. $this->code = $code; 18. $this->duration = $duration; 19. $this->isPublished = $isPublished; 20. $this->subTitle = $subTitle; 21. $this->program = $program; 22. } 23. }
  2. 1. final class MeetingDuration { 2. private $start; 3. private

    $end; 4. 5. public function __construct(DateTimeImmutable $start, DateTimeImmutable $end) { 6. $this->start = $start; 7. $this->end = $end; 8. $this->meetingCannotEndBeforeStart(); 9. } 10. 11. private function meetingCannotEndBeforeStart(): void { 12. if ($this->start > $this->end) { 13. throw InvalidMeetingDuration::becauseDurationEndsBeforeStarting(); 14. } 15. } 16. }
  3. 1. final class Program { 2. private $program; 3. 4.

    /** @param Slot[] $program */ 5. public function __construct(array $program) { 6. $this->program = $program; 7. $this->programSlotsCannotOccurInTheSameRoomAtTheSameTime(); 8. } 9. 10. private function programSlotsCannotOccurInTheSameRoomAtTheSameTime(): void { 11. foreach ($this->slotsStartingAt(0) as $index => $thisSlot) { 12. foreach ($this->slotsStartingAt($index + 1) as $thatSlot) { 13. if ($thisSlot->overlapsWith($thatSlot)) { 14. throw InvalidProgram::becauseProgramSlotsOverlap(); 15. } 16. } 17. } 18. } 19. 20. /** @return Slot[] */ 21. private function slotsStartingAt(int $index): array { 22. return array_slice($this->program, $index); 23. } 24. }
  4. 1. final class Slot { 2. private $duration; 3. private

    $title; 4. private $room; 5. 6. public function __construct(SlotDuration $duration, string $title, string $room) { 7. $this->duration = $duration; 8. $this->title = $title; 9. $this->room = $room; 10. } 11. 12. public function overlapsWith(Slot $that): bool { 13. return $this->room === $that->room 14. && $this->duration->overlapsWith($that->duration); 15. } 16. }
  5. 1. final class SlotDuration { 2. private $start; 3. private

    $end; 4. 5. public function __construct(DateTimeImmutable $start, DateTimeImmutable $end) { 6. $this->start = $start; 7. $this->end = $end; 8. $this->slotCannotEndBeforeStart(); 9. $this->slotMustStartAndEndOnTheSameDay(); 10. } 11. 12. private function slotCannotEndBeforeStart(): void {...} 13. 14. private function slotMustStartAndEndOnTheSameDay(): void {...} 15. 16. public function overlapsWith(SlotDuration $that): bool { 17. return !$this->before($that) && !$that->before($this); 18. } 19. 20. private function before(SlotDuration $that): bool { 21. return $that->start >= $this->end; 22. } 23. }
  6. 1. final class Meeting { 2. private $meetingId; 3. private

    $title; 4. private $description; 5. private $code; 6. private $duration; 7. private $isPublished; 8. private $subTitle; 9. private $program; 10. 11. public function __construct(UuidInterface $meetingId, string $title, string 12. $description, string $code, MeetingDuration $duration, bool $isPublished, 13. string $subTitle, Program $program) { 14. $this->meetingId = $meetingId; 15. $this->title = $title; 16. $this->description = $description; 17. $this->code = $code; 18. $this->duration = $duration; 19. $this->isPublished = $isPublished; 20. $this->subTitle = $subTitle; 21. $this->program = $program; 22. } 23. }
  7. 1. final class MeetingTest extends TestCase { 2. public function

    testThatValidMeetingsCanBeInstantiated() { 3. $this->assertInstanceOf(Meeting::class, 4. new Meeting( 5. Uuid::uuid4(), 6. 'This is a test', 7. 'This is a test description', 8. 'M01', 9. new MeetingDuration( 10. new DateTimeImmutable('2018-02-20 19:00'), 11. new DateTimeImmutable('2018-02-20 22:00') 12. ), 13. false, 14. 'This is a test sub title', 15. new Program([]) 16. ) 17. ); 18. } 19. } $ vendor/bin/phpunit -c phpunit.xml.dist tests/ PHPUnit 5.7.27 by Sebastian Bergmann and contributors. ........ 8 / 8 (100%) Time: 25 ms, Memory: 4.00MB OK (8 tests, 8 assertions)
  8. 1. final class MeetingTest extends TestCase { 2. public function

    testThatValidMeetingsCanBeInstantiated() { 3. $this->assertInstanceOf(Meeting::class, 4. new Meeting( 5. Uuid::uuid4(), 6. new MeetingPresentation( 7. 'This is a test', 8. 'This is a test description', 9. 'This is a test sub title' 10. ), 11. 'M01', 12. new MeetingDuration( 13. new DateTimeImmutable('2018-02-20 19:00'), 14. new DateTimeImmutable('2018-02-20 22:00') 15. ), 16. false, 17. 'This is a test sub title', 18. new Program([]) 19. ) 20. ); 21. } 22. } OK (8 tests, 8 assertions)
  9. 1. final class MeetingPresentationTest extends TestCase { 2. public function

    testThatPresentationMustHaveTitle() { 3. $this->expectException(InvalidMeetingPresentation::class); 4. new MeetingPresentation('', '', ''); 5. } 6. } ..F...... 9 / 9 (100%) Time: 25 ms, Memory: 4.00MB There was 1 failure: 1) Pelshoff\Meeting\test\MeetingPresentationTest::testThatPresentationMustHaveTitle Failed asserting that exception of type "Pelshoff\Meeting\InvalidMeetingPresentation" is thrown. FAILURES! Tests: 9, Assertions: 9, Failures: 1.
  10. 1. final class MeetingPresentation { 2. private $title; 3. private

    $description; 4. private $subTitle; 5. 6. public function __construct(string $title, string $description, string $subTitle) { 7. $this->title = $title; 8. $this->description = $description; 9. $this->subTitle = $subTitle; 10. $this->presentationMustHaveTitle(); 11. } 12. 13. private function presentationMustHaveTitle(): void { 14. if (mb_strlen($this->title) < 5) { 15. throw InvalidMeetingPresentation::becauseTitleIsMissing(); 16. } 17. } 18. } OK (9 tests, 9 assertions)
  11. 1. final class Meeting { 2. private $meetingId; 3. private

    $presentation; 4. private $code; 5. private $duration; 6. private $isPublished; 7. private $program; 8. 9. public function __construct(UuidInterface $meetingId, MeetingPresentation 10. $presentation, string $code, MeetingDuration $duration, bool $isPublished, 11. Program $program) { 12. $this->meetingId = $meetingId; 13. $this->presentation = $presentation; 14. $this->code = $code; 15. $this->duration = $duration; 16. $this->isPublished = $isPublished; 17. $this->program = $program; 18. } 19. }
  12. 1. final class Meeting { 2. private $meetingId; 3. private

    $presentation; 4. private $code; 5. private $duration; 6. private $isPublished; 7. private $program; 8. 9. public function __construct(UuidInterface $meetingId, MeetingPresentation 10. $presentation, string $code, MeetingDuration $duration, bool $isPublished, 11. Program $program) { 12. $this->meetingId = $meetingId; 13. $this->presentation = $presentation; 14. $this->code = $code; 15. $this->duration = $duration; 16. $this->isPublished = $isPublished; 17. $this->program = $program; 18. } 19. }
  13. 1. final class Meeting { 2. private $meetingId; 3. private

    $presentation; 4. private $code; 5. private $duration; 6. private $isPublished; 7. private $program; 8. 9. public function __construct(UuidInterface $meetingId, MeetingPresentation 10. $presentation, string $code, MeetingDuration $duration, bool $isPublished, 11. Program $program) { 12. $this->meetingId = $meetingId; 13. $this->presentation = $presentation; 14. $this->code = $code; 15. $this->duration = $duration; 16. $this->isPublished = $isPublished; 17. $this->program = $program; 18. } 19. }
  14. 1. final class Program { 2. private $duration; 3. private

    $program; 4. 5. /** @param Slot[] $program */ 6. public function __construct(MeetingDuration $duration, array $program) { 7. $this->duration = $duration; 8. $this->program = $program; 9. $this->programSlotsCannotOccurInTheSameRoomAtTheSameTime(); 10. } 11. 12. private function programSlotsCannotOccurInTheSameRoomAtTheSameTime(): void {...} 13. 14. /** @return Slot[] */ 15. private function slotsStartingAt(int $index): array {...} 16. } OK (9 tests, 9 assertions)
  15. 1. public function testThatMeetingCanBeRescheduled() { 2. $meeting = new Meeting($meetingId

    = Uuid::uuid4(), 3. ... 4. new MeetingDuration( 5. new DateTimeImmutable('2018-02-20 19:00'), 6. new DateTimeImmutable('2018-02-20 22:00') 7. )... 8. new SlotDuration( 9. new DateTimeImmutable('2018-02-20 20:00'), 10. new DateTimeImmutable('2018-02-20 21:00') 11. ),...; 12. $expected = new Meeting($meetingId, 13. ... 14. new MeetingDuration( 15. new DateTimeImmutable('2018-02-21 07:00'), 16. new DateTimeImmutable('2018-02-21 10:00') 17. )... 18. new SlotDuration( 19. new DateTimeImmutable('2018-02-21 08:00'), 20. new DateTimeImmutable('2018-02-21 09:00') 21. )...; 22. $meeting->reschedule(new DateTimeImmutable('2018-02-21 07:00')); 23. $this->assertEquals($expected, $meeting); 24. } Error: Call to undefined method Pelshoff\Meeting\Meeting::reschedule()
  16. 1. final class Meeting { 2. ... 3. public function

    reschedule(DateTimeImmutable $newStartDate): void { 4. $this->program = $this->program->rescheduled($newStartDate); 5. } 6. }
  17. 1. final class Program { 2. ... 3. public function

    rescheduled(DateTimeImmutable $newStartDate): Program { 4. $newDuration = $this->duration->rescheduled($newStartDate); 5. $diff = $this->duration->intervalToStartOf($newDuration); 6. $newProgram = array_map(function (Slot $slot) use ($diff) { 7. return $slot->movedBy($diff); 8. }, $this->program); 9. return new self($newDuration, $newProgram); 10. } 11. }
  18. 1. final class MeetingDuration { 2. ... 3. public function

    rescheduled(DateTimeImmutable $newStartDate): MeetingDuration { 4. $newEndDate = $this->end->add($this->start->diff($newStartDate)); 5. return new self($newStartDate, $newEndDate); 6. } 7. 8. public function intervalToStartOf(MeetingDuration $that): DateInterval { 9. return $this->start->diff($that->start); 10. }}
  19. 1. final class Slot { 2. ... 3. public function

    movedBy(DateInterval $diff): Slot { 4. return new self( 5. $this->duration->movedBy($diff), 6. $this->title, 7. $this->room 8. ); 9. } 10. }
  20. 1. final class SlotDuration { 2. ... 3. public function

    movedBy(DateInterval $diff): SlotDuration { 4. return new self($this->start->add($diff), $this->end->add($diff)); 5. } 6. } .......... 10 / 10 (100%) Time: 29 ms, Memory: 4.00MB OK (10 tests, 10 assertions)
  21. 1. final class TicketService { 2. /** @var TicketRepository */

    3. private $ticketRepository; 4. 5. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 6. bool $forReserve): array { 7. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 8. 9. $availableTickets = []; 10. if ($forReserve) { 11. foreach ($tickets as $ticket) { 12. if (!$publicOnly || ($this->checkAvailability($ticket, []) 13. && $this->ticketRepository->checkAllowed($ticket, $user))) { 14. $availableTickets[$ticket->getId()] = $ticket; 15. } 16. } 17. return $availableTickets; 18. } 19. 20. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 21. 22. foreach ($tickets as $ticket) { 23. if (!$publicOnly || ($this->checkAvailability($ticket, $currentSoldPerTicket) 24. && $this->ticketRepository->checkAllowed($ticket, $user))) { 25. $availableTickets[$ticket->getId()] = $ticket; 26. } 27. } 28. 29. return $availableTickets; 30. }
  22. 1. final class TicketService { 2. /** @var TicketRepository */

    3. private $ticketRepository; 4. 5. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 6. bool $forReserve): array { 7. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 8. 9. $availableTickets = []; 10. if ($forReserve) { 11. foreach ($tickets as $ticket) { 12. if (!$publicOnly || ($this->checkAvailability($ticket, []) 13. && $this->ticketRepository->checkAllowed($ticket, $user))) { 14. $availableTickets[$ticket->getId()] = $ticket; 15. } 16. } 17. return $availableTickets; 18. } 19. 20. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 21. 22. foreach ($tickets as $ticket) { 23. if (!$publicOnly || ($this->checkAvailability($ticket, $currentSoldPerTicket) 24. && $this->ticketRepository->checkAllowed($ticket, $user))) { 25. $availableTickets[$ticket->getId()] = $ticket; 26. } 27. } 28. 29. return $availableTickets; 30. }
  23. 1. private function checkAvailability(Ticket $ticket, array $currentSoldPerTicket): bool { 2.

    if (!$ticket->getIsPublic()) { 3. return false; 4. } 5. 6. if ($ticket->getNumberOfTickets() && isset($currentSoldPerTicket[$ticket->getId()]) 7. && $currentSoldPerTicket[$ticket->getId()] >= $ticket->getNumberOfTickets()) { 8. return false; 9. } 10. 11. if ($ticket->getStartDate() && new DateTimeImmutable() < $ticket->getStartDate()) { 12. return false; 13. } 14. 15. if ($ticket->getEndDate() && new DateTimeImmutable() > $ticket->getEndDate()) { 16. return false; 17. } 18. 19. return true; 20. }
  24. 1. final class Ticket { 2. private $id; 3. private

    $isPublic; 4. private $numberOfTickets; 5. private $startDate; 6. private $endDate; 7. 8. public function __construct(int $id, bool $isPublic, int $numberOfTickets, 9. ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate) { 10. $this->id = $id; 11. $this->isPublic = $isPublic; 12. $this->numberOfTickets = $numberOfTickets; 13. $this->startDate = $startDate; 14. $this->endDate = $endDate; 15. }
  25. 1. interface TicketRepository 2. { 3. /** 4. * @param

    Meeting $meeting 5. * @return Ticket[] 6. * Do a query 7. */ 8. public function getMeetingTickets(Meeting $meeting): array; 9. /** 10. * @param Meeting $meeting 11. * @return array 12. * Do a query 13. */ 14. public function getNumberOfCurrentSoldTickets(Meeting $meeting): array; 15. /** 16. * @param Ticket $ticket 17. * @param User $user 18. * @return bool 19. * allowed by user invitation? 20. * allowed by group? 21. * allowed by selection? 22. * Anyway, do a query 23. */ 24. public function checkAllowed(Ticket $ticket, User $user): bool; 25. }
  26. 1. final class TicketServiceTest extends TestCase { 2. public function

    testThatGetAvailableTicketsGivesTheOnlyTicketAvailable() { 3. $meeting = $this->givenAnUpcomingMeeting(); 4. $ticket = $this->givenAPublicTicket(); 5. $user = $this->givenAUser(); 6. $this->whenTicketsForMeeting([$ticket], $meeting); 7. $this->whenNoTicketsSold(); 8. 9. $expected = [$ticket->getId() => $ticket]; 10. $actual = $this->ticketService->getAvailableTickets($meeting, false, $user, 11. false); 12. 13. $this->assertEquals($expected, $actual); 14. } ........... 11 / 11 (100%) Time: 32 ms, Memory: 4.00MB OK (11 tests, 11 assertions)
  27. 1. private function givenAnUpcomingMeeting() { 2. return new Meeting(...); 3.

    } 4. private function givenAPublicTicket() { 5. return new Ticket(mt_rand(), true, 0, null, null); 6. } 7. private function whenTicketsForMeeting(array $tickets, Meeting $meeting) { 8. $this->ticketRepository->expects($this->any()) 9. ->method('getMeetingTickets') 10. ->with($meeting) 11. ->will($this->returnValue($tickets)); 12. } 13. private function whenNoTicketsSold() { 14. $this->ticketRepository->expects($this->any()) 15. ->method('getNumberOfCurrentSoldTickets') 16. ->will($this->returnValue([])); 17. } 18. private function givenAUser() { 19. return new User(); 20. } 21. protected function setUp() { 22. $this->ticketRepository = $this->getMockBuilder(TicketRepository::class) 23. ->getMock(); 24. $this->ticketService = new TicketService($this->ticketRepository); 25. }
  28. 1. public function testThatGetAvailableTicketsFiltersDisallowedTickets() { 2. $meeting = $this->givenAnUpcomingMeeting(); 3.

    $allTickets = [ 4. $this->givenAPublicTicket(), 5. $this->givenAPublicTicket(), 6. $this->givenAPublicTicket(), 7. $allowedTicket = $this->givenAPublicTicket(), 8. ]; 9. $user = $this->givenAUser(); 10. $this->whenTicketsForMeeting($allTickets, $meeting); 11. $this->whenUserOnlyAllowedForTicket($allowedTicket, $user); 12. $this->whenNoTicketsSold(); 13. 14. $expected = [$allowedTicket->getId() => $allowedTicket]; 15. $actual = $this->ticketService->getAvailableTickets($meeting, true, $user, false); 16. 17. $this->assertEquals($expected, $actual); 18. } ............ 12 / 12 (100%) Time: 33 ms, Memory: 4.00MB OK (12 tests, 12 assertions)
  29. 1. private function whenUserOnlyAllowedForTicket(Ticket $ticket, User $user) { 2. $this->ticketRepository->expects($this->any())

    3. ->method('checkAllowed') 4. ->withConsecutive($this->anything(), $this->anything(), $this->anything(), 5. [$ticket, $user]) 6. ->willReturnOnConsecutiveCalls(false, false, false, true); 7. }
  30. 1. public function testThatSoldOutTicketsAreNotAvailable() { 2. $meeting = $this->givenAnUpcomingMeeting(); 3.

    $ticket = $this->givenALimitedTicket(); 4. $user = $this->givenAUser(); 5. $this->whenTicketsForMeeting([$ticket], $meeting); 6. $this->whenTicketsAreAllowed(); 7. $this->whenTicketIsSoldOut($ticket); 8. 9. $expected = []; 10. $actual = $this->ticketService->getAvailableTickets($meeting, true, $user, false); 11. 12. $this->assertEquals($expected, $actual); 13. } 14. public function testThatSoldOutTicketsAreAvailableForReserve() { 15. $meeting = $this->givenAnUpcomingMeeting(); 16. $ticket = $this->givenALimitedTicket(); 17. $user = $this->givenAUser(); 18. $this->whenTicketsForMeeting([$ticket], $meeting); 19. $this->whenTicketsAreAllowed(); 20. $this->whenTicketIsSoldOut($ticket); 21. 22. $expected = [$ticket->getId() => $ticket]; 23. $actual = $this->ticketService->getAvailableTickets($meeting, true, $user, true); 24. 25. $this->assertEquals($expected, $actual); 26. } OK (14 tests, 14 assertions)
  31. 1. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 2.

    bool $forReserve): array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. 5. $availableTickets = []; 6. if ($forReserve) { 7. foreach ($tickets as $ticket) { 8. if (!$publicOnly || ($this->checkAvailability($ticket, []) 9. && $this->ticketRepository->checkAllowed($ticket, $user))) { 10. $availableTickets[$ticket->getId()] = $ticket; 11. } 12. } 13. return $availableTickets; 14. } 15. 16. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 17. 18. foreach ($tickets as $ticket) { 19. if (!$publicOnly || ($this->checkAvailability($ticket, $currentSoldPerTicket) 20. && $this->ticketRepository->checkAllowed($ticket, $user))) { 21. $availableTickets[$ticket->getId()] = $ticket; 22. } 23. } 24. 25. return $availableTickets; 26. }
  32. 1. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 2. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 3. $ticketIsAvailableForReserve

    = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 4. foreach ($tickets as $ticket) { 5. $ticketIsAvailableForReserve[$ticket->getId()] = $this->checkAvailability($ticket, []); 6. $ticketIsAvailableOtherwise[$ticket->getId()] = 7. $this->checkAvailability($ticket, $currentSoldPerTicket); 8. $ticketIsAllowedForUser[$ticket->getId()] = 9. $this->ticketRepository->checkAllowed($ticket, $user); 10. } 11. 12. $availableTickets = []; 13. if ($forReserve) { 14. foreach ($tickets as $ticket) { 15. if (!$publicOnly || ($ticketIsAvailableForReserve[$ticket->getId()] 16. && $ticketIsAllowedForUser[$ticket->getId()])) { 17. $availableTickets[$ticket->getId()] = $ticket; 18. } 19. } 20. return $availableTickets; 21. } 22. 23. foreach ($tickets as $ticket) { 24. if (!$publicOnly || ($ticketIsAvailableOtherwise[$ticket->getId()] 25. && $ticketIsAllowedForUser[$ticket->getId()])) { 26. $availableTickets[$ticket->getId()] = $ticket; 27. } 28. } 29. 30. return $availableTickets;
  33. 1. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 2. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 3. $ticketIsAvailableForReserve

    = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 4. foreach ($tickets as $ticket) { 5. $ticketIsAvailableForReserve[$ticket->getId()] = $this->checkAvailability($ticket, []); 6. $ticketIsAvailableOtherwise[$ticket->getId()] = 7. $this->checkAvailability($ticket, $currentSoldPerTicket); 8. $ticketIsAllowedForUser[$ticket->getId()] = 9. $this->ticketRepository->checkAllowed($ticket, $user); 10. } 11. 12. $availableTickets = []; 13. if ($forReserve) { 14. foreach ($tickets as $ticket) { 15. if (!$publicOnly || ($ticketIsAvailableForReserve[$ticket->getId()] 16. && $ticketIsAllowedForUser[$ticket->getId()])) { 17. $availableTickets[$ticket->getId()] = $ticket; 18. } 19. } 20. return $availableTickets; 21. } 22. 23. foreach ($tickets as $ticket) { 24. if (!$publicOnly || ($ticketIsAvailableOtherwise[$ticket->getId()] 25. && $ticketIsAllowedForUser[$ticket->getId()])) { 26. $availableTickets[$ticket->getId()] = $ticket; 27. } 28. } 29. 30. return $availableTickets;
  34. 1. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 2.

    bool $forReserve): array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 6. foreach ($tickets as $ticket) { 7. $ticketIsAvailableForReserve[$ticket->getId()] = $this->checkAvailability($ticket, []); 8. $ticketIsAvailableOtherwise[$ticket->getId()] = 9. $this->checkAvailability($ticket, $currentSoldPerTicket); 10. $ticketIsAllowedForUser[$ticket->getId()] = 11. $this->ticketRepository->checkAllowed($ticket, $user); 12. } 13. 14. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 15. 16. $availableTickets = []; 17. foreach ($tickets as $ticket) { 18. if (!$publicOnly || ($ticketIsAvailable[$ticket->getId()] 19. && $ticketIsAllowedForUser[$ticket->getId()])) { 20. $availableTickets[$ticket->getId()] = $ticket; 21. } 22. } 23. 24. return $availableTickets; 25. } OK (14 tests, 14 assertions)
  35. 1. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 2.

    bool $forReserve): array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 6. foreach ($tickets as $ticket) { 7. $ticketIsAvailableForReserve[$ticket->getId()] = $this->checkAvailability($ticket, []); 8. $ticketIsAvailableOtherwise[$ticket->getId()] = 9. $this->checkAvailability($ticket, $currentSoldPerTicket); 10. $ticketIsAllowedForUser[$ticket->getId()] = 11. $this->ticketRepository->checkAllowed($ticket, $user); 12. } 13. 14. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 15. 16. $availableTickets = []; 17. foreach ($tickets as $ticket) { 18. if (!$publicOnly || ($ticketIsAvailable[$ticket->getId()] 19. && $ticketIsAllowedForUser[$ticket->getId()])) { 20. $availableTickets[$ticket->getId()] = $ticket; 21. } 22. } 23. 24. return $availableTickets; 25. }
  36. 1. private function checkAvailability(Ticket $ticket, array $currentSoldPerTicket): bool { 2.

    if (!$ticket->getIsPublic()) { 3. return false; 4. } 5. 6. if ($ticket->getNumberOfTickets() && isset($currentSoldPerTicket[$ticket->getId()]) 7. && $currentSoldPerTicket[$ticket->getId()] >= $ticket->getNumberOfTickets()) { 8. return false; 9. } 10. 11. if ($ticket->getStartDate() && new DateTimeImmutable() < $ticket->getStartDate()) { 12. return false; 13. } 14. 15. if ($ticket->getEndDate() && new DateTimeImmutable() > $ticket->getEndDate()) { 16. return false; 17. } 18. 19. return true; 20. }
  37. 1. private function checkAvailability(Ticket $ticket, array $currentSoldPerTicket): bool { 2.

    return $this->ticketIsOpenForSale($ticket) 3. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 4. } 5. private function thereAreTicketsLeftForSale(Ticket $ticket, array $currentSoldPerTicket): 6. bool { 7. if ($ticket->getNumberOfTickets() && isset($currentSoldPerTicket[$ticket->getId()]) 8. && $currentSoldPerTicket[$ticket->getId()] >= $ticket->getNumberOfTickets()) { 9. return false; 10. } 11. return true; 12. } 13. private function ticketIsOpenForSale(Ticket $ticket): bool { 14. if (!$ticket->isPublic()) { 15. return false; 16. } 17. if ($ticket->getStartDate() && new DateTimeImmutable() < $ticket->getStartDate()) { 18. return false; 19. } 20. if ($ticket->getEndDate() && new DateTimeImmutable() > $ticket->getEndDate()) { 21. return false; 22. } 23. return true; 24. }
  38. 1. private function checkAvailability(Ticket $ticket, array $currentSoldPerTicket): bool { 2.

    return $this->ticketIsOpenForSale($ticket) 3. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 4. } 5. private function thereAreTicketsLeftForSale(Ticket $ticket, array $currentSoldPerTicket): 6. bool { 7. if ($ticket->getNumberOfTickets() && isset($currentSoldPerTicket[$ticket->getId()]) 8. && $currentSoldPerTicket[$ticket->getId()] >= $ticket->getNumberOfTickets()) { 9. return false; 10. } 11. return true; 12. } 13. private function ticketIsOpenForSale(Ticket $ticket): bool { 14. if (!$ticket->isPublic()) { 15. return false; 16. } 17. if ($ticket->getStartDate() && new DateTimeImmutable() < $ticket->getStartDate()) { 18. return false; 19. } 20. if ($ticket->getEndDate() && new DateTimeImmutable() > $ticket->getEndDate()) { 21. return false; 22. } 23. return true; 24. }
  39. 1. private function checkAvailability(Ticket $ticket, array $currentSoldPerTicket): bool { 2.

    return $ticket->isOpenForSaleOn(new DateTimeImmutable()) 3. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 4. } 5. private function thereAreTicketsLeftForSale(Ticket $ticket, array $currentSoldPerTicket): 6. bool { 7. if ($ticket->getNumberOfTickets() && isset($currentSoldPerTicket[$ticket->getId()]) 8. && $currentSoldPerTicket[$ticket->getId()] >= $ticket->getNumberOfTickets()) { 9. return false; 10. } 11. return true; 12. } 13. final class Ticket { 14. public function isOpenForSaleOn(DateTimeImmutable $date): bool { 15. if (!$this->isPublic()) { 16. return false; 17. } 18. if ($this->getStartDate() && $date < $this->getStartDate()) { 19. return false; 20. } 21. if ($this->getEndDate() && $date > $this->getEndDate()) { 22. return false; 23. } 24. return true; 25. }
  40. 1. private function checkAvailability(Ticket $ticket, array $currentSoldPerTicket): bool { 2.

    return $ticket->isOpenForSaleOn(new DateTimeImmutable()) 3. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 4. } 5. private function thereAreTicketsLeftForSale(Ticket $ticket, array $currentSoldPerTicket): 6. bool { 7. if ($ticket->getNumberOfTickets() && isset($currentSoldPerTicket[$ticket->getId()]) 8. && $currentSoldPerTicket[$ticket->getId()] >= $ticket->getNumberOfTickets()) { 9. return false; 10. } 11. return true; 12. } 13. final class Ticket { 14. public function isOpenForSaleOn(DateTimeImmutable $date): bool { 15. if (!$this->isPublic()) { 16. return false; 17. } 18. if ($this->getStartDate() && $date < $this->getStartDate()) { 19. return false; 20. } 21. if ($this->getEndDate() && $date > $this->getEndDate()) { 22. return false; 23. } 24. return true; 25. }
  41. 1. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 2.

    bool $forReserve): array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 6. foreach ($tickets as $ticket) { 7. $ticketIsAvailableForReserve[$ticket->getId()] = $this->checkAvailability($ticket, []); 8. $ticketIsAvailableOtherwise[$ticket->getId()] = 9. $this->checkAvailability($ticket, $currentSoldPerTicket); 10. $ticketIsAllowedForUser[$ticket->getId()] = 11. $this->ticketRepository->checkAllowed($ticket, $user); 12. } 13. 14. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 15. 16. $availableTickets = []; 17. foreach ($tickets as $ticket) { 18. if (!$publicOnly || ($ticketIsAvailable[$ticket->getId()] 19. && $ticketIsAllowedForUser[$ticket->getId()])) { 20. $availableTickets[$ticket->getId()] = $ticket; 21. } 22. } 23. 24. return $availableTickets; 25. }
  42. 1. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 2.

    bool $forReserve): array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 9. && $this->thereAreTicketsLeftForSale($ticket, []); 10. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 11. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 12. $ticketIsAllowedForUser[$ticket->getId()] = 13. $this->ticketRepository->checkAllowed($ticket, $user); 14. } 15. 16. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 17. 18. $availableTickets = []; 19. foreach ($tickets as $ticket) { 20. if (!$publicOnly || ($ticketIsAvailable[$ticket->getId()] 21. && $ticketIsAllowedForUser[$ticket->getId()])) { 22. $availableTickets[$ticket->getId()] = $ticket; 23. } 24. } 25. 26. return $availableTickets; 27. }
  43. 1. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 2.

    bool $forReserve): array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. $ticketIsAllowedForUser[$ticket->getId()] = 12. $this->ticketRepository->checkAllowed($ticket, $user); 13. } 14. 15. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 16. 17. $availableTickets = []; 18. foreach ($tickets as $ticket) { 19. if (!$publicOnly || ($ticketIsAvailable[$ticket->getId()] 20. && $ticketIsAllowedForUser[$ticket->getId()])) { 21. $availableTickets[$ticket->getId()] = $ticket; 22. } 23. } 24. 25. return $availableTickets; 26. } OK (14 tests, 14 assertions)
  44. 1. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 2.

    bool $forReserve): array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. $ticketIsAllowedForUser[$ticket->getId()] = 12. $this->ticketRepository->checkAllowed($ticket, $user); 13. } 14. 15. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 16. 17. $availableTickets = []; 18. foreach ($tickets as $ticket) { 19. if (!$publicOnly || ($ticketIsAvailable[$ticket->getId()] 20. && $ticketIsAllowedForUser[$ticket->getId()])) { 21. $availableTickets[$ticket->getId()] = $ticket; 22. } 23. } 24. 25. return $availableTickets; 26. }
  45. 1. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 2.

    bool $forReserve): array { 3. if (!$publicOnly) { 4. return $this->ticketRepository->getMeetingTickets($meeting); 5. } 6. // ... 7. 8. Failed asserting that two arrays are equal. 9. --- Expected 10. +++ Actual 11. @@ @@ 12. Array ( 13. - 1623135705 => Pelshoff\Meeting\Ticket Object (...) 14. + 0 => Pelshoff\Meeting\Ticket Object (...) 15. ) 16. 17. /data/presentatie/tests/TicketServiceTest.php:77 18. 19. FAILURES! 20. Tests: 14, Assertions: 14, Failures: 3.
  46. 1. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 2.

    bool $forReserve): array { 3. if ($publicOnly) { 4. return $this->getPubliclyAvailableTickets($meeting, $user, $forReserve); 5. } 6. return $this->getPrivatelyAvailableTickets($meeting); 7. } 8. 9. public function getPrivatelyAvailableTickets(Meeting $meeting): array { 10. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 11. foreach ($tickets as $ticket) { 12. $availableTickets[$ticket->getId()] = $ticket; 13. } 14. return $availableTickets; 15. } 16. 17. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, 18. bool $forReserve): array { 19. /**/ 20. } OK (14 tests, 14 assertions)
  47. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve):array {

    2. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 3. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 4. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 5. $today = new DateTimeImmutable(); 6. foreach ($tickets as $ticket) { 7. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 8. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 9. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 10. $ticketIsAllowedForUser[$ticket->getId()] = 11. $this->ticketRepository->checkAllowed($ticket, $user); 12. } 13. 14. 15. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 16. 17. $availableTickets = []; 18. foreach ($tickets as $ticket) { 19. if ($ticketIsAvailable[$ticket->getId()] && $ticketIsAllowedForUser[$ticket->getId()]) { 20. $availableTickets[$ticket->getId()] = $ticket; 21. } 22. } 23. 24. return $availableTickets; 25. }
  48. 1. final class TicketService { 2. 3. /** @deprecated Use

    getPrivatelyAvailableTickets or getPubliclyAvailableTickets */ 4. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 5. bool $forReserve): array {...} 6. 7. public function getPrivatelyAvailableTickets(Meeting $meeting): array {...} 8. 9. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, 10. bool $forReserve): array {...} 11. 12. ... 13. }
  49. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): 2.

    array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. $ticketIsAllowedForUser[$ticket->getId()] = 12. $this->ticketRepository->checkAllowed($ticket, $user); 13. } 14. 15. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 16. 17. $availableTickets = []; 18. foreach ($tickets as $ticket) { 19. if ($ticketIsAvailable[$ticket->getId()] && $ticketIsAllowedForUser[$ticket->getId()]) { 20. $availableTickets[$ticket->getId()] = $ticket; 21. } 22. } 23. 24. return $availableTickets; 25. }
  50. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): 2.

    array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. $ticketIsAllowedForUser[$ticket->getId()] = 12. $this->ticketRepository->checkAllowed($ticket, $user); 13. } 14. 15. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 16. 17. $leftTickets = []; 18. foreach ($tickets as $ticket) { 19. if ($ticketIsAvailable[$ticket->getId()]) { 20. $leftTickets[$ticket->getId()] = $ticket; 21. } 22. } 23. 24. $allowedTickets = []; 25. foreach ($leftTickets as $ticket) { 26. if ($ticketIsAllowedForUser[$ticket->getId()]) { 27. $allowedTickets[$ticket->getId()] = $ticket; 28. } 29. } 30. 31. return $allowedTickets; 32. }
  51. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): 2.

    array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = $ticketIsAllowedForUser = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. $ticketIsAllowedForUser[$ticket->getId()] = 12. $this->ticketRepository->checkAllowed($ticket, $user); 13. } 14. 15. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 16. 17. $leftTickets = []; 18. foreach ($tickets as $ticket) { 19. if ($ticketIsAvailable[$ticket->getId()]) { 20. $leftTickets[$ticket->getId()] = $ticket; 21. } 22. } 23. 24. $allowedTickets = []; 25. foreach ($leftTickets as $ticket) { 26. if ($ticketIsAllowedForUser[$ticket->getId()]) { 27. $allowedTickets[$ticket->getId()] = $ticket; 28. } 29. } 30. 31. return $allowedTickets; 32. }
  52. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): 2.

    array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. } 12. 13. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 14. 15. $leftTickets = []; 16. foreach ($tickets as $ticket) { 17. if ($ticketIsAvailable[$ticket->getId()]) { 18. $leftTickets[$ticket->getId()] = $ticket; 19. } 20. } 21. 22. $allowedTickets = []; 23. foreach ($leftTickets as $ticket) { 24. if ($this->ticketRepository->checkAllowed($ticket, $user)) { 25. $allowedTickets[$ticket->getId()] = $ticket; 26. } 27. } 28. 29. return $allowedTickets; 30. }
  53. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): 2.

    array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. } 12. 13. $openTickets = []; 14. foreach ($tickets as $ticket) { 15. if ($ticketIsAvailableForReserve[$ticket->getId()]) { 16. $openTickets[$ticket->getId()] = $ticket; 17. } 18. } 19. 20. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 21. 22. $leftTickets = []; 23. foreach ($openTickets as $ticket) { 24. if ($ticketIsAvailable[$ticket->getId()]) { 25. $leftTickets[$ticket->getId()] = $ticket; 26. } 27. } 28. 29. $allowedTickets = []; 30. ...
  54. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): 2.

    array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. } 12. 13. $openTickets = []; 14. foreach ($tickets as $ticket) { 15. if ($ticketIsAvailableForReserve[$ticket->getId()]) { 16. $openTickets[$ticket->getId()] = $ticket; 17. } 18. } 19. 20. $ticketIsAvailable = $forReserve ? $ticketIsAvailableForReserve : $ticketIsAvailableOtherwise; 21. 22. $leftTickets = []; 23. foreach ($openTickets as $ticket) { 24. if ($ticketIsAvailable[$ticket->getId()]) { 25. $leftTickets[$ticket->getId()] = $ticket; 26. } 27. } 28. 29. $allowedTickets = []; 30. ...
  55. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): 2.

    array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. } 12. 13. $openTickets = []; 14. foreach ($tickets as $ticket) { 15. if ($ticketIsAvailableForReserve[$ticket->getId()]) { 16. $openTickets[$ticket->getId()] = $ticket; 17. } 18. } 19. 20. $leftTickets = $openTickets; 21. if (!$forReserve) { 22. $leftTickets = []; 23. foreach ($openTickets as $ticket) { 24. if ($ticketIsAvailableOtherwise[$ticket->getId()]) { 25. $leftTickets[$ticket->getId()] = $ticket; 26. } 27. } 28. } 29. 30. $allowedTickets = []; 31. ...
  56. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): 2.

    array { 3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 5. $ticketIsAvailableForReserve = $ticketIsAvailableOtherwise = []; 6. $today = new DateTimeImmutable(); 7. foreach ($tickets as $ticket) { 8. $ticketIsAvailableForReserve[$ticket->getId()] = $ticket->isOpenForSaleOn($today); 9. $ticketIsAvailableOtherwise[$ticket->getId()] = $ticket->isOpenForSaleOn($today) 10. && $this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket); 11. } 12. 13. $openTickets = []; 14. foreach ($tickets as $ticket) { 15. if ($ticketIsAvailableForReserve[$ticket->getId()]) { 16. $openTickets[$ticket->getId()] = $ticket; 17. } 18. } 19. 20. $leftTickets = $openTickets; 21. if (!$forReserve) { 22. $leftTickets = []; 23. foreach ($openTickets as $ticket) { 24. if ($ticketIsAvailableOtherwise[$ticket->getId()]) { 25. $leftTickets[$ticket->getId()] = $ticket; 26. } 27. } 28. } 29. 30. $allowedTickets = []; 31. ...
  57. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 3. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 4. $today = new DateTimeImmutable(); 5. 6. $openTickets = []; 7. foreach ($tickets as $ticket) { 8. if ($ticket->isOpenForSaleOn($today)) { 9. $openTickets[$ticket->getId()] = $ticket; 10. } 11. } 12. 13. $leftTickets = $openTickets; 14. if (!$forReserve) { 15. $leftTickets = []; 16. foreach ($openTickets as $ticket) { 17. if ($this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket)) { 18. $leftTickets[$ticket->getId()] = $ticket; 19. } 20. } 21. } 22. 23. $allowedTickets = []; 24. foreach ($leftTickets as $ticket) { 25. if ($this->ticketRepository->checkAllowed($ticket, $user)) { 26. $allowedTickets[$ticket->getId()] = $ticket; 27. } 28. } 29. 30. return $allowedTickets; 31. }
  58. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 3. $today = new DateTimeImmutable(); 4. 5. $openTickets = []; 6. foreach ($tickets as $ticket) { 7. if ($ticket->isOpenForSaleOn($today)) { 8. $openTickets[$ticket->getId()] = $ticket; 9. } 10. } 11. 12. $allowedTickets = []; 13. foreach ($openTickets as $ticket) { 14. if ($this->ticketRepository->checkAllowed($ticket, $user)) { 15. $allowedTickets[$ticket->getId()] = $ticket; 16. } 17. } 18. 19. if ($forReserve) { 20. return $allowedTickets; 21. } 22. 23. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 24. $leftTickets = []; 25. foreach ($allowedTickets as $ticket) { 26. if ($this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket)) { 27. $leftTickets[$ticket->getId()] = $ticket; 28. } 29. } 30. 31. return $leftTickets; 32. }
  59. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 3. $today = new DateTimeImmutable(); 4. 5. $openTickets = []; 6. foreach ($tickets as $ticket) { 7. if ($ticket->isOpenForSaleOn($today)) { 8. $openTickets[$ticket->getId()] = $ticket; 9. } 10. } 11. 12. $allowedTickets = []; 13. foreach ($openTickets as $ticket) { 14. if ($this->ticketRepository->checkAllowed($ticket, $user)) { 15. $allowedTickets[$ticket->getId()] = $ticket; 16. } 17. } 18. 19. if ($forReserve) { 20. return $allowedTickets; 21. } 22. 23. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 24. $leftTickets = []; 25. foreach ($allowedTickets as $ticket) { 26. if ($this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket)) { 27. $leftTickets[$ticket->getId()] = $ticket; 28. } 29. } 30. 31. return $leftTickets; 32. }
  60. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. $openTickets = $this->getTicketsOpenForSaleOn($meeting, new DateTimeImmutable()); 3. 4. $allowedTickets = []; 5. foreach ($openTickets as $ticket) { 6. if ($this->ticketRepository->checkAllowed($ticket, $user)) { 7. $allowedTickets[$ticket->getId()] = $ticket; 8. } 9. } 10. 11. if ($forReserve) { 12. return $allowedTickets; 13. } 14. 15. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 16. $leftTickets = []; 17. foreach ($allowedTickets as $ticket) { 18. if ($this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket)) { 19. $leftTickets[$ticket->getId()] = $ticket; 20. } 21. } 22. 23. return $leftTickets; 24. } 25. 26. private function getTicketsOpenForSaleOn(Meeting $meeting, DateTimeImmutable $date): array {...}
  61. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. $openTickets = $this->getTicketsOpenForSaleOn($meeting, new DateTimeImmutable()); 3. 4. $allowedTickets = []; 5. foreach ($openTickets as $ticket) { 6. if ($this->ticketRepository->checkAllowed($ticket, $user)) { 7. $allowedTickets[$ticket->getId()] = $ticket; 8. } 9. } 10. 11. if ($forReserve) { 12. return $allowedTickets; 13. } 14. 15. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 16. $leftTickets = []; 17. foreach ($allowedTickets as $ticket) { 18. if ($this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket)) { 19. $leftTickets[$ticket->getId()] = $ticket; 20. } 21. } 22. 23. return $leftTickets; 24. } 25. 26. private function getTicketsOpenForSaleOn(Meeting $meeting, DateTimeImmutable $date): array {...}
  62. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. $allowedTickets = $this->getTicketsUserCanReserve($meeting, $user); 3. 4. if ($forReserve) { 5. return $allowedTickets; 6. } 7. 8. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 9. $leftTickets = []; 10. foreach ($allowedTickets as $ticket) { 11. if ($this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket)) { 12. $leftTickets[$ticket->getId()] = $ticket; 13. } 14. } 15. 16. return $leftTickets; 17. } 18. 19. private function getTicketsOpenForSaleOn(Meeting $meeting, DateTimeImmutable $date): array {...} 20. 21. private function getTicketsUserCanReserve(Meeting $meeting, User $user): array {...}
  63. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. $allowedTickets = $this->getTicketsUserCanReserve($meeting, $user); 3. 4. if ($forReserve) { 5. return $allowedTickets; 6. } 7. 8. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 9. $leftTickets = []; 10. foreach ($allowedTickets as $ticket) { 11. if ($this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket)) { 12. $leftTickets[$ticket->getId()] = $ticket; 13. } 14. } 15. 16. return $leftTickets; 17. } 18. 19. private function getTicketsOpenForSaleOn(Meeting $meeting, DateTimeImmutable $date): array {...} 20. 21. private function getTicketsUserCanReserve(Meeting $meeting, User $user): array {...}
  64. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. if ($forReserve) { 3. return $this->getTicketsUserCanReserve($meeting, $user); 4. } 5. 6. $allowedTickets = $this->getTicketsUserCanReserve($meeting, $user); 7. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 8. $leftTickets = []; 9. foreach ($allowedTickets as $ticket) { 10. if ($this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket)) { 11. $leftTickets[$ticket->getId()] = $ticket; 12. } 13. } 14. 15. return $leftTickets; 16. } 17. 18. private function getTicketsOpenForSaleOn(Meeting $meeting, DateTimeImmutable $date): array {...} 19. 20. private function getTicketsUserCanReserve(Meeting $meeting, User $user): array {...}
  65. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. if ($forReserve) { 3. return $this->getTicketsUserCanReserve($meeting, $user); 4. } 5. 6. $allowedTickets = $this->getTicketsUserCanReserve($meeting, $user); 7. $currentSoldPerTicket = $this->ticketRepository->getNumberOfCurrentSoldTickets($meeting); 8. $leftTickets = []; 9. foreach ($allowedTickets as $ticket) { 10. if ($this->thereAreTicketsLeftForSale($ticket, $currentSoldPerTicket)) { 11. $leftTickets[$ticket->getId()] = $ticket; 12. } 13. } 14. 15. return $leftTickets; 16. } 17. 18. private function getTicketsOpenForSaleOn(Meeting $meeting, DateTimeImmutable $date): array {...} 19. 20. private function getTicketsUserCanReserve(Meeting $meeting, User $user): array {...}
  66. 1. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array

    { 2. if ($forReserve) { 3. return $this->getTicketsUserCanReserve($meeting, $user); 4. } 5. return $this->getTicketsUserCanPurchase($meeting, $user); 6. } 7. 8. private function getTicketsOpenForSaleOn(Meeting $meeting, DateTimeImmutable $date): array {...} 9. 10. private function getTicketsUserCanReserve(Meeting $meeting, User $user): array {...} 11. 12. private function getTicketsUserCanPurchase(Meeting $meeting, User $user): array {...}
  67. 1. /** @deprecated Use getTicketsUserCanReserve or getTicketsUserCanPurchase */ 2. public

    function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array { 3. if ($forReserve) { 4. return $this->getTicketsUserCanReserve($meeting, $user); 5. } 6. return $this->getTicketsUserCanPurchase($meeting, $user); 7. } 8. 9. private function getTicketsOpenForSaleOn(Meeting $meeting, DateTimeImmutable $date): array {...} 10. 11. public function getTicketsUserCanReserve(Meeting $meeting, User $user): array {...} 12. 13. public function getTicketsUserCanPurchase(Meeting $meeting, User $user): array {...} OK (14 tests, 14 assertions)
  68. 1. private function getTicketsOpenForSaleOn(Meeting $meeting, DateTimeImmutable $date): 2. array {

    3. $tickets = $this->ticketRepository->getMeetingTickets($meeting); 4. $openTickets = []; 5. foreach ($tickets as $ticket) { 6. if ($ticket->isOpenForSaleOn($today)) { 7. $openTickets[$ticket->getId()] = $ticket; 8. } 9. } 10. return $openTickets; 11. }
  69. 1. final class Meeting { 2. ... 3. public function

    getTickets(): array { 4. return $this->tickets; 5. } 6. 7. public function getTicketsOpenForSaleOn(DateTimeImmutable $date): array { 8. $openTickets = []; 9. foreach ($this->tickets as $ticket) { 10. if ($ticket->ticketIsOpenForSaleOn($date)) { 11. $openTickets[$ticket->getId()] = $ticket; 12. } 13. } 14. return $openTickets; 15. } 16. } .............. 14 / 14 (100%) Time: 43 ms, Memory: 4.00MB OK (14 tests, 14 assertions)
  70. 1. final class TicketService { 2. /** @deprecated Use getPrivatelyAvailableTickets,

    getTicketsUserCanReserve or getTicketsUserCanPurchase */ 3. public function getAvailableTickets(Meeting $meeting, bool $publicOnly, User $user, 4. bool $forReserve): array {...} 5. 6. public function getPrivatelyAvailableTickets(Meeting $meeting): array {...} 7. 8. /** @deprecated Use getTicketsUserCanReserve or getTicketsUserCanPurchase */ 9. public function getPubliclyAvailableTickets(Meeting $meeting, User $user, bool $forReserve): array {...} 10. 11. public function getTicketsUserCanReserve(Meeting $meeting, User $user): array {...} 12. 13. private function getTicketsUserCanPurchase(Meeting $meeting, User $user): array {...} 14. 15. private function thereAreTicketsLeftForSale(Ticket $ticket, array $currentSoldPerTicket): bool {...} 16. }
  71. 1. public function testThatTicketsCannotBeSoldWhenMeetingHasStarted() { 2. $meeting = new Meeting(

    3. ..., 4. new Program( 5. new MeetingDuration( 6. new DateTimeImmutable('2018-02-20 19:00'), 7. new DateTimeImmutable('2018-02-20 22:00') 8. ), 9. [] 10. ), 11. [new Ticket(1, true, 0, null, null)] 12. ); 13. 14. $expected = []; 15. $actual = $meeting->getTicketsOpenForSaleOn( 16. new DateTimeImmutable('2018-02-20 20:00') 17. ); 18. 19. $this->assertEquals($expected, $actual); 20. } --- Expected +++ Actual @@ @@ Array ( + 1 => Pelshoff\Meeting\Ticket Object (...) )
  72. 1. public function getTicketsOpenForSaleOn(DateTimeImmutable $date): array { 2. if ($this->program->hasStartedOn($date))

    { 3. return []; 4. } 5. $openTickets = []; 6. foreach ($this->tickets as $ticket) { 7. if ($ticket->isOpenForSaleOn($date)) { 8. $openTickets[$ticket->getId()] = $ticket; 9. } 10. } 11. return $openTickets; 12. } ............... 15 / 15 (100%) Time: 84 ms, Memory: 4.00MB OK (15 tests, 15 assertions)