bool. * @param array $context Fixer context. */ public function __construct( array &$plan, array $enabled, array $context ) { $this->plan = &$plan; $this->enabled = $enabled; $this->context = $context; } /** * Whether a fix is on. * * @param string $fix Fix id. * @return bool */ public function on( $fix ) { return ! empty( $this->enabled[ $fix ] ); } /** * Sets an attribute. * * @param int $ord Element ordinal. * @param string $attribute Attribute name. * @param mixed $value Value (true for a boolean attribute, false to remove the attribute). */ public function set( $ord, $attribute, $value ) { $this->plan['mods'][ $ord ]['set'][ $attribute ] = $value; } /** * Whether an attribute is already planned for an element. * * @param int $ord Element ordinal. * @param string $attribute Attribute name. * @return bool */ public function planned( $ord, $attribute ) { return isset( $this->plan['mods'][ $ord ]['set'][ $attribute ] ); } /** * Adds HTML right after an element's opening tag. * * @param int $ord Element ordinal. * @param string $html HTML (already escaped). */ public function prepend( $ord, $html ) { $current = isset( $this->plan['inserts'][ $ord ]['open'] ) ? $this->plan['inserts'][ $ord ]['open'] : ''; $this->plan['inserts'][ $ord ]['open'] = $current . $html; } /** * Adds HTML right before an element's closing tag. * * @param int $ord Element ordinal. * @param string $html HTML (already escaped). */ public function append( $ord, $html ) { $current = isset( $this->plan['inserts'][ $ord ]['close'] ) ? $this->plan['inserts'][ $ord ]['close'] : ''; $this->plan['inserts'][ $ord ]['close'] = $html . $current; } /** * Names a link, button or control. With visible text in it (a share count, * say), the name goes in hidden text before that text, so what people see * stays part of the name; otherwise in aria-label. * * @param array $element Recorded element. * @param string $label Name. * @param string $fix Fix id to count it under. */ public function label( array $element, $label, $fix = 'icon_labels' ) { $label = trim( (string) $label ); if ( '' === $label ) { return; } if ( '' !== $element['text'] && in_array( $element['tag'], Html_Analyzer::NAMED_BY_CONTENT, true ) ) { $this->prepend( $element['ord'], '' . esc_html( $label ) . ' ' ); } else { $this->set( $element['ord'], 'aria-label', $label ); } $this->count( $fix ); } /** * Puts a real button over an icon that only reacted to mouse clicks (a span * or div with the product's click handler). The click on the button bubbles * up to the product's handler, so it keeps working, and keyboards can now * reach it and press it. * * @param array $element Recorded element (must not be void). * @param string $label Button name. * @param string $css_position Optional: when the host is not positioned, 'relative' is set inline. */ public function keyboard_button( array $element, $label, $css_position = '' ) { if ( isset( $element['attrs'][ Compat::KB_MARK ] ) ) { return; } $this->set( $element['ord'], Compat::KB_MARK, '1' ); if ( 'relative' === $css_position ) { $style = isset( $element['attrs']['style'] ) && is_string( $element['attrs']['style'] ) ? rtrim( trim( $element['attrs']['style'] ), ';' ) . ';' : ''; $this->set( $element['ord'], 'style', $style . 'position:relative' ); } $this->prepend( $element['ord'], '' ); $this->count( 'theme_compat' ); } /** * Wraps an element's content in a real button (a heading that opens a * toggle on click, for example), so it can be focused and pressed. * * @param array $element Recorded element whose content is text only. */ public function wrap_in_button( array $element ) { if ( isset( $element['attrs'][ Compat::KB_MARK ] ) ) { return; } $this->set( $element['ord'], Compat::KB_MARK, '1' ); $this->prepend( $element['ord'], '' ); $this->count( 'theme_compat' ); } /** * Counts a fix. * * @param string $fix Fix id. */ public function count( $fix ) { $this->plan['counts'][ $fix ] = isset( $this->plan['counts'][ $fix ] ) ? $this->plan['counts'][ $fix ] + 1 : 1; } }