q( '//img' ) as $img ) { $role = strtolower( $img->getAttribute( 'role' ) ); if ( 'presentation' === $role || 'none' === $role || 'true' === $img->getAttribute( 'aria-hidden' ) ) { continue; } if ( Html::is_hidden( $img ) ) { continue; } $w = $img->getAttribute( 'width' ); $h = $img->getAttribute( 'height' ); if ( '1' === $w && '1' === $h ) { continue; // Tracking pixel. } $has_alt = $img->hasAttribute( 'alt' ); $alt = trim( $img->getAttribute( 'alt' ) ); $named = '' !== trim( $img->getAttribute( 'aria-label' ) ) || '' !== trim( $img->getAttribute( 'aria-labelledby' ) ); $link = $this->sole_link( $img ); if ( $link && '' === $alt && ! $named ) { $c->add( 'img-link-no-name', $link, array( 'message' => __( 'The link contains only an image with no alt text.', 'a11ymate' ) ) ); continue; } if ( ! $has_alt && ! $named && '' === trim( $img->getAttribute( 'title' ) ) ) { $c->add( 'img-alt-missing', $img ); continue; } if ( '' === $alt ) { continue; } $base = strtolower( pathinfo( wp_parse_url( $img->getAttribute( 'src' ), PHP_URL_PATH ) ? wp_parse_url( $img->getAttribute( 'src' ), PHP_URL_PATH ) : '', PATHINFO_FILENAME ) ); if ( preg_match( '/\.(jpe?g|png|gif|webp|svg|avif|bmp|tiff?)$/i', $alt ) || preg_match( '/^(img|dsc|dscn|image|photo|pic|screenshot|screen shot|untitled|wp|capture)[-_ ]?\d+/i', $alt ) || ( strlen( $base ) > 4 && strtolower( $alt ) === $base && preg_match( '/[\d_]/', $base ) ) ) { $c->add( 'img-alt-filename', $img, array( 'alt' => $alt ) ); continue; } $lower = strtolower( $alt ); foreach ( $phrases['redundantAlt'] as $p ) { if ( 0 === strpos( $lower, $p ) ) { $c->add( 'img-alt-redundant', $img, array( 'alt' => $alt ) ); break; } } if ( strlen( $alt ) > 150 ) { $c->add( 'img-alt-long', $img, array( 'length' => strlen( $alt ) ) ); } } foreach ( $c->q( "//svg[@role='img']" ) as $svg ) { if ( 'true' === $svg->getAttribute( 'aria-hidden' ) ) { continue; } if ( '' === Html::svg_name( $svg ) && '' === trim( $svg->getAttribute( 'aria-labelledby' ) ) ) { $c->add( 'svg-role-img-no-name', $svg ); } } foreach ( $c->q( "//input[translate(@type,'IMAGE','image')='image']" ) as $in ) { if ( '' === trim( $in->getAttribute( 'alt' ) ) && '' === trim( $in->getAttribute( 'aria-label' ) ) && '' === trim( $in->getAttribute( 'title' ) ) && '' === trim( $in->getAttribute( 'aria-labelledby' ) ) ) { $c->add( 'input-image-alt', $in ); } } foreach ( $c->q( '//area[@href]' ) as $area ) { if ( '' === trim( $area->getAttribute( 'alt' ) ) && '' === trim( $area->getAttribute( 'aria-label' ) ) ) { $c->add( 'area-alt', $area ); } } } /** * If the image is the only content of a link, return the link. * * @param \DOMElement $img Image. * @return \DOMElement|null */ private function sole_link( \DOMElement $img ) { $node = $img->parentNode; while ( $node instanceof \DOMElement && in_array( strtolower( $node->tagName ), array( 'span', 'figure', 'picture', 'div' ), true ) ) { $node = $node->parentNode; } if ( ! $node instanceof \DOMElement || 'a' !== strtolower( $node->tagName ) || ! $node->hasAttribute( 'href' ) ) { return null; } if ( '' !== Html::clean( Html::text_of( $node ) ) && '' !== trim( Html::clean( Html::text_of( $node ) ) ) ) { return null; } if ( '' !== trim( $node->getAttribute( 'aria-label' ) ) || '' !== trim( $node->getAttribute( 'aria-labelledby' ) ) || '' !== trim( $node->getAttribute( 'title' ) ) ) { return null; } return $node; } }