- Rebuild the widget server-backed: it renders only when GET state allows (logged-in FE user of the configured group), so the script tag is safe on public pages; form with mini rich text (bold/italic/ list), file attachment chips and Ctrl+V image paste - a paste lazily creates the draft feedback, uploads and inserts the image inline - Note pad badge mirrors the server item count; the pad button links to the overview page via new extension setting overviewPid, exposed as overviewUrl in GET state (slug lookup) - Embed /fileadmin images of notes into the feedback mail as CID parts: relative srcs are dead in mail clients and dev sits behind basic auth; attachment links stay absolute URLs - public/widget-test.html: dev test page, doubles as the reference implementation of the React login flow (fetch felogin JSON form incl. __RequestToken, urlencoded POST to /_json + form.action) - Docs section 5x (fe_comment v2 incl. CSRF login lesson, templateRootPaths.10 collision, cache:flush before extension:setup)
114 lines
3.4 KiB
PHP
114 lines
3.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Evomedien\FeComment\Service;
|
|
|
|
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
|
|
/**
|
|
* Typed access to the extension configuration (Settings > Extension
|
|
* Configuration > fe_comment). Every accessor is failure-tolerant: an
|
|
* unconfigured extension behaves like "everything empty, headless mode".
|
|
*/
|
|
final class ExtensionSettings
|
|
{
|
|
/** @var array<string,mixed> */
|
|
private array $settings;
|
|
|
|
public function __construct()
|
|
{
|
|
try {
|
|
$this->settings = (array)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('fe_comment');
|
|
} catch (\Throwable) {
|
|
$this->settings = [];
|
|
}
|
|
}
|
|
|
|
/** @return string[] */
|
|
public function mailTo(): array
|
|
{
|
|
return $this->addressList('mailTo');
|
|
}
|
|
|
|
/** @return string[] */
|
|
public function mailCc(): array
|
|
{
|
|
return $this->addressList('mailCc');
|
|
}
|
|
|
|
/** @return string[] */
|
|
public function mailBcc(): array
|
|
{
|
|
return $this->addressList('mailBcc');
|
|
}
|
|
|
|
public function subject(): string
|
|
{
|
|
$subject = trim((string)($this->settings['subject'] ?? ''));
|
|
return $subject !== '' ? $subject : 'Page feedback';
|
|
}
|
|
|
|
/** Master switch: off serves an empty widget and rejects submissions. */
|
|
public function enabled(): bool
|
|
{
|
|
return (bool)($this->settings['enabled'] ?? true);
|
|
}
|
|
|
|
/** FE user group required to use the widget; 0 = any logged-in user. */
|
|
public function feUserGroup(): int
|
|
{
|
|
return (int)($this->settings['feUserGroup'] ?? 0);
|
|
}
|
|
|
|
/** Storage pid for the feedback records (backend visibility). */
|
|
public function storagePid(): int
|
|
{
|
|
return (int)($this->settings['storagePid'] ?? 0);
|
|
}
|
|
|
|
/** Page uid of the feedback overview page; 0 = no overview link. */
|
|
public function overviewPid(): int
|
|
{
|
|
return (int)($this->settings['overviewPid'] ?? 0);
|
|
}
|
|
|
|
/**
|
|
* Selectable recipients, parsed from "Label <mail>; Label2 <mail2>".
|
|
* The index doubles as the id the widget sends back.
|
|
*
|
|
* @return array<int,array{label:string,email:string}>
|
|
*/
|
|
public function recipients(): array
|
|
{
|
|
$recipients = [];
|
|
foreach (GeneralUtility::trimExplode(';', (string)($this->settings['recipients'] ?? ''), true) as $entry) {
|
|
if (preg_match('/^(.*)<([^>]+)>\s*$/', $entry, $m) && GeneralUtility::validEmail(trim($m[2]))) {
|
|
$recipients[] = ['label' => trim($m[1]) ?: trim($m[2]), 'email' => trim($m[2])];
|
|
} elseif (GeneralUtility::validEmail(trim($entry))) {
|
|
$recipients[] = ['label' => trim($entry), 'email' => trim($entry)];
|
|
}
|
|
}
|
|
return $recipients;
|
|
}
|
|
|
|
/** true = headless: TYPO3 injects nothing, the front end embeds the widget itself. */
|
|
public function jsonOutput(): bool
|
|
{
|
|
return (bool)($this->settings['jsonOutput'] ?? true);
|
|
}
|
|
|
|
/** @return string[] valid mail addresses only */
|
|
private function addressList(string $key): array
|
|
{
|
|
$addresses = [];
|
|
foreach (GeneralUtility::trimExplode(',', (string)($this->settings[$key] ?? ''), true) as $address) {
|
|
if (GeneralUtility::validEmail($address)) {
|
|
$addresses[] = $address;
|
|
}
|
|
}
|
|
return $addresses;
|
|
}
|
|
}
|