public static ActiveLinkResponseFilter::setLinkActiveClass($html_markup, $current_path, $is_front, $url_language, array $query)
Sets the "is-active" class on relevant links.
This is a PHP implementation of the drupal.active-link JavaScript library.
@todo Once a future version of PHP supports parsing HTML5 properly (i.e. doesn't fail on https://www.drupal.org/comment/7938201#comment-7938201) then we can get rid of this manual parsing and use DOMDocument instead.
Parameters
string $html_markup.: The HTML markup to update.
string $current_path: The system path of the currently active page.
bool $is_front: Whether the current page is the front page (which implies the current path might also be <front>).
string $url_language: The language code of the current URL.
array $query: The query string for the current URL.
Return value
string The updated HTML markup.
File
- core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php, line 126
Class
- ActiveLinkResponseFilter
- Subscribes to filter HTML responses, to set the 'is-active' class on links.
Namespace
Drupal\Core\EventSubscriber
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | public static function setLinkActiveClass( $html_markup , $current_path , $is_front , $url_language , array $query ) { $search_key_current_path = 'data-drupal-link-system-path="' . $current_path . '"' ; $search_key_front = 'data-drupal-link-system-path="<front>"' ; $offset = 0; // There are two distinct conditions that can make a link be marked active: // 1. A link has the current path in its 'data-drupal-link-system-path' // attribute. // 2. We are on the front page and a link has the special '<front>' value in // its 'data-drupal-link-system-path' attribute. while ( strpos ( $html_markup , $search_key_current_path , $offset ) !== FALSE || ( $is_front && strpos ( $html_markup , $search_key_front , $offset ) !== FALSE)) { $pos_current_path = strpos ( $html_markup , $search_key_current_path , $offset ); // Only look for links with the special '<front>' system path if we are // actually on the front page. $pos_front = $is_front ? strpos ( $html_markup , $search_key_front , $offset ) : FALSE; // Determine which of the two values is the next match: the exact path, or // the <front> special case. $pos_match = NULL; if ( $pos_front === FALSE) { $pos_match = $pos_current_path ; } elseif ( $pos_current_path === FALSE) { $pos_match = $pos_front ; } elseif ( $pos_current_path < $pos_front ) { $pos_match = $pos_current_path ; } else { $pos_match = $pos_front ; } // Find beginning and ending of opening tag. $pos_tag_start = NULL; for ( $i = $pos_match ; $pos_tag_start === NULL && $i > 0; $i --) { if ( $html_markup [ $i ] === '<' ) { $pos_tag_start = $i ; } } $pos_tag_end = NULL; for ( $i = $pos_match ; $pos_tag_end === NULL && $i < strlen ( $html_markup ); $i ++) { if ( $html_markup [ $i ] === '>' ) { $pos_tag_end = $i ; } } // Get the HTML: this will be the opening part of a single tag, e.g.: // <a href="/" data-drupal-link-system-path="<front>"> $tag = substr ( $html_markup , $pos_tag_start , $pos_tag_end - $pos_tag_start + 1); // Parse it into a DOMDocument so we can reliably read and modify // attributes. $dom = new \DOMDocument(); @ $dom ->loadHTML( '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>' . $tag . '</body></html>' ); $node = $dom ->getElementsByTagName( 'body' )->item(0)->firstChild; // Ensure we don't set the "active" class twice on the same element. $class = $node ->getAttribute( 'class' ); $add_active = !in_array( 'is-active' , explode ( ' ' , $class )); // The language of an active link is equal to the current language. if ( $add_active && $url_language ) { if ( $node ->hasAttribute( 'hreflang' ) && $node ->getAttribute( 'hreflang' ) !== $url_language ) { $add_active = FALSE; } } // The query parameters of an active link are equal to the current // parameters. if ( $add_active ) { if ( $query ) { if (! $node ->hasAttribute( 'data-drupal-link-query' ) || $node ->getAttribute( 'data-drupal-link-query' ) !== Json::encode( $query )) { $add_active = FALSE; } } else { if ( $node ->hasAttribute( 'data-drupal-link-query' )) { $add_active = FALSE; } } } // Only if the path, the language and the query match, we set the // "is-active" class. if ( $add_active ) { if ( strlen ( $class ) > 0) { $class .= ' ' ; } $class .= 'is-active' ; $node ->setAttribute( 'class' , $class ); // Get the updated tag. $updated_tag = $dom ->saveXML( $node , LIBXML_NOEMPTYTAG); // saveXML() added a closing tag, remove it. $updated_tag = substr ( $updated_tag , 0, strrpos ( $updated_tag , '<' )); $html_markup = str_replace ( $tag , $updated_tag , $html_markup ); // Ensure we only search the remaining HTML. $offset = $pos_tag_end - strlen ( $tag ) + strlen ( $updated_tag ); } else { // Ensure we only search the remaining HTML. $offset = $pos_tag_end + 1; } } return $html_markup ; } |
Please login to continue.