From 25a90b04aa60db1251334bac8e66b28a2903ba9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Fri, 6 Oct 2023 18:14:05 +0200 Subject: [PATCH] WIP: Implement closer BPN integration --- .gitignore | 2 + config/services.yaml | 5 + migrations/Version20231006134112.php | 39 ++++ migrations/Version20231006144941.php | 39 ++++ migrations/Version20231006145056.php | 33 ++++ migrations/Version20231006152954.php | 31 +++ migrations/Version20231006153242.php | 31 +++ migrations/Version20231006155227.php | 31 +++ src/BusProNet/ApiClient.php | 1 - .../DataProvider/ProductDataProvider.php | 39 ---- src/BusProNet/Model/Product.php | 46 ----- src/BusProNet/ResponseParser.php | 25 --- src/Command/BpnImportCommand.php | 125 +++++++++++++ .../Admin/Autocomplete/BpnDateController.php | 32 ++++ .../Admin/Autocomplete/HotelController.php | 43 ----- .../Admin/Autocomplete/ProductController.php | 43 ----- src/Entity/Assignment.php | 12 +- src/Entity/BpnDate.php | 176 ++++++++++++++++++ src/Form/AssignmentType.php | 7 +- src/Repository/BpnDateRepository.php | 61 ++++++ src/Repository/Traits/QueryHelperTrait.php | 11 ++ templates/admin/assignment/_form.html.twig | 2 +- tests/BusProNet/ResponseParserTest.php | 18 -- 23 files changed, 628 insertions(+), 224 deletions(-) create mode 100644 migrations/Version20231006134112.php create mode 100644 migrations/Version20231006144941.php create mode 100644 migrations/Version20231006145056.php create mode 100644 migrations/Version20231006152954.php create mode 100644 migrations/Version20231006153242.php create mode 100644 migrations/Version20231006155227.php delete mode 100644 src/BusProNet/DataProvider/ProductDataProvider.php delete mode 100644 src/BusProNet/Model/Product.php create mode 100644 src/Command/BpnImportCommand.php create mode 100644 src/Controller/Admin/Autocomplete/BpnDateController.php delete mode 100644 src/Controller/Admin/Autocomplete/HotelController.php delete mode 100644 src/Controller/Admin/Autocomplete/ProductController.php create mode 100644 src/Entity/BpnDate.php create mode 100644 src/Repository/BpnDateRepository.php create mode 100644 src/Repository/Traits/QueryHelperTrait.php diff --git a/.gitignore b/.gitignore index 867c67a..a1b5d9e 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ yarn-error.log ###> liip/imagine-bundle ### /public/media/cache/ ###< liip/imagine-bundle ### + +xmlexport \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index d17f25f..fb25930 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -42,6 +42,11 @@ services: method: onLogout dispatcher: security.event_dispatcher.main + App\Command\BpnImportCommand: + arguments: + $connection: '@doctrine.dbal.default_connection' + $xmlFilesPath: '%kernel.project_dir%/xmlexport' + App\BusProNet\ApiClient: arguments: $logger: '@monolog.logger.bpn' diff --git a/migrations/Version20231006134112.php b/migrations/Version20231006134112.php new file mode 100644 index 0000000..adbe235 --- /dev/null +++ b/migrations/Version20231006134112.php @@ -0,0 +1,39 @@ +addSql('CREATE TABLE bpn_date (id INT AUTO_INCREMENT NOT NULL, product_id INT NOT NULL, hotel_id INT NOT NULL, bus_pro_id INT NOT NULL, date_from DATE NOT NULL COMMENT \'(DC2Type:date_immutable)\', date_to DATE NOT NULL COMMENT \'(DC2Type:date_immutable)\', bus TINYINT(1) NOT NULL, INDEX IDX_18E376D24584665A (product_id), INDEX IDX_18E376D23243BB18 (hotel_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE bpn_hotel (id INT AUTO_INCREMENT NOT NULL, bus_pro_id INT NOT NULL, code VARCHAR(32) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE bpn_product (id INT AUTO_INCREMENT NOT NULL, bus_pro_id INT NOT NULL, name VARCHAR(255) NOT NULL, code VARCHAR(32) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE bpn_date ADD CONSTRAINT FK_18E376D24584665A FOREIGN KEY (product_id) REFERENCES bpn_date (id)'); + $this->addSql('ALTER TABLE bpn_date ADD CONSTRAINT FK_18E376D23243BB18 FOREIGN KEY (hotel_id) REFERENCES bpn_hotel (id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE bpn_date DROP FOREIGN KEY FK_18E376D24584665A'); + $this->addSql('ALTER TABLE bpn_date DROP FOREIGN KEY FK_18E376D23243BB18'); + $this->addSql('DROP TABLE bpn_date'); + $this->addSql('DROP TABLE bpn_hotel'); + $this->addSql('DROP TABLE bpn_product'); + } +} diff --git a/migrations/Version20231006144941.php b/migrations/Version20231006144941.php new file mode 100644 index 0000000..0d532e1 --- /dev/null +++ b/migrations/Version20231006144941.php @@ -0,0 +1,39 @@ +addSql('ALTER TABLE bpn_date DROP FOREIGN KEY FK_18E376D24584665A'); + $this->addSql('ALTER TABLE bpn_date DROP FOREIGN KEY FK_18E376D23243BB18'); + $this->addSql('DROP INDEX IDX_18E376D24584665A ON bpn_date'); + $this->addSql('DROP INDEX IDX_18E376D23243BB18 ON bpn_date'); + $this->addSql('ALTER TABLE bpn_date ADD code VARCHAR(32) NOT NULL, ADD product VARCHAR(255) NOT NULL, ADD hotel VARCHAR(255) NOT NULL, DROP product_id, DROP hotel_id'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE bpn_date ADD product_id INT NOT NULL, ADD hotel_id INT NOT NULL, DROP code, DROP product, DROP hotel'); + $this->addSql('ALTER TABLE bpn_date ADD CONSTRAINT FK_18E376D24584665A FOREIGN KEY (product_id) REFERENCES bpn_date (id)'); + $this->addSql('ALTER TABLE bpn_date ADD CONSTRAINT FK_18E376D23243BB18 FOREIGN KEY (hotel_id) REFERENCES bpn_hotel (id)'); + $this->addSql('CREATE INDEX IDX_18E376D24584665A ON bpn_date (product_id)'); + $this->addSql('CREATE INDEX IDX_18E376D23243BB18 ON bpn_date (hotel_id)'); + } +} diff --git a/migrations/Version20231006145056.php b/migrations/Version20231006145056.php new file mode 100644 index 0000000..b42258b --- /dev/null +++ b/migrations/Version20231006145056.php @@ -0,0 +1,33 @@ +addSql('DROP TABLE bpn_hotel'); + $this->addSql('DROP TABLE bpn_product'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE TABLE bpn_hotel (id INT AUTO_INCREMENT NOT NULL, bus_pro_id INT NOT NULL, code VARCHAR(32) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, name VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '); + $this->addSql('CREATE TABLE bpn_product (id INT AUTO_INCREMENT NOT NULL, bus_pro_id INT NOT NULL, name VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, code VARCHAR(32) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '); + } +} diff --git a/migrations/Version20231006152954.php b/migrations/Version20231006152954.php new file mode 100644 index 0000000..6eb2fe0 --- /dev/null +++ b/migrations/Version20231006152954.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE bpn_date ADD hotel_code VARCHAR(32) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE bpn_date DROP hotel_code'); + } +} diff --git a/migrations/Version20231006153242.php b/migrations/Version20231006153242.php new file mode 100644 index 0000000..e6e8fe4 --- /dev/null +++ b/migrations/Version20231006153242.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE bpn_date ADD pickups JSON NOT NULL COMMENT \'(DC2Type:json)\''); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE bpn_date DROP pickups'); + } +} diff --git a/migrations/Version20231006155227.php b/migrations/Version20231006155227.php new file mode 100644 index 0000000..5510dd1 --- /dev/null +++ b/migrations/Version20231006155227.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE bpn_date ADD hotel_bus_pro_id INT NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE bpn_date DROP hotel_bus_pro_id'); + } +} diff --git a/src/BusProNet/ApiClient.php b/src/BusProNet/ApiClient.php index 3f230a5..c485046 100644 --- a/src/BusProNet/ApiClient.php +++ b/src/BusProNet/ApiClient.php @@ -16,7 +16,6 @@ class ApiClient { public const TYPE_NOTIFICATION = 'HINWEIS'; public const TYPE_CUSTOMER_DATA = 'KUNDENKONTO'; - public const TYPE_PRODUCTS = 'PRODUKTE'; public const TYPE_BASE_DATA_COUNTRIES = 'STAMMLAENDER'; public const TYPE_BASE_DATA_PICKUPS = 'STAMMZUSTIEGE'; public const TYPE_BASE_DATA_HOTELS = 'STAMMHOTELS'; diff --git a/src/BusProNet/DataProvider/ProductDataProvider.php b/src/BusProNet/DataProvider/ProductDataProvider.php deleted file mode 100644 index b694f6c..0000000 --- a/src/BusProNet/DataProvider/ProductDataProvider.php +++ /dev/null @@ -1,39 +0,0 @@ -cache->get('bpn_products', function (ItemInterface $item) { - $item->expiresAfter(3600); - - return $this - ->apiClient - ->getBaseData(ApiClient::TYPE_PRODUCTS) - ->getItems() - ; - }); - } catch (ApiClientException $e) { - $products = []; - } - - return $products; - } - - public function get(int $busProId): ?Product - { - return $this->getAll()[$busProId] ?? null; - } -} \ No newline at end of file diff --git a/src/BusProNet/Model/Product.php b/src/BusProNet/Model/Product.php deleted file mode 100644 index f7e6c91..0000000 --- a/src/BusProNet/Model/Product.php +++ /dev/null @@ -1,46 +0,0 @@ -id; - } - - public function setId(?int $id): static - { - $this->id = $id; - - return $this; - } - - public function getCode(): ?string - { - return $this->code; - } - - public function setCode(?string $code): static - { - $this->code = $code; - - return $this; - } - - public function getName(): ?string - { - return $this->name; - } - - public function setName(?string $name): static - { - $this->name = $name; - - return $this; - } -} \ No newline at end of file diff --git a/src/BusProNet/ResponseParser.php b/src/BusProNet/ResponseParser.php index a5c5c3e..04b56d2 100644 --- a/src/BusProNet/ResponseParser.php +++ b/src/BusProNet/ResponseParser.php @@ -12,7 +12,6 @@ use App\BusProNet\Model\CrmAttributesResponse; use App\BusProNet\Model\Hotel; use App\BusProNet\Model\NotificationResponse; use App\BusProNet\Model\Pickup; -use App\BusProNet\Model\Product; use App\BusProNet\Model\ProfileResponse; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -59,8 +58,6 @@ class ResponseParser return $this->createPickupsResponse($xml); case ApiClient::TYPE_BASE_DATA_HOTELS: return $this->createHotelsResponse($xml); - case ApiClient::TYPE_PRODUCTS: - return $this->createProductsResponse($xml); } throw new ResponseParserException('Unable to parse XML response'); @@ -241,28 +238,6 @@ class ResponseParser return new BaseDataResponse($hotels); } - public function createProductsResponse(\SimpleXMLElement $xml): BaseDataResponse - { - $products = []; - - foreach ($xml->xpath('produkte/produkt') as $item) { - $code = (string) $item->attributes()['code']; - if (true === empty($code)) { - continue; - } - $id = (int) $item->attributes()['id']; - $product = new Product(); - $product - ->setId($id) - ->setName((string) $item->attributes()['bezeichnung']) - ->setCode($code) - ; - $products[$id] = $product; - } - - return new BaseDataResponse($products); - } - private function resolveOptions(array $options): array { $optionsResolver = new OptionsResolver(); diff --git a/src/Command/BpnImportCommand.php b/src/Command/BpnImportCommand.php new file mode 100644 index 0000000..024bc2b --- /dev/null +++ b/src/Command/BpnImportCommand.php @@ -0,0 +1,125 @@ +name('Ziel_*.xml') + ->in($this->xmlFilesPath) + ; + + $totalCount = count($xmlFiles); + + if (0 === $totalCount) { + $io->error('No XML files available or found'); + + return Command::FAILURE; + } + + // Flush dates + $this + ->connection + ->executeQuery('TRUNCATE TABLE bpn_date') + ; + + $io->info('Found '.$totalCount.' XML files'); + $datesCount = 0; + + // Iterate over xml files + foreach ($xmlFiles as $xmlFile) { + + // Load xml file into simplexml object + $xml = simplexml_load_file($xmlFile); + + // Iterate over all dates + foreach ($xml->xpath('reise/termin') as $dateXml) { + $product = (string) $dateXml->xpath('text')[0]; + $busProId = (int) $dateXml->attributes()['idbuspro']; + $code = (string) $dateXml->attributes()['code']; + $dateFrom = \DateTimeImmutable::createFromFormat('d.m.Y', (string) $dateXml->attributes()['termin']); + $dateTo = \DateTimeImmutable::createFromFormat('d.m.Y', (string) $dateXml->attributes()['bis']); + $bus = false; + + // Iterate over all service entries and look for 'bus' + foreach ($dateXml->xpath('lei_befoerderung/leistung') as $serviceXml) { + if ('BUS' === (string) $serviceXml->attributes()['unterart']) { + $bus = true; + break; + } + } + + // Find pickups + $datePickups = []; + foreach ($dateXml->xpath('zustiege/zustieg') as $pickupXml) { + $pickupBusProId = (int) $pickupXml->attributes()['idbuspro']; + if ($pickupBusProId) { + $pickup = $this->pickupDataProvider->get($pickupBusProId); + $datePickups[] = [ + 'busProId' => $pickupBusProId, + 'city' => $pickup->getCity(), + 'street' => $pickup->getStreet(), + 'time' => (string) $pickupXml->attributes()['zeit'], + ]; + } + } + + // Iterate over all hotel entries + foreach ($dateXml->xpath('hotel') as $hotelXml) { + $hotelBusProId = (int) $hotelXml->attributes()['idbuspro']; + $hotel = $this->hotelDataProvider->get($hotelBusProId); + + // Finally store collected data + $this + ->connection + ->insert('bpn_date', [ + 'code' => $code, + 'bus_pro_id' => $busProId, + 'date_from' => $dateFrom->format('Y-m-d'), + 'date_to' => $dateTo->format('Y-m-d'), + 'product' => $product, + 'hotel' => $hotel->getName(), + 'hotel_code' => $hotel->getCode(), + 'hotel_bus_pro_id' => $hotelBusProId, + 'bus' => (int) $bus, + 'pickups' => json_encode($datePickups), + ]) + ; + ++$datesCount; + } + } + } + + $io->info('Imported '.$datesCount.' dates'); + + return Command::SUCCESS; + } +} diff --git a/src/Controller/Admin/Autocomplete/BpnDateController.php b/src/Controller/Admin/Autocomplete/BpnDateController.php new file mode 100644 index 0000000..1b37673 --- /dev/null +++ b/src/Controller/Admin/Autocomplete/BpnDateController.php @@ -0,0 +1,32 @@ +getContent(), true, 512, JSON_THROW_ON_ERROR); + $queryString = $query['search']; + } catch (\JsonException $e) { + throw $this->createNotFoundException(); + } + + $dates = $this->bpnDateRepository->getAutocompletionData($queryString); + + return $this->json($dates); + } +} \ No newline at end of file diff --git a/src/Controller/Admin/Autocomplete/HotelController.php b/src/Controller/Admin/Autocomplete/HotelController.php deleted file mode 100644 index 9a1aef6..0000000 --- a/src/Controller/Admin/Autocomplete/HotelController.php +++ /dev/null @@ -1,43 +0,0 @@ -getContent(), true, 512, JSON_THROW_ON_ERROR); - $queryString = $query['search']; - } catch (\JsonException $e) { - throw $this->createNotFoundException(); - } - - $hotels = $this->hotelDataProvider->getAll(); - $data = []; - - foreach ($hotels as $hotel) { - $name = $hotel->getName(); - if (1 === preg_match('/'.preg_quote($queryString, '/').'/i', $name)) { - $data[] = [ - 'value' => $hotel->getBusProId(), - 'text' => sprintf('%s (%s)', $name, $hotel->getCode()), - ]; - } - } - - return $this->json($data); - } -} \ No newline at end of file diff --git a/src/Controller/Admin/Autocomplete/ProductController.php b/src/Controller/Admin/Autocomplete/ProductController.php deleted file mode 100644 index e131ddf..0000000 --- a/src/Controller/Admin/Autocomplete/ProductController.php +++ /dev/null @@ -1,43 +0,0 @@ -getContent(), true, 512, JSON_THROW_ON_ERROR); - $queryString = $query['search']; - } catch (\JsonException $e) { - throw $this->createNotFoundException(); - } - - $products = $this->productDataProvider->getAll(); - $data = []; - - foreach ($products as $product) { - $name = $product->getName(); - if (1 === preg_match('/'.preg_quote($queryString, '/').'/i', $name)) { - $data[] = [ - 'value' => $product->getId(), - 'text' => sprintf('%s (%s)', $name, $product->getCode()), - ]; - } - } - - return $this->json($data); - } -} \ No newline at end of file diff --git a/src/Entity/Assignment.php b/src/Entity/Assignment.php index 9e143f8..2978ac8 100644 --- a/src/Entity/Assignment.php +++ b/src/Entity/Assignment.php @@ -27,9 +27,9 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa #[ORM\Column(type: 'string', length: 36, unique: true)] private string $uuid; - #[ORM\Column(nullable: true)] + #[ORM\ManyToOne] #[Assert\NotNull(message: 'Bitte gib die Destination an')] - private ?int $destinationBusProId = null; + private ?BpnDate $destination = null; #[ORM\ManyToOne] #[Assert\NotNull(message: 'Bitte gib das Jobprofil an')] @@ -93,14 +93,14 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa return $this->uuid; } - public function getDestinationBusProId(): ?int + public function getDestination(): ?BpnDate { - return $this->destinationBusProId; + return $this->destination; } - public function setDestinationBusProId(?int $destinationBusProId): static + public function setDestination(?BpnDate $destination): static { - $this->destinationBusProId = $destinationBusProId; + $this->destination = $destination; return $this; } diff --git a/src/Entity/BpnDate.php b/src/Entity/BpnDate.php new file mode 100644 index 0000000..af910c4 --- /dev/null +++ b/src/Entity/BpnDate.php @@ -0,0 +1,176 @@ +bus = false; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getBusProId(): ?int + { + return $this->busProId; + } + + public function setBusProId(int $busProId): static + { + $this->busProId = $busProId; + + return $this; + } + + public function getDateFrom(): ?\DateTimeImmutable + { + return $this->dateFrom; + } + + public function setDateFrom(\DateTimeImmutable $dateFrom): static + { + $this->dateFrom = $dateFrom; + + return $this; + } + + public function getDateTo(): ?\DateTimeImmutable + { + return $this->dateTo; + } + + public function setDateTo(\DateTimeImmutable $dateTo): static + { + $this->dateTo = $dateTo; + + return $this; + } + + public function isBus(): ?bool + { + return $this->bus; + } + + public function setBus(bool $bus): static + { + $this->bus = $bus; + + return $this; + } + + public function getCode(): ?string + { + return $this->code; + } + + public function setCode(string $code): static + { + $this->code = $code; + + return $this; + } + + public function getProduct(): ?string + { + return $this->product; + } + + public function setProduct(string $product): static + { + $this->product = $product; + + return $this; + } + + public function getHotel(): ?string + { + return $this->hotel; + } + + public function setHotel(string $hotel): static + { + $this->hotel = $hotel; + + return $this; + } + + public function getHotelCode(): ?string + { + return $this->hotelCode; + } + + public function setHotelCode(?string $hotelCode): static + { + $this->hotelCode = $hotelCode; + + return $this; + } + + public function getHotelBusProId(): ?int + { + return $this->hotelBusProId; + } + + public function setHotelBusProId(?int $hotelBusProId): static + { + $this->hotelBusProId = $hotelBusProId; + + return $this; + } + + public function getPickups(): array + { + return $this->pickups; + } + + public function setPickups(array $pickups): static + { + $this->pickups = $pickups; + + return $this; + } +} diff --git a/src/Form/AssignmentType.php b/src/Form/AssignmentType.php index a02ef6c..0407247 100644 --- a/src/Form/AssignmentType.php +++ b/src/Form/AssignmentType.php @@ -3,6 +3,7 @@ namespace App\Form; use App\Entity\Assignment; +use App\Entity\BpnDate; use App\Entity\Fee; use App\Entity\JobProfile; use App\Entity\User; @@ -25,9 +26,11 @@ class AssignmentType extends AbstractType 'label' => 'Anzahl', 'required' => false, ]) - ->add('destinationBusProId', AutocompleteChoiceType::class, [ + ->add('destination', AutocompleteEntityType::class, [ 'label' => 'Destination', - 'endpoint_route' => 'app_admin_autocomplete_hotel', + 'class' => BpnDate::class, + 'label_property' => 'product', + 'endpoint_route' => 'app_admin_autocomplete_bpndate', ]) ->add('jobProfile', EntityType::class, [ 'label' => 'Jobprofil', diff --git a/src/Repository/BpnDateRepository.php b/src/Repository/BpnDateRepository.php new file mode 100644 index 0000000..4c16062 --- /dev/null +++ b/src/Repository/BpnDateRepository.php @@ -0,0 +1,61 @@ + + * + * @method BpnDate|null find($id, $lockMode = null, $lockVersion = null) + * @method BpnDate|null findOneBy(array $criteria, array $orderBy = null) + * @method BpnDate[] findAll() + * @method BpnDate[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class BpnDateRepository extends ServiceEntityRepository +{ + use QueryHelperTrait; + + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, BpnDate::class); + } + + public function getAutocompletionData(string $search): array + { + $qb = $this->createQueryBuilder('bpn_date'); + + $dates = $qb + ->select('bpn_date.id', 'bpn_date.product', 'bpn_date.hotel', 'bpn_date.dateFrom', 'bpn_date.dateTo') + ->where($qb->expr()->orX( + $qb->expr()->like('bpn_date.product', ':product'), + $qb->expr()->like('bpn_date.hotel', ':hotel') + )) + ->setParameter('product', '%'.$this->escapeLikeWildcards($search).'%') + ->setParameter('hotel', '%'.$this->escapeLikeWildcards($search).'%') + ->orderBy('bpn_date.product', 'ASC') + ->addOrderBy('bpn_date.dateFrom', 'ASC') + ->getQuery() + ->getArrayResult() + ; + + $data = [ + [ + 'value' => '', + 'text' => '...', + ], + ]; + + foreach ($dates as $date) { + $data[] = [ + 'value' => $date['id'], + 'text' => sprintf('%s (%s - %s)', $date['product'], $date['dateFrom']->format('d.m.y'), $date['dateTo']->format('d.m.y')), + ]; + } + + return $data; + } +} diff --git a/src/Repository/Traits/QueryHelperTrait.php b/src/Repository/Traits/QueryHelperTrait.php new file mode 100644 index 0000000..f12da4e --- /dev/null +++ b/src/Repository/Traits/QueryHelperTrait.php @@ -0,0 +1,11 @@ +
- {{ form_row(form.destinationBusProId) }} + {{ form_row(form.destination) }} {{ form_row(form.contact) }}
diff --git a/tests/BusProNet/ResponseParserTest.php b/tests/BusProNet/ResponseParserTest.php index d0a53c5..fdc1e9b 100644 --- a/tests/BusProNet/ResponseParserTest.php +++ b/tests/BusProNet/ResponseParserTest.php @@ -92,24 +92,6 @@ class ResponseParserTest extends TestCase $this->assertEquals('Gaststätte', $hotel->getType()); } - public function testParseSuccessfulProductsResponse(): void - { - $content = ''; - - $parser = $this->getParserInstance(); - $response = $parser->parseXmlString(ApiClient::TYPE_PRODUCTS, $content); - - $this->assertInstanceOf(BaseDataResponse::class, $response); - - $products = $response->getItems(); - $this->assertCount(3, $products); - - $product = reset($products); - $this->assertEquals(389, $product->getId()); - $this->assertEquals('ANDA', $product->getCode()); - $this->assertEquals('Andalusien', $product->getName()); - } - private function getParserInstance(): ResponseParser { return new ResponseParser([