diff -u b/core/modules/search/search.module b/core/modules/search/search.module --- b/core/modules/search/search.module +++ b/core/modules/search/search.module @@ -646,7 +646,9 @@ */ function search_excerpt($keys, $text, $langcode = NULL) { // We highlight around non-indexable or CJK characters. - $boundary = '(?:(?<=[' . Unicode::PREG_CLASS_WORD_BOUNDARY . PREG_CLASS_CJK . '])|(?=[' . Unicode::PREG_CLASS_WORD_BOUNDARY . PREG_CLASS_CJK . ']))'; + $boundary_character = '[' . Unicode::PREG_CLASS_WORD_BOUNDARY . PREG_CLASS_CJK . ']'; + $preceded_by_boundary = '(?<=' . $boundary_character . ')'; + $followed_by_boundary = '(?=' . $boundary_character . ')'; // Extract positive keywords and phrases. preg_match_all('/ ("([^"]+)"|(?!OR)([^" ]+))/', ' ' . $keys, $matches); @@ -662,7 +664,7 @@ // search_simplify(). $temp_keys = array(); foreach ($keys as $key) { - $key = _search_find_match_with_simplify($key, $text, $boundary, $langcode); + $key = _search_find_match_with_simplify($key, $text, $boundary_character, $langcode); if (isset($key)) { // Quote slashes so they can be used in regular expressions. $temp_keys[] = preg_quote($key, '/'); @@ -697,7 +699,7 @@ // we are requiring a match on a word boundary, make sure $text starts // and ends with a space. $matches = array(); - if (preg_match('/' . $boundary . $key . $boundary . '/iu', ' ' . $text . ' ', $matches, PREG_OFFSET_CAPTURE, $look_start[$key])) { + if (preg_match('/' . $preceded_by_boundary . $key . $followed_by_boundary . '/iu', ' ' . $text . ' ', $matches, PREG_OFFSET_CAPTURE, $look_start[$key])) { $found_position = $matches[0][1]; $look_start[$key] = $found_position + 1; // Keep track of which keys we found this time, in case we need to @@ -783,7 +785,7 @@ // Highlight keywords. Must be done at once to prevent conflicts ('strong' // and ''). - $text = trim(preg_replace('/' . $boundary . '(?:' . implode('|', $keys) . ')' . $boundary . '/iu', '\0', ' ' . $text . ' ')); + $text = trim(preg_replace('/' . $preceded_by_boundary . '(?:' . implode('|', $keys) . ')' . $followed_by_boundary . '/iu', '\0', ' ' . $text . ' ')); return [ '#markup' => $text, '#allowed_tags' => ['strong'] @@ -802,7 +804,8 @@ * @param string $text * The text to search for the keyword. * @param string $boundary - * Regular expression for boundary characters between words. + * Regular expression for the boundary character class (characters that + * indicate spaces between words). * @param string|null $langcode * Language code for the language of $text, if known. * @@ -813,6 +816,9 @@ * not located, NULL is returned. */ function _search_find_match_with_simplify($key, $text, $boundary, $langcode = NULL) { + $preceded_by_boundary = '(?<=' . $boundary . ')'; + $followed_by_boundary = '(?=' . $boundary . ')'; + // See if $key appears as-is. When testing, make sure $text starts/ends with // a space, because we require $key to be surrounded by word boundary // characters. @@ -820,7 +826,7 @@ if ($temp == '') { return NULL; } - if (preg_match('/' . $boundary . preg_quote($temp, '/') . $boundary . '/iu', ' ' . $text . ' ')) { + if (preg_match('/' . $preceded_by_boundary . preg_quote($temp, '/') . $followed_by_boundary . '/iu', ' ' . $text . ' ')) { return $temp; } @@ -830,7 +836,7 @@ $new_text = \Drupal::service('transliteration')->removeDiacritics($new_text); $new_key = Unicode::strtolower($temp); $new_key = \Drupal::service('transliteration')->removeDiacritics($new_key); - if (preg_match('/' . $boundary . preg_quote($new_key, '/') . $boundary . '/iu', ' ' . $new_text . ' ')) { + if (preg_match('/' . $preceded_by_boundary . preg_quote($new_key, '/') . $followed_by_boundary . '/u', ' ' . $new_text . ' ')) { $position = Unicode::strpos($new_text, $new_key); return Unicode::substr($text, $position, Unicode::strlen($new_key)); } @@ -844,7 +850,7 @@ } // Split $text into words, keeping track of where the word boundaries are. - $words = preg_split('/' . $boundary . '/iu', $text, NULL, PREG_SPLIT_OFFSET_CAPTURE); + $words = preg_split('/' . $boundary . '+/u', $text, NULL, PREG_SPLIT_OFFSET_CAPTURE); // Add an entry pointing to the end of the string, for the loop below. $words[] = array('', strlen($text)); $num_words = count($words);