Newsgroup: it.comp.www.php
Titolo: evidenziare parole nel testo

Per un sito che sto facendo mi serve di evidenziare in un dato testo
delle parole, non volevo farlo in javascript ma metterlo direttamente
in php, lo script che ho scritto sembra funzionare, solamente che cn
certe parole ci mettemoooltissimo tempo, alcune volte va in timout la
pagina, ho pensato a questo e non alla str_replace perchè ho pensato
al caso in cui cercassi nel testo anche qualcosa tipo "span", e che
facendo più str_replace consecutive darebbe problemi...
Mi potete dare una mano ad ottimizzarlo????
qui il codice...
cerca contiene le parole da evidenziare
esempio "pippo pluto paperino"
$sostituti contiene la lista dei codici con cui ogni parola va
evidenziata
$txt è il testo
grazie a chi mi darà una mano...
function createSostitute($arg)
{
	$palette[0]="yellow";
	$palette[1]="blue";
	$palette[2]="fuchsia";
	$palette[3]="gray";
	$palette[4]="green";
	$palette[5]="lime";
	$palette[6]="#00CED1";
	$palette[7]="#D2691E";
	$palette[8]="olive";
	$palette[9]="purple";
	$palette[10]="red";
	$palette[11]="silver";
	$palette[12]="teal";
	$palette[13]="yellow";
	$palette[14]="#00FFFF";
	$palette[15]="#008B8B";
	$palette[16]="#FF8C00";
	$palette[17]="#FF1493";
	$palette[18]="#00BFFF";
	$palette[19]="#FFD700";
	$palette[20]="#ADFF2F";
	$palette[21]="#7CFC00";
	$palette[22]="#FF00FF";
	$palette[23]="#4682B4";
	$palette[24]="#D02090";
	$palette[25]="#FFA07A";
	$palette[26]="#F08080";
	$palette[27]="#F0E68C";
	$palette[28]="#DAA520";
	$palette[29]="#D19275";
	$palette[30]="#6495ED";
	$argv=explode(" ",$arg);
	$argc=count($argv);
	for($i=0;$i<$argc;$i++)
	{
		$sostituti[strtolower($argv[$i])]=$palette[($i%count($palette))];
	}
	return $sostituti;
}
if(isset($_REQUEST['cerca']))
{
	$arg=$_REQUEST['cerca'];
	$sostituti=createSostitute($arg);
}
//Fine calcolo degli argomenti
function evidenzia($sostituzione,$msg)
{
	//Caso base
	if($msg=="") return "";		//Forse ridondante
	if(strlen($msg)==1)		//Se è 1 carattere solo non può essere ridiviso
	{
		if(isset($sostituzione[strtolower($msg)]))
		{
			return "<span style=\"background-color:
".$sostituzione[strtolower($msg)]." \">" .$msg. "</span>";
		}
		else
		{
			return $msg;
		}
	};
	//E' lui??
	if(isset($sostituzione[strtolower($msg)]))
	{
		return "<span style=\"background-color:
".$sostituzione[strtolower($msg)]." \">" .$msg. "</span>";
	}
	//Passo
	$c=strlen($msg);
	$c=round($c/2);
	$prima=substr($msg, 0, $c);
	$dopo =substr($msg,$c,strlen($msg));
	$p = evidenzia($sostituzione,$prima);
	$d = evidenzia($sostituzione,$dopo);
	$a=strlen($p);
	$b=strlen($d);
	for($i=0;$i<$a;$i++)
	{
		for($j=0;$j<$b;$j++)
		{
			if(substr($p, strlen($p)-$i,strlen($p))==substr($prima,
strlen($prima)-$i,strlen($prima)))
			{
				if(substr($d,0,$j)==substr($dopo,0,$j))
				{
					$str=substr($p, strlen($p)-$i,strlen($p)).substr($d,0,$j);
					if(isset($sostituzione[strtolower($str)]))
					{
						return substr($p,0, strlen($p)-$i)."<span
style=\"background-color: ".$sostituzione[strtolower($str)]." \">"
.$str. "</span>".substr($d,$j,strlen($d));
					}
				}
				else
				{
					$j=$b;
				}
			}
			else
			{
				$i=$a;
			}
		}
	}
	return $p . $d;
}
evidenzia($sostituti,$text);

