elements (text, aria-label, title or an inner image alt) and * image inputs (), which need non-empty alt text because * they are functional controls. */ final class ButtonNameRule implements Rule { /** * Returns the stable rule identifier. * * @return string */ public function id(): string { return 'button-name'; } /** * Returns the WCAG success criterion this rule maps to. * * @return string */ public function wcag(): string { return '4.1.2'; } /** * Evaluates buttons and image inputs for a missing accessible name. * * @param DOMDocument $dom Parsed document. * @param DOMXPath $xpath XPath helper for the document. * @param array $context Optional scan context. * @return list */ public function evaluate( DOMDocument $dom, DOMXPath $xpath, array $context = array() ): array { $issues = array(); foreach ( $xpath->query( '//button' ) as $button ) { if ( ! $button instanceof DOMElement ) { continue; } if ( 'true' === $button->getAttribute( 'aria-hidden' ) ) { continue; } if ( '' === $this->accessibleName( $button ) ) { $issues[] = new Issue( ruleId: $this->id(), wcag: $this->wcag(), severity: Severity::Error, message: __( 'Button has no discernible text.', 'a11yfleet' ), context: '