Compare commits

...
17 Commits
Author SHA1 Message Date
fromme 9b3550ec40 feat: migrate to native lazy loading of images 2026-09-12 12:08:09 +02:00
fromme d9943619f6 chore: cleanup 2026-09-12 12:04:52 +02:00
fromme e33b57c9f1 feat: disable chatbot in page footer 2026-09-12 12:04:33 +02:00
fromme dc594efee1 chore: remove obsolete vue component 2026-09-12 11:52:46 +02:00
fromme 432d8da350 chore: update redis config 2026-09-12 11:31:29 +02:00
fromme 5b338eeab6 chore: align redis config with prod 2026-09-12 11:27:08 +02:00
fromme 05ceae5100 fix: simplify generated captchas to improve ux 2026-09-12 11:22:49 +02:00
fromme f005272242 chore: align php version with prod 2026-09-10 13:51:37 +02:00
fromme 7d856d1031 chore: align mariadb version with prod 2026-09-10 13:50:26 +02:00
fromme f9e94231a7 chore: update project dependencies 2026-09-10 12:54:35 +02:00
fromme 0a3e8f59cb fix: repair broken backend search and improve copy traceability 2026-09-10 12:52:55 +02:00
fromme a01d1ba0c5 chore: drop dead description column from product table 2026-09-10 11:50:38 +02:00
fromme 6828e49663 fix: declare importer-written date columns as passthrough 2026-09-10 11:50:38 +02:00
fromme 46001a02ed fix: add TCA default 0 to relation selects for MySQL strict mode 2026-09-10 10:17:10 +02:00
fromme 5e39e39b90 chore: finalize deployer config to new target host 2026-09-10 09:01:22 +02:00
fromme 8dad782603 feat: integrate with redis for improved performance 2026-09-08 18:27:00 +02:00
fromme 0e6a65dfa0 feat: integrate with bunny.net cdn for images 2026-09-05 10:47:00 +02:00
94 changed files with 945 additions and 4512 deletions
+38
View File
@@ -0,0 +1,38 @@
name: redis
repository: ddev/ddev-redis
version: v2.2.0
install_date: "2026-09-08T18:12:40+02:00"
project_files:
- docker-compose.redis.yaml
- redis/scripts/settings.ddev.redis.php
- redis/scripts/setup-drupal-settings.sh
- redis/scripts/setup-redis-optimized-config.sh
- redis/redis.conf
- redis/advanced.conf
- redis/append.conf
- redis/general.conf
- redis/io.conf
- redis/memory.conf
- redis/network.conf
- redis/security.conf
- redis/snapshots.conf
- commands/host/redis-backend
- commands/redis/redis-cli
- commands/redis/redis-flush
global_files: []
removal_actions:
- |
#ddev-description:Remove redis settings if applicable
files=(
"${DDEV_APPROOT}/${DDEV_DOCROOT}/sites/default/settings.ddev.redis.php"
"${DDEV_APPROOT}/.ddev/docker-compose.redis_extra.yaml"
)
for file in "${files[@]}"; do
if [ -f "$file" ]; then
if grep -q '#ddev-generated' "$file"; then
rm -f "$file"
else
echo "Unwilling to remove '$file' because it does not have #ddev-generated in it; you can manually delete it if it is safe to delete."
fi
fi
done
+124
View File
@@ -0,0 +1,124 @@
#!/usr/bin/env bash
#ddev-generated
## Description: Use a different key-value store for Redis
## Usage: redis-backend <image> [optimize]
## Example: ddev redis-backend redis-alpine optimize
REDIS_DOCKER_IMAGE=${1:-}
REDIS_CONFIG=${2:-}
NAME=$REDIS_DOCKER_IMAGE
function show_help() {
cat <<EOF
Usage: ddev redis-backend <image|alias> [optimize]
Choose from predefined aliases, or provide any Redis-compatible Docker image.
Note that not every Docker image can work right away, and you may need to override
the "command:" in the docker-compose.redis_extra.yaml file
Available aliases:
redis redis:7
redis-alpine redis:7-alpine
valkey valkey/valkey:8
valkey-alpine valkey/valkey:8-alpine
Custom backend:
You can specify any Docker image, e.g.:
ddev redis-backend redis:6
Optional:
optimize Apply additional Redis configuration with resource limits
optimized Same as optimize
Examples:
ddev redis-backend redis-alpine optimize
ddev redis-backend valkey
ddev redis-backend redis:7.2-alpine
EOF
exit 0
}
function optimize_config() {
[[ "$REDIS_CONFIG" != "optimized" && "$REDIS_CONFIG" != "optimize" ]] && return
ddev dotenv set .ddev/.env.redis --redis-optimized=true
}
function change_hostname() {
[[ "${REDIS_HOSTNAME:-}" == "" ]] && return
ddev dotenv set .ddev/.env.redis --redis-hostname="$REDIS_HOSTNAME"
}
function cleanup() {
rm -f "$DDEV_APPROOT/.ddev/.env.redis"
rm -rf "$DDEV_APPROOT/.ddev/redis/"
rm -f "$DDEV_APPROOT/.ddev/docker-compose.redis.yaml" "$DDEV_APPROOT/.ddev/docker-compose.redis_extra.yaml"
redis_volume="ddev-$(ddev status -j | docker run -i --rm ddev/ddev-utilities jq -r '.raw.name')_redis"
if docker volume ls -q | grep -qw "$redis_volume"; then
ddev stop
docker volume rm "$redis_volume"
fi
}
function check_docker_image() {
echo "Pulling ${REDIS_DOCKER_IMAGE}..."
if ! docker pull "$REDIS_DOCKER_IMAGE"; then
echo >&2 "❌ Unable to pull ${REDIS_DOCKER_IMAGE}"
exit 2
fi
}
function use_docker_image() {
[[ "$REDIS_DOCKER_IMAGE" != "redis:7" ]] && ddev dotenv set .ddev/.env.redis --redis-docker-image="$REDIS_DOCKER_IMAGE"
REPO=$(ddev add-on list --installed -j 2>/dev/null | docker run -i --rm ddev/ddev-utilities jq -r '.raw[] | select(.Name=="redis") | .Repository // empty' 2>/dev/null)
ddev add-on get "${REPO:-ddev/ddev-redis}"
}
case "$REDIS_DOCKER_IMAGE" in
redis)
NAME="Redis 7"
REDIS_DOCKER_IMAGE="redis:7"
;;
redis-alpine)
NAME="Redis 7 Alpine"
REDIS_DOCKER_IMAGE="redis:7-alpine"
;;
valkey)
NAME="Valkey 8"
REDIS_DOCKER_IMAGE="valkey/valkey:8"
REDIS_HOSTNAME="valkey"
;;
valkey-alpine)
NAME="Valkey 8 Alpine"
REDIS_DOCKER_IMAGE="valkey/valkey:8-alpine"
REDIS_HOSTNAME="valkey"
;;
""|--help|-h)
show_help
;;
*)
NAME="$REDIS_DOCKER_IMAGE"
# Allow unknown image, nothing to override
;;
esac
check_docker_image
cleanup
optimize_config
change_hostname
use_docker_image
echo
echo "✅ Redis backend: $REDIS_DOCKER_IMAGE"
if [[ "$REDIS_CONFIG" == "optimized" || "$REDIS_CONFIG" == "optimize" ]]; then
echo "⚙️ Redis config: optimized"
else
echo "⚙️ Redis config: default"
fi
echo
echo "📝 Commit the '.ddev' directory to version control"
echo
echo "🔄 Redis config available after 'ddev restart'"
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env sh
#ddev-generated
## Description: Run redis-cli inside the Redis container
## Usage: redis-cli [flags] [args]
## Example: "ddev redis-cli KEYS *" or "ddev redis-cli INFO" or "ddev redis-cli --version"
## Aliases: redis
if [ -f /etc/redis/conf/security.conf ]; then
redis-cli -p 6379 -h "${REDIS_HOSTNAME:-redis}" -a redis --no-auth-warning $@
else
redis-cli -p 6379 -h "${REDIS_HOSTNAME:-redis}" $@
fi
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env sh
#ddev-generated
## Description: Flush all cache inside the Redis container
## Usage: redis-flush
## Example: "ddev redis-flush"
if [ -f /etc/redis/conf/security.conf ]; then
redis-cli -p 6379 -h "${REDIS_HOSTNAME:-redis}" -a redis --no-auth-warning FLUSHALL ASYNC
else
redis-cli -p 6379 -h "${REDIS_HOSTNAME:-redis}" FLUSHALL ASYNC
fi
+77 -41
View File
@@ -1,9 +1,8 @@
name: ep-reisen
type: typo3
docroot: public
php_version: "7.4"
webserver_type: nginx-fpm
router_http_port: "80"
router_https_port: "443"
xdebug_enabled: false
additional_hostnames:
- ep-events
@@ -16,36 +15,57 @@ additional_hostnames:
additional_fqdns: []
database:
type: mariadb
version: "10.2"
version: "11.4"
hooks:
post-start:
- exec: .ddev/claude-code/install.sh
- exec: .ddev/codex-cli/install.sh
webimage_extra_packages: [ripgrep, bubblewrap, socat]
use_dns_when_possible: true
timezone: Europe/Berlin
composer_version: "2"
web_environment:
- TYPO3_CONTEXT=Development
nodejs_version: "18"
corepack_enable: false
# Key features of DDEV's config.yaml:
# name: <projectname> # Name of the project, automatically provides
# http://projectname.ddev.site and https://projectname.ddev.site
# If the name is omitted, the project will take the name of the enclosing directory,
# which is useful if you want to have a copy of the project side by side with this one.
# type: <projecttype> # drupal6/7/8, backdrop, typo3, wordpress, php
# type: <projecttype> # asterios, backdrop, cakephp, codeigniter, craftcms, drupal, drupal6, drupal7, drupal8, drupal9, drupal10, drupal11, drupal12, generic, joomla, laravel, magento, magento2, maho, modx, php, shopware6, silverstripe, symfony, typo3, wordpress, wp-bedrock
# See https://docs.ddev.com/en/stable/users/quickstart/ for more
# information on the different project types
# docroot: <relative_path> # Relative path to the directory containing index.php.
# php_version: "8.1" # PHP version to use, "5.6", "7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3"
# php_version: "8.4" # PHP version to use, "5.6" through "8.5"
# You can explicitly specify the webimage but this
# is not recommended, as the images are often closely tied to DDEV's' behavior,
# is not recommended, as the images are often closely tied to DDEV's behavior,
# so this can break upgrades.
# webimage: <docker_image> # nginx/php docker image.
# webimage: <docker_image>
# Its unusual to change this option, and we dont recommend it without Docker experience and a good reason.
# Typically, this means additions to the existing web image using a .ddev/web-build/Dockerfile.*
# database:
# type: <dbtype> # mysql, mariadb, postgres
# version: <version> # database version, like "10.4" or "8.0"
# MariaDB versions can be 5.5-10.8 and 10.11, MySQL versions can be 5.5-8.0
# PostgreSQL versions can be 9-16.
# version: <version> # database version, like "10.11" or "8.0"
# MariaDB versions can be 5.5-10.8, 10.11, 11.4, 11.8, 12.3
# MySQL versions can be 5.5-8.0, 8.4, 9.7
# PostgreSQL versions can be 9-18
# You can explicitly specify the dbimage but this
# is not recommended, as the images are often closely tied to DDEV's behavior,
# so this can break upgrades.
# dbimage: <docker_image>
# Its unusual to change this option, and we dont recommend it without Docker experience and a good reason.
# Typically, this means additions to the existing db image using a .ddev/db-build/Dockerfile.*
# router_http_port: <port> # Port to be used for http (defaults to global configuration, usually 80)
# router_https_port: <port> # Port for https (defaults to global configuration, usually 443)
@@ -55,14 +75,24 @@ nodejs_version: "18"
# "ddev xdebug" to enable Xdebug and "ddev xdebug off" to disable it work better,
# as leaving Xdebug enabled all the time is a big performance hit.
# xhprof_enabled: false # Set to true to enable Xhprof and "ddev start" or "ddev restart"
# Note that for most people the commands
# "ddev xhprof" to enable Xhprof and "ddev xhprof off" to disable it work better,
# as leaving Xhprof enabled all the time is a big performance hit.
# xhgui_http_port: "8143"
# xhgui_https_port: "8142"
# The XHGui ports can be changed from the default 8143 and 8142
# Very rarely used
# webserver_type: nginx-fpm, apache-fpm, or nginx-gunicorn
# host_xhgui_port: "8142"
# Can be used to change the host binding port of the XHGui
# application. Rarely used; only when port conflict and
# bind_all_ports is used (normally with router disabled)
# xhprof_mode: [prepend|xhgui|global]
# Default is "xhgui"
# webserver_type: nginx-fpm, apache-fpm, generic
# timezone: Europe/Berlin
# If timezone is unset, DDEV will attempt to derive it from the host system timezone
# using the $TZ environment variable or the /etc/localtime symlink.
# This is the timezone used in the containers and by PHP;
# it can be set to any valid timezone,
# see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
@@ -74,22 +104,27 @@ nodejs_version: "18"
# commands are executed.
# composer_version: "2"
# You can set it to "" or "2" (default) for Composer v2 or "1" for Composer v1
# You can set it to "" or "2" (default) for Composer v2
# to use the latest major version available at the time your container is built.
# It is also possible to use each other Composer version channel. This includes:
# It is also possible to use any other Composer version channel. This includes:
# - 2.2 (latest Composer LTS version)
# - stable
# - preview
# - snapshot
# Alternatively, an explicit Composer version may be specified, for example "2.2.18".
# To reinstall Composer after the image was built, run "ddev debug refresh".
# To reinstall Composer after the image was built, run "ddev utility rebuild".
# nodejs_version: "18"
# change from the default system Node.js version to another supported version, like 16, 18, 20.
# Note that you can use 'ddev nvm' or nvm inside the web container to provide nearly any
# Node.js version, including v6, etc.
# You only need to configure this if you are not using nvm and you want to use a major
# version that is not the default.
# nodejs_root: <relative_path>
# Relative path to the directory containing the Node.js version file from the
# project root. Only used with "nodejs_version: auto" or "nodejs_version: engine".
# nodejs_version: "24"
# change from the default system Node.js version to any other version.
# See https://docs.ddev.com/en/stable/users/configuration/config/#nodejs_version for more information
# and https://www.npmjs.com/package/n#specifying-nodejs-versions for the full documentation.
# corepack_enable: false
# Change to 'true' to 'corepack enable' and gain access to latest versions of yarn/pnpm
# additional_hostnames:
# - somename
@@ -119,7 +154,7 @@ nodejs_version: "18"
# ddev_version_constraint: ""
# Example:
# ddev_version_constraint: ">= 1.22.4"
# ddev_version_constraint: ">= 1.24.8"
# This will enforce that the running ddev version is within this constraint.
# See https://github.com/Masterminds/semver#checking-version-constraints for
# supported constraint formats
@@ -146,10 +181,8 @@ nodejs_version: "18"
# - "global": uses the value from the global config.
# - "none": disables performance optimization for this project.
# - "mutagen": enables Mutagen for this project.
# - "nfs": enables NFS for this project.
#
# See https://ddev.readthedocs.io/en/latest/users/install/performance/#nfs
# See https://ddev.readthedocs.io/en/latest/users/install/performance/#mutagen
# See https://docs.ddev.com/en/stable/users/install/performance/#mutagen
# fail_on_hook_fail: False
# Decide whether 'ddev start' should be interrupted by a failing hook
@@ -178,10 +211,10 @@ nodejs_version: "18"
# The mailpit port is not normally bound on the host at all, instead being routed
# through ddev-router, but it can be bound directly to localhost if specified here.
# webimage_extra_packages: [php7.4-tidy, php-bcmath]
# webimage_extra_packages: ['php${DDEV_PHP_VERSION}-tidy', 'php${DDEV_PHP_VERSION}-yac']
# Extra Debian packages that are needed in the webimage can be added here
# dbimage_extra_packages: [telnet,netcat]
# dbimage_extra_packages: [netcat, telnet, sudo]
# Extra Debian packages that are needed in the dbimage can be added here
# use_dns_when_possible: true
@@ -193,22 +226,25 @@ nodejs_version: "18"
# project_tld: ddev.site
# The top-level domain used for project URLs
# The default "ddev.site" allows DNS lookup via a wildcard
# If you prefer you can change this to "ddev.local" to preserve
# pre-v1.9 behavior.
# ngrok_args: --basic-auth username:pass1234
# Provide extra flags to the "ngrok http" command, see
# https://ngrok.com/docs/ngrok-agent/config or run "ngrok http -h"
# share_default_provider: ngrok
# The default share provider to use for "ddev share"
# Defaults to global configuration, usually "ngrok"
# Can be "ngrok" or "cloudflared" or the name of a custom provider from .ddev/share-providers/
# share_provider_args: --basic-auth username:pass1234
# Provide extra flags to the share provider script
# See https://docs.ddev.com/en/stable/users/configuration/config/#share_provider_args
# disable_settings_management: false
# If true, DDEV will not create CMS-specific settings files like
# Drupal's settings.php/settings.ddev.php or TYPO3's AdditionalConfiguration.php
# Drupal's settings.php/settings.ddev.php or TYPO3's additional.php
# In this case the user must provide all such settings.
# You can inject environment variables into the web container with:
# web_environment:
# - SOMEENV=somevalue
# - SOMEOTHERENV=someothervalue
# - SOMEENV=somevalue
# - SOMEOTHERENV=someothervalue
# no_project_mount: false
# (Experimental) If true, DDEV will not mount the project into the web container;
@@ -260,7 +296,7 @@ nodejs_version: "18"
# override_config: false
# By default, config.*.yaml files are *merged* into the configuration
# But this means that some things can't be overridden
# For example, if you have 'use_dns_when_possible: true'' you can't override it with a merge
# For example, if you have 'use_dns_when_possible: true' you can't override it with a merge
# and you can't erase existing hooks or all environment variables.
# However, with "override_config: true" in a particular config.*.yaml file,
# 'use_dns_when_possible: false' can override the existing values, and
@@ -270,13 +306,13 @@ nodejs_version: "18"
# web_environment: []
# or
# additional_hostnames: []
# can have their intended affect. 'override_config' affects only behavior of the
# can have their intended effect. 'override_config' affects only behavior of the
# config.*.yaml file it exists in.
# Many DDEV commands can be extended to run tasks before or after the
# DDEV command is executed, for example "post-start", "post-import-db",
# "pre-composer", "post-composer"
# See https://ddev.readthedocs.io/en/stable/users/extend/custom-commands/ for more
# See https://docs.ddev.com/en/stable/users/extend/custom-commands/ for more
# information on the commands that can be extended and the tasks you can define
# for them. Example:
#hooks:
+27
View File
@@ -0,0 +1,27 @@
#ddev-generated
services:
redis:
container_name: ddev-${DDEV_SITENAME}-redis
image: ${REDIS_DOCKER_IMAGE:-redis:7}
hostname: ${REDIS_HOSTNAME:-redis}
# These labels ensure this service is discoverable by ddev.
labels:
com.ddev.site-name: ${DDEV_SITENAME}
com.ddev.approot: ${DDEV_APPROOT}
restart: "no"
expose:
- 6379
volumes:
- ".:/mnt/ddev_config"
- "ddev-global-cache:/mnt/ddev-global-cache"
- "./redis:/etc/redis/conf"
- "redis:/data"
command: /etc/redis/conf/redis.conf
x-ddev:
describe-url-port: |
Backend: ${REDIS_DOCKER_IMAGE:-redis:7}
describe-info: |
Pass: <none>
volumes:
redis:
+13
View File
@@ -0,0 +1,13 @@
# Redis configuration.
# #ddev-generated
# Example configuration files for reference:
# http://download.redis.io/redis-stable/redis.conf
# http://download.redis.io/redis-stable/sentinel.conf
maxmemory 128mb
maxmemory-policy allkeys-lru
# to disable Redis persistence, remove ddev-generated from this file,
# and uncomment the two lines below:
#appendonly no
#save ""
-1
View File
@@ -15,7 +15,6 @@ public/typo3conf/ext/*/
public/typo3conf/ext/ep_events/Resources/Public/
public/typo3conf/ext/ep_theme/Resources/Public/
public/typo3conf/LocalConfiguration.php
public/typo3conf/AdditionalConfiguration.php
public/typo3conf/PackageStates.php
public/typo3conf/l10n
public/typo3temp
-3284
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
16
18
+3 -1
View File
@@ -15,6 +15,7 @@
"ext-json": "*",
"ext-libxml": "*",
"ext-pdo": "*",
"ext-redis": "*",
"ext-simplexml": "*",
"b13/container": "^1.3",
"blueways/bw-captcha": "^3.1",
@@ -24,6 +25,7 @@
"georgringer/news": "^8.5",
"gridelementsteam/gridelements": "^10.0",
"helhum/typo3-console": "^6.4",
"jweiland/replacer": "^2.1",
"kigkonsult/icalcreator": "^2.29",
"league/csv": "^9.2",
"league/oauth2-client": "^2.8",
@@ -96,7 +98,7 @@
"config": {
"sort-packages": true,
"platform": {
"php": "7.4.13"
"php": "7.4.33"
},
"allow-plugins": {
"typo3/cms-composer-installers": true,
Generated
+95 -28
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": "0842a6e9476f96ae559c7d2e900c3be2",
"content-hash": "38fb94ebf504e8413d37c94f929e4b47",
"packages": [
{
"name": "b13/container",
@@ -1583,6 +1583,72 @@
],
"time": "2023-01-08T21:22:53+00:00"
},
{
"name": "jweiland/replacer",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/jweiland-net/replacer.git",
"reference": "feec487ea9c3573d1e8d80245dd9763352492357"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jweiland-net/replacer/zipball/feec487ea9c3573d1e8d80245dd9763352492357",
"reference": "feec487ea9c3573d1e8d80245dd9763352492357",
"shasum": ""
},
"require": {
"typo3/cms-core": "^9.5 || ^10.4 || ^11.0"
},
"replace": {
"typo3-ter/replacer": "self.version"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"nimut/testing-framework": "^6.0",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"roave/security-advisories": "dev-latest"
},
"type": "typo3-cms-extension",
"extra": {
"typo3/cms": {
"app-dir": ".build",
"web-dir": ".build/public",
"extension-key": "replacer"
}
},
"autoload": {
"psr-4": {
"JWeiland\\Replacer\\": "Classes"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0-or-later"
],
"authors": [
{
"name": "Pascal Rinker",
"email": "[email protected]",
"role": "Developer"
}
],
"description": "Replaces string patterns from the page. You can use it to replace URLs for Content Delivery Network (CDN).",
"homepage": "http://www.jweiland.net",
"keywords": [
"TYPO3 CMS",
"jw",
"replacer",
"typo3"
],
"support": {
"email": "[email protected]",
"issues": "https://github.com/jweiland-net/replacer/issues",
"source": "https://github.com/jweiland-net/replacer"
},
"time": "2022-06-02T09:29:20+00:00"
},
{
"name": "kigkonsult/icalcreator",
"version": "v2.39.2",
@@ -2055,24 +2121,24 @@
},
{
"name": "masterminds/html5",
"version": "2.10.1",
"version": "2.11.0",
"source": {
"type": "git",
"url": "https://github.com/Masterminds/html5-php.git",
"reference": "fd5018f6815fff903946d0564977b44ce8010e29"
"reference": "a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fd5018f6815fff903946d0564977b44ce8010e29",
"reference": "fd5018f6815fff903946d0564977b44ce8010e29",
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7",
"reference": "a1e7a2f88ee13635d86fc61cfbdf2306a76ddfc7",
"shasum": ""
},
"require": {
"ext-dom": "*",
"php": ">=5.3.0"
"php": ">=7.4"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9 || ^10"
"phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10"
},
"type": "library",
"extra": {
@@ -2116,9 +2182,9 @@
],
"support": {
"issues": "https://github.com/Masterminds/html5-php/issues",
"source": "https://github.com/Masterminds/html5-php/tree/2.10.1"
"source": "https://github.com/Masterminds/html5-php/tree/2.11.0"
},
"time": "2026-06-23T18:43:15+00:00"
"time": "2026-08-18T06:18:41+00:00"
},
{
"name": "nikic/php-parser",
@@ -2575,16 +2641,16 @@
},
{
"name": "phpstan/phpdoc-parser",
"version": "2.3.3",
"version": "2.3.5",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3"
"reference": "148cefffaf0233e4c08cc13db8a195a56dd6dfe9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fb19eedd2bb67ff8cf7a5502ad329e701d6398a3",
"reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/148cefffaf0233e4c08cc13db8a195a56dd6dfe9",
"reference": "148cefffaf0233e4c08cc13db8a195a56dd6dfe9",
"shasum": ""
},
"require": {
@@ -2616,9 +2682,9 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.3"
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.5"
},
"time": "2026-07-08T07:01:06+00:00"
"time": "2026-08-31T16:05:28+00:00"
},
{
"name": "psr/cache",
@@ -5044,16 +5110,16 @@
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.38.1",
"version": "v1.42.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "dc21118016c039a66235cf93d96b435ffb282412"
"reference": "51b5ff5ba85452b31ec6f55490b08148612339d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/dc21118016c039a66235cf93d96b435ffb282412",
"reference": "dc21118016c039a66235cf93d96b435ffb282412",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/51b5ff5ba85452b31ec6f55490b08148612339d9",
"reference": "51b5ff5ba85452b31ec6f55490b08148612339d9",
"shasum": ""
},
"require": {
@@ -5107,7 +5173,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.38.1"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.42.0"
},
"funding": [
{
@@ -5127,20 +5193,20 @@
"type": "tidelift"
}
],
"time": "2026-05-25T15:22:23+00:00"
"time": "2026-08-24T10:51:20+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.38.0",
"version": "v1.42.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b"
"reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b",
"reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502",
"reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502",
"shasum": ""
},
"require": {
@@ -5192,7 +5258,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0"
},
"funding": [
{
@@ -5212,7 +5278,7 @@
"type": "tidelift"
}
],
"time": "2026-05-25T13:48:31+00:00"
"time": "2026-08-07T06:33:24+00:00"
},
{
"name": "symfony/polyfill-mbstring",
@@ -9581,11 +9647,12 @@
"ext-json": "*",
"ext-libxml": "*",
"ext-pdo": "*",
"ext-redis": "*",
"ext-simplexml": "*"
},
"platform-dev": {},
"platform-overrides": {
"php": "7.4.13"
"php": "7.4.33"
},
"plugin-api-version": "2.9.0"
}
+5 -40
View File
@@ -25,6 +25,7 @@ add('shared_dirs', [
$rsyncOptions = [
'exclude' => [
'.ddev',
'.claude',
'.DS_Store',
'.git',
'.github',
@@ -56,29 +57,13 @@ $rsyncOptions = [
'timeout' => 300,
];
host('production')
->setHostname('185.237.67.190')
->setRemoteUser('p546128')
->setForwardAgent(true)
->setSshMultiplexing(true)
->setDeployPath('/home/www/p546128/html/{{application}}')
->set('buspronet_path', '/home/www/p546128/html/kuschick/buspronet/buspronet')
->set('bin/php', '/usr/local/bin/php')
->set('http_user', 'p546128')
->set('writable_mode', 'chmod')
->set('bin/composer', '/usr/local/bin/composer')
->set('composer_options', '--prefer-dist --no-progress --no-interaction --optimize-autoloader')
->set('rsync_src', __DIR__)
->set('rsync', $rsyncOptions)
->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{current_path}}/public/ --web-url=https://www.ep-reisen.de')
;
host('hetzner')
host('prod')
->setHostname('dedi10193.your-server.de')
->setRemoteUser('eptypo3')
->setForwardAgent(true)
->setSshMultiplexing(true)
->setDeployPath('/usr/home/eptypo3/public_html/{{application}}')
->set('buspronet_path', '/usr/home/eptypo3/public_html/kuschick/buspronet/buspronet')
->set('bin/php', '/usr/bin/php74')
->set('http_user', 'eptypo3')
->set('writable_mode', 'chmod')
@@ -86,27 +71,7 @@ host('hetzner')
->set('composer_options', '--prefer-dist --no-progress --no-interaction --optimize-autoloader')
->set('rsync_src', __DIR__)
->set('rsync', $rsyncOptions)
->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{current_path}}/public/ --web-url=https://test.ep-reisen.de')
;
host('staging')
->setHostname('185.237.67.190')
->setRemoteUser('p546128')
->setForwardAgent(true)
->setSshMultiplexing(true)
->setDeployPath('/home/www/p546128/html/{{application}}-staging')
->set('buspronet_path', '/home/www/p546128/html/kuschick/buspronet/buspronet')
->set('bin/php', '/usr/local/bin/php')
->set('http_user', 'p546128')
->set('writable_mode', 'chmod')
->set('bin/composer', '/usr/local/bin/composer')
->set('composer_options', '--prefer-dist --no-progress --no-interaction --optimize-autoloader')
->set('rsync_src', __DIR__)
->set('rsync', $rsyncOptions)
->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{current_path}}/public/ --web-url=https://staging.ep-reisen.de --web-basic-auth=ep:reisen')
->add('shared_files', [
'{{typo3_webroot}}/.htpasswd',
])
->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{current_path}}/public/ --web-url=https://www.ep-reisen.de')
;
task('deploy', [
@@ -123,7 +88,7 @@ task('deploy', [
'deploy:publish',
'cachetool:clear:opcache',
'typo3:cache:flush',
// 'deploy:buspronet:symlink',
'deploy:buspronet:symlink',
]);
task('deploy:buspronet:symlink', function () {
-18
View File
@@ -21,10 +21,8 @@
"glightbox": "^3.0.9",
"htmx.org": "^1.9.12",
"jquery": "^3.6.0",
"lazysizes": "^5.3.2",
"leaflet": "^1.7.1",
"normalize.css": "^8.0.1",
"picturefill": "^3.0.3",
"slick-carousel": "^1.8.1",
"sticky-js": "^1.3.0",
"stimulus-use": "^0.52.0",
@@ -6017,12 +6015,6 @@
"shell-quote": "^1.8.4"
}
},
"node_modules/lazysizes": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/lazysizes/-/lazysizes-5.3.2.tgz",
"integrity": "sha512-22UzWP+Vedi/sMeOr8O7FWimRVtiNJV2HCa+V8+peZOw6QbswN9k58VUhd7i6iK5bw5QkYrF01LJbeJe0PV8jg==",
"license": "MIT"
},
"node_modules/leaflet": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
@@ -6963,16 +6955,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/picturefill": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/picturefill/-/picturefill-3.0.3.tgz",
"integrity": "sha512-JDdx+3i4fs2pkqwWZJgGEM2vFWsq+01YsQFT9CKPGuv2Q0xSdrQZoxi9XwyNARTgxiOdgoAwWQRluLRe/JQX2g==",
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"license": "MIT",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
-2
View File
@@ -24,10 +24,8 @@
"glightbox": "^3.0.9",
"htmx.org": "^1.9.12",
"jquery": "^3.6.0",
"lazysizes": "^5.3.2",
"leaflet": "^1.7.1",
"normalize.css": "^8.0.1",
"picturefill": "^3.0.3",
"slick-carousel": "^1.8.1",
"sticky-js": "^1.3.0",
"stimulus-use": "^0.52.0",
@@ -0,0 +1,114 @@
<?php
$redisOptions = [
'hostname' => '/run/redis_eptypo3/redis.sock',
'port' => 0,
];
if (getenv('IS_DDEV_PROJECT') == 'true') {
$redisOptions = [
'hostname' => 'redis',
'port' => 6379,
];
$GLOBALS['TYPO3_CONF_VARS'] = array_replace_recursive(
$GLOBALS['TYPO3_CONF_VARS'],
[
'DB' => [
'Connections' => [
'Default' => [
'dbname' => 'db',
'driver' => 'mysqli',
'host' => 'db',
'password' => 'db',
'port' => '3306',
'user' => 'db',
],
],
],
// This GFX configuration allows processing by installed ImageMagick 6
'GFX' => [
'processor' => 'ImageMagick',
'processor_path' => '/usr/bin/',
'processor_path_lzw' => '/usr/bin/',
],
// This mail configuration sends all emails to mailpit
'MAIL' => [
'transport' => 'smtp',
'transport_smtp_encrypt' => false,
'transport_smtp_server' => 'localhost:1025',
],
'SYS' => [
'trustedHostsPattern' => '.*.*',
'devIPmask' => '*',
'displayErrors' => 1,
],
]
);
}
// Fail fast instead of blocking indefinitely when redis is unreachable.
$redisOptions['connectionTimeout'] = 2;
// Note: the cache identifiers must stay unprefixed ('pages', not 'cache_pages'). These
// assignments replace the definitions from LocalConfiguration.php wholesale, so 'groups'
// and the compression/lifetime options have to be repeated here.
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['pages'] = [
'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class,
'backend' => \TYPO3\CMS\Core\Cache\Backend\RedisBackend::class,
'options' => $redisOptions + [
'database' => 0,
'compression' => true,
],
'groups' => ['pages'],
];
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['hash'] = [
'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class,
'backend' => \TYPO3\CMS\Core\Cache\Backend\RedisBackend::class,
'options' => $redisOptions + [
'database' => 1,
],
'groups' => ['pages'],
];
// Own database: RedisBackend::flush() issues FLUSHDB and the keys carry no per-cache
// prefix, so two caches sharing a database flush each other.
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['rootline'] = [
'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class,
'backend' => \TYPO3\CMS\Core\Cache\Backend\RedisBackend::class,
'options' => $redisOptions + [
'database' => 2,
'compression' => true,
'defaultLifetime' => 2592000,
],
'groups' => ['pages'],
];
// suppress php deprecation warnings flooding typo3 logs
$GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandlerErrors'] =
$GLOBALS['TYPO3_CONF_VARS']['SYS']['errorHandlerErrors'] & ~E_DEPRECATED & ~E_USER_DEPRECATED;
/*
$GLOBALS['TYPO3_CONF_VARS']['BE']['cookieSameSite'] = 'lax';
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['oauth2_client'] = [
'providers' => [
'myep' => [
'label' => 'MyEP',
'iconIdentifier' => 'ep-logo',
'scopes' => [
\Waldhacker\Oauth2Client\Service\Oauth2ProviderManager::SCOPE_BACKEND,
],
'options' => [
'clientId' => '8df8f314ce17e8b716f86f9c24564746',
'clientSecret' => '7ff2532abc06f2b48438fc2e6e0278c8fdfb0e2de839889f4d5d17fd4a37cfffcca3bb19166331cc6ced462550611b33f08e9a3a993270d8c786a884c7fe935b',
'urlAuthorize' => 'https://myep-next-booking.ddev.site/authorize',
'urlAccessToken' => 'https://myep-next-booking.ddev.site/token',
'urlResourceOwnerDetails' => 'https://myep-next-booking.ddev.site/api/userinfo',
'scopes' => ['email', 'id', 'roles', 'profile'],
'scopeSeparator' => ' ',
],
],
],
];
*/
@@ -39,6 +39,7 @@ return [
'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',
@@ -53,6 +54,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -36,6 +36,7 @@ return [
'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',
@@ -50,6 +51,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -37,6 +37,7 @@ return [
'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',
@@ -51,6 +52,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -38,6 +38,7 @@ return [
'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',
@@ -52,6 +53,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -50,6 +50,7 @@ return [
'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',
@@ -64,6 +65,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -449,6 +451,7 @@ return [
'label' => 'Ansprechpartner',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epevents_domain_model_contact',
'foreign_table_where' => 'AND 1=1 order by name',
@@ -461,6 +464,7 @@ return [
'label' => 'Unterkunft',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epevents_domain_model_hotel',
'foreign_table_where' => 'AND 1=1 order by name',
@@ -473,6 +477,7 @@ return [
'label' => 'Location',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epevents_domain_model_location',
'foreign_table_where' => 'AND 1=1 order by name',
@@ -35,6 +35,7 @@ return [
'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',
@@ -49,6 +50,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -38,6 +38,7 @@ return [
'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',
@@ -52,12 +53,13 @@ return [
'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_epevents_domain_model_offer',
'foreign_table_where' => 'AND tx_epevents_domain_model_offer.pid=###CURRENT_PID### AND tx_epevents_domain_model_offer.sys_language_uid IN (-1,0)',
'foreign_table' => 'tx_epevents_domain_model_traveltype',
'foreign_table_where' => 'AND tx_epevents_domain_model_traveltype.pid=###CURRENT_PID### AND tx_epevents_domain_model_traveltype.sys_language_uid IN (-1,0)',
],
],
'l10n_diffsource' => [
@@ -4,9 +4,6 @@ import Vue from 'vue'
import $ from 'jquery'
import VueSession from 'vue-session'
import 'lazysizes';
import 'lazysizes/plugins/attrchange/ls.attrchange';
const slick = require('slick-carousel');
const Sticky = require('sticky-js');
const $window = $(window);
@@ -38,9 +38,9 @@
<div class="card card--no-form offerlist-item__card">
<div class="card__inner">
<picture>
<source media="(max-width: 512px)" :data-srcset="offer.teaserImageMobile + ' 500w'"/>
<img class="card__image scale lazyload" data-sizes="auto"
:data-src="offer.teaserImage" alt="">
<source media="(max-width: 512px)" :srcset="offer.teaserImageMobile"/>
<img class="card__image scale"
:src="offer.teaserImage" alt="" loading="lazy">
</picture>
<div class="card__caption">
<span class="card__subtitle" v-html="offer.name"></span>
@@ -4,6 +4,7 @@ return [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_badge',
'default_sortby' => 'ORDER BY title',
'label' => 'title',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -18,7 +19,7 @@ return [
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'headline,subline',
'searchFields' => 'title,subtitle',
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
],
'types' => [
@@ -35,6 +36,7 @@ return [
'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',
@@ -49,6 +51,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -4,6 +4,7 @@ return [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_city',
'default_sortby' => 'ORDER BY name',
'label' => 'name_internal',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -40,6 +41,7 @@ return [
'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',
@@ -54,6 +56,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -405,6 +408,7 @@ return [
'label' => 'Land',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_country',
'minitems' => 1,
@@ -416,6 +420,7 @@ return [
'label' => 'Gebiet',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_region',
'minitems' => 1,
@@ -427,6 +432,7 @@ return [
'label' => 'Officetipp',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_officetip',
'items' => [
@@ -5,6 +5,7 @@ return [
'default_sortby' => 'ORDER BY name',
'sortby' => 'sorting',
'label' => 'name',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -43,6 +44,7 @@ return [
'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',
@@ -57,6 +59,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -20,7 +20,7 @@ return [
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'code',
'searchFields' => 'room_code,room_label',
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
],
'types' => [
@@ -34,6 +34,7 @@ return [
'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',
@@ -48,6 +49,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -145,6 +147,7 @@ return [
'label' => 'Unterkunft',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_hotel',
'minitems' => 1,
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_country',
'label' => 'name_internal',
'prependAtCopy' => '[COPY %s]',
'default_sortby' => 'ORDER BY name_internal',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
@@ -42,6 +43,7 @@ return [
'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',
@@ -56,6 +58,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -387,6 +390,7 @@ return [
'label' => 'Officetipp',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_officetip',
'items' => [
@@ -401,6 +405,7 @@ return [
'label' => 'Gebiet für Schneehöhen',
'config' => [
'type' => 'select',
'default' => 0,
'items' => [
['Keine Zuordnung', 0]
],
@@ -38,6 +38,7 @@ return [
'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',
@@ -52,6 +53,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -142,6 +144,57 @@ return [
'type' => 'passthrough',
],
],
// Denormalized columns written by DateImportService, which rebuilds this table
// wholesale. They are TEXT NOT NULL, and MySQL cannot default that, so without a
// TCA entry DataHandler omits them and every INSERT fails under STRICT_TRANS_TABLES.
'product_keywords' => [
'exclude' => true,
'config' => [
'type' => 'passthrough',
],
],
'product_teaser' => [
'exclude' => true,
'config' => [
'type' => 'passthrough',
],
],
'concept_popup_text' => [
'exclude' => true,
'config' => [
'type' => 'passthrough',
],
],
'country_keywords' => [
'exclude' => true,
'config' => [
'type' => 'passthrough',
],
],
'region_keywords' => [
'exclude' => true,
'config' => [
'type' => 'passthrough',
],
],
'city_keywords' => [
'exclude' => true,
'config' => [
'type' => 'passthrough',
],
],
'hotel_keywords' => [
'exclude' => true,
'config' => [
'type' => 'passthrough',
],
],
'hotel_teaser' => [
'exclude' => true,
'config' => [
'type' => 'passthrough',
],
],
'bus_pro_id' => [
'exclude' => false,
'label' => 'BusPro ID',
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_fact',
'label' => 'label',
'prependAtCopy' => '[COPY %s]',
'default_sortby' => 'ORDER BY label',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
@@ -18,7 +19,7 @@ return [
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'name,tags,',
'searchFields' => 'name,label,keywords',
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
],
'types' => [
@@ -34,6 +35,7 @@ return [
'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',
@@ -48,6 +50,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_faq',
'label' => 'label',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -35,6 +36,7 @@ return [
'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',
@@ -49,6 +51,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -5,6 +5,7 @@ return [
'default_sortby' => 'ORDER BY price',
'sortby' => 'sorting',
'label' => 'title',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -52,6 +53,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -55,6 +55,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -5,6 +5,7 @@ return [
'default_sortby' => 'ORDER BY price',
'sortby' => 'sorting',
'label' => 'title',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -53,6 +54,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -4,6 +4,7 @@ return [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_hotel',
'default_sortby' => 'ORDER BY name',
'label' => 'name',
'prependAtCopy' => '[COPY %s]',
'label_userFunc' => \EP\EpProducts\Service\LabelService::class . '->getHotelLabel',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
@@ -51,6 +52,7 @@ return [
'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',
@@ -65,6 +67,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -488,6 +491,7 @@ return [
'label' => 'Land',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_country',
'minitems' => 1,
@@ -499,6 +503,7 @@ return [
'label' => 'Gebiet',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_region',
'minitems' => 1,
@@ -510,6 +515,7 @@ return [
'label' => 'Ort',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_city',
'minitems' => 1,
@@ -49,12 +49,13 @@ return [
'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_infobox',
'foreign_table_where' => 'AND tx_epproducts_domain_model_infobox.pid=###CURRENT_PID### AND tx_epproducts_domain_model_infobox.sys_language_uid IN (-1,0)',
'foreign_table' => 'tx_epproducts_domain_model_hotel_mapping',
'foreign_table_where' => 'AND tx_epproducts_domain_model_hotel_mapping.pid=###CURRENT_PID### AND tx_epproducts_domain_model_hotel_mapping.sys_language_uid IN (-1,0)',
],
],
'l10n_diffsource' => [
@@ -114,6 +115,7 @@ return [
'label' => 'Produkt',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_product',
'minitems' => 1,
@@ -4,6 +4,7 @@ return [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_infobox',
'default_sortby' => 'ORDER BY title',
'label' => 'title',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -18,7 +19,7 @@ return [
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'name',
'searchFields' => 'title,text',
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
],
'types' => [
@@ -51,6 +52,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -4,6 +4,7 @@ return [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_journey',
'default_sortby' => 'ORDER BY name',
'label' => 'name',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -33,6 +34,7 @@ return [
'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',
@@ -47,12 +49,13 @@ return [
'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_city',
'foreign_table_where' => 'AND tx_epproducts_domain_model_city.pid=###CURRENT_PID### AND tx_epproducts_domain_model_city.sys_language_uid IN (-1,0)',
'foreign_table' => 'tx_epproducts_domain_model_journey',
'foreign_table_where' => 'AND tx_epproducts_domain_model_journey.pid=###CURRENT_PID### AND tx_epproducts_domain_model_journey.sys_language_uid IN (-1,0)',
],
],
'l10n_diffsource' => [
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_matchcode',
'label' => 'code',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -34,6 +35,7 @@ return [
'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',
@@ -48,6 +50,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_officetip',
'label' => 'label',
'prependAtCopy' => '[COPY %s]',
'label_userFunc' => \EP\EpProducts\Service\LabelService::class . '->getOfficetipLabel',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
@@ -18,7 +19,7 @@ return [
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'text,author,product,',
'searchFields' => 'label,text,author',
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
],
'types' => [
@@ -34,6 +35,7 @@ return [
'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',
@@ -48,6 +50,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -133,6 +136,7 @@ return [
'label' => 'Autor',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_teammember',
'minitems' => 1,
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_product',
'label' => 'name_internal',
'prependAtCopy' => '[COPY %s]',
'label_userFunc' => \EP\EpProducts\Service\LabelService::class . '->getProductLabel',
'default_sortby' => 'ORDER BY name_internal',
'tstamp' => 'tstamp',
@@ -54,6 +55,7 @@ return [
'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',
@@ -68,6 +70,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -631,6 +634,7 @@ return [
'label' => 'Konzept',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_concept',
'foreign_table_where' => 'AND 1=1 ORDER BY name',
@@ -643,6 +647,7 @@ return [
'label' => 'Land',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_country',
'foreign_table_where' => 'AND 1=1 ORDER BY name',
@@ -655,6 +660,7 @@ return [
'label' => 'Gebiet',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_region',
'foreign_table_where' => 'AND 1=1 ORDER BY name',
@@ -667,6 +673,7 @@ return [
'label' => 'Stadt/Ort',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_city',
'foreign_table_where' => 'AND 1=1 ORDER BY name',
@@ -679,6 +686,7 @@ return [
'label' => 'Anreise',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_journey',
'foreign_table_where' => 'AND 1=1 ORDER BY name',
@@ -735,6 +743,7 @@ return [
'label' => 'Unterkunft für Belegungskalender',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_hotel',
'foreign_table_where' => 'AND 1=1 ORDER BY tx_epproducts_domain_model_hotel.name',
@@ -748,6 +757,7 @@ return [
'label' => 'Officetipp',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_officetip',
'items' => [
@@ -787,6 +797,7 @@ return [
'label' => 'Produkt',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_product',
'foreign_table_where' => 'AND tx_epproducts_domain_model_product.uid != ###THIS_UID### ORDER BY tx_epproducts_domain_model_product.name_internal',
@@ -858,6 +869,7 @@ return [
'label' => 'Badge',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_badge',
'foreign_table_where' => 'AND tx_epproducts_domain_model_badge.deleted = 0 ORDER BY tx_epproducts_domain_model_badge.title',
@@ -873,6 +885,7 @@ return [
'label' => 'Infobox nicht buchbar',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_infobox',
'foreign_table_where' => 'AND tx_epproducts_domain_model_infobox.deleted = 0 ORDER BY tx_epproducts_domain_model_infobox.title',
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_region',
'label' => 'name_internal',
'prependAtCopy' => '[COPY %s]',
'default_sortby' => 'ORDER BY name_internal',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
@@ -45,6 +46,7 @@ return [
'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',
@@ -59,6 +61,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -480,6 +483,7 @@ return [
'label' => 'Land',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_country',
'minitems' => 1,
@@ -515,6 +519,7 @@ return [
'label' => 'Officetip',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_officetip',
'items' => [
@@ -529,6 +534,7 @@ return [
'label' => 'Gebiet für Schneehöhen',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['Keine Zuordnung', 0]
@@ -544,6 +550,7 @@ return [
'label' => 'Webcam',
'config' => [
'type' => 'select',
'default' => 0,
'items' => [
['Keine Zuordnung', 0]
],
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_reseller',
'label' => 'name',
'prependAtCopy' => '[COPY %s]',
'default_sortby' => 'ORDER BY name',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
@@ -32,6 +33,7 @@ return [
'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',
@@ -46,6 +48,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -3,6 +3,7 @@ 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',
@@ -18,7 +19,7 @@ return [
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'name,tags,',
'searchFields' => 'code',
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
],
'types' => [
@@ -34,6 +35,7 @@ return [
'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',
@@ -48,6 +50,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_snowreport',
'label' => 'region_name',
'prependAtCopy' => '[COPY %s]',
'default_sortby' => 'ORDER BY region_name',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
@@ -18,7 +19,7 @@ return [
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'regionName,',
'searchFields' => 'region_name',
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
],
'types' => [
@@ -35,6 +36,7 @@ return [
'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',
@@ -49,6 +51,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_staticsearchparams',
'label' => 'name',
'prependAtCopy' => '[COPY %s]',
'default_sortby' => 'ORDER BY name',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
@@ -35,6 +36,7 @@ return [
'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',
@@ -49,12 +51,13 @@ return [
'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_product',
'foreign_table_where' => 'AND tx_epproducts_domain_model_product.pid=###CURRENT_PID### AND tx_epproducts_domain_model_product.sys_language_uid IN (-1,0)',
'foreign_table' => 'tx_epproducts_domain_model_staticsearchparams',
'foreign_table_where' => 'AND tx_epproducts_domain_model_staticsearchparams.pid=###CURRENT_PID### AND tx_epproducts_domain_model_staticsearchparams.sys_language_uid IN (-1,0)',
],
],
'l10n_diffsource' => [
@@ -156,6 +159,7 @@ return [
'label' => 'Land',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_country',
'foreign_table_where' => 'AND 1=1 ORDER BY name',
@@ -171,6 +175,7 @@ return [
'label' => 'Gebiet',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_region',
'foreign_table_where' => 'AND 1=1 ORDER BY name',
@@ -186,6 +191,7 @@ return [
'label' => 'Hotel',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tx_epproducts_domain_model_hotel',
'foreign_table_where' => 'AND 1=1 ORDER BY tx_epproducts_domain_model_hotel.name',
@@ -4,6 +4,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_teammember',
'label' => 'name',
'prependAtCopy' => '[COPY %s]',
'default_sortby' => 'ORDER BY name',
'sortby' => 'sorting',
'tstamp' => 'tstamp',
@@ -39,6 +40,7 @@ return [
'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',
@@ -53,6 +55,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -4,9 +4,11 @@ return [
'title' => 'Reiseinformationen',
'default_sortby' => 'ORDER BY title',
'label' => 'title',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'origUid' => 't3_origuid',
'dividers2tabs' => true,
'versioningWS' => true,
'languageField' => 'sys_language_uid',
@@ -18,7 +20,7 @@ return [
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'name',
'searchFields' => 'title,travel_code',
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
],
'types' => [
@@ -55,12 +57,13 @@ return [
'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_infobox',
'foreign_table_where' => 'AND tx_epproducts_domain_model_infobox.pid=###CURRENT_PID### AND tx_epproducts_domain_model_infobox.sys_language_uid IN (-1,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' => [
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'Reiseinfo Link',
'label' => 'title',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
@@ -51,12 +52,13 @@ return [
'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_faq',
'foreign_table_where' => 'AND tx_epproducts_domain_model_faq.pid=###CURRENT_PID### AND tx_epproducts_domain_model_faq.sys_language_uid IN (-1,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' => [
@@ -3,9 +3,11 @@ return [
'ctrl' => [
'title' => 'Reiseinfo Teaser',
'label' => 'title',
'prependAtCopy' => '[COPY %s]',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'origUid' => 't3_origuid',
'dividers2tabs' => true,
'versioningWS' => true,
'hideTable' => true,
@@ -51,12 +53,13 @@ return [
'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_faq',
'foreign_table_where' => 'AND tx_epproducts_domain_model_faq.pid=###CURRENT_PID### AND tx_epproducts_domain_model_faq.sys_language_uid IN (-1,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' => [
@@ -3,6 +3,7 @@ return [
'ctrl' => [
'title' => 'LLL:EXT:ep_products/Resources/Private/Language/locallang.xlf:tx_epproducts_domain_model_webcam',
'label' => 'name',
'prependAtCopy' => '[COPY %s]',
'default_sortby' => 'ORDER BY name',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
@@ -33,6 +34,7 @@ return [
'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',
@@ -47,12 +49,13 @@ return [
'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_snowreport',
'foreign_table_where' => 'AND tx_epproducts_domain_model_snowreport.pid=###CURRENT_PID### AND tx_epproducts_domain_model_snowreport.sys_language_uid IN (-1,0)',
'foreign_table' => 'tx_epproducts_domain_model_webcam',
'foreign_table_where' => 'AND tx_epproducts_domain_model_webcam.pid=###CURRENT_PID### AND tx_epproducts_domain_model_webcam.sys_language_uid IN (-1,0)',
],
],
'l10n_diffsource' => [
@@ -152,6 +155,7 @@ return [
'label' => 'Skigebiet',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingleBox',
'foreign_table' => 'tx_epproducts_domain_model_snowreport',
],
@@ -26,7 +26,6 @@ CREATE TABLE tx_epproducts_domain_model_product
external_link varchar(255) DEFAULT '' NOT NULL,
tour_link varchar(255) DEFAULT '' NOT NULL,
path_segment varchar(255) DEFAULT '' NOT NULL,
description text NOT NULL,
teaser text NOT NULL,
teaser_long text NOT NULL,
header_title varchar(255) DEFAULT '' NOT NULL,
@@ -1,49 +0,0 @@
<?php
namespace EP\EpTheme\ViewHelpers;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\ViewHelpers\ImageViewHelper;
class LazyLoadImageViewHelper extends ImageViewHelper
{
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('loaderimg', 'string', '', false);
}
public function render(): string
{
parent::render();
$src = $this->tag->getAttribute('src');
$this->tag->removeAttribute('src');
$this->tag->addAttribute('data', ['src' => $src], false);
if (isset($this->arguments['loaderimg'])) {
$loaderImage = $this->imageService->getImage($this->arguments['loaderimg'], null, false);
$processingInstructions = [
'width' => $this->arguments['width'],
'height' => $this->arguments['height'],
'minWidth' => $this->arguments['minWidth'],
'minHeight' => $this->arguments['minHeight'],
'maxWidth' => $this->arguments['maxWidth'],
'maxHeight' => $this->arguments['maxHeight'],
];
$processedLoaderImage = $this->imageService->applyProcessingInstructions($loaderImage, $processingInstructions);
$loaderImageUri = $this->imageService->getImageUri($processedLoaderImage, $this->arguments['absolute']);
$this->tag->addAttribute('src', $loaderImageUri);
}
$classes = $this->tag->getAttribute('class');
$classItems = GeneralUtility::trimExplode(' ', $classes, true);
$classItems[] = 'lazyload';
$classes = implode(' ', array_unique($classItems));
$this->tag->addAttribute('class', $classes);
// ensure a11y compliance
$this->tag->removeAttribute('title');
return $this->tag->render();
}
}
@@ -35,6 +35,7 @@ return [
'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',
@@ -49,6 +50,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -37,6 +37,7 @@ return [
'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',
@@ -51,6 +52,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -211,6 +213,7 @@ return [
'label' => 'LLL:EXT:ep_theme/Resources/Private/Language/locallang_db.xlf:tx_eptheme_domain_model_lineup.tt_content',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tt_content',
'minitems' => 0,
@@ -39,6 +39,7 @@ return [
'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',
@@ -53,6 +54,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
@@ -242,6 +244,7 @@ return [
'label' => 'LLL:EXT:ep_theme/Resources/Private/Language/locallang_db.xlf:tx_eptheme_domain_model_slide.page',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'pages',
'minitems' => 0,
@@ -15,3 +15,10 @@ module.tx_form.settings.yamlConfigurations {
1630994710 = EXT:ep_theme/Configuration/Yaml/FormsBase.yaml
1630994711 = EXT:ep_theme/Configuration/Yaml/FormFinishersBackend.yaml
}
plugin.tx_bwcaptcha.settings {
charset = abcdefghjkmnpqrtuvwxy34679
length = 4
width = 220
height = 60
}
@@ -0,0 +1,10 @@
config.tx_replacer {
enable_regex = 1
search {
10 = /"\/?(fileadmin|typo3temp|uploads)/
}
replace {
10 = "https://cdn.ep-reisen.de/$1
}
}
@@ -1,8 +1,3 @@
// Import dependencies
require('lazysizes')
require('lazysizes/plugins/unveilhooks/ls.unveilhooks')
// require('picturefill')
// Polyfills
// import smoothscroll from 'smoothscroll-polyfill'
// smoothscroll.polyfill()
@@ -1,791 +0,0 @@
<template>
<div class="relative">
<div class="mb-8"
v-show="!submitted">
<label class="mb-2 font-bold">
Zeitraum
</label>
<input type="text"
class="form-field"
placeholder="von... bis" ref="picker"/>
<p class="text-sm mt-2" v-if="mainSeasonFrom && mainSeasonTo">
in der Hauptsaison {{ mainSeasonFrom }}-{{ mainSeasonTo }} mind. {{ minBookingDays }} Tage
</p>
<p class="text-sm italic mt-2"
v-show="nightsCount === 1">
Einzelne Nächte sind nur auf Anfrage buchbar
</p>
</div>
<div class="mb-8 grid sm:grid-cols-2 gap-8"
v-show="!submitted">
<div>
<label class="mb-2 font-bold">
Personenzahl
</label>
<input type="number"
class="form-field"
min="30"
v-model.number="selectedPax"
@change="onPaxUpdated()"
v-show="nightsCount > 0"/>
<p class="text-sm italic"
v-show="nightsCount === 0">
Bitte zuerst einen Zeitraum wählen
</p>
</div>
<div>
<label class="mb-2 font-bold">
davon Kinder 0-3 Jahre
</label>
<input type="number"
class="form-field"
min="0"
v-model.number="childrenCount"
@change="onPaxUpdated()"
v-show="nightsCount > 0"/>
<p class="text-sm italic"
v-show="nightsCount === 0">
Bitte zuerst einen Zeitraum wählen
</p>
<p class="text-sm italic"
v-show="nightsCount > 0">
Kinder werden nur bei Strom- und Abfallgebühren berücksichtigt.
</p>
</div>
<div>
<label class="mb-2 font-bold">
davon Kinder 4-5 Jahre*
</label>
<input type="number"
class="form-field"
min="0"
v-model.number="minorsCount"
@change="onPaxUpdated()"
v-show="nightsCount > 0"/>
<p class="text-sm italic"
v-show="nightsCount === 0">
Bitte zuerst einen Zeitraum wählen
</p>
</div>
<div v-if="adolescentsAge > 0">
<label class="mb-2 font-bold">
davon Kinder 6-{{ adolescentsAge }} Jahre*
</label>
<input type="number"
class="form-field"
min="0"
v-model.number="adolescentsCount"
@change="onPaxUpdated()"
v-show="nightsCount > 0"/>
<p class="text-sm italic"
v-show="nightsCount === 0">
Bitte zuerst einen Zeitraum wählen
</p>
</div>
<div class="sm:col-span-2 text-sm">
*Die Kosten für Essen und Kurtaxe werden wir entsprechend der Altersstruktur der Gäste in der Rechnung
anpassen.
</div>
</div>
<div class="mb-8"
v-show="options.length > 0 && !submitted">
<div class="mb-2 font-bold">
Optionale Zusatzleistungen
</div>
<ul class="mb-0 p-0 space-y-2">
<li v-for="option of options" :key="option.uid">
<label class="flex items-start">
<input type="checkbox"
class="w-5 h-5 border-ep-primary-light ring-0 bg-transparent focus:ring-0 focus:border-none text-ep-primary"
v-model="selectedOptions"
:value="option">
<span class="pl-2 leading-none">{{ option.title }}{{ formatOptionPriceType(option) }}</span>
</label>
</li>
</ul>
</div>
<div class="mb-8"
v-show="boards.length > 0 && !submitted">
<label class="mb-2 font-bold">
Verpflegungsleistungen
</label>
<select class="form-field"
v-model="selectedBoard"
v-if="selectedPax >= 30">
<option :value="null" disabled>bitte auswählen</option>
<option v-for="board of boards"
:value="board"
:key="board.uid">
{{ board.title }} ({{ formatCurrency(board.price) }} pro Person und Nacht)
</option>
</select>
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.board"
v-html="formErrors.board"></div>
<div v-show="selectedPax < 30">
<span class="text-red-600">Erst ab 30 Personen buchbar.</span>
</div>
</div>
<div class="mb-8">
<div class="pb-2" v-if="submitted">
<p class="text-lg font-bold pb-2">
Vielen Dank für Deine {{ mode === 'booking' ? 'Buchung' : 'Anfrage' }}.
</p>
<p>
Für folgendes habt ihr euch entschieden:
</p>
</div>
<div class="p-2 uppercase bg-ep-primary-dark text-white w-full">
Preise
</div>
<div class="bg-zinc-100 p-2 mb-2">
<table class="w-full" v-show="nightsCount > 0">
<tbody>
<tr class="odd:bg-zinc-100">
<th class="text-left py-2">Zeitraum</th>
<td>{{ rangeFormatted }}, {{ nightsCount }} Nächte</td>
</tr>
<tr class="odd:bg-zinc-100">
<th class="text-left py-2">Personenzahl</th>
<td>
{{ selectedPax }}<span v-if="childrenCount > 0">, davon Kinder {{ childrenCount }}</span>
</td>
</tr>
<tr class="odd:bg-zinc-100">
<th class="text-left py-2">Basispreis</th>
<td>{{ formatCurrency(pricePax.base) }}</td>
</tr>
<tr class="odd:bg-zinc-100"
v-if="pricePax.additional.EUR > 0 || pricePax.additional.CHF > 0">
<th class="text-left py-2">Aufpreis Personenzahl</th>
<td>{{ formatCurrency(pricePax.additional) }}</td>
</tr>
<tr class="odd:bg-zinc-100"
v-if="priceShortTerm.EUR > 0 || priceShortTerm.CHF > 0">
<th class="text-left py-2">Aufpreis Kurzzeit</th>
<td>{{ formatCurrency(priceShortTerm) }}</td>
</tr>
<tr class="odd:bg-zinc-100"
v-for="selectedOption in selectedOptions">
<th class="text-left py-2">{{ selectedOption.title }}</th>
<td>{{ formatCurrency(calculateOptionPrice(selectedOption)) }}</td>
</tr>
<tr class="odd:bg-zinc-100"
v-if="priceBoard.EUR > 0 || priceBoard.CHF > 0">
<th class="text-left py-2">{{ selectedBoard.title }}</th>
<td>{{ formatCurrency(priceBoard) }}</td>
</tr>
<tr class="odd:bg-zinc-100"
v-if="false === isSelfCatering && undersubscriptionLimit > 0">
<th class="text-left py-2">Verpflegungs-Aufschlag für Gruppen unter {{ undersubscriptionLimit }} Personen</th>
<td>{{ formatCurrency(pricePax.undersubscription) }}</td>
</tr>
<tr class="odd:bg-zinc-100"
v-if="priceRunningCosts.EUR > 0 || priceRunningCosts.CHF > 0">
<th class="text-left py-2">Strom- und Abfallgebühren</th>
<td>{{ formatCurrency(priceRunningCosts) }}</td>
</tr>
<tr class="odd:bg-zinc-100">
<th class="text-left py-2">Gesamtpreis</th>
<td>
<strong>{{ formatCurrency(priceTotal) }}</strong>
<br>
<small>{{ taxLabel }}</small>
</td>
</tr>
</tbody>
</table>
<p class="text-sm italic"
v-show="nightsCount === 0">
Bitte zuerst einen Zeitraum wählen
</p>
</div>
<div v-if="mode === 'booking' && submitted">
Bitte beachtet, dass die Buchung bei uns eingegangen, aber <strong>noch nicht bestätigt</strong> ist.
Wir behalten uns vor, die Buchungen auf Verfügbarkeit und Länge des gewünschten Aufenthalts zu prüfen.
Erst wenn wir euch die Buchung per Mail bestätigt haben, wird sie bindend.
</div>
<div v-if="mode === 'inquiry' && submitted">
Die Anfrage ist bei uns eingegangen und wird schnellstmöglich bearbeitet. Wir melden uns telefonisch
oder per Mail bei euch.
</div>
</div>
<div class="mb-8"
v-show="nightsCount > 0 && !submitted">
<div class="p-2 uppercase bg-ep-primary-dark text-white w-full">
Jetzt <span v-if="!forceInquiry">buchen</span><span v-if="forceInquiry">anfragen</span>
</div>
<div class="bg-zinc-100 p-2">
<div class="grid md:grid-cols-2 gap-4 mb-4">
<div :class="{ 'has-error': formErrors.name }">
<label class="font-bold mb-2">
Name*
</label>
<input type="text"
class="form-field"
v-model="name">
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.name"
v-html="formErrors.name"></div>
</div>
<div :class="{ 'has-error': formErrors.street }">
<label class="font-bold mb-2">
Strasse, Nr.*
</label>
<input type="text"
class="form-field"
v-model="street">
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.street"
v-html="formErrors.street"></div>
</div>
<div :class="{ 'has-error': formErrors.postcode }">
<label class="font-bold mb-2">
Postleitzahl*
</label>
<input type="text"
class="form-field"
v-model="postcode">
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.postcode"
v-html="formErrors.postcode"></div>
</div>
<div :class="{ 'has-error': formErrors.city }">
<label class="font-bold mb-2">
Ort*
</label>
<input type="text"
class="form-field"
v-model="city">
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.city"
v-html="formErrors.city"></div>
</div>
<div :class="{ 'has-error': formErrors.group }">
<label class="font-bold mb-2">
Name der Gruppe*
</label>
<input type="text"
class="form-field"
v-model="group">
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.group"
v-html="formErrors.group"></div>
</div>
<div :class="{ 'has-error': formErrors.email }">
<label class="font-bold mb-2">
E-Mail*
</label>
<input type="text"
class="form-field"
v-model="email">
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.email"
v-html="formErrors.email"></div>
</div>
<div :class="{ 'has-error': formErrors.phone }">
<label class="font-bold mb-2">
Telefon*
</label>
<input type="text"
class="form-field"
v-model="phone">
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.phone"
v-html="formErrors.phone"></div>
</div>
<div>
<label class="font-bold mb-2">
Bemerkungen/Wünsche
</label>
<textarea class="form-field"
cols="30"
rows="3"
v-model="remarks"/>
</div>
<div v-if="mode === 'booking'" :class="{ 'has-error': formErrors.confirmation }">
<label for="confirmation" class="flex items-start">
<input type="checkbox" v-model="confirmation" name="confirmation" id="confirmation">
<span class="block ml-2">
Durch Anklicken des Buttons 'Buchung abschicken' bestätige ich, dass ich die
<a :href="termsUrls[countryCode]"
class="text-ep-primary" target="_blank">
Allgemeinen Geschäftsbedingungen (AGB)
</a> gelesen habe und damit einverstanden bin, dass eine
kostenpflichtige Buchung zustande kommt.
</span>
</label>
<div class="text-sm text-red-600 mt-1"
v-show="formErrors.confirmation"
v-html="formErrors.confirmation"></div>
</div>
</div>
<div class="py-4">
Ihr erhaltet von uns eine Bestätigung. Wir behalten uns vor die Buchung zu prüfen. Erst nach
Rückbestätigung von uns gilt die Buchung auch von unserer Seite als bindend.
</div>
<div class="flex items-center space-x-2">
<button class="button bg-button"
type="submit"
v-if="!forceInquiry"
@click.prevent="submitForm('booking')">
Buchung abschicken
</button>
<button class="button bg-button"
:class="{ 'button--small bg-ep-secondary': !forceInquiry }"
type="submit"
@click.prevent="submitForm('inquiry')">
als Anfrage senden
</button>
</div>
</div>
</div>
<div>
<img :src="logoAt" alt="" v-if="countryCode === 'AT'" class="block w-full h-auto max-w-24">
<img :src="logoCh" alt="" v-if="countryCode === 'CH'" class="block w-full h-auto max-w-24">
</div>
<div class="fixed top-0 left-0 inset-0 bg-white/85 flex items-center justify-center" v-show="processing">
<img :src="loaderUri" alt="Loading...">
</div>
</div>
</template>
<script>
import dayjs from 'dayjs'
import 'dayjs/locale/de'
import 'flatpickr';
import {German} from 'flatpickr/dist/l10n/de';
import Vue from 'vue';
export default {
name: 'GroupsPriceCalculator',
props: {
loaderUri: {
type: String,
required: true
},
endpoint: {
type: String,
required: true
},
logoAt: {
type: String,
},
logoCh: {
type: String,
},
configsJson: {
type: String,
required: true
},
boardsJson: {
type: String,
required: true
},
optionsJson: {
type: String,
required: true
},
runningCostsFactorEur: {
type: Number,
default: 2.5,
},
runningCostsFactorChf: {
type: Number,
default: 2.9,
},
undersubscription30Eur: {
type: Number,
default: 5.0,
},
undersubscription30Chf: {
type: Number,
default: 5.0,
},
undersubscription40Eur: {
type: Number,
default: 2.5,
},
undersubscription40Chf: {
type: Number,
default: 2.5,
},
countryCode: {
type: String,
required: true
},
shortTermFactors: {
type: Array,
default() {
return [
{ nights: 1, factor: 0.3 },
{ nights: 2, factor: 0.2 },
{ nights: 3, factor: 0.1 },
]
}
},
mainSeasonFrom: {
type: String,
default: null,
},
mainSeasonTo: {
type: String,
default: null,
},
minBookingDays: {
type: Number,
default: 5,
},
taxLabel: {
type: String,
default: 'zzgl. vorab zu entrichtender Ortstaxe',
},
adolescentsAge: {
type: Number,
default: 0,
}
},
data() {
return {
configs: JSON.parse(this.configsJson),
boards: JSON.parse(this.boardsJson),
options: JSON.parse(this.optionsJson),
processing: false,
submitted: false,
picker: null,
formErrors: {},
selectedFrom: null,
selectedTo: null,
selectedRange: [],
selectedPax: 30,
childrenCount: 0,
minorsCount: 0,
adolescentsCount: 0,
selectedOptions: [],
selectedBoard: null,
name: '',
email: '',
phone: '',
remarks: '',
group: '',
street: '',
postcode: '',
city: '',
mode: 'booking',
confirmation: false,
termsUrls: {
AT: 'https://www.ep-reisen.de/fileadmin/user_upload/allgemein/AGB_Gruppen/AGB_Gruppen_CLLT_Touristik_GmbH.pdf',
CH: 'https://www.ep-reisen.de/fileadmin/user_upload/allgemein/AGB_Gruppen/AVB_Gruppen_AlpineVacation_GmbH.pdf',
IT: 'https://www.ep-reisen.de/fileadmin/user_upload/allgemein/AGB_Gruppen/AGB_Gruppen_E_P_Reisen.pdf',
}
}
},
methods: {
formatCurrency({ EUR, CHF }) {
let price
if ('CH' === this.countryCode) {
let formatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'CHF',
})
price = formatter.format(CHF)
} else {
let formatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR',
})
price = formatter.format(EUR)
}
return price
},
calculateOptionPrice(option) {
let price = {
EUR: 0,
CHF: 0,
};
let optionPriceEUR = option.price.EUR
let optionPriceCHF = option.price.CHF
if (1 === option.type) {
price.EUR = optionPriceEUR;
price.CHF = optionPriceCHF;
} else if (2 === option.type) {
price.EUR = optionPriceEUR * this.paxCount;
price.CHF = optionPriceCHF * this.paxCount;
} else if (3 === option.type) {
price.EUR = optionPriceEUR * this.nightsCount;
price.CHF = optionPriceCHF * this.nightsCount;
} else if (4 === option.type) {
price.EUR = optionPriceEUR * this.nightsCount * this.paxCount;
price.CHF = optionPriceCHF * this.nightsCount * this.paxCount;
}
return price;
},
formatOptionPriceType(option) {
if (2 === option.type) {
return ` (${this.formatCurrency(option.price)} pro Person)`
}
if (3 === option.type) {
return ` (${this.formatCurrency(option.price)} pro Nacht)`
}
if (4 === option.type) {
return ` (${this.formatCurrency(option.price)} pro Person und Nacht)`
}
return ` (${this.formatCurrency(option.price)})`
},
initSelectableRanges() {
let enabledDates = [];
for (let config of this.configs) {
const dateFrom = dayjs(config.dateFrom);
const dateTo = dayjs(config.dateTo);
enabledDates.push({
from: dateFrom.format('DD.MM.YYYY'),
to: dateTo.format('DD.MM.YYYY')
});
}
this.picker.set('enable', enabledDates);
if (enabledDates.length > 0) {
const firstDate = enabledDates[0].from;
this.picker.set('minDate', firstDate);
}
},
updateSelectedRange() {
let range = [];
let currentDate = this.selectedFrom;
while (currentDate < this.selectedTo) {
range.push(currentDate);
currentDate = currentDate.add(1, 'day');
}
this.selectedRange = range;
},
onPaxUpdated() {
if (this.selectedPax < 30) {
this.selectedBoard = null;
}
},
submitForm(mode) {
this.mode = mode
let confirmation = 'inquiry' === mode ? true : this.confirmation
let formData = new URLSearchParams({
'tx_epproducts_ajax[groupsPriceInquiry][mode]': mode,
'tx_epproducts_ajax[groupsPriceInquiry][confirmation]': confirmation ? '1' : '0',
'tx_epproducts_ajax[groupsPriceInquiry][name]': this.name ? this.name : '',
'tx_epproducts_ajax[groupsPriceInquiry][group]': this.group ? this.group : '',
'tx_epproducts_ajax[groupsPriceInquiry][street]': this.street ? this.street : '',
'tx_epproducts_ajax[groupsPriceInquiry][postcode]': this.postcode ? this.postcode : '',
'tx_epproducts_ajax[groupsPriceInquiry][city]': this.city ? this.city : '',
'tx_epproducts_ajax[groupsPriceInquiry][email]': this.email? this.email : '',
'tx_epproducts_ajax[groupsPriceInquiry][phone]': this.phone ? this.phone : '',
'tx_epproducts_ajax[groupsPriceInquiry][remarks]': this.remarks,
'tx_epproducts_ajax[groupsPriceInquiry][dateFrom]': this.selectedFrom.format('DD.MM.YYYY'),
'tx_epproducts_ajax[groupsPriceInquiry][dateTo]': this.selectedTo.format('DD.MM.YYYY'),
'tx_epproducts_ajax[groupsPriceInquiry][nights]': this.nightsCount,
'tx_epproducts_ajax[groupsPriceInquiry][pax]': this.selectedPax,
'tx_epproducts_ajax[groupsPriceInquiry][children]': this.childrenCount,
'tx_epproducts_ajax[groupsPriceInquiry][minors]': this.minorsCount,
'tx_epproducts_ajax[groupsPriceInquiry][adolescents]': this.adolescentsCount,
'tx_epproducts_ajax[groupsPriceInquiry][summary][paxBase]': this.formatCurrency(this.pricePax.base),
'tx_epproducts_ajax[groupsPriceInquiry][summary][paxAdditional]': this.formatCurrency(this.pricePax.additional),
'tx_epproducts_ajax[groupsPriceInquiry][summary][undersubscription]': this.formatCurrency(this.pricePax.undersubscription),
'tx_epproducts_ajax[groupsPriceInquiry][summary][shortTerm]': this.formatCurrency(this.priceShortTerm),
'tx_epproducts_ajax[groupsPriceInquiry][summary][options]': this.formatCurrency(this.priceOptions),
'tx_epproducts_ajax[groupsPriceInquiry][summary][board]': this.formatCurrency(this.priceBoard),
'tx_epproducts_ajax[groupsPriceInquiry][summary][runningCosts]': this.formatCurrency(this.priceRunningCosts),
'tx_epproducts_ajax[groupsPriceInquiry][summary][total]': this.formatCurrency(this.priceTotal),
})
if (this.selectedBoard) {
formData.append('tx_epproducts_ajax[groupsPriceInquiry][board]', this.selectedBoard.uid)
}
this.selectedOptions.map(option => (
formData.append('tx_epproducts_ajax[groupsPriceInquiry][options][]', option.uid)
))
this.processing = true;
this.submitted = false;
fetch(this.endpoint, { method: 'POST', body: formData })
.then(response => response.json())
.then((json) => {
if ('validation' === json.status) {
this.formErrors = json.errors
} else {
this.submitted = true;
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'event': 'Preisberechnung'
})
}
})
.finally(() => {
this.processing = false
})
},
},
computed: {
isSelfCatering() {
let selectedBoard = this.selectedBoard
if (null === selectedBoard) {
return true
}
if ('CH' === this.countryCode) {
return selectedBoard.price.CHF === 0
} else {
return selectedBoard.price.EUR === 0
}
},
undersubscriptionLimit() {
if (this.paxCount < 40) {
return 40
} else if (this.paxCount < 50) {
return 50
}
return 0
},
paxCount() {
// subtract number of children from pax for price calculation, but minimum 30 pax
return Math.max(this.selectedPax - this.childrenCount, 30)
},
nightsCount() {
return this.selectedRange.length;
},
forceInquiry() {
return 1 === this.selectedRange.length
},
rangeFormatted() {
if (null === this.selectedFrom || null === this.selectedTo) {
return '-';
}
return this.selectedFrom.format('DD.MM.YYYY') + ' - ' + this.selectedTo.format('DD.MM.YYYY');
},
pricePax() {
let base = {
EUR: 0,
CHF: 0,
}
let additional = {
EUR: 0,
CHF: 0,
}
let undersubscription = {
EUR: 0,
CHF: 0,
}
for (let date of this.selectedRange) {
for (let config of this.configs) {
if (date >= dayjs(config.dateFrom) && date < dayjs(config.dateTo)) {
base.EUR += config.price.EUR
base.CHF += config.price.CHF
let included = config.personsIncluded
if (this.paxCount > included) {
let additionalPax = this.paxCount - included
additional.EUR += additionalPax * config.priceAdditionalPerson.EUR
additional.CHF += additionalPax * config.priceAdditionalPerson.CHF
}
}
}
}
if (false === this.isSelfCatering) {
if (this.paxCount < 40) {
undersubscription.EUR = this.paxCount * this.undersubscription30Eur * this.selectedRange.length
undersubscription.CHF = this.paxCount * this.undersubscription30Chf * this.selectedRange.length
} else if (this.paxCount < 50) {
undersubscription.EUR = this.paxCount * this.undersubscription40Eur * this.selectedRange.length
undersubscription.CHF = this.paxCount * this.undersubscription40Chf * this.selectedRange.length
}
}
return {base, additional, undersubscription}
},
priceOptions() {
let price = {
EUR: 0,
CHF: 0,
};
for (let option of this.selectedOptions) {
let optionPrice = this.calculateOptionPrice(option)
price.EUR += optionPrice.EUR;
price.CHF += optionPrice.CHF;
}
return price;
},
priceBoard() {
let price = {
EUR: 0,
CHF: 0,
}
if (this.selectedBoard) {
price.EUR = this.selectedBoard.price.EUR * this.nightsCount * this.paxCount;
price.CHF = this.selectedBoard.price.CHF * this.nightsCount * this.paxCount;
}
return price
},
priceShortTerm() {
let price = {
EUR: 0,
CHF: 0,
}
const totalPricePax = this.pricePax.base.EUR + this.pricePax.additional.EUR;
const totalPricePaxCHF = this.pricePax.base.CHF + this.pricePax.additional.CHF;
const shorTermFactor = this.shortTermFactors.find(element => element.nights === this.nightsCount);
if (undefined !== shorTermFactor) {
price.EUR = totalPricePax * shorTermFactor.factor;
price.CHF = totalPricePaxCHF * shorTermFactor.factor;
}
return price
},
priceRunningCosts() {
return {
EUR: this.nightsCount * this.selectedPax * this.runningCostsFactorEur,
CHF: this.nightsCount * this.selectedPax * this.runningCostsFactorChf,
}
},
priceTotal() {
let totalEUR = this.pricePax.base.EUR
+ this.pricePax.additional.EUR
+ this.pricePax.undersubscription.EUR
+ this.priceOptions.EUR
+ this.priceBoard.EUR
+ this.priceShortTerm.EUR
+ this.priceRunningCosts.EUR
let totalCHF = 0
// calculate CHF price when pax price in CHF is available since CHF prices may not be provided via CMS yet
if (0 < this.pricePax.base.CHF) {
totalCHF = this.pricePax.base.CHF
+ this.pricePax.additional.CHF
+ this.pricePax.undersubscription.CHF
+ this.priceOptions.CHF
+ this.priceBoard.CHF
+ this.priceShortTerm.CHF
+ this.priceRunningCosts.CHF
}
return {
EUR: totalEUR,
CHF: totalCHF,
}
}
},
mounted() {
Vue.nextTick(() => {
this.picker = flatpickr(this.$refs.picker, {
mode: 'range',
dateFormat: 'd.m.Y',
locale: German,
onChange: selectedDates => {
if (2 === selectedDates.length) {
this.selectedFrom = dayjs(selectedDates[0]);
this.selectedTo = dayjs(selectedDates[1]);
this.updateSelectedRange();
}
}
});
this.initSelectableRanges();
});
}
}
</script>
@@ -1,10 +0,0 @@
// Initialize vue app
import Vue from 'vue'
import vueCustomElement from 'vue-custom-element'
import 'document-register-element/build/document-register-element'
import GroupsPriceCalculator from './components/GroupsPriceCalculator'
Vue.use(vueCustomElement)
Vue.config.productionTip = false
Vue.customElement('groups-price-calculator', GroupsPriceCalculator)
@@ -3,7 +3,3 @@
@apply block w-full h-auto;
}
img.lazyloading {
background: url(../../images/lazy.png) no-repeat top center;
}
@@ -18,12 +18,12 @@
</f:if>
<f:if condition="{image}">
<f:then>
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{city.name}" />
<f:image image="{image}"
loading="lazy"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{city.name}" />
</f:then>
<f:else>
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png"
@@ -1,6 +1,5 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:section name="Teaser">
@@ -18,12 +17,12 @@
</f:if>
<f:if condition="{image}">
<f:then>
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{concept.name}" />
<f:image image="{image}"
loading="lazy"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{concept.name}" />
</f:then>
<f:else>
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png"
@@ -13,12 +13,12 @@
<div class="col-span-2 md:col-span-1">
<div class="relative max-w-md mx-auto mb-8">
<f:if condition="{image}">
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{image.alternative}" />
<f:image image="{image}"
loading="lazy"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{image.alternative}" />
</f:if>
<a href="tel:{settings.phoneNumber -> v:format.pregReplace(pattern: '/[\-\s]/', replacement: '')}"
rel="nofollow"
@@ -1,6 +1,5 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:alias map="{button: data.flexForm.buttons.0}">
@@ -11,11 +10,11 @@
<div class="col-md-6">
<a href="{f:uri.typolink(parameter: button.container.link)}" title="{button.container.label -> f:format.raw()}">
<f:if condition="{image}">
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto rounded-full"
width="400"
alt="{image.alternative}" />
<f:image image="{image}"
loading="lazy"
class="block w-full h-auto rounded-full"
width="400"
alt="{image.alternative}" />
</f:if>
</a>
</div>
@@ -11,12 +11,12 @@
<div class="md:flex md:items-start py-4">
<div class="px-16 pb-4 md:px-4 md:pb-0 md:w-1/6">
<f:if condition="{image}">
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{image.alternative}" />
<f:image image="{image}"
loading="lazy"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{image.alternative}" />
</f:if>
</div>
<div class="px-16 md:px-4 md:w-5/6 md:pl-8 text-center text-white md:text-left" data-rte-content>
@@ -14,12 +14,12 @@
<div class="col-span-2 md:col-span-1">
<div class="relative max-w-md mx-auto mb-8">
<f:if condition="{teaserImage}">
<ep:lazyLoadImage image="{teaserImage}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{teaserImage.alternative}" />
<f:image image="{teaserImage}"
loading="lazy"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{teaserImage.alternative}" />
</f:if>
<a href="tel:{settings.phoneNumber -> v:format.pregReplace(pattern: '/[\-\s]/', replacement: '')}"
rel="nofollow"
@@ -1,6 +1,5 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:alias map="{button: data.flexForm.buttons.0}">
@@ -11,11 +10,11 @@
<div class="col-md-6">
<a href="{f:uri.typolink(parameter: button.container.link)}" title="{button.container.label -> f:format.raw()}">
<f:if condition="{teaserImage}">
<ep:lazyLoadImage image="{teaserImage}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto rounded-full"
width="400"
alt="{teaserImage.alternative}" />
<f:image image="{teaserImage}"
loading="lazy"
class="block w-full h-auto rounded-full"
width="400"
alt="{teaserImage.alternative}" />
</f:if>
</a>
</div>
@@ -11,12 +11,12 @@
<div class="md:flex md:items-start py-4">
<div class="px-16 pb-4 md:px-4 md:pb-0 md:w-1/6">
<f:if condition="{teaserImage}">
<ep:lazyLoadImage image="{teaserImage}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{teaserImage.alternative}" />
<f:image image="{teaserImage}"
loading="lazy"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{teaserImage.alternative}" />
</f:if>
</div>
<div class="px-16 md:px-4 md:w-5/6 md:pl-8 text-center text-white md:text-left" data-rte-content>
@@ -158,11 +158,11 @@
target="_blank"
rel="nofollow"
title="Global Compact">
<ep:lazyLoadImage src="EXT:ep_theme/Resources/Public/images/global_compact.png"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="100"
alt="Global Compact" />
<f:image src="EXT:ep_theme/Resources/Public/images/global_compact.png"
loading="lazy"
class="block w-full h-auto"
width="100"
alt="Global Compact" />
</a>
</div>
</div>
@@ -184,8 +184,10 @@
<f:format.raw>{totalRatings.jsonData->f:format.json()}</f:format.raw>
</script>
<f:if condition="{site.identifier} == 'ep-reisen'">
<f:render partial="Chatbot" arguments="{_all}"/>
</f:if>
<f:comment><!--
<f:if condition="{site.identifier} == 'ep-reisen'">
<f:render partial="Chatbot" arguments="{_all}"/>
</f:if>
--></f:comment>
</html>
@@ -9,12 +9,12 @@
{ep:icon(icon: 'flag-{hotel.country.code -> f:format.case(mode: \'lower\')}', class: 'w-8 h-6 absolute top-0 left-0')}
<f:if condition="{hotel.images.original.0}">
<f:then>
<ep:lazyLoadImage image="{hotel.images.original.0}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{hotel.name}" />
<f:image image="{hotel.images.original.0}"
loading="lazy"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{hotel.name}" />
</f:then>
<f:else>
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png"
@@ -15,12 +15,12 @@
<a href="{f:uri.image(image: image, cropVariant: 'zoom', maxWidth: '2560')}"
title="{image.title}"
data-action="lightbox#open">
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="770"
height="430c+100"
alt="{image.alternative}"/>
<f:image image="{image}"
loading="lazy"
class="block w-full h-auto"
width="770"
height="430c+100"
alt="{image.alternative}"/>
</a>
</f:alias>
<f:if condition="{thumbnails}">
@@ -35,12 +35,12 @@
data-lightbox-caption="{image.originalResource.description}"
title="{image.title}"
class="block">
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="150"
height="85c+100"
alt="{image.alternative}"/>
<f:image image="{image}"
loading="lazy"
class="block w-full h-auto"
width="150"
height="85c+100"
alt="{image.alternative}"/>
</a>
</f:if>
</f:for>
@@ -1,6 +1,5 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<div class="odd:bg-zinc-50 p-4" data-rte-content>
@@ -18,12 +17,12 @@
</h3>
{journey.byCar -> f:format.html()}
<f:if condition="{journey.image}">
<ep:lazyLoadImage image="{journey.image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="770"
height="430c+100"
alt="{journey.image.alternative}" />
<f:image image="{journey.image}"
loading="lazy"
class="block w-full h-auto"
width="770"
height="430c+100"
alt="{journey.image.alternative}" />
</f:if>
</f:if>
</div>
@@ -10,8 +10,9 @@
<f:then>
<f:if condition="{newsItem.mediaPreviews.0}">
<f:alias map="{mediaElement: '{newsItem.mediaPreviews.0}'}">
<img class="block w-full h-auto lazyload"
data-src="{f:uri.image(image: mediaElement, width: '640', height: '360c+50')}"
<img class="block w-full h-auto"
src="{f:uri.image(image: mediaElement, width: '640', height: '360c+50')}"
loading="lazy"
alt="{mediaElement.originalResource.alternative}">
</f:alias>
</f:if>
@@ -19,8 +20,9 @@
<f:else>
<f:if condition="{newsItem.media}">
<f:alias map="{mediaElement: '{newsItem.media.0}'}">
<img class="block w-full h-auto lazyload"
data-src="{f:uri.image(image: mediaElement, width: '640', height: '360c+50')}"
<img class="block w-full h-auto"
src="{f:uri.image(image: mediaElement, width: '640', height: '360c+50')}"
loading="lazy"
alt="{mediaElement.originalResource.alternative}">
</f:alias>
</f:if>
@@ -8,11 +8,11 @@
</div>
<div class="col-span-1">
<f:if condition="{officetip.author.image}">
<ep:lazyLoadImage image="{officetip.author.image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="120"
alt="{officetip.author.name}" />
<f:image image="{officetip.author.image}"
loading="lazy"
class="block w-full h-auto"
width="120"
alt="{officetip.author.name}" />
</f:if>
</div>
<div class="col-span-2">
@@ -16,19 +16,19 @@
<div class="relative{f:if(condition: landscape, then: ' sm:w-2/5')}">
<f:if condition="{productImage}">
<f:then>
<ep:lazyLoadImage image="{productImage}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{product.name}" />
<f:image image="{productImage}"
loading="lazy"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{product.name}" />
</f:then>
<f:else>
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{product.name}" />
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{product.name}" />
</f:else>
</f:if>
<div class="absolute top-0 left-0 z-20 inset-x-0 p-2 flex justify-between items-center {f:if(condition: concept, then: 'bg-concept-{concept.code}/70', else: 'bg-ep-primary/80')}">
@@ -18,12 +18,12 @@
</f:if>
<f:if condition="{image}">
<f:then>
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{region.name}" />
<f:image image="{image}"
loading="lazy"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{region.name}" />
</f:then>
<f:else>
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png"
@@ -1,6 +1,5 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:if condition="{region.webcam.available}">
@@ -13,11 +12,11 @@
data-action="lightbox#open"
data-lightbox-caption="Webcam {region.name}"
title="Webcam {region.name}">
<ep:lazyLoadImage src="{region.webcam.url}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="330"
alt="Webcam {region.name}" />
<f:image src="{region.webcam.url}"
loading="lazy"
class="block w-full h-auto"
width="330"
alt="Webcam {region.name}" />
</a>
</div>
</f:if>
@@ -1,6 +1,5 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:if condition="{region.regionMaps}">
@@ -17,11 +16,11 @@
data-lightbox-index="{iteration.cycle}"
data-lightbox-caption="Pistenplan {region.name}"
title="Pistenplan {region.name}">
<ep:lazyLoadImage image="{regionMap}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="330"
alt="{regionMap.alternative}"/>
<f:image image="{regionMap}"
loading="lazy"
class="block w-full h-auto"
width="330"
alt="{regionMap.alternative}"/>
</a>
</f:for>
</div>
@@ -1,6 +1,5 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:v="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
@@ -11,11 +10,11 @@
Teamer vor Ort
</p>
<f:if condition="{teamerInCharge.image}">
<ep:lazyLoadImage image="{teamerInCharge.image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto mb-4"
width="330"
alt="{teamerInCharge.name}"/>
<f:image image="{teamerInCharge.image}"
loading="lazy"
class="block w-full h-auto mb-4"
width="330"
alt="{teamerInCharge.name}"/>
</f:if>
<p>{teamerInCharge.name}</p>
</div>
@@ -9,12 +9,12 @@
<f:if condition="{context.country}">
{ep:icon(icon: 'flag-{context.country.code -> f:format.case(mode: \'lower\')}', class: 'w-8 h-6 absolute top-0 left-0')}
</f:if>
<ep:lazyLoadImage image="{teaserImage}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{teaserImage.alternative}" />
<f:image image="{teaserImage}"
loading="lazy"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{teaserImage.alternative}" />
</div>
<div class="flex-1 flex flex-col pt-4 bg-white border border-t-0 border-zinc-200">
<a href="{f:uri.typolink(parameter: data.header_link)}" class="px-2 peer headline--3 mb-2 no-underline">
@@ -1,62 +1,61 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:if condition="{image.uid}">
<f:then>
<picture>
<source media="(min-width: 1201px)" data-srcset="{f:uri.image(
<source media="(min-width: 1201px)" srcset="{f:uri.image(
image: image, width: '370', height: '220c-100'
)} 370w"/>
<source media="(max-width: 1200px)" data-srcset="{f:uri.image(
<source media="(max-width: 1200px)" srcset="{f:uri.image(
image: image, width: '320', height: '160c-100'
)} 320w"/>
<source media="(max-width: 991px)" data-srcset="{f:uri.image(
<source media="(max-width: 991px)" srcset="{f:uri.image(
image: image, width: '360', height: '200c-100'
)} 360w"/>
<source media="(max-width: 768px)" data-srcset="{f:uri.image(
<source media="(max-width: 768px)" srcset="{f:uri.image(
image: image, width: '500', height: '250c-100'
)} 500w"/>
<source media="(max-width: 512px)" data-srcset="{f:uri.image(
<source media="(max-width: 512px)" srcset="{f:uri.image(
image: image, width: '350', height: '175c-100'
)} 350w"/>
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="500"
height="250c-100"
alt="{image.alternative}" />
<f:image image="{image}"
loading="lazy"
class="block w-full h-auto"
width="500"
height="250c-100"
alt="{image.alternative}" />
</picture>
</f:then>
<f:else>
<picture>
<source media="(min-width: 1201px)" data-srcset="{f:uri.image(
<source media="(min-width: 1201px)" srcset="{f:uri.image(
src: 'EXT:ep_theme/Resources/Public/images/header-winter.jpg',
width: '370', height: '220c-100'
)} 370w"/>
<source media="(max-width: 1200px)" data-srcset="{f:uri.image(
<source media="(max-width: 1200px)" srcset="{f:uri.image(
src: 'EXT:ep_theme/Resources/Public/images/header-winter.jpg',
width: '320', height: '160c-100'
)} 420w"/>
<source media="(max-width: 991px)" data-srcset="{f:uri.image(
)} 320w"/>
<source media="(max-width: 991px)" srcset="{f:uri.image(
src: 'EXT:ep_theme/Resources/Public/images/header-winter.jpg',
width: '360', height: '200c-100'
)} 360w"/>
<source media="(max-width: 768px)" data-srcset="{f:uri.image(
<source media="(max-width: 768px)" srcset="{f:uri.image(
src: 'EXT:ep_theme/Resources/Public/images/header-winter.jpg',
width: '500', height: '250c-100'
)} 500w"/>
<source media="(max-width: 512px)" data-srcset="{f:uri.image(
<source media="(max-width: 512px)" srcset="{f:uri.image(
src: 'EXT:ep_theme/Resources/Public/images/header-winter.jpg',
width: '350', height: '175c-100'
)} 320w"/>
<ep:lazyLoadImage src="EXT:ep_theme/Resources/Public/images/header-winter.jpg"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="360"
height="270c-100"
alt="" />
)} 350w"/>
<f:image src="EXT:ep_theme/Resources/Public/images/header-winter.jpg"
loading="lazy"
class="block w-full h-auto"
width="360"
height="270c-100"
alt="" />
</picture>
</f:else>
</f:if>
@@ -1,25 +1,27 @@
<f:if condition="{image}">
<f:then>
<picture class="product-teaser__image">
<source media="(min-width: 1201px)" data-srcset="{f:uri.image(
<source media="(min-width: 1201px)" srcset="{f:uri.image(
image: image, width: '320', height: '200c-100'
)} 320w"/>
<source media="(max-width: 1200px)" data-srcset="{f:uri.image(
<source media="(max-width: 1200px)" srcset="{f:uri.image(
image: image, width: '220', height: '130c-100'
)} 220w"/>
<source media="(max-width: 991px)" data-srcset="{f:uri.image(
<source media="(max-width: 991px)" srcset="{f:uri.image(
image: image, width: '260', height: '220c-100'
)} 260w"/>
<source media="(max-width: 768px)" data-srcset="{f:uri.image(
<source media="(max-width: 768px)" srcset="{f:uri.image(
image: image, width: '320', height: '140c-100'
)} 320w"/>
<img class="scale lazyload" alt="{image.alternative}"
src="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/lazy.png', width: '260', height: '160')}"
data-src="{f:uri.image(image: image, width: '260', height: '160c-100')}"
<img class="scale" alt="{image.alternative}"
src="{f:uri.image(image: image, width: '260', height: '160c-100')}"
loading="lazy"
>
</picture>
</f:then>
<f:else>
<img class="scale" data-src="https://placehold.it/400x300" alt="">
<img class="scale" alt=""
src="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/lazy.png', width: '260', height: '160')}"
loading="lazy">
</f:else>
</f:if>
@@ -7,8 +7,9 @@
{data.bodytext -> f:format.html()}
<f:if condition="{files}">
<f:link.typolink parameter="{files.0.link}" title="{files.0.originalResource.title}">
<img class="img-responsive lazyload"
data-src="{f:uri.image(image: files.0, maxWidth: '770')}"
<img class="img-responsive"
src="{f:uri.image(image: files.0, maxWidth: '770')}"
loading="lazy"
alt="{files.0.originalResource.alternative}">
</f:link.typolink>
</f:if>
@@ -1,7 +1,6 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:v="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:section name="Content">
@@ -25,12 +24,12 @@
<f:section name="Image">
<div class="{cssClasses}">
<f:link.typolink parameter="{image.link}">
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="400c"
height="400"
alt="{image.alternative}" />
<f:image image="{image}"
loading="lazy"
class="block w-full h-auto"
width="400c"
height="400"
alt="{image.alternative}" />
</f:link.typolink>
</div>
</f:section>
@@ -10,12 +10,11 @@
<f:for each="{items}" as="item" iteration="iteration">
<div class="lg:flex odd:flex-row-reverse justify-between items-end mb-16">
<div class="mb-4 lg:mb-0 lg:w-1/2">
<ep:lazyLoadImage image="{item.image.0}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="768"
alt="{item.data.name}"
title="{item.data.name}" />
<f:image image="{item.image.0}"
loading="lazy"
class="block w-full h-auto"
width="768"
alt="{item.data.name}"/>
</div>
<div class="lg:w-1/2">
<div class="px-4 {f:if(condition: iteration.isEven, then: 'lg:pl-12', else: 'lg:pr-12')}">
@@ -1,6 +1,5 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
<f:layout name="Bare"/>
@@ -12,12 +11,12 @@
<use href="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/icons_sprite.svg')}#icon-flag-{country.code -> f:format.case(mode: 'lower')}"></use>
</svg>
<f:if condition="{country.teaserImages}">
<ep:lazyLoadImage image="{country.teaserImages.0}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{country.name}" />
<f:image image="{country.teaserImages.0}"
loading="lazy"
class="block w-full h-full object-cover"
width="400c"
height="300c"
alt="{country.name}" />
</f:if>
</div>
<div class="flex-1 flex flex-col pt-4 bg-white border border-t-0 border-zinc-200">
@@ -182,12 +182,11 @@
title="360°-Rundgang {hotel.name}">
<f:if condition="{product.tourThumbnail}">
<f:then>
<ep:lazyLoadImage image="{product.tourThumbnail}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="330"
alt="360°-Rundgang {hotel.name}"
title="360°-Rundgang {hotel.name}"/>
<f:image image="{product.tourThumbnail}"
loading="lazy"
class="block w-full h-auto"
width="330"
alt="360°-Rundgang {hotel.name}"/>
</f:then>
<f:else>
<div class="button bg-button w-full">
@@ -335,11 +334,11 @@
data-lightbox-caption="{image.originalResource.description}"
data-action="lightbox#open"
class="{f:if(condition: iteration.isFirst, then: 'col-span-4')}">
<ep:lazyLoadImage image="{image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto"
width="{f:if(condition: iteration.isFirst, then: '400', else: '160')}"
height="{f:if(condition: iteration.isFirst, then: '225c+100', else: '160c+100')}"/>
<f:image image="{image}"
loading="lazy"
class="block w-full h-auto"
width="{f:if(condition: iteration.isFirst, then: '400', else: '160')}"
height="{f:if(condition: iteration.isFirst, then: '225c+100', else: '160c+100')}"/>
</a>
</f:for>
</div>
@@ -1,7 +1,6 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers"
xmlns:v="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers">
<f:layout name="Default"/>
@@ -28,13 +27,12 @@
arguments: '{member: member}'
)}">
<f:if condition="{member.image}">
<ep:lazyLoadImage image="{member.image}"
loaderimg="EXT:ep_theme/Resources/Public/images/lazy.png"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{member.name}"
title="{member.name}" />
<f:image image="{member.image}"
loading="lazy"
class="block w-full h-auto rounded-full"
width="400"
height="400c"
alt="{member.name}"/>
</f:if>
<div class="text-center text-zinc-800 pt-2">
<span class="block font-bold text-xl">
@@ -39,6 +39,7 @@ return [
'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',
@@ -53,6 +54,7 @@ return [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['', 0],
-1
View File
@@ -9,7 +9,6 @@ Encore
.setOutputPath('./public/typo3conf/ext/ep_theme/Resources/Public/')
.setPublicPath('/typo3conf/ext/ep_theme/Resources/Public/')
.addEntry('main', './public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/main.js')
.addEntry('groups-calculator', './public/typo3conf/ext/ep_theme/Resources/Private/Assets/js/groups-calculator.js')
.addStyleEntry('rte', './public/typo3conf/ext/ep_theme/Resources/Private/Assets/scss/rte.scss')
.splitEntryChunks()
.enableSingleRuntimeChunk()