diff --git a/packages/ep_products/Classes/Controller/TravelinfoController.php b/packages/ep_products/Classes/Controller/TravelinfoController.php new file mode 100644 index 0000000..8e2e44b --- /dev/null +++ b/packages/ep_products/Classes/Controller/TravelinfoController.php @@ -0,0 +1,108 @@ +apiClient = $apiClient; + $this->travelinfoRepository = $travelinfoRepository; + } + + public function travelCodeAction(string $travelCode): ResponseInterface + { + // find specific travel info by code including travel date first + $travelInfo = $this->travelinfoRepository->findOneBy(['travelCode' => $travelCode]); + + // find general travel info by code without travel date as fallback + if (null === $travelInfo) { + $travelCodeBase = substr($travelCode, 0, -6); + $travelInfo = $this->travelinfoRepository->findOneBy(['travelCode' => $travelCodeBase]); + } + + // return 404 in case no travel info is available as last resort + if (null === $travelInfo) { + $response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction( + $this->request, + 'Reiseinformationen nicht gefunden' + ); + throw new ImmediateResponseException($response, 1731071856); + } + + $this->handleRequest($travelCode, $travelInfo); + return $this->htmlResponse(); + } + + public function travelInfoAction(Travelinfo $travelInfo): ResponseInterface + { + $travelCode = $travelInfo->getTravelCode(); + + $this->handleRequest($travelCode, $travelInfo); + return $this->htmlResponse(); + } + + private function handleRequest(string $travelCode, Travelinfo $travelInfo) + { + + // fetch travel data via API call + try { + $travelData = $this->apiClient->getTravel($travelCode); + } catch (ApiException $e) { + $travelData = []; + } + + try { + $pickupsPlanning = $this->apiClient->getPickupsPlanning($travelCode); + } catch (ApiException $e) { + $pickupsPlanning = []; + } + + // extract courses from additional services + $courses = array_filter($travelData['additionalServices'] ?? [], function ($service) { + return 'KUR' === $service['subType']; + }); + + // extract board services from included services + $includedServicesBoard = $travelData['selectionGroups'][self::SELECTION_ID_BOARD] ?? []; + $board = $includedServicesBoard['selections'] ?? []; + + // extract bus departure time if applicable + $departureDayTime = null; + $service = array_filter($travelData['transportationServices'] ?? [], function ($service) { + return 'BUS' === $service['subType'] && 'RUECK' === $service['direction']; + }); + if ($serviceDetail = reset($service)) { + $departureDayTime = $serviceDetail['dayTime']; + } + + $this->view->assign('travelInfo', $travelInfo); + $this->view->assign('travelData', $travelData); + $this->view->assign('pickupsPlanning', $pickupsPlanning); + $this->view->assign('courses', $courses); + $this->view->assign('board', $board); + $this->view->assign('departureDayTime', $departureDayTime); + } +} diff --git a/packages/ep_products/Classes/Domain/Model/Travelinfo.php b/packages/ep_products/Classes/Domain/Model/Travelinfo.php new file mode 100644 index 0000000..ad55bf2 --- /dev/null +++ b/packages/ep_products/Classes/Domain/Model/Travelinfo.php @@ -0,0 +1,329 @@ + + */ + protected $teasers; + + /** + * @var ObjectStorage + */ + protected $links; + + /** + * @var string + */ + protected $travelCode; + + /** + * @var Product + */ + protected $product; + + /** + * @var bool + */ + protected $hideAddress = false; + + public function __construct() + { + $this->initStorageObjects(); + } + + protected function initStorageObjects() + { + $this->teasers = new ObjectStorage(); + $this->links = new ObjectStorage(); + } + + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param string $title + */ + public function setTitle($title) + { + $this->title = $title; + } + + public function getHeaderImage() + { + return $this->headerImage; + } + + public function setHeaderImage($headerImage) + { + $this->headerImage = $headerImage; + + return $this; + } + + public function getFooterImage() + { + return $this->footerImage; + } + + public function setFooterImage($footerImage) + { + $this->footerImage = $footerImage; + + return $this; + } + + public function getSubline() + { + return $this->subline; + } + + public function setSubline($subline) + { + $this->subline = $subline; + + return $this; + } + + public function getHeadline() + { + return $this->headline; + } + + public function setHeadline($headline) + { + $this->headline = $headline; + + return $this; + } + + public function getIntroText() + { + return $this->introText; + } + + public function setIntroText($introText) + { + $this->introText = $introText; + + return $this; + } + + public function getBusInfoText() + { + return $this->busInfoText; + } + + public function setBusInfoText($busInfoText) + { + $this->busInfoText = $busInfoText; + + return $this; + } + + public function getDepartureText() + { + return $this->departureText; + } + + public function setDepartureText($departureText) + { + $this->departureText = $departureText; + + return $this; + } + + public function getFooterText() + { + return $this->footerText; + } + + public function setFooterText($footerText) + { + $this->footerText = $footerText; + + return $this; + } + + public function getAdditionalInfo() + { + return $this->additionalInfo; + } + + public function setAdditionalInfo($additionalInfo) + { + $this->additionalInfo = $additionalInfo; + + return $this; + } + + public function getImportantPhoneNumbers() + { + return $this->importantPhoneNumbers; + } + + public function setImportantPhoneNumbers($importantPhoneNumbers) + { + $this->importantPhoneNumbers = $importantPhoneNumbers; + + return $this; + } + + public function getImportantLinks() + { + return $this->importantLinks; + } + + public function setImportantLinks($importantLinks) + { + $this->importantLinks = $importantLinks; + + return $this; + } + + public function getSelfArrangedText() + { + return $this->selfArrangedText; + } + + public function setSelfArrangedText($selfArrangedText) + { + $this->selfArrangedText = $selfArrangedText; + + return $this; + } + + public function getTeasers() + { + return $this->teasers; + } + + public function setTeasers($teasers) + { + $this->teasers = $teasers; + } + + public function getLinks() + { + return $this->links; + } + + public function setLinks($links) + { + $this->links = $links; + + return $this; + } + + public function getTravelCode() + { + return $this->travelCode; + } + + public function setTravelCode($travelCode) + { + $this->travelCode = $travelCode; + + return $this; + } + + public function getProduct() + { + return $this->product; + } + + public function setProduct($product) + { + $this->product = $product; + return $this; + } + + public function isHideAddress() + { + return $this->hideAddress; + } + + public function setHideAddress($hideAddress) + { + $this->hideAddress = $hideAddress; + return $this; + } +} + diff --git a/packages/ep_products/Classes/Domain/Model/TravelinfoLink.php b/packages/ep_products/Classes/Domain/Model/TravelinfoLink.php new file mode 100644 index 0000000..fc395f0 --- /dev/null +++ b/packages/ep_products/Classes/Domain/Model/TravelinfoLink.php @@ -0,0 +1,60 @@ +title; + } + + /** + * @param string $title + */ + public function setTitle($title) + { + $this->title = $title; + } + + public function getLink() + { + return $this->link; + } + + public function setLink($link) + { + $this->link = $link; + } + + public function getIcon() + { + return $this->icon; + } + + public function setIcon($icon) + { + $this->icon = $icon; + } +} + diff --git a/packages/ep_products/Classes/Domain/Model/TravelinfoTeaser.php b/packages/ep_products/Classes/Domain/Model/TravelinfoTeaser.php new file mode 100644 index 0000000..ae15345 --- /dev/null +++ b/packages/ep_products/Classes/Domain/Model/TravelinfoTeaser.php @@ -0,0 +1,76 @@ +title; + } + + /** + * @param string $title + */ + public function setTitle($title) + { + $this->title = $title; + } + + public function getBodytext() + { + return $this->bodytext; + } + + public function setBodytext($bodytext) + { + $this->bodytext = $bodytext; + } + + public function getCategory() + { + return $this->category; + } + + public function setCategory($category) + { + $this->category = $category; + } + + public function getImage() + { + return $this->image; + } + + public function setImage($image) + { + $this->image = $image; + } +} + diff --git a/packages/ep_products/Classes/Domain/Repository/TravelinfoRepository.php b/packages/ep_products/Classes/Domain/Repository/TravelinfoRepository.php new file mode 100644 index 0000000..f62f188 --- /dev/null +++ b/packages/ep_products/Classes/Domain/Repository/TravelinfoRepository.php @@ -0,0 +1,6 @@ + [ + 'title' => 'Reiseinformationen', + 'default_sortby' => 'ORDER BY title', + 'label' => 'title', + 'prependAtCopy' => '[COPY %s]', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'origUid' => 't3_origuid', + 'dividers2tabs' => true, + 'versioningWS' => true, + 'languageField' => 'sys_language_uid', + 'transOrigPointerField' => 'l10n_parent', + 'transOrigDiffSourceField' => 'l10n_diffsource', + 'delete' => 'deleted', + 'enablecolumns' => [ + 'disabled' => 'hidden', + 'starttime' => 'starttime', + 'endtime' => 'endtime', + ], + 'searchFields' => 'title,travel_code', + 'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg', + ], + 'types' => [ + '1' => [ + 'showitem' => '--palette--;;basics,--div--;Texte,--palette--;;text,--div--;Bilder,--palette--;;images', + ], + ], + 'palettes' => [ + 'basics' => ['showitem' => 'title,path_segment,--linebreak--,travel_code,hide_address,--linebreak--,links, + --linebreak--,teasers'], + 'text' => ['showitem' => 'subline,headline,--linebreak--,intro_text,--linebreak--, bus_info_text,--linebreak--, + departure_text,--linebreak--,footer_text,--linebreak--,self_arranged_text,--linebreak--,additional_info, + --linebreak--,important_phone_numbers,--linebreak--,important_links'], + 'images' => ['showitem' => 'header_image,--linebreak--,footer_image'], + ], + 'columns' => [ + 'sys_language_uid' => [ + 'exclude' => 0, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', + 'config' => ['type' => 'language'], + ], + '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' => [ + ['label' => '', 'value' => 0], + ], + 'foreign_table' => 'tx_epproducts_domain_model_travelinfo', + 'foreign_table_where' => 'AND tx_epproducts_domain_model_travelinfo.pid=###CURRENT_PID### AND tx_epproducts_domain_model_travelinfo.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' => 'datetime', + 'size' => 13, + 'checkbox' => 0, + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true, + ], + ], + ], + 'endtime' => [ + 'exclude' => 0, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime', + 'config' => [ + 'type' => 'datetime', + 'size' => 13, + 'checkbox' => 0, + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true, + ], + ], + ], + + 'title' => [ + 'exclude' => false, + 'label' => 'Titel (nur intern genutzt)', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'eval' => 'trim', + 'required' => true + ], + ], + 'subline' => [ + 'exclude' => 0, + 'label' => 'Subline', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'eval' => 'trim' + ], + ], + 'headline' => [ + 'exclude' => 0, + 'label' => 'Headline', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'eval' => 'trim' + ], + ], + 'header_image' => [ + 'exclude' => 0, + 'label' => 'Headerbild', + 'config' => [ + // TODO: Important! Verify that the fieldname value in foreign table either matches the column name + // or is set properly in the following TCA, see https://docs.typo3.org/permalink/t3tca:confval-inline-foreign-match-fields + 'type' => 'file', + 'allowed' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], + 'appearance' => [ + 'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference' + ], + 'overrideChildTca' => [ + 'types' => [ + FileType::IMAGE->value => [ + 'showitem' => ' + --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;;filePalette', + ], + ], + ], + 'maxitems' => 1, + 'minitems' => 1, + ], + ], + 'footer_image' => [ + 'exclude' => 0, + 'label' => 'Footerbild', + 'config' => [ + // TODO: Important! Verify that the fieldname value in foreign table either matches the column name + // or is set properly in the following TCA, see https://docs.typo3.org/permalink/t3tca:confval-inline-foreign-match-fields + 'type' => 'file', + 'allowed' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], + 'appearance' => [ + 'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference' + ], + 'overrideChildTca' => [ + 'types' => [ + FileType::IMAGE->value => [ + 'showitem' => ' + --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;;filePalette', + ], + ], + ], + 'maxitems' => 1, + 'minitems' => 1, + ], + ], + 'travel_code' => [ + 'exclude' => false, + 'label' => 'Reisecode', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'eval' => 'trim', + 'required' => true + ], + ], + 'hide_address' => [ + 'exclude' => 0, + 'label' => 'Adresse ausblenden', + 'config' => [ + 'type' => 'check', + ], + ], + 'intro_text' => [ + 'exclude' => false, + 'label' => 'Introtext', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 3, + 'eval' => 'trim', + 'enableRichtext' => true, + 'required' => true, + ] + ], + 'bus_info_text' => [ + 'exclude' => false, + 'label' => 'Businfo', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 3, + 'eval' => 'trim', + 'enableRichtext' => true, + ] + ], + 'departure_text' => [ + 'exclude' => false, + 'label' => 'Abreise', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 3, + 'eval' => 'trim', + 'enableRichtext' => true, + ] + ], + 'footer_text' => [ + 'exclude' => false, + 'label' => 'Footertext', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 3, + 'eval' => 'trim', + 'enableRichtext' => true, + 'required' => true, + ] + ], + 'self_arranged_text' => [ + 'exclude' => false, + 'label' => 'Eigenanreise', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 15, + 'eval' => 'trim', + 'enableRichtext' => true, + ] + ], + 'additional_info' => [ + 'exclude' => false, + 'label' => 'Weitere Infos', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 15, + 'eval' => 'trim', + 'enableRichtext' => true, + ] + ], + 'important_phone_numbers' => [ + 'exclude' => false, + 'label' => 'Wichtige Telefonnummern', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 15, + 'eval' => 'trim', + 'enableRichtext' => true, + ] + ], + 'important_links' => [ + 'exclude' => false, + 'label' => 'Wichtige Links', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 15, + 'eval' => 'trim', + 'enableRichtext' => true, + ] + ], + 'teasers' => [ + 'exclude' => false, + 'label' => 'Inhalte', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_epproducts_domain_model_travelinfoteaser', + 'foreign_sortby' => 'sorting', + 'foreign_field' => 'tx_epproducts_travelinfo', + 'minitems' => 0, + 'maxitems' => 99, + 'appearance' => [ + 'collapseAll' => true, + 'expandSingle' => true, + 'levelLinksPosition' => 'bottom', + 'useSortable' => true, + 'showPossibleLocalizationRecords' => false, + 'showAllLocalizationLink' => false, + 'showSynchronizationLink' => false, + 'enabledControls' => [ + 'info' => false, + ], + ], + 'behaviour' => [ + 'allowLanguageSynchronization' => false, + ], + ] + ], + 'links' => [ + 'exclude' => false, + 'label' => 'Links', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_epproducts_domain_model_travelinfolink', + 'foreign_sortby' => 'sorting', + 'foreign_field' => 'tx_epproducts_travelinfo', + 'minitems' => 0, + 'maxitems' => 3, + 'appearance' => [ + 'collapseAll' => true, + 'expandSingle' => true, + 'levelLinksPosition' => 'bottom', + 'useSortable' => true, + 'showPossibleLocalizationRecords' => false, + 'showAllLocalizationLink' => false, + 'showSynchronizationLink' => false, + 'enabledControls' => [ + 'info' => false, + ], + ], + 'behaviour' => [ + 'allowLanguageSynchronization' => false, + ], + ] + ], + 'path_segment' => [ + 'exclude' => 0, + 'label' => 'URL', + 'config' => [ + 'type' => 'slug', + 'generatorOptions' => [ + 'fields' => ['title'], + 'prefixParentPageSlug' => false, + 'replacements' => [ + '/' => '-', + ], + ], + 'fallbackCharacter' => '-', + 'eval' => 'unique', + ], + ], + ], +]; diff --git a/packages/ep_products/Configuration/TCA/tx_epproducts_domain_model_travelinfolink.php b/packages/ep_products/Configuration/TCA/tx_epproducts_domain_model_travelinfolink.php new file mode 100644 index 0000000..4656981 --- /dev/null +++ b/packages/ep_products/Configuration/TCA/tx_epproducts_domain_model_travelinfolink.php @@ -0,0 +1,152 @@ + [ + 'title' => 'Reiseinfo Link', + 'label' => 'title', + 'prependAtCopy' => '[COPY %s]', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'dividers2tabs' => true, + 'versioningWS' => true, + 'hideTable' => true, + 'languageField' => 'sys_language_uid', + 'transOrigPointerField' => 'l10n_parent', + 'transOrigDiffSourceField' => 'l10n_diffsource', + 'delete' => 'deleted', + 'enablecolumns' => [ + 'disabled' => 'hidden', + 'starttime' => 'starttime', + 'endtime' => 'endtime', + ], + 'searchFields' => 'title', + 'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg', + ], + 'types' => [ + '1' => [ + 'showitem' => '--palette--;;basics,link', + ], + ], + 'palettes' => [ + 'basics' => ['showitem' => 'title,icon,hidden'], + ], + 'columns' => [ + + 'sys_language_uid' => [ + 'exclude' => false, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', + 'config' => ['type' => 'language'], + ], + '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' => [ + ['label' => '', 'value' => 0], + ], + 'foreign_table' => 'tx_epproducts_domain_model_travelinfolink', + 'foreign_table_where' => 'AND tx_epproducts_domain_model_travelinfolink.pid=###CURRENT_PID### AND tx_epproducts_domain_model_travelinfolink.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' => false, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.hidden', + 'config' => [ + 'type' => 'check', + ], + ], + 'starttime' => [ + 'exclude' => false, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime', + 'config' => [ + 'type' => 'datetime', + 'size' => 13, + 'checkbox' => 0, + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true, + ], + ], + ], + 'endtime' => [ + 'exclude' => false, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime', + 'config' => [ + 'type' => 'datetime', + 'size' => 13, + 'checkbox' => 0, + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true, + ], + ], + ], + + 'title' => [ + 'exclude' => false, + 'label' => 'Bezeichnung', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'eval' => 'trim', + 'required' => true + ], + ], + 'link' => [ + 'exclude' => false, + 'label' => 'Link', + 'config' => [ + 'type' => 'link', + 'size' => 30, + 'required' => true + ], + ], + 'icon' => [ + 'exclude' => 0, + 'label' => 'Icon', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + ['label' => 'Anreise', 'value' => 'travel'], + ['label' => 'Skipass', 'value' => 'skipass'], + ['label' => 'Kurse', 'value' => 'course'], + ['label' => 'Verpflegung', 'value' => 'food'], + ['label' => 'Gepäck', 'value' => 'luggage'], + ['label' => 'Lift', 'value' => 'lift'], + ['label' => 'Webcam', 'value' => 'webcam'], + ['label' => 'Wetter', 'value' => 'weather'], + ['label' => 'Wissenswertes', 'value' => 'chat'], + ['label' => 'Währung', 'value' => 'currency'], + ], + ], + ], + 'tx_epproducts_travelinfo' => [ + 'config' => [ + 'type' => 'passthrough' + ] + ], + 'sorting' => [ + 'config' => [ + 'type' => 'passthrough' + ] + ], + ], +]; diff --git a/packages/ep_products/Configuration/TCA/tx_epproducts_domain_model_travelinfoteaser.php b/packages/ep_products/Configuration/TCA/tx_epproducts_domain_model_travelinfoteaser.php new file mode 100644 index 0000000..d846836 --- /dev/null +++ b/packages/ep_products/Configuration/TCA/tx_epproducts_domain_model_travelinfoteaser.php @@ -0,0 +1,210 @@ + [ + 'title' => 'Reiseinfo Teaser', + 'label' => 'title', + 'prependAtCopy' => '[COPY %s]', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'origUid' => 't3_origuid', + 'dividers2tabs' => true, + 'versioningWS' => true, + 'hideTable' => true, + 'languageField' => 'sys_language_uid', + 'transOrigPointerField' => 'l10n_parent', + 'transOrigDiffSourceField' => 'l10n_diffsource', + 'delete' => 'deleted', + 'enablecolumns' => [ + 'disabled' => 'hidden', + 'starttime' => 'starttime', + 'endtime' => 'endtime', + ], + 'searchFields' => 'title', + 'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg', + ], + 'types' => [ + '1' => [ + 'showitem' => '--palette--;;basics,bodytext,image', + ], + ], + 'palettes' => [ + 'basics' => ['showitem' => 'title,category,hidden'], + ], + 'columns' => [ + + 'sys_language_uid' => [ + 'exclude' => false, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', + 'config' => ['type' => 'language'], + ], + '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' => [ + ['label' => '', 'value' => 0], + ], + 'foreign_table' => 'tx_epproducts_domain_model_travelinfoteaser', + 'foreign_table_where' => 'AND tx_epproducts_domain_model_travelinfoteaser.pid=###CURRENT_PID### AND tx_epproducts_domain_model_travelinfoteaser.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' => false, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.hidden', + 'config' => [ + 'type' => 'check', + ], + ], + 'starttime' => [ + 'exclude' => false, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime', + 'config' => [ + 'type' => 'datetime', + 'size' => 13, + 'checkbox' => 0, + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true, + ], + ], + ], + 'endtime' => [ + 'exclude' => false, + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime', + 'config' => [ + 'type' => 'datetime', + 'size' => 13, + 'checkbox' => 0, + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true, + ], + ], + ], + + 'title' => [ + 'exclude' => false, + 'label' => 'Bezeichnung/Überschrift', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'eval' => 'trim', + 'required' => true + ], + ], + 'bodytext' => [ + 'exclude' => false, + 'label' => 'Text', + 'config' => [ + 'type' => 'text', + 'cols' => 40, + 'rows' => 15, + 'eval' => 'trim', + 'enableRichtext' => true, + 'required' => true, + ] + ], + 'image' => [ + 'exclude' => 0, + 'label' => 'Bild', + 'config' => [ + // TODO: Important! Verify that the fieldname value in foreign table either matches the column name + // or is set properly in the following TCA, see https://docs.typo3.org/permalink/t3tca:confval-inline-foreign-match-fields + 'type' => 'file', + 'allowed' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], + 'appearance' => [ + 'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference' + ], + 'overrideChildTca' => [ + 'types' => [ + FileType::IMAGE->value => [ + 'showitem' => ' + --palette--;LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + --palette--;;filePalette', + ], + ], + 'columns' => [ + 'crop' => [ + 'config' => [ + 'cropVariants' => [ + 'default' => [ + 'title' => 'Alle Geräte', + 'allowedAspectRatios' => [ + 'teaser' => [ + 'title' => 'quadtratisch', + 'value' => 1, + ], + ], + ], + ], + ], + ], + ], + ], + 'maxitems' => 1, + 'minitems' => 1, + ], + ], + 'category' => [ + 'exclude' => 0, + 'label' => 'Kategorie/Icon', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + ['label' => 'Anreise', 'value' => 'travel'], + ['label' => 'Auto', 'value' => 'car'], + ['label' => 'Bus', 'value' => 'bus'], + ['label' => 'Gepäck', 'value' => 'luggage'], + ['label' => 'Getränke', 'value' => 'drinks'], + ['label' => 'Kurse', 'value' => 'course'], + ['label' => 'Lift', 'value' => 'lift'], + ['label' => 'Programm', 'value' => 'program'], + ['label' => 'Skipass', 'value' => 'skipass'], + ['label' => 'Verpflegung', 'value' => 'food'], + ['label' => 'Webcam', 'value' => 'webcam'], + ['label' => 'Wetter', 'value' => 'weather'], + ['label' => 'Wissenswertes', 'value' => 'chat'], + ['label' => 'Leihmaterial', 'value' => 'rental'], + ['label' => 'Teilnehmer', 'value' => 'participants'], + ['label' => 'Bett', 'value' => 'bed'], + ['label' => 'Ablauf', 'value' => 'sequence'], + ['label' => 'Partner', 'value' => 'partner'], + ], + 'maxitems' => 1, + 'minitems' => 1, + ], + ], + 'tx_epproducts_travelinfo' => [ + 'config' => [ + 'type' => 'passthrough' + ] + ], + 'sorting' => [ + 'config' => [ + 'type' => 'passthrough' + ] + ], + ], +]; diff --git a/packages/ep_products/ext_localconf.php b/packages/ep_products/ext_localconf.php index 81158de..1cdd5e0 100644 --- a/packages/ep_products/ext_localconf.php +++ b/packages/ep_products/ext_localconf.php @@ -2,6 +2,7 @@ use TYPO3\CMS\Extbase\Utility\ExtensionUtility; use EP\EpProducts\Controller\ProductController; use EP\EpProducts\Controller\SearchController; +use EP\EpProducts\Controller\TravelinfoController; use EP\EpProducts\Controller\WatchlistController; use EP\EpProducts\Controller\AjaxFilterPanelController; use EP\EpProducts\Controller\AjaxSearchController; @@ -72,6 +73,14 @@ $boot = function () { ] ); + ExtensionUtility::configurePlugin( + 'EpProducts', + 'travelinfo', + [ + TravelinfoController::class => 'travelInfo,travelCode', + ] + ); + ExtensionUtility::configurePlugin( 'EpProducts', 'ajax', diff --git a/packages/ep_theme/Resources/Private/Layouts/Page/Travelinfo.html b/packages/ep_theme/Resources/Private/Layouts/Page/Travelinfo.html new file mode 100644 index 0000000..b89f0a4 --- /dev/null +++ b/packages/ep_theme/Resources/Private/Layouts/Page/Travelinfo.html @@ -0,0 +1,28 @@ + + +
+ + + + +
Login
+
My E&P
+
+
+
+ +
+ + + diff --git a/packages/ep_theme/Resources/Private/Partials/Travelinfo.html b/packages/ep_theme/Resources/Private/Partials/Travelinfo.html new file mode 100644 index 0000000..39924d3 --- /dev/null +++ b/packages/ep_theme/Resources/Private/Partials/Travelinfo.html @@ -0,0 +1,532 @@ + + + +
+
+ +
+
+
+ Reiseinformation +
+ +
+
+
+
+

+ {travelInfo.subline} + {travelInfo.headline} +

+ {travelInfo.introText -> f:format.html()} + +

+ {travelData.label} {travelData.dateFrom -> f:format.date(format: 'd.m.Y')} - {travelData.dateTo -> f:format.date(format: 'd.m.Y')} +

+
+
+
+
+
+
+
+ +
+
+ Anreise +
+
+
+ + + +

+ Adresse +

+

+ {travelData.hotel.name} +
+ {travelData.hotel.street} +
+ {travelData.hotel.country} {travelData.hotel.city} +

+
+
+ + + + + + + +
+
+ +
+ +
+
+
+
+
+
+ + + + + + + +
+
+ +
+ +
+
+
+
+
+
+
+
+
+ +

+ Eigenanreise +

+ {travelInfo.selfArrangedText -> f:format.html()} +
+
+
+
+
+

+ Sei vorbereitet! + Organisatorisches +

+
+
+ + + +
+
+
+ +
+
+
+ +
+
+ Weitere Infos +
+
+
+ {travelInfo.additionalInfo -> f:format.html()} +
+
+
+ +
+
+
+ Wichtige Telefon­nummern +
+
+
+ +

+ Busbegleitung / Reiseleitung +
+ {travelData.guide.name} {travelData.guide.phone} +

+
+ {travelInfo.importantPhoneNumbers -> f:format.html()} +
+
+
+ +
+
+
+ Wichtige Links vor Ort +
+
+
+ {travelInfo.importantLinks -> f:format.html()} +
+
+
+
+
+
+ {travelInfo.footerText -> f:format.html()} + +
+
+ +
+
+ + +
+
+ + + + + +
+
+
+
+
+ +
+
+
+
+
+

+ {teaser.title} +

+ + + + +
    + +
  • + {item.label} +
  • +
    +
+
+
+
+ + + +

+ Folgende Kurse finden statt +

+
    + +
  • + {course.label} +
  • +
    +
+
+ +

+ Bei Eurer Reise finden keine Kurse statt. +

+
+
+
+
+ {teaser.bodytext -> f:format.html()} +
+
+ +
+
+
+
+
+ + + +
+ +
+
+ {item.title -> f:format.raw()} +
+
+
+ + +

+ Bus-Zustiege +

+

+ Bitte findet euch mindestens 20 Minuten vor Abfahrt an der gebuchten Haltestelle ein. +

+ {travelInfo.busInfoText -> f:format.html()} + + + + + + + + + + + +
+ Zustieg + + Datum/Uhrzeit +
+ {pickup.city}
{pickup.location} +
+ {pickup.datetime -> f:format.date(format: 'd.m.Y')}
{pickup.datetime -> f:format.date(format: 'H:i')} Uhr +
+ +

+ Die Rückreise mit dem Bus startet {departureDayTime}. +

+
+ {travelInfo.departureText -> f:format.html()} +
+ + +

+ Bus-Zustiege +

+

+ Bitte findet euch mindestens 20 Minuten vor Abfahrt an der gebuchten Haltestelle ein. +

+ {travelInfo.busInfoText -> f:format.html()} + + + + + + + + + + + +
+ Zustieg + + Datum/Uhrzeit +
+ {pickup.city}
{pickup.street} +
+ {pickup.time -> f:format.date(format: 'd.m.Y')}
{pickup.time -> f:format.date(format: 'H:i')} Uhr +
+ +

+ Die Rückreise mit dem Bus startet {departureDayTime}. +

+
+ {travelInfo.departureText -> f:format.html()} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ep_theme/Resources/Private/Templates/Page/Travelinfo.html b/packages/ep_theme/Resources/Private/Templates/Page/Travelinfo.html new file mode 100644 index 0000000..a74b139 --- /dev/null +++ b/packages/ep_theme/Resources/Private/Templates/Page/Travelinfo.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/packages/ep_theme/Resources/Private/Templates/Travelinfo/TravelCode.html b/packages/ep_theme/Resources/Private/Templates/Travelinfo/TravelCode.html new file mode 100644 index 0000000..9015bcd --- /dev/null +++ b/packages/ep_theme/Resources/Private/Templates/Travelinfo/TravelCode.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/packages/ep_theme/Resources/Private/Templates/Travelinfo/TravelInfo.html b/packages/ep_theme/Resources/Private/Templates/Travelinfo/TravelInfo.html new file mode 100644 index 0000000..9015bcd --- /dev/null +++ b/packages/ep_theme/Resources/Private/Templates/Travelinfo/TravelInfo.html @@ -0,0 +1,11 @@ + + + + + + + + +