Add Container Options
This commit is contained in:
1 parent
f515de54ad
commit
c720696781
23 files changed
+584
-22
No files matched your search
@@ -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';
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user