3v4l.org

run code in 300+ PHP versions simultaneously
<?php function getCopiedText($model, $answer, $min = 4) { //replace all space characters from model with single white-space $model = preg_replace('/\s+/iu', ' ', $model); //ensure there are no double spaces in the answer. $answer = str_replace(' ', ' ', $answer); $test = new CachingIterator(new ArrayIterator(explode(' ', $answer))); $words = $matches = []; $p = $match = null; //test each word foreach($test as $i => $word) { $words[] = $word; $escapedWords[] = preg_replace('/\s+/iu', ' ', $word); $count = count($words); if ($count === 2) { //save pointer at second word match $p = $i; } //check if the phrase of words exists in the model if (false !== stripos($model, implode(' ', $escapedWords))) { //only match phrases with the minimum or more words if ($count >= $min) { //reset back to here for more matches $match = implode(' ', $words); if (!$test->hasNext()) { //add the the last word to the phrase $matches[$match] = true; $p = null; } } } else { //the phrase of words was no longer found if (null !== $match && !isset($matches[$match])) { //add the matched phrase to the list of matches $matches[$match] = true; $p = null; $iterator = $test->getInnerIterator(); if ($iterator->valid()) { //rewind pointer back to the current word since a partial phrase less than 4 words was matched $iterator->seek($i); } } elseif (null !== $p) { //match not found, determine if we need to rewind the pointer $iterator = $test->getInnerIterator(); if ($iterator->valid()) { //rewind pointer back to second word since a partial phrase less than 4 words was matched $iterator->seek($p); } $p = null; } //reset testing $escapedWords = $words = []; $match = null; } } //highlight the matched phrases in the answer if (!empty($matches)) { $phrases = array_keys($matches); //sort phrases by the length array_multisort(array_map('strlen', $phrases), $phrases); //filter the matches as regular expression patterns //order by longest phrase first to ensure double highlighting of smaller phrases $phrases = array_map(function($phrase) { return '/(' . preg_quote($phrase, '/') . ')/iu'; }, array_reverse($phrases)); $answer = preg_replace($phrases, '<span style="color:blue">$0</span>', $answer); } return $answer; } $modelAnswer = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry`s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.'; $answers = [ "NOT IN is simply\ndummy text of NOT in when an unknown printer took\na galley -this- is simply dummy text of the printing and typesetting industry", "NOT IN is simply\ndummy (\$1) /text NOT in when an unknown printer took a galley -this- is simply dummy text of the printing and typesetting industry", ]; foreach($answers as $answer) { echo getCopiedText($modelAnswer, $answer) . \PHP_EOL; echo '----' . \PHP_EOL; }
Output for 7.1.25 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.33, 8.2.0 - 8.2.29, 8.3.0 - 8.3.26, 8.4.1 - 8.4.13
NOT IN <span style="color:blue">is simply dummy text of</span> NOT in <span style="color:blue">when an unknown printer took a galley</span> -this- <span style="color:blue">is simply dummy text of the printing and typesetting industry</span> ---- NOT IN is simply dummy ($1) /text NOT in <span style="color:blue">when an unknown printer took a galley</span> -this- <span style="color:blue">is simply dummy text of the printing and typesetting industry</span> ----

preferences:
122.04 ms | 409 KiB | 5 Q