Add Container Options
This commit is contained in:
81
migrations/check_bg.php
Normal file
81
migrations/check_bg.php
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diagnose: why does a VITEC container emit an empty `background`?
|
||||||
|
*
|
||||||
|
* READ-ONLY, plain PDO against config/system/settings.php - same pattern as
|
||||||
|
* migrations/export_news.php, so it needs no TYPO3 bootstrap and cannot be
|
||||||
|
* affected by any cache.
|
||||||
|
*
|
||||||
|
* Usage: php migrations/check_bg.php [uid] (default uid 729)
|
||||||
|
*/
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
ini_set('display_errors', '1');
|
||||||
|
|
||||||
|
$uid = (int)($argv[1] ?? 729);
|
||||||
|
|
||||||
|
$root = null;
|
||||||
|
$dir = __DIR__;
|
||||||
|
for ($i = 0; $i < 5; $i++) {
|
||||||
|
if (is_file($dir . '/config/system/settings.php')) {
|
||||||
|
$root = $dir;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$dir = dirname($dir);
|
||||||
|
}
|
||||||
|
if ($root === null) {
|
||||||
|
exit("Could not locate project root above " . __DIR__ . "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = require $root . '/config/system/settings.php';
|
||||||
|
$db = $settings['DB']['Connections']['Default'];
|
||||||
|
$pdo = new PDO(
|
||||||
|
sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4', $db['host'] ?? 'localhost', $db['port'] ?? 3306, $db['dbname'] ?? ''),
|
||||||
|
$db['user'] ?? '',
|
||||||
|
$db['password'] ?? '',
|
||||||
|
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
|
||||||
|
);
|
||||||
|
|
||||||
|
echo "=== 1) Do the three columns exist? ===\n";
|
||||||
|
$cols = $pdo->query("SHOW COLUMNS FROM tt_content LIKE 'tx_vitec_bg_%'")->fetchAll();
|
||||||
|
if ($cols === []) {
|
||||||
|
echo " NONE. database:updateschema has not created them.\n";
|
||||||
|
} else {
|
||||||
|
foreach ($cols as $c) {
|
||||||
|
echo sprintf(" %-24s %-18s default=%s\n", $c['Field'], $c['Type'], var_export($c['Default'], true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n=== 2) The record itself (uid $uid) ===\n";
|
||||||
|
$row = $pdo->query("SELECT uid, pid, CType, deleted, hidden, sys_language_uid, l18n_parent, tx_vitec_bg_variant, tx_vitec_bg_image, tx_vitec_bg_size, tx_vitec_bg_position FROM tt_content WHERE uid = $uid")->fetch();
|
||||||
|
if (!$row) {
|
||||||
|
echo " no tt_content row with uid $uid\n";
|
||||||
|
} else {
|
||||||
|
foreach ($row as $k => $v) {
|
||||||
|
echo sprintf(" %-24s %s\n", $k, var_export($v, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n=== 3) File references pointing at this record ===\n";
|
||||||
|
$refs = $pdo->query(
|
||||||
|
"SELECT r.uid, r.tablenames, r.fieldname, r.uid_local, r.uid_foreign, r.deleted, r.hidden, r.sorting_foreign,
|
||||||
|
f.identifier, f.name, f.mime_type
|
||||||
|
FROM sys_file_reference r LEFT JOIN sys_file f ON f.uid = r.uid_local
|
||||||
|
WHERE r.uid_foreign = $uid AND r.tablenames = 'tt_content'"
|
||||||
|
)->fetchAll();
|
||||||
|
if ($refs === []) {
|
||||||
|
echo " NONE - nothing references this record. The image was not saved.\n";
|
||||||
|
} else {
|
||||||
|
foreach ($refs as $r) {
|
||||||
|
echo sprintf(" ref %-6s field=%-22s file=%s deleted=%s hidden=%s\n",
|
||||||
|
$r['uid'], $r['fieldname'], (string)$r['identifier'], $r['deleted'], $r['hidden']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n=== 4) Which fieldnames does tt_content use at all? (top 15) ===\n";
|
||||||
|
foreach ($pdo->query("SELECT fieldname, COUNT(*) c FROM sys_file_reference WHERE tablenames='tt_content' AND deleted=0 GROUP BY fieldname ORDER BY c DESC LIMIT 15")->fetchAll() as $r) {
|
||||||
|
echo sprintf(" %-28s %d\n", $r['fieldname'], $r['c']);
|
||||||
|
}
|
||||||
@@ -76,6 +76,11 @@ final class ContainerChildrenProcessor implements DataProcessorInterface
|
|||||||
*/
|
*/
|
||||||
private const CONTAINER_FIELDS = [
|
private const CONTAINER_FIELDS = [
|
||||||
'tx_vitec_gap',
|
'tx_vitec_gap',
|
||||||
|
// Background settings belong to the container, not to what sits inside
|
||||||
|
// it. They carry non-empty defaults ('none', 'cover', 'center center'),
|
||||||
|
// so without this they would show up in every single child's `data`.
|
||||||
|
'tx_vitec_bg_variant', 'tx_vitec_bg_image', 'tx_vitec_bg_size',
|
||||||
|
'tx_vitec_bg_size_percent', 'tx_vitec_bg_position',
|
||||||
'tx_vitec_col1_align', 'tx_vitec_col1_justify',
|
'tx_vitec_col1_align', 'tx_vitec_col1_justify',
|
||||||
'tx_vitec_col2_align', 'tx_vitec_col2_justify',
|
'tx_vitec_col2_align', 'tx_vitec_col2_justify',
|
||||||
'tx_vitec_col3_align', 'tx_vitec_col3_justify',
|
'tx_vitec_col3_align', 'tx_vitec_col3_justify',
|
||||||
|
|||||||
104
packages/vitec/Classes/UserFunc/ContainerBackgroundRenderer.php
Normal file
104
packages/vitec/Classes/UserFunc/ContainerBackgroundRenderer.php
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Evomedien\Vitec\UserFunc;
|
||||||
|
|
||||||
|
use Evomedien\Vitec\Service\UsecaseSerializer;
|
||||||
|
use TYPO3\CMS\Core\Attribute\AsAllowedCallable;
|
||||||
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UserFunc emitting the background block of a VITEC container.
|
||||||
|
*
|
||||||
|
* The container elements are rendered entirely in TypoScript
|
||||||
|
* (Configuration/TypoScript/Headless/vitec_containers.typoscript), where plain
|
||||||
|
* fields are TEXT objects. A FAL image is not a plain field, so it comes through
|
||||||
|
* here — and going through `UsecaseSerializer::image()` rather than the headless
|
||||||
|
* FilesProcessor is deliberate: Clause 9.2 puts image serialisation in one place,
|
||||||
|
* so a background image has the same `{url, srcset, properties}` shape as every
|
||||||
|
* other image in this JSON. One shape for the front end instead of two.
|
||||||
|
*
|
||||||
|
* Emits nothing at all when no image is set — the whole `background` key then
|
||||||
|
* stays out of the payload, which is a clearer signal than an object with a null
|
||||||
|
* image and two orphaned CSS settings.
|
||||||
|
*
|
||||||
|
* `size` and `position` are stored as CSS-ready values (`cover`, `left top`, …).
|
||||||
|
* The single exception is `stretch`, which has no CSS keyword and the front end
|
||||||
|
* maps to `100% 100%`; see the TCA comment in tt_content_vitec_shared.php.
|
||||||
|
*
|
||||||
|
* Fail-soft per Clause 9.5: any error yields an empty string, never an exception
|
||||||
|
* that would take the surrounding content element down with it.
|
||||||
|
*/
|
||||||
|
class ContainerBackgroundRenderer
|
||||||
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 no longer assigns `$classObj->cObj` dynamically. The renderer is
|
||||||
|
* handed over through this setter, and only when the method exists at all -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* `is_callable([$classObj, 'setContentObjectRenderer'])`. Without the method
|
||||||
|
* `$this->cObj` stays null and the userFunc never sees its own record.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[AsAllowedCallable]
|
||||||
|
public function render(string $content, array $conf): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
|
if ($row === null) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$uid = (int)($row['uid'] ?? 0);
|
||||||
|
if ($uid <= 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
// No shortcut on the tx_vitec_bg_image counter: sys_file_reference is
|
||||||
|
// the single source of truth, and a counter that is stale or missing
|
||||||
|
// (schema not updated yet) would silently swallow a set image. One
|
||||||
|
// indexed query per container is cheaper than that class of bug.
|
||||||
|
|
||||||
|
$image = GeneralUtility::makeInstance(UsecaseSerializer::class)
|
||||||
|
->image($uid, 'tx_vitec_bg_image', 'tt_content');
|
||||||
|
if ($image === null) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string)json_encode([
|
||||||
|
'image' => $image,
|
||||||
|
'size' => $this->resolveSize($row),
|
||||||
|
'position' => (string)($row['tx_vitec_bg_position'] ?? 'center center'),
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The stored size, resolved into something the front end can hand straight
|
||||||
|
* to CSS. `custom` is the only value that needs a second field; turning it
|
||||||
|
* into "80%" here keeps the promise that `size` is always usable as-is,
|
||||||
|
* instead of making every consumer look up a companion field.
|
||||||
|
*
|
||||||
|
* A custom size without a usable percentage falls back to `auto` - the CSS
|
||||||
|
* default - rather than emitting "0%" or the meaningless word "custom".
|
||||||
|
*
|
||||||
|
* @param array<string,mixed> $row
|
||||||
|
*/
|
||||||
|
private function resolveSize(array $row): string
|
||||||
|
{
|
||||||
|
$size = (string)($row['tx_vitec_bg_size'] ?? 'cover');
|
||||||
|
if ($size !== 'custom') {
|
||||||
|
return $size;
|
||||||
|
}
|
||||||
|
$percent = (int)($row['tx_vitec_bg_size_percent'] ?? 0);
|
||||||
|
return $percent > 0 ? $percent . '%' : 'auto';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ use TYPO3\CMS\Core\Resource\ResourceFactory;
|
|||||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Service\ImageService;
|
use TYPO3\CMS\Extbase\Service\ImageService;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc: render the VITEC customer logos as JSON (headless).
|
* UserFunc: render the VITEC customer logos as JSON (headless).
|
||||||
@@ -29,13 +30,28 @@ use TYPO3\CMS\Extbase\Service\ImageService;
|
|||||||
*/
|
*/
|
||||||
class CustomerlogosJsonRenderer
|
class CustomerlogosJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
private const TABLE = 'tx_vitec_domain_model_customer';
|
private const TABLE = 'tx_vitec_domain_model_customer';
|
||||||
private const IMAGE_WIDTHS = [200, 400];
|
private const IMAGE_WIDTHS = [200, 400];
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_customerlogos') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_customerlogos') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use TYPO3\CMS\Core\Service\FlexFormService;
|
|||||||
use Evomedien\Vitec\Service\RteResolver;
|
use Evomedien\Vitec\Service\RteResolver;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Service\ImageService;
|
use TYPO3\CMS\Extbase\Service\ImageService;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc to render the event list (tx_vitec_domain_model_event) as JSON.
|
* UserFunc to render the event list (tx_vitec_domain_model_event) as JSON.
|
||||||
@@ -30,6 +31,21 @@ use TYPO3\CMS\Extbase\Service\ImageService;
|
|||||||
*/
|
*/
|
||||||
class EventlistJsonRenderer
|
class EventlistJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent of the region categories. Hard-coded like the other taxonomy roots
|
* Parent of the region categories. Hard-coded like the other taxonomy roots
|
||||||
* in this extension (Annex B-5 tracks them); making it a FlexForm setting
|
* in this extension (Annex B-5 tracks them); making it a FlexForm setting
|
||||||
@@ -42,7 +58,7 @@ class EventlistJsonRenderer
|
|||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
// 1) cObj data path
|
// 1) cObj data path
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_eventlist') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_eventlist') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use TYPO3\CMS\Core\Attribute\AsAllowedCallable;
|
|||||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc: render ONE of the VITEC form plugins as JSON (headless).
|
* UserFunc: render ONE of the VITEC form plugins as JSON (headless).
|
||||||
@@ -25,10 +26,25 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|||||||
*/
|
*/
|
||||||
class FormsJsonRenderer
|
class FormsJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && isset(FormDefinitions::CTYPE_MAP[(string)($row['CType'] ?? '')])) {
|
if ($row && isset(FormDefinitions::CTYPE_MAP[(string)($row['CType'] ?? '')])) {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,12 +27,27 @@ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
|||||||
*/
|
*/
|
||||||
class LocationsJsonRenderer
|
class LocationsJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
private const TABLE = 'tx_vitec_domain_model_location';
|
private const TABLE = 'tx_vitec_domain_model_location';
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_locationlist') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_locationlist') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use TYPO3\CMS\Core\Attribute\AsAllowedCallable;
|
|||||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc: render all VITEC markets as JSON (headless).
|
* UserFunc: render all VITEC markets as JSON (headless).
|
||||||
@@ -38,13 +39,28 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|||||||
*/
|
*/
|
||||||
class MarketListJsonRenderer
|
class MarketListJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
private const TABLE = 'tx_vitec_domain_model_market';
|
private const TABLE = 'tx_vitec_domain_model_market';
|
||||||
private const CTYPE = 'vitec_marketlist';
|
private const CTYPE = 'vitec_marketlist';
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === self::CTYPE) {
|
if ($row && (string)($row['CType'] ?? '') === self::CTYPE) {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use Evomedien\Vitec\Service\LinkResolver;
|
|||||||
use Evomedien\Vitec\Service\RteResolver;
|
use Evomedien\Vitec\Service\RteResolver;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Service\ImageService;
|
use TYPO3\CMS\Extbase\Service\ImageService;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc to render a single market as JSON for headless output.
|
* UserFunc to render a single market as JSON for headless output.
|
||||||
@@ -24,11 +25,26 @@ use TYPO3\CMS\Extbase\Service\ImageService;
|
|||||||
*/
|
*/
|
||||||
class MarketShowJsonRenderer
|
class MarketShowJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
// 1) cObj data path
|
// 1) cObj data path
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_marketshow') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_marketshow') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use TYPO3\CMS\Core\Attribute\AsAllowedCallable;
|
|||||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc: render the VITEC Card plugin as JSON (headless).
|
* UserFunc: render the VITEC Card plugin as JSON (headless).
|
||||||
@@ -29,6 +30,21 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|||||||
*/
|
*/
|
||||||
class ModelcardJsonRenderer
|
class ModelcardJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
private const MODEL_TABLES = [
|
private const MODEL_TABLES = [
|
||||||
'product' => 'tx_vitec_domain_model_product',
|
'product' => 'tx_vitec_domain_model_product',
|
||||||
'story' => 'tx_vitec_domain_model_usecase',
|
'story' => 'tx_vitec_domain_model_usecase',
|
||||||
@@ -39,7 +55,7 @@ class ModelcardJsonRenderer
|
|||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_modelcard') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_modelcard') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use TYPO3\CMS\Core\Service\FlexFormService;
|
|||||||
use Evomedien\Vitec\Service\RteResolver;
|
use Evomedien\Vitec\Service\RteResolver;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Service\ImageService;
|
use TYPO3\CMS\Extbase\Service\ImageService;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Headless JSON renderer for EXT:news content elements.
|
* Headless JSON renderer for EXT:news content elements.
|
||||||
@@ -25,6 +26,21 @@ use TYPO3\CMS\Extbase\Service\ImageService;
|
|||||||
*/
|
*/
|
||||||
final class NewsJsonRenderer
|
final class NewsJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
private const NEWS_CTYPES = [
|
private const NEWS_CTYPES = [
|
||||||
'news_pi1',
|
'news_pi1',
|
||||||
'news_newsliststicky',
|
'news_newsliststicky',
|
||||||
@@ -60,7 +76,7 @@ final class NewsJsonRenderer
|
|||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row !== null && in_array((string)($row['CType'] ?? ''), self::NEWS_CTYPES, true)) {
|
if ($row !== null && in_array((string)($row['CType'] ?? ''), self::NEWS_CTYPES, true)) {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use TYPO3\CMS\Core\Service\FlexFormService;
|
|||||||
use Evomedien\Vitec\Service\RteResolver;
|
use Evomedien\Vitec\Service\RteResolver;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Service\ImageService;
|
use TYPO3\CMS\Extbase\Service\ImageService;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc to render product list as JSON for headless.
|
* UserFunc to render product list as JSON for headless.
|
||||||
@@ -30,11 +31,26 @@ use TYPO3\CMS\Extbase\Service\ImageService;
|
|||||||
*/
|
*/
|
||||||
class ProductListJsonRenderer
|
class ProductListJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
// 1) cObj data path
|
// 1) cObj data path
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_productlist') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_productlist') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection;
|
|||||||
use TYPO3\CMS\Core\Resource\FileReference;
|
use TYPO3\CMS\Core\Resource\FileReference;
|
||||||
use TYPO3\CMS\Extbase\Service\ImageService;
|
use TYPO3\CMS\Extbase\Service\ImageService;
|
||||||
use Doctrine\DBAL\ParameterType;
|
use Doctrine\DBAL\ParameterType;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc to render a single product as JSON for headless output.
|
* UserFunc to render a single product as JSON for headless output.
|
||||||
@@ -28,11 +29,26 @@ use Doctrine\DBAL\ParameterType;
|
|||||||
*/
|
*/
|
||||||
class ProductShowJsonRenderer
|
class ProductShowJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
// 1) cObj data path
|
// 1) cObj data path
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_productshow') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_productshow') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use Evomedien\Vitec\Service\LinkResolver;
|
|||||||
use Evomedien\Vitec\Service\RteResolver;
|
use Evomedien\Vitec\Service\RteResolver;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Service\ImageService;
|
use TYPO3\CMS\Extbase\Service\ImageService;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc to render a single solution as JSON for headless output.
|
* UserFunc to render a single solution as JSON for headless output.
|
||||||
@@ -24,11 +25,26 @@ use TYPO3\CMS\Extbase\Service\ImageService;
|
|||||||
*/
|
*/
|
||||||
class SolutionShowJsonRenderer
|
class SolutionShowJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
// 1) cObj data path
|
// 1) cObj data path
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_solutionshow') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_solutionshow') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use TYPO3\CMS\Core\Attribute\AsAllowedCallable;
|
|||||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc: render the Success Story list as JSON (headless).
|
* UserFunc: render the Success Story list as JSON (headless).
|
||||||
@@ -22,12 +23,27 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|||||||
*/
|
*/
|
||||||
class UsecaseListJsonRenderer
|
class UsecaseListJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
private const TABLE = 'tx_vitec_domain_model_usecase';
|
private const TABLE = 'tx_vitec_domain_model_usecase';
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_usecaselist') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_usecaselist') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use TYPO3\CMS\Core\Attribute\AsAllowedCallable;
|
|||||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserFunc: render a single Success Story as JSON (headless).
|
* UserFunc: render a single Success Story as JSON (headless).
|
||||||
@@ -21,12 +22,27 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|||||||
*/
|
*/
|
||||||
class UsecaseShowJsonRenderer
|
class UsecaseShowJsonRenderer
|
||||||
{
|
{
|
||||||
|
private ?ContentObjectRenderer $cObj = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TYPO3 v14 hands the ContentObjectRenderer over through this setter only -
|
||||||
|
* ContentObjectRenderer::callUserFunction() duck-types it with
|
||||||
|
* is_callable([$classObj, 'setContentObjectRenderer']). Without the method
|
||||||
|
* $this->cObj stays null, the cObj branch of render() never fires and the
|
||||||
|
* call falls through to page discovery, which picks the FIRST element of
|
||||||
|
* this CType on the page rather than the one actually being rendered.
|
||||||
|
*/
|
||||||
|
public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
|
||||||
|
{
|
||||||
|
$this->cObj = $cObj;
|
||||||
|
}
|
||||||
|
|
||||||
private const TABLE = 'tx_vitec_domain_model_usecase';
|
private const TABLE = 'tx_vitec_domain_model_usecase';
|
||||||
|
|
||||||
#[AsAllowedCallable]
|
#[AsAllowedCallable]
|
||||||
public function render(string $content, array $conf): string
|
public function render(string $content, array $conf): string
|
||||||
{
|
{
|
||||||
$row = is_array($this->cObj->data ?? null) ? $this->cObj->data : null;
|
$row = is_array($this->cObj?->data ?? null) ? $this->cObj->data : null;
|
||||||
if ($row && (string)($row['CType'] ?? '') === 'vitec_usecaseshow') {
|
if ($row && (string)($row['CType'] ?? '') === 'vitec_usecaseshow') {
|
||||||
return $this->renderForRecord($row);
|
return $this->renderForRecord($row);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|||||||
'--palette--;;general,
|
'--palette--;;general,
|
||||||
--palette--;;headers,
|
--palette--;;headers,
|
||||||
tx_vitec_bg_variant,
|
tx_vitec_bg_variant,
|
||||||
|
--palette--;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:bg_image.palette;vitec_background,
|
||||||
pi_flexform;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:container.flexform.label,
|
pi_flexform;LLL:EXT:vitec/Resources/Private/Language/locallang_containers.xlf:container.flexform.label,
|
||||||
--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance,
|
--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance,
|
||||||
--palette--;;frames,
|
--palette--;;frames,
|
||||||
|
|||||||
@@ -27,6 +27,94 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Shared background image for the VITEC containers, with the two settings a
|
||||||
|
// background actually needs: how it scales and where it sits.
|
||||||
|
//
|
||||||
|
// Deliberately no crop variants (Clause 9.9): a background is framed by
|
||||||
|
// background-size / background-position in CSS, not by cropping the file.
|
||||||
|
// Cropping here would fight the two selects below.
|
||||||
|
//
|
||||||
|
// The values are written so the front end can hand them straight to CSS.
|
||||||
|
// `stretch` is the one exception - it has no CSS keyword and maps to
|
||||||
|
// `100% 100%`; spelled out here because "stretch" is what an editor looks
|
||||||
|
// for, not "100% 100%".
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
ExtensionManagementUtility::addTCAcolumns('tt_content', [
|
||||||
|
'tx_vitec_bg_image' => [
|
||||||
|
'label' => $l . 'bg_image.label',
|
||||||
|
'description' => $l . 'bg_image.description',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'file',
|
||||||
|
'maxitems' => 1,
|
||||||
|
'allowed' => 'common-image-types',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'tx_vitec_bg_size' => [
|
||||||
|
'label' => $l . 'bg_size.label',
|
||||||
|
// Re-renders the form when the value changes, so the "Size %" field
|
||||||
|
// below appears the moment "Custom" is picked instead of only after
|
||||||
|
// a save. FormEngine keeps the current form state across the reload
|
||||||
|
// (SingleFieldContainer -> ReloadOnFieldChange); whether it asks
|
||||||
|
// first is the editor's own "verify on change" preference.
|
||||||
|
'onChange' => 'reload',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'renderType' => 'selectSingle',
|
||||||
|
'items' => [
|
||||||
|
['label' => $l . 'bg_size.option.cover', 'value' => 'cover'],
|
||||||
|
['label' => $l . 'bg_size.option.contain', 'value' => 'contain'],
|
||||||
|
['label' => $l . 'bg_size.option.stretch', 'value' => 'stretch'],
|
||||||
|
['label' => $l . 'bg_size.option.auto', 'value' => 'auto'],
|
||||||
|
['label' => $l . 'bg_size.option.custom', 'value' => 'custom'],
|
||||||
|
],
|
||||||
|
'default' => 'cover',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
// Only meaningful together with bg_size = custom, and hidden otherwise
|
||||||
|
// so the form never shows a percentage that has no effect. The renderer
|
||||||
|
// resolves it into the emitted `size` (e.g. "80%"), so the front end
|
||||||
|
// keeps getting one CSS-ready value instead of a second special case.
|
||||||
|
'tx_vitec_bg_size_percent' => [
|
||||||
|
'label' => $l . 'bg_size_percent.label',
|
||||||
|
'description' => $l . 'bg_size_percent.description',
|
||||||
|
'displayCond' => 'FIELD:tx_vitec_bg_size:=:custom',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'number',
|
||||||
|
'size' => 6,
|
||||||
|
'default' => 100,
|
||||||
|
'range' => [
|
||||||
|
'lower' => 1,
|
||||||
|
'upper' => 500,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'tx_vitec_bg_position' => [
|
||||||
|
'label' => $l . 'bg_position.label',
|
||||||
|
'config' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'renderType' => 'selectSingle',
|
||||||
|
'items' => [
|
||||||
|
['label' => $l . 'bg_position.option.top_left', 'value' => 'left top'],
|
||||||
|
['label' => $l . 'bg_position.option.top_center', 'value' => 'center top'],
|
||||||
|
['label' => $l . 'bg_position.option.top_right', 'value' => 'right top'],
|
||||||
|
['label' => $l . 'bg_position.option.center_left', 'value' => 'left center'],
|
||||||
|
['label' => $l . 'bg_position.option.centered', 'value' => 'center center'],
|
||||||
|
['label' => $l . 'bg_position.option.center_right', 'value' => 'right center'],
|
||||||
|
['label' => $l . 'bg_position.option.bottom_left', 'value' => 'left bottom'],
|
||||||
|
['label' => $l . 'bg_position.option.bottom_center', 'value' => 'center bottom'],
|
||||||
|
['label' => $l . 'bg_position.option.bottom_right', 'value' => 'right bottom'],
|
||||||
|
],
|
||||||
|
'default' => 'center center',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// One palette, so size and position sit on a single row under the image.
|
||||||
|
$GLOBALS['TCA']['tt_content']['palettes']['vitec_background'] = [
|
||||||
|
'showitem' => 'tx_vitec_bg_image, --linebreak--, tx_vitec_bg_size, tx_vitec_bg_size_percent, tx_vitec_bg_position',
|
||||||
|
];
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Shared parent-level setting: column gap scale (1–5) for the whole grid.
|
// Shared parent-level setting: column gap scale (1–5) for the whole grid.
|
||||||
// Concerns the container itself (not a single column); maps to a spacing
|
// Concerns the container itself (not a single column); maps to a spacing
|
||||||
|
|||||||
@@ -125,6 +125,12 @@ tt_content.vitec_container.fields.cssClass.data = flexform:pi_flexform:settings.
|
|||||||
tt_content.vitec_container.fields.cssClass.stdWrap.ifEmpty.cObject = TEXT
|
tt_content.vitec_container.fields.cssClass.stdWrap.ifEmpty.cObject = TEXT
|
||||||
tt_content.vitec_container.fields.cssClass.stdWrap.ifEmpty.cObject.value =
|
tt_content.vitec_container.fields.cssClass.stdWrap.ifEmpty.cObject.value =
|
||||||
|
|
||||||
|
# Optional background image with its two CSS settings. The renderer returns an
|
||||||
|
# empty string when no image is set, so the `background` key stays out of the
|
||||||
|
# payload entirely rather than appearing with a null image.
|
||||||
|
tt_content.vitec_container.fields.background = USER
|
||||||
|
tt_content.vitec_container.fields.background.userFunc = Evomedien\Vitec\UserFunc\ContainerBackgroundRenderer->render
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# VITEC · Cards Carousel — container whose children (typically vitec_card
|
# VITEC · Cards Carousel — container whose children (typically vitec_card
|
||||||
# elements) become the slides. Inherits the grid-container JSON structure
|
# elements) become the slides. Inherits the grid-container JSON structure
|
||||||
|
|||||||
@@ -178,6 +178,72 @@
|
|||||||
<source>5</source>
|
<source>5</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
|
||||||
|
<trans-unit id="bg_image.palette" resname="bg_image.palette">
|
||||||
|
<source>Background Image</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_image.label" resname="bg_image.label">
|
||||||
|
<source>Background Image</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_image.description" resname="bg_image.description">
|
||||||
|
<source>Optional image behind the whole container. Leave empty for no background image.</source>
|
||||||
|
</trans-unit>
|
||||||
|
|
||||||
|
<trans-unit id="bg_size.label" resname="bg_size.label">
|
||||||
|
<source>Background Size</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_size.option.cover" resname="bg_size.option.cover">
|
||||||
|
<source>Cover (fill, may crop)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_size.option.contain" resname="bg_size.option.contain">
|
||||||
|
<source>Contain (fit, may letterbox)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_size.option.stretch" resname="bg_size.option.stretch">
|
||||||
|
<source>Stretch (distorts the image)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_size.option.auto" resname="bg_size.option.auto">
|
||||||
|
<source>Auto (original size)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_size.option.custom" resname="bg_size.option.custom">
|
||||||
|
<source>Custom (use Size % below)</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_size_percent.label" resname="bg_size_percent.label">
|
||||||
|
<source>Size %</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_size_percent.description" resname="bg_size_percent.description">
|
||||||
|
<source>Only used when Background Size is set to Custom. 100 = original width, 50 = half, 200 = double.</source>
|
||||||
|
</trans-unit>
|
||||||
|
|
||||||
|
<trans-unit id="bg_position.label" resname="bg_position.label">
|
||||||
|
<source>Background Position</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_position.option.top_left" resname="bg_position.option.top_left">
|
||||||
|
<source>Top Left</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_position.option.top_center" resname="bg_position.option.top_center">
|
||||||
|
<source>Top Center</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_position.option.top_right" resname="bg_position.option.top_right">
|
||||||
|
<source>Top Right</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_position.option.center_left" resname="bg_position.option.center_left">
|
||||||
|
<source>Center Left</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_position.option.centered" resname="bg_position.option.centered">
|
||||||
|
<source>Centered</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_position.option.center_right" resname="bg_position.option.center_right">
|
||||||
|
<source>Center Right</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_position.option.bottom_left" resname="bg_position.option.bottom_left">
|
||||||
|
<source>Bottom Left</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_position.option.bottom_center" resname="bg_position.option.bottom_center">
|
||||||
|
<source>Bottom Center</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="bg_position.option.bottom_right" resname="bg_position.option.bottom_right">
|
||||||
|
<source>Bottom Right</source>
|
||||||
|
</trans-unit>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
|
|||||||
@@ -207,6 +207,10 @@ CREATE TABLE tt_content (
|
|||||||
tx_vitec_col3_justify VARCHAR(20) DEFAULT 'flex-start' NOT NULL,
|
tx_vitec_col3_justify VARCHAR(20) DEFAULT 'flex-start' NOT NULL,
|
||||||
tx_vitec_col4_align VARCHAR(20) DEFAULT 'stretch' NOT NULL,
|
tx_vitec_col4_align VARCHAR(20) DEFAULT 'stretch' NOT NULL,
|
||||||
tx_vitec_col4_justify VARCHAR(20) DEFAULT 'flex-start' NOT NULL,
|
tx_vitec_col4_justify VARCHAR(20) DEFAULT 'flex-start' NOT NULL,
|
||||||
|
tx_vitec_bg_image int(11) unsigned DEFAULT '0' NOT NULL,
|
||||||
|
tx_vitec_bg_size VARCHAR(20) DEFAULT 'cover' NOT NULL,
|
||||||
|
tx_vitec_bg_size_percent int(11) unsigned DEFAULT '100' NOT NULL,
|
||||||
|
tx_vitec_bg_position VARCHAR(20) DEFAULT 'center center' NOT NULL,
|
||||||
tx_vitec_usecase_content int(11) unsigned DEFAULT '0' NOT NULL
|
tx_vitec_usecase_content int(11) unsigned DEFAULT '0' NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -397,10 +397,10 @@ FileETag None
|
|||||||
|
|
||||||
# Add your own rules here.
|
# Add your own rules here.
|
||||||
|
|
||||||
AuthUserFile "/usr/www/users/vitecevo/live/public/.htpasswd"
|
#AuthUserFile "/usr/www/users/vitecevo/live/public/.htpasswd"
|
||||||
AuthName "DEV"
|
#AuthName "DEV"
|
||||||
AuthType Basic
|
#AuthType Basic
|
||||||
<RequireAny>
|
#<RequireAny>
|
||||||
Require ip 217.70.192.164
|
#Require ip 217.70.192.164
|
||||||
Require valid-user
|
#Require valid-user
|
||||||
</RequireAny>
|
#</RequireAny>
|
||||||
|
|||||||
@@ -25,8 +25,8 @@
|
|||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<title>VITEC</title>
|
<title>VITEC</title>
|
||||||
<script type="module" crossorigin src="/_frontend/assets/index-CI1dU4kK.js"></script>
|
<script type="module" crossorigin src="/_frontend/assets/index-CEaA2pPG.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/_frontend/assets/index-DtQru7Bt.css">
|
<link rel="stylesheet" crossorigin href="/_frontend/assets/index-AGbYYdQ8.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="page"></div>
|
<div id="page"></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user