Allow heading tags (h1-h6) in ContentSanitizer so news editor headings render

This commit is contained in:
2026-06-04 07:52:57 +02:00
parent 0b33a1b074
commit 15870ddb1f
191 changed files with 15453 additions and 1786 deletions

View File

@@ -377,10 +377,41 @@ final class StudioNewsController extends Controller
'og_image' => ['nullable', 'string', 'max:2048'],
'relations' => ['nullable', 'array', 'max:12'],
'relations.*.entity_type' => ['required_with:relations', Rule::in(array_column($this->news->relationTypeOptions(), 'value'))],
'relations.*.entity_id' => ['required_with:relations', 'integer', 'min:1'],
'relations.*.entity_id' => ['nullable', 'integer', 'min:1'],
'relations.*.external_url' => ['nullable', 'string', 'max:2048'],
'relations.*.context_label' => ['nullable', 'string', 'max:120'],
]);
$relationErrors = [];
foreach ((array) ($validated['relations'] ?? []) as $index => $relation) {
$entityType = trim(Str::lower((string) ($relation['entity_type'] ?? '')));
if ($entityType === NewsService::RELATION_SOURCE) {
$externalUrl = $this->normalizeExternalRelationUrl($relation['external_url'] ?? null);
if ($externalUrl === null) {
$relationErrors["relations.{$index}.external_url"] = 'Source relations need a valid URL.';
continue;
}
$validated['relations'][$index]['entity_id'] = null;
$validated['relations'][$index]['external_url'] = $externalUrl;
continue;
}
if ((int) ($relation['entity_id'] ?? 0) < 1) {
$relationErrors["relations.{$index}.entity_id"] = 'Select a related entity.';
}
$validated['relations'][$index]['external_url'] = null;
}
if ($relationErrors !== []) {
throw ValidationException::withMessages($relationErrors);
}
if (($validated['editorial_status'] ?? null) === NewsArticle::EDITORIAL_STATUS_SCHEDULED && empty($validated['published_at'])) {
throw ValidationException::withMessages([
'published_at' => 'Scheduled articles need a publish date and time.',
@@ -390,6 +421,25 @@ final class StudioNewsController extends Controller
return $validated;
}
private function normalizeExternalRelationUrl(mixed $value): ?string
{
$url = trim((string) ($value ?? ''));
if ($url === '') {
return null;
}
if (preg_match('/^\[[^\]]+\]\((https?:\/\/[^)]+)\)$/i', $url, $matches) === 1) {
$url = trim((string) ($matches[1] ?? ''));
}
if ($url === '' || filter_var($url, FILTER_VALIDATE_URL) === false) {
return null;
}
return Str::limit($url, 2048, '');
}
private function tagPayload(): array
{
return NewsTag::query()