tagName) !== 'table') { return null; } // Data tables usually contain headers ( elements). If it is a layout table, this rule is not mandatory. $thElements = $element->getElementsByTagName('th'); if ($thElements->length === 0) { return null; } // Check if there is a direct child $hasCaption = false; $captionElements = $element->getElementsByTagName('caption'); foreach ($captionElements as $caption) { if ($caption->parentNode === $element && trim($caption->textContent) !== '') { $hasCaption = true; break; } } if ($hasCaption) { return null; } // Check for aria-label or aria-labelledby or summary attributes $hasAriaLabel = ($element->hasAttribute('aria-label') && trim($element->getAttribute('aria-label')) !== '') || ($element->hasAttribute('aria-labelledby') && trim($element->getAttribute('aria-labelledby')) !== ''); $hasSummary = $element->hasAttribute('summary') && trim($element->getAttribute('summary')) !== ''; if ($hasAriaLabel || $hasSummary) { return null; } return $this->createViolation( $element, $this->getDescription(), 'Add a element directly inside the or use the aria-label attribute to describe the table.' ); } }