facendo più str_replace consecutive darebbe problemi...
Ti conviene risolvere in altro modo. Per esempio fare una replace in piu'
passaggi. Questa qui sotto ignora tutto cio' che e' fra <segni di tag>, e
in prima battuta rimpiazza la stringa con ((x)), e dopo rimpiazza tutti i
((x)) con la stringa di destinazione.
In questo modo se per es. la stringa cerca "pippo" e contiene "span", non
c'e' conflitto: la prima sostituzione trasforma "pippo" in "((1))" (e non
hai stringhe di sostituzione nella forma "((x))"), e la seconda trasforma
"((1))", e quindi per essa "span" non ha significato.
Ovviamente non l'ho testata piu' del minimo indispensabile - non ti posso
garantire che non sia l'equivalente di una fork bomb.
Si puo' fare la stessa cosa con due str_replace - ma io l'ho fatta usando
preg_replace_callback per poter escludere i tag HTML gia' presenti.
Facendola con due preg_replace, potresti effettuare il match anche per le
parole intere: qui come vedi "spanne" matcha "span".
=============
$subst1 = array( 'pippo', 'span', 'strong', 'green' );
$subst  = array();
$subst2 = array();
foreach($subst1 as $i => $word)
{
        $subst[$word]   = "(($i))";
        $subst2[$i]     = "<span style=\"background-color:
green;\"><strong>$word</strong></span>";
}
function replace_text($string)
{
        GLOBAL $subst;
        return str_replace(array_keys($subst), array_values($subst),
$string[0]);
}
$text   = <<<TESTO
Pippo e il dottor Strong misurano a spanne il green del<br />
Jolly Hotel dove Pippo giochera' una partita a <em><u>golf</u></em>.
TESTO;
$text   = substr(
                str_replace(array_values($subst), array_values($subst2),
                        preg_replace_callback("/>([^<>]+)</",
'replace_text', ">$text<")
                ),
                1, -1);
print $text;
Leonardo SE&O
-- 
Dawn is near, the time is short (Human aircraft! Hard to port!)
We eight reindeers of the night work as one in silent flight.
Let not one damn house pass by (Who taught that guy how to fly?)
Each year sees more girls and boys: how many of them can we bring toys?

 esempio "pippo pluto paperino"
[..]
usa le regex e vedrai che tutto diventera' semplice semplice..
prova a scrivere qualcosa e se non ci riesci torna pure a chiedere..
-- 
www.iuz-lab.info


* @version     3.1.1
* @link
http://aidanlister.com/repos/v/function.str_highlight.php
* @param       string          $text           Haystack - The text to
search
* @param       array|string    $needle         Needle - The string to
highlight
* @param       bool            $options        Bitwise set of options
* @return      Text with needle highlighted
*/
function evidenzia_testo($text, $needle, $options = null)
{
	global $config;
	// Highlighting
	$highlight =
$config['evidenzia_apri'].'\1'.$config['evidenzia_chiudi'];
	// Select pattern to use
	if ($options & STR_HIGHLIGHT_SIMPLE)
	{
  		$pattern = '#(%s)#';
		$sl_pattern = '#(%s)#';
	}
	else
	{
		$pattern = '#(?!<.*?)(%s)(?![^<>]*?>)#';
		$sl_pattern = '#<a\s(?:.*?)>(%s)</a>#';
	}
	// Case sensitivity
	if (!($options & STR_HIGHLIGHT_CASESENS))
	{
		$pattern .= 'i';
		$sl_pattern .= 'i';
	}
	$needle = (array) $needle;
	foreach ($needle as $needle_s)
	{
		$needle_s = preg_quote($needle_s);
		// Escape needle with optional whole word check
		if ($options & STR_HIGHLIGHT_WHOLEWD)
		{
			$needle_s = '\b' . $needle_s . '\b';
		}
		// Strip links
		if ($options & STR_HIGHLIGHT_STRIPLINKS)
		{
			$sl_regex = sprintf($sl_pattern, $needle_s);
         $text = preg_replace($sl_regex, '\1', $text);
      }
      $regex = sprintf($pattern, $needle_s);
      $text = preg_replace($regex, $highlight, $text);
   }
 
   return $text;
}
?>

 ...
Dimenticavo: $config['evidenzia_apri'] contiene il tag di apertura per
evidenziare. $config['evidenzia_chiudi'] quello di chiusura.
Personalizza tu.
E' scritto molto bene, è molto veloce e funziona alla perfezione. Ciao.