feat: derive room type from occupancy instead of a mapping table
This commit is contained in:
@@ -30,12 +30,17 @@ namespace EP\EpProducts\Domain\Model;
|
|||||||
class Room
|
class Room
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const ROOM_TYPE_UNCLASSIFIED = 0;
|
||||||
const ROOM_TYPE_FOR_ONE = 1;
|
const ROOM_TYPE_FOR_ONE = 1;
|
||||||
const ROOM_TYPE_FOR_TWO = 2;
|
const ROOM_TYPE_FOR_TWO = 2;
|
||||||
const ROOM_TYPE_FOR_THREE = 3;
|
const ROOM_TYPE_FOR_THREE = 3;
|
||||||
const ROOM_TYPE_FOR_FOUR = 4;
|
const ROOM_TYPE_FOR_FOUR = 4;
|
||||||
const ROOM_TYPE_WITH_OTHERS = 5;
|
const ROOM_TYPE_FOR_FIVE = 5;
|
||||||
const ROOM_TYPE_OTHER = 6;
|
const ROOM_TYPE_FOR_SIX = 6;
|
||||||
|
const ROOM_TYPE_FOR_SEVEN = 7;
|
||||||
|
const ROOM_TYPE_FOR_EIGHT = 8;
|
||||||
|
const ROOM_TYPE_FOR_NINE_PLUS = 9;
|
||||||
|
const ROOM_TYPE_WITH_OTHERS = 10;
|
||||||
|
|
||||||
const ROOM_STATUS_AVAILABLE = 1;
|
const ROOM_STATUS_AVAILABLE = 1;
|
||||||
const ROOM_STATUS_ON_REQUEST = 2;
|
const ROOM_STATUS_ON_REQUEST = 2;
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace EP\EpProducts\Domain\Model;
|
|
||||||
|
|
||||||
/***************************************************************
|
|
||||||
*
|
|
||||||
* Copyright notice
|
|
||||||
*
|
|
||||||
* (c) 2016 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!
|
|
||||||
***************************************************************/
|
|
||||||
|
|
||||||
class RoomMapping extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $code = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
protected $type = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getCode()
|
|
||||||
{
|
|
||||||
return $this->code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $code
|
|
||||||
*/
|
|
||||||
public function setCode($code)
|
|
||||||
{
|
|
||||||
$this->code = $code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getType()
|
|
||||||
{
|
|
||||||
return $this->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $type
|
|
||||||
*/
|
|
||||||
public function setType($type)
|
|
||||||
{
|
|
||||||
$this->type = $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -76,9 +76,11 @@ class ProductRepository extends AbstractRepository
|
|||||||
'date.services_included as servicesIncluded', 'date.skipass_included as skiPassIncluded',
|
'date.services_included as servicesIncluded', 'date.skipass_included as skiPassIncluded',
|
||||||
'date.bus_available as busAvailable', 'date.new as new',
|
'date.bus_available as busAvailable', 'date.new as new',
|
||||||
'date.min_price as minPrice', 'date.nights as nights', 'date.available as available',
|
'date.min_price as minPrice', 'date.nights as nights', 'date.available as available',
|
||||||
'date.pseudo_price as pseudoPrice', 'date.hide_booking_button as hideBookingButton',
|
'date.pseudo_price as pseudoPrice', 'date.hide_booking_button as hideBookingButton'
|
||||||
'room.type as roomType'
|
|
||||||
)
|
)
|
||||||
|
// The GROUP BY below collapses many room rows per group; an arbitrary
|
||||||
|
// room.type would hide most types from the filter facet.
|
||||||
|
->addSelectLiteral('GROUP_CONCAT(DISTINCT room.type) as roomTypes')
|
||||||
->from('tx_epproducts_domain_model_date', 'date')
|
->from('tx_epproducts_domain_model_date', 'date')
|
||||||
->leftJoin('date', 'tx_epproducts_domain_model_concept', 'con', 'date.concept = con.uid')
|
->leftJoin('date', 'tx_epproducts_domain_model_concept', 'con', 'date.concept = con.uid')
|
||||||
->leftJoin('date', 'tx_epproducts_domain_model_room', 'room', 'room.date = date.uid')
|
->leftJoin('date', 'tx_epproducts_domain_model_room', 'room', 'room.date = date.uid')
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace EP\EpProducts\Domain\Repository;
|
|
||||||
|
|
||||||
/***************************************************************
|
|
||||||
*
|
|
||||||
* Copyright notice
|
|
||||||
*
|
|
||||||
* (c) 2016 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!
|
|
||||||
***************************************************************/
|
|
||||||
|
|
||||||
class RoomMappingRepository extends AbstractRepository
|
|
||||||
{}
|
|
||||||
@@ -60,11 +60,6 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface
|
|||||||
*/
|
*/
|
||||||
protected $pid = 0;
|
protected $pid = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $roomMappings = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
@@ -90,6 +85,11 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface
|
|||||||
*/
|
*/
|
||||||
protected $importSourceFactory;
|
protected $importSourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var RoomTypeResolver
|
||||||
|
*/
|
||||||
|
protected $roomTypeResolver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
@@ -101,15 +101,18 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface
|
|||||||
* @param ConfigurationManagerInterface $configurationManager
|
* @param ConfigurationManagerInterface $configurationManager
|
||||||
* @param CacheService $cacheService
|
* @param CacheService $cacheService
|
||||||
* @param ProductImportSourceFactory $importSourceFactory
|
* @param ProductImportSourceFactory $importSourceFactory
|
||||||
|
* @param RoomTypeResolver $roomTypeResolver
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ConfigurationManagerInterface $configurationManager,
|
ConfigurationManagerInterface $configurationManager,
|
||||||
CacheService $cacheService,
|
CacheService $cacheService,
|
||||||
ProductImportSourceFactory $importSourceFactory
|
ProductImportSourceFactory $importSourceFactory,
|
||||||
|
RoomTypeResolver $roomTypeResolver
|
||||||
) {
|
) {
|
||||||
$this->configurationManager = $configurationManager;
|
$this->configurationManager = $configurationManager;
|
||||||
$this->cacheService = $cacheService;
|
$this->cacheService = $cacheService;
|
||||||
$this->importSourceFactory = $importSourceFactory;
|
$this->importSourceFactory = $importSourceFactory;
|
||||||
|
$this->roomTypeResolver = $roomTypeResolver;
|
||||||
|
|
||||||
$settings = GeneralUtility::removeDotsFromTS(
|
$settings = GeneralUtility::removeDotsFromTS(
|
||||||
$this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT)
|
$this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT)
|
||||||
@@ -130,7 +133,6 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface
|
|||||||
public function import($path): int
|
public function import($path): int
|
||||||
{
|
{
|
||||||
$this->db = $this->getDbConnection();
|
$this->db = $this->getDbConnection();
|
||||||
$this->getRoomMappings();
|
|
||||||
$this->getHotelMappings();
|
$this->getHotelMappings();
|
||||||
$this->importPickups($path);
|
$this->importPickups($path);
|
||||||
$this->createTempTables();
|
$this->createTempTables();
|
||||||
@@ -594,13 +596,9 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$roomTypeKey = mb_strtolower($code);
|
$label = (string) $roomXml->attributes()['zimmertext'];
|
||||||
if (array_key_exists($roomTypeKey, $this->roomMappings)) {
|
$roomMinPax = (int) $roomXml->attributes()['MinPax'];
|
||||||
$roomType = $this->roomMappings[$roomTypeKey];
|
$pax = (int) $roomXml->attributes()['MaxPax'];
|
||||||
} else {
|
|
||||||
$this->logger->warning('room type not found', ['code' => $code]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$available = (int) $roomXml->attributes()['verfuegbar'];
|
$available = (int) $roomXml->attributes()['verfuegbar'];
|
||||||
$price = (int) $roomXml->attributes()['preis'];
|
$price = (int) $roomXml->attributes()['preis'];
|
||||||
@@ -610,12 +608,23 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$pax = (int) $roomXml->attributes()['MinPax'];
|
$roomType = $this->roomTypeResolver->resolve($code, $label, $pax, $roomMinPax);
|
||||||
if (0 === $minPax || $pax < $minPax) {
|
|
||||||
$minPax = $pax;
|
if ($pax < 1 && $roomMinPax < 1) {
|
||||||
|
$this->logger->warning('room without occupancy', ['code' => $code, 'zimmertext' => $label]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->roomTypeResolver->needsReview($code, $label, $pax)) {
|
||||||
|
$this->logger->warning(
|
||||||
|
'single-occupancy room without single-use marker',
|
||||||
|
['code' => $code, 'zimmertext' => $label]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 === $minPax || $roomMinPax < $minPax) {
|
||||||
|
$minPax = $roomMinPax;
|
||||||
}
|
}
|
||||||
|
|
||||||
$pax = (int) $roomXml->attributes()['MaxPax'];
|
|
||||||
$availableTotal += $available * $pax;
|
$availableTotal += $available * $pax;
|
||||||
|
|
||||||
// Determine lowest price of available rooms
|
// Determine lowest price of available rooms
|
||||||
@@ -648,7 +657,7 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface
|
|||||||
'bus_pro_id' => (int) $roomXml->attributes()['idbuspro_zimmer'],
|
'bus_pro_id' => (int) $roomXml->attributes()['idbuspro_zimmer'],
|
||||||
'code' => $code,
|
'code' => $code,
|
||||||
'type' => $roomType,
|
'type' => $roomType,
|
||||||
'name' => (string) $roomXml->attributes()['zimmertext'],
|
'name' => $label,
|
||||||
'pax' => $pax,
|
'pax' => $pax,
|
||||||
'nights' => (int) $roomXml->attributes()['naechte'],
|
'nights' => (int) $roomXml->attributes()['naechte'],
|
||||||
'price' => $price,
|
'price' => $price,
|
||||||
@@ -791,16 +800,6 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getRoomMappings(): void
|
|
||||||
{
|
|
||||||
$sql = 'SELECT code, type FROM tx_epproducts_domain_model_roommapping WHERE deleted = 0 AND hidden = 0';
|
|
||||||
$roomMappings = $this->db->fetchAllAssociative($sql);
|
|
||||||
foreach ($roomMappings as $mapping) {
|
|
||||||
$key = trim(mb_strtolower($mapping['code']));
|
|
||||||
$this->roomMappings[$key] = $mapping['type'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getHotelMappings(): void
|
protected function getHotelMappings(): void
|
||||||
{
|
{
|
||||||
$sql = '
|
$sql = '
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace EP\EpProducts\Service;
|
namespace EP\EpProducts\Service;
|
||||||
|
|
||||||
use EP\EpProducts\Domain\Model\Dto\FilterOptions;
|
use EP\EpProducts\Domain\Model\Dto\FilterOptions;
|
||||||
|
use EP\EpProducts\Domain\Model\Room;
|
||||||
use EP\EpProducts\Domain\Model\SearchResult;
|
use EP\EpProducts\Domain\Model\SearchResult;
|
||||||
use Symfony\Component\OptionsResolver\Options;
|
use Symfony\Component\OptionsResolver\Options;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
@@ -212,6 +213,12 @@ class FilterService implements SingletonInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($item['rooms'] as $roomType) {
|
foreach ($item['rooms'] as $roomType) {
|
||||||
|
// Type 0 is not a room (Baby) and must never become a filter option:
|
||||||
|
// it has no label, so it would render as an empty checkbox and leave
|
||||||
|
// a hole in the option list.
|
||||||
|
if ((int) $roomType === Room::ROOM_TYPE_UNCLASSIFIED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!\in_array($roomType, $roomTypes, false)) {
|
if (!\in_array($roomType, $roomTypes, false)) {
|
||||||
$roomTypes[] = $roomType;
|
$roomTypes[] = $roomType;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace EP\EpProducts\Service;
|
||||||
|
|
||||||
|
/***************************************************************
|
||||||
|
*
|
||||||
|
* Copyright notice
|
||||||
|
*
|
||||||
|
* (c) 2016 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\Domain\Model\Room;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derives the room type from the data each <preis> element carries.
|
||||||
|
*
|
||||||
|
* Replaces the former tx_epproducts_domain_model_roommapping lookup: zimmercode is
|
||||||
|
* neither unique per room nor a function of room type, so a code-keyed table cannot
|
||||||
|
* classify this data. MaxPax is the advertised occupancy and is present on every row.
|
||||||
|
*/
|
||||||
|
class RoomTypeResolver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Phrases in zimmertext that mark a bed shared with other customers.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
const LABEL_PATTERNS_WITH_OTHERS = [
|
||||||
|
'bett im',
|
||||||
|
'mit ander',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Phrases in zimmertext that mark a deliberate single use of a larger room.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
const LABEL_PATTERNS_SINGLE_USE = [
|
||||||
|
'einzel',
|
||||||
|
'1 person',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $code zimmercode
|
||||||
|
* @param string $label zimmertext
|
||||||
|
* @param int $maxPax MaxPax
|
||||||
|
* @param int $minPax MinPax
|
||||||
|
* @return int one of the Room::ROOM_TYPE_* constants
|
||||||
|
*/
|
||||||
|
public function resolve(string $code, string $label, int $maxPax, int $minPax): int
|
||||||
|
{
|
||||||
|
// Not a room: "Babypreis für 0-2 Jährige". Kept in the date record for its
|
||||||
|
// price and availability, but hidden from the filter.
|
||||||
|
if ($code === DateImportService::CODE_BABYROOM) {
|
||||||
|
return Room::ROOM_TYPE_UNCLASSIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->matchesAny($label, static::LABEL_PATTERNS_WITH_OTHERS)) {
|
||||||
|
return Room::ROOM_TYPE_WITH_OTHERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pax = $maxPax > 0 ? $maxPax : $minPax;
|
||||||
|
|
||||||
|
if ($pax >= 1) {
|
||||||
|
// Type numbering is chosen so that type === pax for pax 1-8.
|
||||||
|
return $pax >= 9 ? Room::ROOM_TYPE_FOR_NINE_PLUS : $pax;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No usable occupancy - should never happen on current data, the caller logs it.
|
||||||
|
return Room::ROOM_TYPE_WITH_OTHERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tripwire for an under-matching label pattern: a row classified as a single room
|
||||||
|
* whose label carries no single-use marker is most likely a shared bed phrased in
|
||||||
|
* a way LABEL_PATTERNS_WITH_OTHERS does not yet cover.
|
||||||
|
*
|
||||||
|
* @param string $code zimmercode
|
||||||
|
* @param string $label zimmertext
|
||||||
|
* @param int $maxPax MaxPax
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function needsReview(string $code, string $label, int $maxPax): bool
|
||||||
|
{
|
||||||
|
if ($this->resolve($code, $label, $maxPax, $maxPax) !== Room::ROOM_TYPE_FOR_ONE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($maxPax !== 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !$this->matchesAny($label, static::LABEL_PATTERNS_SINGLE_USE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $label
|
||||||
|
* @param array $patterns
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function matchesAny(string $label, array $patterns): bool
|
||||||
|
{
|
||||||
|
foreach ($patterns as $pattern) {
|
||||||
|
if (mb_strpos(mb_strtolower($label), mb_strtolower($pattern)) !== false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ use EP\EpProducts\Domain\Model\SearchResult;
|
|||||||
use EP\EpProducts\Domain\Repository\ProductRepository;
|
use EP\EpProducts\Domain\Repository\ProductRepository;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use TYPO3\CMS\Core\SingletonInterface;
|
use TYPO3\CMS\Core\SingletonInterface;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
|
||||||
class SearchResultService implements SingletonInterface
|
class SearchResultService implements SingletonInterface
|
||||||
{
|
{
|
||||||
@@ -216,8 +217,10 @@ class SearchResultService implements SingletonInterface
|
|||||||
$item['filterMetadata']['boardTypes'][] = $boardType;
|
$item['filterMetadata']['boardTypes'][] = $boardType;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($row['roomType']) && !\in_array($row['roomType'], $item['rooms'], false)) {
|
foreach (GeneralUtility::trimExplode(',', (string) ($row['roomTypes'] ?? ''), true) as $roomType) {
|
||||||
$item['rooms'][] = $row['roomType'];
|
if (!\in_array($roomType, $item['rooms'], false)) {
|
||||||
|
$item['rooms'][] = $roomType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!\in_array($row['nights'], $item['nights'], false)) {
|
if (!\in_array($row['nights'], $item['nights'], false)) {
|
||||||
|
|||||||
-144
@@ -1,144 +0,0 @@
|
|||||||
<?php
|
|
||||||
return [
|
|
||||||
'ctrl' => [
|
|
||||||
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_roommapping',
|
|
||||||
'label' => 'code',
|
|
||||||
'prependAtCopy' => '[COPY %s]',
|
|
||||||
'default_sortby' => 'ORDER BY code',
|
|
||||||
'tstamp' => 'tstamp',
|
|
||||||
'crdate' => 'crdate',
|
|
||||||
'cruser_id' => 'cruser_id',
|
|
||||||
'dividers2tabs' => true,
|
|
||||||
'versioningWS' => false,
|
|
||||||
'languageField' => 'sys_language_uid',
|
|
||||||
'transOrigPointerField' => 'l10n_parent',
|
|
||||||
'transOrigDiffSourceField' => 'l10n_diffsource',
|
|
||||||
'delete' => 'deleted',
|
|
||||||
'enablecolumns' => [
|
|
||||||
'disabled' => 'hidden',
|
|
||||||
'starttime' => 'starttime',
|
|
||||||
'endtime' => 'endtime',
|
|
||||||
],
|
|
||||||
'searchFields' => 'code',
|
|
||||||
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
|
|
||||||
],
|
|
||||||
'types' => [
|
|
||||||
'1' => ['showitem' => 'code, type'],
|
|
||||||
],
|
|
||||||
'palettes' => [
|
|
||||||
'1' => ['showitem' => ''],
|
|
||||||
],
|
|
||||||
'columns' => [
|
|
||||||
|
|
||||||
'sys_language_uid' => [
|
|
||||||
'exclude' => 0,
|
|
||||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
|
|
||||||
'config' => [
|
|
||||||
'type' => 'select',
|
|
||||||
'default' => 0,
|
|
||||||
'renderType' => 'selectSingle',
|
|
||||||
'foreign_table' => 'sys_language',
|
|
||||||
'foreign_table_where' => 'ORDER BY sys_language.title',
|
|
||||||
'items' => [
|
|
||||||
['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', -1],
|
|
||||||
['LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.default_value', 0]
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'l10n_parent' => [
|
|
||||||
'displayCond' => 'FIELD:sys_language_uid:>:0',
|
|
||||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
|
|
||||||
'config' => [
|
|
||||||
'type' => 'select',
|
|
||||||
'default' => 0,
|
|
||||||
'renderType' => 'selectSingle',
|
|
||||||
'items' => [
|
|
||||||
['', 0],
|
|
||||||
],
|
|
||||||
'foreign_table' => 'tx_epproducts_domain_model_roommapping',
|
|
||||||
'foreign_table_where' => 'AND tx_epproducts_domain_model_roommapping.pid=###CURRENT_PID### AND tx_epproducts_domain_model_roommapping.sys_language_uid IN (-1,0)',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'l10n_diffsource' => [
|
|
||||||
'config' => [
|
|
||||||
'type' => 'passthrough',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
|
|
||||||
't3ver_label' => [
|
|
||||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.versionLabel',
|
|
||||||
'config' => [
|
|
||||||
'type' => 'input',
|
|
||||||
'size' => 30,
|
|
||||||
'max' => 255,
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
'hidden' => [
|
|
||||||
'exclude' => 0,
|
|
||||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.hidden',
|
|
||||||
'config' => [
|
|
||||||
'type' => 'check',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'starttime' => [
|
|
||||||
'exclude' => 0,
|
|
||||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
|
|
||||||
'config' => [
|
|
||||||
'type' => 'input',
|
|
||||||
'size' => 13,
|
|
||||||
'eval' => 'datetime',
|
|
||||||
'checkbox' => 0,
|
|
||||||
'default' => 0,
|
|
||||||
'behaviour' => [
|
|
||||||
'allowLanguageSynchronization' => true,
|
|
||||||
],
|
|
||||||
'renderType' => 'inputDateTime',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'endtime' => [
|
|
||||||
'exclude' => 0,
|
|
||||||
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
|
|
||||||
'config' => [
|
|
||||||
'type' => 'input',
|
|
||||||
'size' => 13,
|
|
||||||
'eval' => 'datetime',
|
|
||||||
'checkbox' => 0,
|
|
||||||
'default' => 0,
|
|
||||||
'behaviour' => [
|
|
||||||
'allowLanguageSynchronization' => true,
|
|
||||||
],
|
|
||||||
'renderType' => 'inputDateTime',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
|
|
||||||
'code' => [
|
|
||||||
'exclude' => 0,
|
|
||||||
'label' => 'Code',
|
|
||||||
'config' => [
|
|
||||||
'type' => 'input',
|
|
||||||
'size' => 30,
|
|
||||||
'eval' => 'trim'
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'type' => [
|
|
||||||
'exclude' => 0,
|
|
||||||
'label' => 'Typ',
|
|
||||||
'config' => [
|
|
||||||
'type' => 'select',
|
|
||||||
'renderType' => 'selectSingle',
|
|
||||||
'items' => [
|
|
||||||
['Einzelzimmer', \EP\EpProducts\Domain\Model\Room::ROOM_TYPE_FOR_ONE],
|
|
||||||
['Doppelzimmer und Apartm. f. 2 Pers.', \EP\EpProducts\Domain\Model\Room::ROOM_TYPE_FOR_TWO],
|
|
||||||
['Zimmer und Apartm. f. 3 Pers.', \EP\EpProducts\Domain\Model\Room::ROOM_TYPE_FOR_THREE],
|
|
||||||
['Zimmer und Apartm. f. 4 Pers.', \EP\EpProducts\Domain\Model\Room::ROOM_TYPE_FOR_FOUR],
|
|
||||||
['Zimmer und Apartm. mit Anderen', \EP\EpProducts\Domain\Model\Room::ROOM_TYPE_WITH_OTHERS],
|
|
||||||
['weitere Zimmer und Apartments', \EP\EpProducts\Domain\Model\Room::ROOM_TYPE_OTHER],
|
|
||||||
],
|
|
||||||
'size' => 1,
|
|
||||||
'minItems' => 1,
|
|
||||||
'maxItems' => 1
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
@@ -39,9 +39,6 @@
|
|||||||
<trans-unit id="tx_epproducts_domain_model_teammember">
|
<trans-unit id="tx_epproducts_domain_model_teammember">
|
||||||
<source>Mitarbeiter/Teamer</source>
|
<source>Mitarbeiter/Teamer</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="tx_epproducts_domain_model_roommapping">
|
|
||||||
<source>Zimmermapping</source>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="tx_epproducts_domain_model_journey">
|
<trans-unit id="tx_epproducts_domain_model_journey">
|
||||||
<source>Anreise</source>
|
<source>Anreise</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
|||||||
@@ -494,47 +494,6 @@ CREATE TABLE tx_epproducts_domain_model_room
|
|||||||
KEY constraints (date, type)
|
KEY constraints (date, type)
|
||||||
);
|
);
|
||||||
|
|
||||||
#
|
|
||||||
# Table structure for table 'tx_epproducts_domain_model_roommapping'
|
|
||||||
#
|
|
||||||
CREATE TABLE tx_epproducts_domain_model_roommapping
|
|
||||||
(
|
|
||||||
|
|
||||||
uid int(11) NOT NULL auto_increment,
|
|
||||||
pid int(11) DEFAULT '0' NOT NULL,
|
|
||||||
|
|
||||||
code varchar(255) DEFAULT '' NOT NULL,
|
|
||||||
type int(11) DEFAULT '0' NOT NULL,
|
|
||||||
|
|
||||||
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
|
|
||||||
crdate int(11) unsigned DEFAULT '0' NOT NULL,
|
|
||||||
cruser_id int(11) unsigned DEFAULT '0' NOT NULL,
|
|
||||||
deleted tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
|
||||||
hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
|
|
||||||
starttime int(11) unsigned DEFAULT '0' NOT NULL,
|
|
||||||
endtime int(11) unsigned DEFAULT '0' NOT NULL,
|
|
||||||
|
|
||||||
t3ver_oid int(11) DEFAULT '0' NOT NULL,
|
|
||||||
t3ver_id int(11) DEFAULT '0' NOT NULL,
|
|
||||||
t3ver_wsid int(11) DEFAULT '0' NOT NULL,
|
|
||||||
t3ver_label varchar(255) DEFAULT '' NOT NULL,
|
|
||||||
t3ver_state tinyint(4) DEFAULT '0' NOT NULL,
|
|
||||||
t3ver_stage int(11) DEFAULT '0' NOT NULL,
|
|
||||||
t3ver_count int(11) DEFAULT '0' NOT NULL,
|
|
||||||
t3ver_tstamp int(11) DEFAULT '0' NOT NULL,
|
|
||||||
t3ver_move_id int(11) DEFAULT '0' NOT NULL,
|
|
||||||
|
|
||||||
sys_language_uid int(11) DEFAULT '0' NOT NULL,
|
|
||||||
l10n_parent int(11) DEFAULT '0' NOT NULL,
|
|
||||||
l10n_diffsource mediumblob,
|
|
||||||
|
|
||||||
PRIMARY KEY (uid),
|
|
||||||
KEY parent (pid),
|
|
||||||
KEY t3ver_oid (t3ver_oid, t3ver_wsid),
|
|
||||||
KEY language (l10n_parent, sys_language_uid)
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Table structure for table 'tx_epproducts_domain_model_concept'
|
# Table structure for table 'tx_epproducts_domain_model_concept'
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -274,8 +274,12 @@
|
|||||||
2: 'DZ / 2er',
|
2: 'DZ / 2er',
|
||||||
3: '3er',
|
3: '3er',
|
||||||
4: '4er',
|
4: '4er',
|
||||||
5: 'ab 5 Pers.',
|
5: '5er',
|
||||||
6: 'mit anderen'
|
6: '6er',
|
||||||
|
7: '7er',
|
||||||
|
8: '8er',
|
||||||
|
9: '9er und mehr',
|
||||||
|
10: 'mit anderen'
|
||||||
}"/>
|
}"/>
|
||||||
<div class="py-2"
|
<div class="py-2"
|
||||||
data-controller="collapse"
|
data-controller="collapse"
|
||||||
@@ -291,6 +295,7 @@
|
|||||||
<div data-collapse-target="container">
|
<div data-collapse-target="container">
|
||||||
<ul class="mb-0 p-0 pt-4 space-y-2">
|
<ul class="mb-0 p-0 pt-4 space-y-2">
|
||||||
<f:for each="{filterOptions.roomTypes}" as="type">
|
<f:for each="{filterOptions.roomTypes}" as="type">
|
||||||
|
<f:if condition="{roomTypes.{type}}">
|
||||||
<li>
|
<li>
|
||||||
<label class="flex items-start">
|
<label class="flex items-start">
|
||||||
<f:form.checkbox class="w-5 h-5 border-ep-primary-light ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
<f:form.checkbox class="w-5 h-5 border-ep-primary-light ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
|
||||||
@@ -302,6 +307,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
|
</f:if>
|
||||||
</f:for>
|
</f:for>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user