Implement day trip option for products

This commit is contained in:
Björn Fromme
2018-08-07 17:42:04 +02:00
parent 464111b5e0
commit 07b0ad3102
13 changed files with 288 additions and 118 deletions
+3 -1
View File
@@ -8,6 +8,7 @@
"type": "project",
"require": {
"php": "^5.6",
"ext-json": "*",
"typo3/cms": "^7.6",
"georgringer/news": "^6.1",
"dmitryd/typo3-realurl": "^2.3",
@@ -65,7 +66,8 @@
"yohang/calendr": "^2.1",
"wyrihaximus/html-compress": "^1.4",
"symfony/serializer": "3.3.*",
"symfony/property-access": "^3.4"
"symfony/property-access": "^3.4",
"symfony/options-resolver": "^3.4"
},
"scripts": {
"typo3-cms-scripts": [
Generated
+6 -6
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "218f290216c085ca0d43c4cb1fde6c13",
"content-hash": "24a1dae8a5e81d4d36f7e5988eaace7a",
"packages": [
{
"name": "cogpowered/finediff",
@@ -1918,16 +1918,16 @@
},
{
"name": "symfony/options-resolver",
"version": "v3.4.13",
"version": "v3.4.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "638f5ad40a6400d78568187522731e5643eed60a"
"reference": "6debc476953a45969ab39afe8dee0b825f356dc7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/638f5ad40a6400d78568187522731e5643eed60a",
"reference": "638f5ad40a6400d78568187522731e5643eed60a",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/6debc476953a45969ab39afe8dee0b825f356dc7",
"reference": "6debc476953a45969ab39afe8dee0b825f356dc7",
"shasum": ""
},
"require": {
@@ -1968,7 +1968,7 @@
"configuration",
"options"
],
"time": "2018-07-07T15:09:44+00:00"
"time": "2018-07-26T08:45:46+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -108,12 +108,18 @@ class AjaxDateController extends ActionController
;
$altLabel = $product->getAltLabel();
}
$template = $this->settings['bpnBookingUrlTemplateCode'];
$paCode = null;
if ($reseller = $this->resellerService->getResellerForCurrentDomain()) {
$paCode = $reseller['paCode'];
} else {
$paCode = null;
}
$datesTable = $this->dateService->getDatesTable($product, $hotel, $filterSettings, $template, $paCode);
$datesTable = $this->dateService->getDatesTable([
'product' => $product,
'hotel' => $hotel,
'filterSettings' => $filterSettings,
'template' => $this->settings['bpnBookingUrlTemplateCode'],
'paCode' => $paCode,
]);
return json_encode([
'dates' => $datesTable,
'bookable' => $product->getBookable(),
@@ -91,12 +91,19 @@ class AjaxTableController extends ActionController
$forcedConceptUid = (int) $this->settings['forcedConceptUid'];
$filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUid, false);
}
$paCode = null;
if ($reseller = $this->resellerService->getResellerForCurrentDomain()) {
$paCode = $reseller['paCode'];
} else {
$paCode = null;
}
$template = $this->settings['bpnBookingUrlTemplateCode'];
$priceTable = $this->dateService->getPriceTable($product, $hotel, $filterSettings, $date, $template, $paCode);
$priceTable = $this->dateService->getPriceTable([
'product' => $product,
'hotel' => $hotel,
'filterSettings' => $filterSettings,
'date' => $date,
'template' => $this->settings['bpnBookingUrlTemplateCode'],
'paCode' => $paCode,
]);
return json_encode([
'dateStart' => $date ? $date->getDateStart()->format('Y-m-d') : '',
'dateEnd' => $date ? $date->getDateEnd()->format('Y-m-d') : '',
@@ -111,13 +118,18 @@ class AjaxTableController extends ActionController
*/
public function pricetableHtmlAction(Product $product, Hotel $hotel)
{
$filterSettings = $this->filterService->getDefaultFilterSettings();
$paCode = null;
if ($reseller = $this->resellerService->getResellerForCurrentDomain()) {
$paCode = $reseller['paCode'];
} else {
$paCode = null;
}
$template = $this->settings['bpnBookingUrlTemplateCode'];
$pricetable = $this->dateService->getPriceTable($product, $hotel, $filterSettings, null, $template, $paCode);
$pricetable = $this->dateService->getPriceTable([
'product' => $product,
'hotel' => $hotel,
'filterSettings' => $this->filterService->getDefaultFilterSettings(),
'template' => $this->settings['bpnBookingUrlTemplateCode'],
'paCode' => $paCode,
]);
$this->view->assign('pricetable', $pricetable);
}
@@ -175,8 +175,11 @@ class ProductController extends ActionController
$hotelUid = $this->settings['hotelUid'];
/** @var \EP\EpProducts\Domain\Model\Hotel $hotel */
$hotel = $this->hotelRepository->findByIdentifier($hotelUid);
$filterSettings = $this->filterService->getDefaultFilterSettings();
$pricetable = $this->dateService->getPriceTable($product, $hotel, $filterSettings);
$pricetable = $this->dateService->getPriceTable([
'product' => $product,
'hotel' => $hotel,
'filterSettings' => $this->filterService->getDefaultFilterSettings(),
]);
$this->view->assign('pricetable', $pricetable);
}
@@ -40,6 +40,11 @@ class Product extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity implements
*/
protected $bookable = true;
/**
* @var bool
*/
protected $daytrip = false;
/**
* @var int
*/
@@ -286,6 +291,22 @@ class Product extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity implements
$this->bookable = (bool) $bookable;
}
/**
* @return bool
*/
public function isDaytrip()
{
return $this->daytrip;
}
/**
* @param bool $daytrip
*/
public function setDaytrip($daytrip)
{
$this->daytrip = $daytrip;
}
/**
* @return int
*/
@@ -33,6 +33,7 @@ use EP\EpProducts\Domain\Model\Product;
use EP\EpProducts\Domain\Repository\DateRepository;
use EP\EpProducts\Domain\Repository\ProductRepository;
use EP\EpProducts\Utility\BookingUrlUtility;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TYPO3\CMS\Core\SingletonInterface;
class DateService implements SingletonInterface
@@ -57,7 +58,12 @@ class DateService implements SingletonInterface
* @param DateRepository $dateRepository
* @param FilterService $filterService
*/
public function __construct(ProductRepository $productRepository, DateRepository $dateRepository, FilterService $filterService)
public function __construct
(
ProductRepository $productRepository,
DateRepository $dateRepository,
FilterService $filterService
)
{
$this->productRepository = $productRepository;
$this->filterService = $filterService;
@@ -65,55 +71,93 @@ class DateService implements SingletonInterface
}
/**
* @param Product $product
* @param Hotel $hotel
* @param FilterSettings|null $filterSettings
* @param Date|null $date
* @param string $template
* @param string $paCode
*
* @param array $options
* @return array
*/
public function getPriceTable
(
Product $product,
Hotel $hotel,
FilterSettings $filterSettings = null,
Date $date = null,
$template = 'base',
$paCode = null
)
public function getPriceTable(array $options)
{
$resolver = new OptionsResolver();
$this->configurePriceTableOptions($resolver);
$resolvedOptions = $resolver->resolve($options);
/** @var Product $product */
$product = $resolvedOptions['product'];
$hotel = $resolvedOptions['hotel'];
$filterSettings = $resolvedOptions['filterSettings'];
$date = $resolvedOptions['date'];
$template = $resolvedOptions['template'];
$paCode = $resolvedOptions['paCode'];
if ($filterSettings === null) {
$filterSettings = $this->filterService->getDefaultFilterSettings();
}
$priceTableData = $this->productRepository->getPricetable($product, $hotel, $filterSettings, $date);
return $this->preprocessPriceTable($priceTableData, $template, $paCode);
return $this->preprocessPriceTable([
'priceTableData' => $this->productRepository->getPricetable($product, $hotel, $filterSettings, $date),
'template' => $template,
'paCode' => $paCode,
'isDayTrip' => $product->isDaytrip(),
]);
}
/**
* @param Product $product
* @param Hotel $hotel
* @param FilterSettings|null $filterSettings
* @param string $template
* @param string $paCode
*
* @param OptionsResolver $resolver
*/
protected function configurePriceTableOptions(OptionsResolver $resolver)
{
$resolver->setRequired(['product', 'hotel']);
$resolver->setDefaults([
'filterSettings' => null,
'date' => null,
'template' => 'base',
'paCode' => null,
]);
$resolver->setAllowedTypes('product', Product::class);
$resolver->setAllowedTypes('hotel', Hotel::class);
$resolver->setAllowedTypes('date', Date::class);
}
/**
* @param array $options
* @return array
*/
public function getDatesTable
(
Product $product,
Hotel $hotel,
FilterSettings $filterSettings = null,
$template = 'base',
$paCode = null
)
public function getDatesTable(array $options)
{
$resolver = new OptionsResolver();
$this->configureDatesTableOptions($resolver);
$resolvedOptions = $resolver->resolve($options);
/** @var Product $product */
$product = $resolvedOptions['product'];
$hotel = $resolvedOptions['hotel'];
$filterSettings = $resolvedOptions['filterSettings'];
$template = $resolvedOptions['template'];
$paCode = $resolvedOptions['paCode'];
if ($filterSettings === null) {
$filterSettings = $this->filterService->getDefaultFilterSettings();
}
$dateTableData = $this->productRepository->getAvailableDates($product, $hotel, $filterSettings);
return $this->preprocessDateTable($dateTableData, $template, $paCode);
return $this->preprocessDateTable([
'dateTableData' => $this->productRepository->getAvailableDates($product, $hotel, $filterSettings),
'template' => $template,
'paCode' => $paCode,
'isDayTrip' => $product->isDaytrip(),
]);
}
/**
* @param OptionsResolver $resolver
*/
protected function configureDatesTableOptions(OptionsResolver $resolver)
{
$resolver->setRequired(['product', 'hotel']);
$resolver->setDefaults([
'filterSettings' => null,
'template' => 'base',
'paCode' => null,
]);
$resolver->setAllowedTypes('product', Product::class);
$resolver->setAllowedTypes('hotel', Hotel::class);
}
/**
@@ -124,8 +168,13 @@ class DateService implements SingletonInterface
*/
public function getEventPriceTable(Product $product, $maxPax = 99, $template = 'base')
{
$priceTableData = $this->productRepository->getEventPriceTable($product);
return $this->preprocessEventPriceTable($priceTableData, $maxPax, $template);
return $this->preprocessEventPriceTable([
'priceTableData' => $priceTableData,
'maxPax' => $maxPax,
'template' => $template,
]);
}
/**
@@ -189,27 +238,37 @@ class DateService implements SingletonInterface
}
/**
* @param array $priceTableData
* @param string $template
* @param string $paCode
*
* @param array $options
* @return array
*/
public function preprocessPriceTable(array $priceTableData, $template, $paCode = null)
public function preprocessPriceTable(array $options)
{
$resolver = new OptionsResolver();
$resolver->setRequired(['priceTableData', 'template']);
$resolver->setDefaults([
'paCode' => null,
'isDayTrip' => false,
]);
$resolvedOptions = $resolver->resolve($options);
$priceTable = [];
$priceTableData = $resolvedOptions['priceTableData'];
$template = $resolvedOptions['template'];
$paCode = $resolvedOptions['paCode'];
$isDayTrip = $resolvedOptions['isDayTrip'];
foreach ($priceTableData as $row)
{
$dateStart = new \DateTime($row['dateStart']);
$dateEnd = new \DateTime($row['dateEnd']);
$bookingUrl = BookingUrlUtility::generateUrl(
$row['dateBusProId'],
$row['hotelBusProId'],
$row['dateEnd'],
$template,
$paCode
);
$bookingUrl = BookingUrlUtility::generateUrl([
'bookingId' => $row['dateBusProId'],
'hotelId' => $row['hotelBusProId'],
'dateEnd' => $row['dateEnd'],
'template' => $template,
'paCode' => $paCode,
'isDayTrip' => $isDayTrip,
]);
$priceTable[] = [
'dateStart' => $dateStart->format('d.m.Y'),
'dateEnd' => $dateEnd->format('d.m.Y'),
@@ -234,26 +293,38 @@ class DateService implements SingletonInterface
}
/**
* @param array $dateTableData
* @param string $template
* @param string $paCode
*
* @param array $options
* @return array
*/
public function preprocessDateTable(array $dateTableData, $template, $paCode = null)
public function preprocessDateTable(array $options)
{
$resolver = new OptionsResolver();
$resolver->setRequired(['dateTableData', 'template']);
$resolver->setDefaults([
'paCode' => null,
'isDayTrip' => false,
]);
$resolvedOptions = $resolver->resolve($options);
$dateTable = [];
$dateTableData = $resolvedOptions['dateTableData'];
$template = $resolvedOptions['template'];
$paCode = $resolvedOptions['paCode'];
$isDayTrip = $resolvedOptions['isDayTrip'];
foreach ($dateTableData as $row)
{
$dateStart = new \DateTime($row['dateStart']);
$dateEnd = new \DateTime($row['dateEnd']);
$bookingUrl = BookingUrlUtility::generateUrl(
$row['dateBusProId'],
$row['hotelBusProId'],
$row['dateEnd'],
$template,
$paCode
);
$bookingUrl = BookingUrlUtility::generateUrl([
'bookingId' => $row['dateBusProId'],
'hotelId' =>$row['hotelBusProId'],
'dateEnd' => $row['dateEnd'],
'template' => $template,
'paCode' => $paCode,
'isDayTrip' => $isDayTrip,
]);
$dateTable[] = [
'dateUid' => $row['dateUid'],
'dateStart' => $dateStart->format('d.m.y'),
@@ -275,15 +346,25 @@ class DateService implements SingletonInterface
}
/**
* @param array $priceTableData
* @param int $maxPax
* @param string $template
* @param string $paCode
*
* @param array $options
* @return array
*/
public function preprocessEventPriceTable(array $priceTableData, $maxPax = 99, $template = 'base', $paCode = null)
public function preprocessEventPriceTable(array $options)
{
$resolver = new OptionsResolver();
$resolver->setRequired(['priceTableData']);
$resolver->setDefaults([
'maxPax' => 99,
'template' => 'base',
'paCode' => null,
]);
$resolvedOptions = $resolver->resolve($options);
$priceTableData = $resolvedOptions['priceTableData'];
$maxPax = $resolvedOptions['maxPax'];
$template = $resolvedOptions['template'];
$paCode = $resolvedOptions['paCode'];
$priceTable = [
Hotel::CATEGORY_STANDARD => [],
Hotel::CATEGORY_COMFORT => [],
@@ -300,13 +381,13 @@ class DateService implements SingletonInterface
'category' => $categoryUid,
'hotelName' => $row['hotelName'],
'hotelTitle' => $row['hotelTitle'],
'bookingUrl' => BookingUrlUtility::generateUrl(
$row['dateBusProId'],
$row['hotelBusProId'],
$row['dateEnd'],
$template,
$paCode
),
'bookingUrl' => BookingUrlUtility::generateUrl([
'bookingId' => $row['dateBusProId'],
'hotelId' => $row['hotelBusProId'],
'dateEnd' => $row['dateEnd'],
'template' => $template,
'paCode' => $paCode,
]),
'rooms' => [],
];
}
@@ -111,12 +111,12 @@ class ResellerService implements SingletonInterface
$data[$row['dateStart']] = $date;
}
$date->bookingurl = BookingUrlUtility::generateResellerUrl(
$row['dateBusProId'],
$row['hotelBusProId'],
$row['dateEnd'],
$paCode
);
$date->bookingurl = BookingUrlUtility::generateResellerUrl([
'bookingId' => $row['dateBusProId'],
'hotelId' => $row['hotelBusProId'],
'dateEnd' => $row['dateEnd'],
'paCode' => $paCode,
]);
$date->rooms['room'][] = Room::fromArray($row);
}
@@ -2,8 +2,6 @@
namespace EP\EpProducts\Utility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/***************************************************************
*
* Copyright notice
@@ -29,6 +27,9 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use Symfony\Component\OptionsResolver\OptionsResolver;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class BookingUrlUtility
{
@@ -37,16 +38,29 @@ class BookingUrlUtility
const URL_BASE = 'https://bpn.ep-reisen.de/buspronet/maske_buchung.php';
/**
* @param int $bookingId
* @param int $hotelId
* @param string $dateEnd
* @param string $template
* @param string $paCode
* @param array $options
* @return string
*/
public static function generateUrl($bookingId, $hotelId, $dateEnd, $template = 'base', $paCode = null)
public static function generateUrl(array $options)
{
$query = static::buildQuery($bookingId, $hotelId, $dateEnd, $template);
$resolver = new OptionsResolver();
$resolver->setRequired(['bookingId', 'hotelId', 'dateEnd']);
$resolver->setDefaults([
'template' => 'base',
'paCode' => null,
'isDayTrip' => false,
]);
$resolvedOptions = $resolver->resolve($options);
$bookingId = $resolvedOptions['bookingId'];
$hotelId = $resolvedOptions['hotelId'];
$dateEnd = $resolvedOptions['dateEnd'];
$template = $resolvedOptions['template'];
$paCode = $resolvedOptions['paCode'];
$isDayTrip = $resolvedOptions['isDayTrip'];
$query = static::buildQuery($bookingId, $hotelId, $dateEnd, $template, $isDayTrip);
$cookie = $_COOKIE[static::COOKIE_NAME];
if (strpos($cookie, '?') !== false) {
@@ -71,15 +85,29 @@ class BookingUrlUtility
}
/**
* @param string $bookingId
* @param string $hotelId
* @param string $dateEnd
* @param string $paCode
* @param array $options
* @return string
*/
public static function generateResellerUrl($bookingId, $hotelId, $dateEnd, $paCode = null)
public static function generateResellerUrl(array $options)
{
$query = static::buildQuery($bookingId, $hotelId, $dateEnd);
$resolver = new OptionsResolver();
$resolver->setRequired(['bookingId', 'hotelId', 'dateEnd']);
$resolver->setDefaults([
'template' => 'base',
'paCode' => null,
'isDayTrip' => false,
]);
$resolvedOptions = $resolver->resolve($options);
$bookingId = $resolvedOptions['bookingId'];
$hotelId = $resolvedOptions['hotelId'];
$dateEnd = $resolvedOptions['dateEnd'];
$template = $resolvedOptions['template'];
$paCode = $resolvedOptions['paCode'];
$isDayTrip = $resolvedOptions['isDayTrip'];
$query = static::buildQuery($bookingId, $hotelId, $dateEnd, $template, $isDayTrip);
if ($paCode !== null) {
$query['agenturcode'] = $paCode;
@@ -93,16 +121,17 @@ class BookingUrlUtility
* @param string $hotelId
* @param string $dateEnd
* @param string $template
* @param bool $isDayTrip
* @return array
*/
protected static function buildQuery($bookingId, $hotelId, $dateEnd, $template = 'base')
protected static function buildQuery($bookingId, $hotelId, $dateEnd, $template = 'base', $isDayTrip = false)
{
$query = [
'id' => $bookingId,
'hotelid' => $hotelId,
];
if ($dateEnd) {
if ($dateEnd && !$isDayTrip) {
$query['ruecktermin'] = date('d.m.Y', strtotime($dateEnd));
}
@@ -30,7 +30,7 @@ return [
concept_description, board_description, additional_services, programme_description, ski_pass_description,
rating_average, rating_votes_count, teaser_images, header_images, images, concept, country, region, city,
journey, facts, officetip, hotels, calendar_hotel, faqs,header_title,header_subtitle, alt_product, alt_label,
video, banner, additional_regions,badge',
video, banner, additional_regions, badge, daytrip',
],
'types' => [
'1' => [
@@ -69,7 +69,7 @@ return [
],
'palettes' => [
'destinations' => ['showitem' => 'country,region,city'],
'top' => ['showitem' => 'searchable, bookable, detail_page'],
'top' => ['showitem' => 'searchable, bookable, daytrip, detail_page'],
'name' => ['showitem' => 'name,code'],
'alternative' => ['showitem' => 'alt_product, alt_label'],
'header' => ['showitem' => 'headline,subline,--linebreak--,header_title,header_subtitle'],
@@ -175,6 +175,13 @@ return [
'type' => 'check',
],
],
'daytrip' => [
'exclude' => 0,
'label' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_product.daytrip',
'config' => [
'type' => 'check',
],
],
'detail_page' => [
'exclude' => 0,
'label' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_product.detail_page',
@@ -18,6 +18,9 @@
<trans-unit id="tx_epproducts_domain_model_product.bookable">
<source>Online buchbar</source>
</trans-unit>
<trans-unit id="tx_epproducts_domain_model_product.daytrip">
<source>Tagesreise</source>
</trans-unit>
<trans-unit id="tx_epproducts_domain_model_product.name">
<source>Name</source>
</trans-unit>
@@ -9,6 +9,7 @@ CREATE TABLE tx_epproducts_domain_model_product (
searchable tinyint(4) unsigned DEFAULT '1' NOT NULL,
bookable tinyint(4) unsigned DEFAULT '1' NOT NULL,
daytrip tinyint(4) unsigned DEFAULT '0' NOT NULL,
name varchar(255) DEFAULT '' NOT NULL,
name_internal varchar(255) DEFAULT '' NOT NULL,
subline varchar(255) DEFAULT '' NOT NULL,
@@ -67,6 +67,11 @@ class BookingViewHelper extends AbstractViewHelper
if ($template === null) {
$template = $this->settings['bpnBookingUrlTemplateCode'];
}
return BookingUrlUtility::generateUrl($bookingId, $hotelId, $template);
$options = [
'bookingId' => $bookingId,
'hotelId' => $hotelId,
'template' => $template,
];
return BookingUrlUtility::generateUrl($options);
}
}