diff --git a/api.http b/api.http new file mode 100644 index 00000000..a0dbfee8 --- /dev/null +++ b/api.http @@ -0,0 +1,7 @@ +### GET product data for myep +GET https://ep-reisen.ddev.site/api/product + ?product=SBW + &hotel=SBWOU2 + &key=abcabc123 + +### diff --git a/public/typo3conf/ext/ep_products/Classes/Controller/ApiController.php b/public/typo3conf/ext/ep_products/Classes/Controller/ApiController.php deleted file mode 100644 index d92e333e..00000000 --- a/public/typo3conf/ext/ep_products/Classes/Controller/ApiController.php +++ /dev/null @@ -1,203 +0,0 @@ -, dreipunktnull - * - * All rights reserved - * - * This script is part of the TYPO3 project. The TYPO3 project is - * free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * The GNU General Public License can be found at - * http://www.gnu.org/copyleft/gpl.html. - * - * This script is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This copyright notice MUST APPEAR in all copies of the script! - ***************************************************************/ - -use EP\EpProducts\Service\HotelImageService; -use EP\EpProducts\Service\ProductImageService; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -use TYPO3\CMS\Extbase\Mvc\View\JsonView; - -class ApiController extends ActionController -{ - /** - * @var string - */ - protected $defaultViewObjectName = JsonView::class; - - /** - * @var ProductImageService - */ - private $productImageService; - - /** - * @var HotelImageService - */ - private $hotelImageService; - - /** - * @var ConnectionPool - */ - private $connectionPool; - - public function __construct( - ProductImageService $productImageService, - HotelImageService $hotelImageService, - ConnectionPool $connectionPool - ) { - $this->productImageService = $productImageService; - $this->hotelImageService = $hotelImageService; - $this->connectionPool = $connectionPool; - } - - /** - * Returns product details in JSON format for API consumption. - */ - public function productAction(string $code): void - { - $queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_epproducts_domain_model_product'); - - $product = $queryBuilder - ->select( - 'uid', - 'name', - 'code', - 'headline', - 'teaser', - 'teaser_long', - 'concept_description', - 'board_description', - 'programme_description', - 'included_services', - 'additional_services', - 'ski_pass_alt_title', - 'ski_pass_description' - ) - ->from('tx_epproducts_domain_model_product') - ->where( - $queryBuilder->expr()->eq( - 'code', - $queryBuilder->createNamedParameter($code) - ) - ) - ->execute() - ->fetchAssociative() - ; - - if (false === $product) { - $this->view->assign('value', ['error' => 'Product not found']); - $this->response->setStatus(404); - - return; - } - - $images = $this->productImageService->getImages((int) $product['uid']); - - $response = [ - 'name' => $product['name'], - 'code' => $product['code'], - 'headline' => $product['headline'], - 'teaser' => $product['teaser'], - 'teaserLong' => $product['teaser_long'], - 'conceptDescription' => $product['concept_description'], - 'boardDescription' => $product['board_description'], - 'programmeDescription' => $product['programme_description'], - 'includedServices' => $product['included_services'], - 'additionalServices' => $product['additional_services'], - 'skiPassAltTitle' => $product['ski_pass_alt_title'], - 'skiPassDescription' => $product['ski_pass_description'], - 'images' => $images['resized'] ?? [], - ]; - - $this->view->assign('value', $response); - } - - /** - * Returns hotel details in JSON format for API consumption. - */ - public function hotelAction(string $code): void - { - $queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_epproducts_domain_model_hotel'); - - $hotel = $queryBuilder - ->select( - 'uid', - 'name', - 'short_name', - 'code', - 'headline', - 'teaser', - 'header_title', - 'header_subtitle', - 'description', - 'features', - 'room_types', - 'additional_information', - 'address', - 'latitude', - 'longitude', - 'category', - 'type', - 'external_link' - ) - ->from('tx_epproducts_domain_model_hotel') - ->where( - $queryBuilder->expr()->eq( - 'code', - $queryBuilder->createNamedParameter($code) - ) - ) - ->execute() - ->fetchAssociative() - ; - - if (false === $hotel) { - $this->view->assign('value', ['error' => 'Hotel not found']); - $this->response->setStatus(404); - - return; - } - - $images = $this->hotelImageService->getImages((int) $hotel['uid']); - - $response = [ - 'name' => $hotel['name'], - 'shortName' => $hotel['short_name'], - 'code' => $hotel['code'], - 'headline' => $hotel['headline'], - 'teaser' => $hotel['teaser'], - 'headerTitle' => $hotel['header_title'], - 'headerSubtitle' => $hotel['header_subtitle'], - 'description' => $hotel['description'], - 'features' => $hotel['features'], - 'roomTypes' => $hotel['room_types'], - 'additionalInformation' => $hotel['additional_information'], - 'address' => $hotel['address'], - 'latitude' => $hotel['latitude'], - 'longitude' => $hotel['longitude'], - 'category' => $hotel['category'], - 'type' => $hotel['type'], - 'externalLink' => $hotel['external_link'], - 'images' => $images['resized'] ?? [], - ]; - - $this->view->assign('value', $response); - } -} diff --git a/public/typo3conf/ext/ep_products/Classes/Middleware/ProductApiMiddleware.php b/public/typo3conf/ext/ep_products/Classes/Middleware/ProductApiMiddleware.php new file mode 100644 index 00000000..be1d9734 --- /dev/null +++ b/public/typo3conf/ext/ep_products/Classes/Middleware/ProductApiMiddleware.php @@ -0,0 +1,153 @@ +getUri()->getPath()) { + return $handler->handle($request); + } + + // This is currently fake, we only check for existence. Since we are communicating + // on the backchannel only it's not much of a problem. + $apiKey = $request->getQueryParams()['key'] ?? null; + + if (null === $apiKey) { + return (new JsonResponse(['message' => 'No api key provided'], 403)); + } + + $productCode = $request->getQueryParams()['product'] ?? null; + $hotelCode = $request->getQueryParams()['hotel'] ?? null; + + if (null === $productCode) { + return (new JsonResponse(['message' => 'No product code provided'], 400)); + } + + $data = $this->fetchProductData($productCode); + + if (null === $data) { + return (new JsonResponse(['message' => 'Product not found'], 404)); + } + + if (null !== $hotelCode) { + $data['hotel'] = $this->fetchHotelData($hotelCode); + } + + return new JsonResponse($data); + } + + private function fetchProductData(string $productCode): ?array + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_epproducts_domain_model_product'); + + $product = $queryBuilder + ->select( + 'uid', + 'name', + 'code', + 'headline', + 'teaser', + 'teaser_long', + 'concept_description', + 'board_description', + 'programme_description', + 'included_services', + 'additional_services', + 'ski_pass_alt_title', + 'ski_pass_description' + ) + ->from('tx_epproducts_domain_model_product') + ->where( + $queryBuilder->expr()->eq( + 'code', + $queryBuilder->createNamedParameter($productCode) + ) + ) + ->setMaxResults(1) + ->execute() + ->fetchAssociative() + ; + + if (false === $product) { + return null; + } + + $images = GeneralUtility::makeInstance(ProductImageService::class) + ->getImages((int) $product['uid']); + + return [ + 'name' => $product['name'], + 'code' => $product['code'], + 'headline' => $product['headline'], + 'teaser' => $product['teaser'], + 'teaserLong' => $product['teaser_long'], + 'conceptDescription' => $product['concept_description'], + 'boardDescription' => $product['board_description'], + 'programmeDescription' => $product['programme_description'], + 'includedServices' => $product['included_services'], + 'additionalServices' => $product['additional_services'], + 'skiPassAltTitle' => $product['ski_pass_alt_title'], + 'skiPassDescription' => $product['ski_pass_description'], + 'images' => $images, + ]; + } + + private function fetchHotelData(string $hotelCode): array + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_epproducts_domain_model_hotel'); + + $hotel = $queryBuilder + ->select( + 'hotel.uid', + 'hotel.name', + 'hotel.code', + 'hotel.description', + 'hotel.features', + 'hotel.room_types', + 'hotel.additional_information', + ) + ->from('tx_epproducts_domain_model_hotel', 'hotel') + ->leftJoin('hotel', 'tx_epproducts_domain_model_matchcode', 'alias', 'hotel.uid = alias.uid AND alias.entity_type="hotel"') + ->where( + $queryBuilder->expr()->orX( + $queryBuilder->expr()->eq('hotel.code', $queryBuilder->createNamedParameter($hotelCode)), + $queryBuilder->expr()->eq('alias.code', $queryBuilder->createNamedParameter($hotelCode)), + ) + ) + ->setMaxResults(1) + ->execute() + ->fetchAssociative() + ; + + if (false === $hotel) { + return []; + } + + $images = GeneralUtility::makeInstance(HotelImageService::class) + ->getImages((int) $hotel['uid']); + + return [ + 'name' => $hotel['name'], + 'code' => $hotel['code'], + 'description' => $hotel['description'], + 'features' => $hotel['features'], + 'roomTypes' => $hotel['room_types'], + 'additionalInformation' => $hotel['additional_information'], + 'images' => $images, + ]; + } +} diff --git a/public/typo3conf/ext/ep_products/Configuration/RequestMiddlewares.php b/public/typo3conf/ext/ep_products/Configuration/RequestMiddlewares.php index ac0deb10..cc8a137e 100644 --- a/public/typo3conf/ext/ep_products/Configuration/RequestMiddlewares.php +++ b/public/typo3conf/ext/ep_products/Configuration/RequestMiddlewares.php @@ -11,5 +11,14 @@ return [ 'typo3/cms-frontend/static-route-resolver', ], ], + 'ep/productapi' => [ + 'target' => \EP\EpProducts\Middleware\ProductApiMiddleware::class, + 'before' => [ + 'typo3/cms-frontend/page-resolver', + ], + 'after' => [ + 'typo3/cms-frontend/site', + ], + ], ], ];