feat: snow reports on TYPO3 13, with a page type for the static pages
The snow report list ("Schneehöhen" plugin) is ported from TYPO3 10:
SnowreportController, SnowreportRepository::getSnowreportsForRegions(),
the plugin registration with its flexform (regions) and the template,
which now formats dates with d.m.Y.
Page type 1705 (/<page>/snowreport) renders only the snow report plugins
of a page, like /form for forms. The static pages of the hybrid setup can
load it to replace the snow reports frozen at export time; each list
carries id="snowreport-<content uid>" for hx-select, since TYPO3 10 gives
the plugin no element of its own. ep:import-snowreport already flushes
the page cache after each import. The suffix is in the PageType enhancer
of every site with snow reports.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
feat: the snow report box includes the spacing of its content element
id="snowreport-<content uid>" moves from the list to a wrapper around
ep:container. The static pages of the hybrid setup no longer export the
snow reports at all, only an empty placeholder that loads the whole box,
spacing included, from /<page>/snowreport, so a page never shows
outdated snow depths.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
62f3bee230
commit
ca2fdc1e13
12 files changed
+211
-1
No files matched your search
@@ -284,6 +284,7 @@ routeEnhancers:
|
||||
/html: 1702
|
||||
/form: 1704
|
||||
/captcha: 3413
|
||||
/snowreport: 1705
|
||||
.json: 1803
|
||||
.ical: 1710
|
||||
sitemap.xml: 1533906435
|
||||
|
||||
@@ -79,7 +79,7 @@ routeEnhancers:
|
||||
hotel_uid: \d+
|
||||
date_from: '\d{4}\-\d{2}\-\d{2}'
|
||||
date_to: '\d{4}\-\d{2}\-\d{2}'
|
||||
# Only for the form and captcha page types; default '' keeps the URLs without trailing slash
|
||||
# Only for the form, captcha and snow report page types; default '' keeps the URLs without trailing slash
|
||||
PageTypeSuffix:
|
||||
type: PageType
|
||||
default: ''
|
||||
@@ -87,6 +87,7 @@ routeEnhancers:
|
||||
map:
|
||||
/form: 1704
|
||||
/captcha: 3413
|
||||
/snowreport: 1705
|
||||
routes:
|
||||
-
|
||||
route: robots.txt
|
||||
|
||||
@@ -68,6 +68,7 @@ routeEnhancers:
|
||||
/html: 1702
|
||||
/form: 1704
|
||||
/captcha: 3413
|
||||
/snowreport: 1705
|
||||
sitemap.xml: 1533906435
|
||||
yoast-snippetpreview.json: 1480321830
|
||||
routes:
|
||||
|
||||
@@ -52,6 +52,7 @@ routeEnhancers:
|
||||
/html: 1702
|
||||
/form: 1704
|
||||
/captcha: 3413
|
||||
/snowreport: 1705
|
||||
sitemap.xml: 1533906435
|
||||
yoast-snippetpreview.json: 1480321830
|
||||
routes:
|
||||
|
||||
@@ -52,6 +52,7 @@ routeEnhancers:
|
||||
/html: 1702
|
||||
/form: 1704
|
||||
/captcha: 3413
|
||||
/snowreport: 1705
|
||||
sitemap.xml: 1533906435
|
||||
yoast-snippetpreview.json: 1480321830
|
||||
routes:
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace EP\EpProducts\Controller;
|
||||
|
||||
use EP\EpProducts\Domain\Repository\SnowreportRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||
|
||||
class SnowreportController extends ActionController
|
||||
{
|
||||
public function __construct(private readonly SnowreportRepository $snowreportRepository)
|
||||
{
|
||||
}
|
||||
|
||||
public function listAction(): ResponseInterface
|
||||
{
|
||||
$regionUids = GeneralUtility::intExplode(',', (string)($this->settings['regionUids'] ?? ''), true);
|
||||
$this->view->assign('data', $this->request->getAttribute('currentContentObject')?->data ?? []);
|
||||
$this->view->assign('list', $this->snowreportRepository->getSnowreportsForRegions($regionUids));
|
||||
return $this->htmlResponse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace EP\EpProducts\Domain\Repository;
|
||||
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
|
||||
class SnowreportRepository extends AbstractRepository
|
||||
{
|
||||
/**
|
||||
* Snow reports of the given regions (all regions with a snow report if empty), one per vendor
|
||||
* record, with region and country data for the list.
|
||||
*/
|
||||
public function getSnowreportsForRegions(array $regionUids = []): array
|
||||
{
|
||||
$qb = $this->getDbConnection()->createQueryBuilder();
|
||||
|
||||
$qb
|
||||
->select(
|
||||
'snowreport.*',
|
||||
'region.name as regionName', 'region.uid as regionUid', 'region.detail_page as regionDetailPage',
|
||||
'country.name as countryName', 'country.uid as countryUid', 'country.code as countryCode',
|
||||
'country.detail_page as countryDetailPage',
|
||||
'season_start as seasonStart', 'season_end as seasonEnd'
|
||||
)
|
||||
->addSelectLiteral('(UNIX_TIMESTAMP() >= snowreport.season_start AND UNIX_TIMESTAMP() <= snowreport.season_end) as inSeason')
|
||||
->from('tx_epproducts_domain_model_snowreport', 'snowreport')
|
||||
->innerJoin('snowreport', 'tx_epproducts_domain_model_region', 'region', 'snowreport.uid = region.snowreport')
|
||||
->innerJoin('region', 'tx_epproducts_domain_model_country', 'country', 'region.country = country.uid')
|
||||
->where('region.snowreport > 0')
|
||||
->groupBy('snowreport.vendor_uid')
|
||||
->orderBy('region.name')
|
||||
;
|
||||
|
||||
if ($regionUids) {
|
||||
$qb->andWhere($qb->expr()->in(
|
||||
'region.uid',
|
||||
$qb->createNamedParameter($regionUids, Connection::PARAM_INT_ARRAY)
|
||||
));
|
||||
}
|
||||
|
||||
return $qb->executeQuery()->fetchAllAssociative();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0"?>
|
||||
<T3DataStructure>
|
||||
<meta>
|
||||
<langDisable>1</langDisable>
|
||||
</meta>
|
||||
<sheets>
|
||||
<sDEF>
|
||||
<ROOT>
|
||||
<sheetTitle>Konfiguration</sheetTitle>
|
||||
<type>array</type>
|
||||
<el>
|
||||
<settings.regionUids>
|
||||
<label>Gebiete einschränken</label>
|
||||
<config>
|
||||
<type>select</type>
|
||||
<renderType>selectMultipleSideBySide</renderType>
|
||||
<foreign_table>tx_epproducts_domain_model_region</foreign_table>
|
||||
<foreign_table_where>AND tx_epproducts_domain_model_region.snowreport > 0 ORDER BY name</foreign_table_where>
|
||||
<minitems>0</minitems>
|
||||
<maxitems>99</maxitems>
|
||||
<size>10</size>
|
||||
</config>
|
||||
</settings.regionUids>
|
||||
</el>
|
||||
</ROOT>
|
||||
</sDEF>
|
||||
</sheets>
|
||||
</T3DataStructure>
|
||||
@@ -43,6 +43,12 @@ call_user_func(function () {
|
||||
'Buchungstabelle'
|
||||
);
|
||||
|
||||
ExtensionUtility::registerPlugin(
|
||||
'EpProducts',
|
||||
'snowreport_list',
|
||||
'Schneehöhen'
|
||||
);
|
||||
|
||||
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['epproducts_product_detail'] = 'pi_flexform';
|
||||
ExtensionManagementUtility::addPiFlexFormValue(
|
||||
'epproducts_product_detail',
|
||||
@@ -61,4 +67,10 @@ call_user_func(function () {
|
||||
'FILE:EXT:ep_products/Configuration/FlexForms/flexform_product_pricetable.xml'
|
||||
);
|
||||
|
||||
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['epproducts_snowreport_list'] = 'pi_flexform';
|
||||
ExtensionManagementUtility::addPiFlexFormValue(
|
||||
'epproducts_snowreport_list',
|
||||
'FILE:EXT:ep_products/Configuration/FlexForms/flexform_snowreport.xml'
|
||||
);
|
||||
|
||||
});
|
||||
@@ -2,6 +2,7 @@
|
||||
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
|
||||
use EP\EpProducts\Controller\ProductController;
|
||||
use EP\EpProducts\Controller\SearchController;
|
||||
use EP\EpProducts\Controller\SnowreportController;
|
||||
use EP\EpProducts\Controller\TravelinfoController;
|
||||
use EP\EpProducts\Controller\WatchlistController;
|
||||
use EP\EpProducts\Controller\AjaxFilterPanelController;
|
||||
@@ -81,6 +82,14 @@ $boot = function () {
|
||||
]
|
||||
);
|
||||
|
||||
ExtensionUtility::configurePlugin(
|
||||
'EpProducts',
|
||||
'snowreport_list',
|
||||
[
|
||||
SnowreportController::class => 'list',
|
||||
]
|
||||
);
|
||||
|
||||
ExtensionUtility::configurePlugin(
|
||||
'EpProducts',
|
||||
'ajax',
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# The snow reports of a page without the page around them (/path/snowreport). The static pages of
|
||||
# the hybrid setup load this with htmx and replace the snow reports of the export with it: the
|
||||
# page URL itself is a static file that never reaches TYPO3, and the snow reports are imported
|
||||
# daily (ep:import-snowreport, which flushes the page cache). Each list carries
|
||||
# id="snowreport-<content uid>" (Templates/Snowreport/List.html) for hx-select.
|
||||
|
||||
tx_eptheme_snowreport = PAGE
|
||||
tx_eptheme_snowreport {
|
||||
typeNum = 1705
|
||||
config {
|
||||
disableAllHeaderCode = 1
|
||||
disablePrefixComment = 1
|
||||
additionalHeaders.10.header = Content-Type: text/html; charset=utf-8
|
||||
additionalHeaders.20.header = X-Robots-Tag: noindex, nofollow
|
||||
admPanel = 0
|
||||
debug = 0
|
||||
}
|
||||
|
||||
10 = CONTENT
|
||||
10 {
|
||||
table = tt_content
|
||||
select {
|
||||
where = {#CType} = 'list' AND {#list_type} = 'epproducts_snowreport_list'
|
||||
orderBy = sorting
|
||||
}
|
||||
# Only the plugin: header and frame stay on the static page
|
||||
renderObj =< tt_content.list.20.epproducts_snowreport_list
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
|
||||
xmlns:v="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true">
|
||||
|
||||
<f:layout name="Default"/>
|
||||
|
||||
<f:section name="Main">
|
||||
<f:comment>
|
||||
The id lets the static pages of the hybrid setup pick this list, with the spacing of
|
||||
ep:container, out of the snow report page type (/path/snowreport), which renders every
|
||||
snow report plugin of a page.
|
||||
</f:comment>
|
||||
<div id="snowreport-{data.uid}">
|
||||
<ep:container data="{data}">
|
||||
<div class="flex flex-col space-y-2">
|
||||
<f:for each="{list}" as="snowreport">
|
||||
<div class="grid md:grid-cols-3 md:gap-y-0">
|
||||
<div class="md:col-span-1 bg-ep-primary-dark p-2 flex items-start space-x-2">
|
||||
{ep:icon(icon: 'flag-{snowreport.countryCode -> f:format.case(mode: \'lower\')}', class: 'w-8 h-6')}
|
||||
<f:link.typolink parameter="{snowreport.regionDetailPage}"
|
||||
title="{snowreport.regionName}"
|
||||
class="text-white uppercase text-lg">
|
||||
{snowreport.regionName}
|
||||
</f:link.typolink>
|
||||
</div>
|
||||
<div class="md:col-span-2 bg-ep-primary-dark/20 p-2">
|
||||
<f:if condition="{snowreport.inSeason}">
|
||||
<f:then>
|
||||
<ul class="flex flex-col space-y-1">
|
||||
<li>
|
||||
<strong>Berg/Tal:</strong> {snowreport.snow_level_mountain -> v:or(alternative: '-')}/{snowreport.snow_level_valley -> v:or(alternative: '-')} cm
|
||||
</li>
|
||||
<li>
|
||||
<strong>Qualität:</strong> {snowreport.snow_quality}
|
||||
</li>
|
||||
<li>
|
||||
<strong>Geöffnete Lifte:</strong> <f:if condition="{snowreport.lifts_opened} > 0"><f:then>{snowreport.lifts_opened}/{snowreport.lifts_total}</f:then><f:else>keine Angabe</f:else></f:if>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Letzter Schneefall:</strong> {f:if(condition: snowreport.last_snowfall, then: '{snowreport.last_snowfall -> f:format.date(format: \'d.m.Y\')}', else: 'keine Angabe')}
|
||||
</li>
|
||||
<li>
|
||||
<strong>Letzte Akt.:</strong> {snowreport.last_update -> f:format.date(format: 'd.m.Y')}
|
||||
</li>
|
||||
</ul>
|
||||
</f:then>
|
||||
<f:else>
|
||||
Saison vom {snowreport.seasonStart -> f:format.date(format: 'd.m.Y')} bis {snowreport.seasonEnd -> f:format.date(format: 'd.m.Y')}
|
||||
</f:else>
|
||||
</f:if>
|
||||
</div>
|
||||
</div>
|
||||
</f:for>
|
||||
</div>
|
||||
</ep:container>
|
||||
</div>
|
||||
</f:section>
|
||||
|
||||
</html>
|
||||
Reference in new issue
Block a user