cms/app/Services/AccessibilityAnalyzer.php

110 lines
3.5 KiB
PHP
Raw Permalink Normal View History

<?php
namespace App\Services;
class AccessibilityAnalyzer
{
/**
* Analyze block-based content for common accessibility issues.
* This method scans for missing alt text, incorrect heading hierarchy, and other WCAG-related gaps.
*
* @param array $content The JSON-encoded block content from the editor.
* @return array A list of identified issues with severity and messages.
*/
public function analyze(array $content): array
{
// Handle multi-locale content
$isMultiLocale = false;
$locales = array_keys($content);
foreach ($locales as $locale) {
if (is_string($locale) && is_array($content[$locale]) && isset($content[$locale][0]['type'])) {
$isMultiLocale = true;
break;
}
}
if ($isMultiLocale) {
$allIssues = [];
foreach ($content as $locale => $localeContent) {
if (is_array($localeContent)) {
$localeIssues = $this->analyzeBlocks($localeContent);
if (!empty($localeIssues)) {
$allIssues[$locale] = $localeIssues;
}
}
}
return $allIssues;
}
return $this->analyzeBlocks($content);
}
/**
* Internal helper to analyze a flat list of blocks.
*
* @param array $content
* @return array
*/
protected function analyzeBlocks(array $content): array
{
$issues = [];
$headings = [];
foreach ($content as $index => $block) {
$type = $block['type'] ?? '';
$data = $block['data'] ?? [];
switch ($type) {
case 'heading':
$level = (int) ($data['level'] ?? 0);
if ($level > 0) {
$headings[] = [
'level' => $level,
'index' => $index
];
}
break;
case 'image':
$alt = $data['alt'] ?? '';
if (empty($alt)) {
$issues[] = [
'severity' => 'error',
'message' => 'Image block is missing alternative text (alt tag).',
'block_index' => $index,
];
}
break;
case 'media':
$alt = $data['alt'] ?? '';
if (empty($alt)) {
$issues[] = [
'severity' => 'warning',
'message' => 'Media block may be missing alternative text.',
'block_index' => $index,
];
}
break;
}
}
if (!empty($headings)) {
$prevLevel = 0;
foreach ($headings as $h) {
$level = $h['level'];
if ($prevLevel > 0 && $level > $prevLevel + 1) {
$issues[] = [
'severity' => 'warning',
'message' => "Skipped heading level from H$prevLevel to H$level. Headings should be sequential.",
'block_index' => $h['index'],
];
}
$prevLevel = $level;
}
}
return $issues;
}
}