feat: api endpoints to fetch product and hotel data in json format

This commit is contained in:
Björn Fromme
2025-10-25 15:33:35 +02:00
parent fd9dd4008e
commit 15374e7faa
3 changed files with 246 additions and 0 deletions
@@ -0,0 +1,203 @@
<?php
declare(strict_types=1);
namespace EP\EpProducts\Controller;
/***************************************************************
*
* Copyright notice
*
* (c) 2025 Björn Fromme <[email protected]>, 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);
}
}
@@ -241,3 +241,38 @@ lib.bookingWidget {
settings =< plugin.tx_epproducts.settings
view =< plugin.tx_epproducts.view
}
# API endpoint for product details (cacheable)
tx_epproducts_api_json = PAGE
tx_epproducts_api_json {
typeNum = 1720
config {
disableAllHeaderCode = 1
disablePrefixComment = 1
additionalHeaders.10.header = Content-type: application/json
additionalHeaders.20.header = Access-Control-Allow-Origin: *
xhtml_cleaning = 0
admPanel = 0
debug = 0
no_cache = 0
sendCacheHeaders = 1
}
10 = USER
10 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
extensionName = EpProducts
pluginName = api
vendorName = EP
controller = Api
action = product
switchableControllerActions {
Api {
1 = product
2 = hotel
}
}
settings =< plugin.tx_epproducts.settings
persistence =< plugin.tx_epproducts.persistence
}
}
@@ -294,6 +294,14 @@ $boot = function () {
]
);
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'EP.ep_products',
'api',
[
'Api' => 'product,hotel',
]
);
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']['ep_products'] =
\EP\EpProducts\Hooks\PageLayoutView::class;