Résultats de la recherche (10 résultats)

Dr DLP
31 Décembre 2004, 16:57
Ce n'est pas un mod que je vais développer, c'est juste pour indiquer quelques trucs et faire partager ce que je viens de finir (:)

L'utilisation du FULL TEXT permet (avec mysql seulement, c'est spécifique) de faire des recherches directement dans les champs avec mysql : pas besoin du système phpbb o๠sont stockés tous les mots (ce qui est indispensable pour être compatible avec toutes les bdd).
C'est un peu déroutant à mettre en place, à cause des clés FULLTEXT, alors voici ma table en exemple :
CREATE TABLE base_posts_text (
  post_text_id int(8) NOT NULL default '0',
  post_text_board int(8) NOT NULL default '0',
  post_text_text text NOT NULL,
  post_text_subject varchar(255) NOT NULL default '',
  PRIMARY KEY  (post_text_id),
  KEY post_text_board (post_text_board),
  FULLTEXT KEY post_text_subject (post_text_subject,post_text_text)
) TYPE=MyISAM;

Il faut donc absolument un champ en text (ce qui doit déjà être le cas) qui contient le message et un champ sujet dans la même table (si elle n'existe pas dans FSB, il suffira de dupliquer le titre du topic de rattachement).
Et ensuite créer une clé fulltext sur ces deux champs dont le nom est celui du champ titre.

Ensuite on peut se lancer dans le mysql à proprement parler. Pour ma part j'utilise ce coup-ci une version allégée avec seulement trois requêtes :

1)
	$sql = mysql_query("SELECT t.topic_id, t.topic_name, pt.post_text_id, pt.post_text_subject, pt.post_text_text 
			FROM " . POSTS_TEXT_TABLE . " AS pt
			LEFT JOIN " . POSTS_TABLE . " AS p ON ( p.post_id = pt.post_text_id )
			LEFT JOIN " . TOPICS_TABLE . " AS t ON ( t.topic_id = p.post_topic )
			WHERE LOCATE('$search_query', pt.post_text_subject) > 0 $where ") or die ("Fhtagn : " . mysql_errno()." : ".mysql_error()."<br />".$sql);

Rien de sorcier, ça cherche simplement si un des titres des messages contient la requête : dans ce cas, la relevance est très forte.

2)
	$sql = mysql_query("SELECT t.topic_id, t.topic_name, pt.post_text_id, pt.post_text_subject, pt.post_text_text, MATCH (pt.post_text_subject, pt.post_text_text)  AGAINST ('$search_query') AS score
			FROM " . POSTS_TEXT_TABLE . " AS pt
			LEFT JOIN " . POSTS_TABLE . " AS p ON ( p.post_id = pt.post_text_id )
			LEFT JOIN " . TOPICS_TABLE . " AS t ON ( t.topic_id = p.post_topic )
			WHERE MATCH (pt.post_text_subject, pt.post_text_text) AGAINST ('$search_query' $booleen) $where ORDER BY score DESC ") or die ("Fhtagn : " . mysql_errno()." : ".mysql_error()."<br />".$sql);

La recherche fulltext à proprement parler avec une recherche croisée titre/message. Le tri est effectué par pertinence (score).
J'ai isolé $booleen (de valeur "IN BOOLEAN MODE" pour effectuer des recherches booléennes) car toutes les versions de mysql ne le supporte pas.
Cette requête ca sortir prioritairement les sujets contenant la requête dans le titre et le message, en les classant par nombre d'occurences. C'est aussi la requête qui permet de trouver les messages contenant la requête dans le corps du message.

3)
		$sql = mysql_query("SELECT t.topic_id, t.topic_name, pt.post_text_id, pt.post_text_subject, pt.post_text_text, SUBSTRING(SOUNDEX(pt.post_text_subject),1,2) AS cosmos , SUBSTRING(SOUNDEX('$search_query'),1,2) AS spatio 
			FROM " . POSTS_TEXT_TABLE . " AS pt
			LEFT JOIN " . POSTS_TABLE . " AS p ON ( p.post_id = pt.post_text_id )
			LEFT JOIN " . TOPICS_TABLE . " AS t ON ( t.topic_id = p.post_topic )
			WHERE SUBSTRING(SOUNDEX(pt.post_text_subject),1,2) = SUBSTRING(SOUNDEX('$search_query'),1,2) $where ") or die ("Fhtagn : " . mysql_errno()." : ".mysql_error()."<br />".$sql);

Requête de secours : la requête "ressemble" au titre du sujet. Ceci est très... autre, avec des résultats très très variables.

Ce sont juste quelques bases : difficile à mettre en oeuvre mais avec de superbes résultats.
Sur un annuaire je fais des recherches croisées titre/description/message, avec 3 clés fulltext, les résultats sont au moins aussi performant que ceux obtenus avec phpbb.

Deux inconvénients : c'est mysql seulement, et sur des recherches comportant beaucoup, beaucoup de messages, c'est lent.

Un peu de doc pour finir : http://dev.mysql.com/doc/mysql/fr/Fulltext_Search.html

Bon courage si quelqu'un essaye :)
 
Dr DLP
30 Décembre 2004, 21:24
Ca s'intègre de manière évidente avec les balises ayant leur pendant en HTML.
<b>, <i>, ...
Mais il n'y en a pas tant que ça.
 
Dr DLP
30 Décembre 2004, 19:02
A ce propos, dans ce passage :
//
// On marque ce sujet comme 'lu' via un tableau sérialisé dans un cookie
//
if ($membre['membre_id'] != INVITE)
{
	$cookie = unserialize(stripslashes($HTTP_COOKIE_VARS[$config['cookie_nom'] . '_sujets']));
	$cookie[$sujet_id]['type'] = LU;
	$cookie[$sujet_id]['forum_id'] = -1;
	$cookie[$sujet_id]['temps'] = $sujet['dernier_message_temps'];
	@setcookie($config['cookie_nom'] . '_sujets', serialize($cookie), 0, $config['cookie_chemin'], $config['cookie_dommaine'], $config['cookie_securite']);
}

Je ne comprends pas pourquoi tu utilises -1 au lieu de l'id du forum.

Un truc tout bête aussi, dans
function recuperer_nouveaux_messages($derniere_visite)
{
	global $bdd, $config, $langue, $HTTP_COOKIE_VARS;

	$cookie = unserialize(stripslashes($HTTP_COOKIE_VARS[$config['cookie_nom'] . '_sujets']));

	$sql = 'SELECT sujet_id, forum_id, dernier_message_temps FROM ' . SUJETS_TABLE . ' 
			WHERE dernier_message_temps >= \'' . ( $derniere_visite === 0 ? time() : $derniere_visite ) . '\'';
	if ( ! $result = $bdd->requete($sql) )
	{
		info($langue['er_titre'], sprintf($langue['er_select'], 'sujets'), __LINE__, __FILE__, $sql);
	}

	$data = array();
	while ( $nouveau = $bdd->tableau($result) )
	{
		$status = ( $cookie[$nouveau['sujet_id']]['type'] == LU && $nouveau['dernier_message_temps'] <= $cookie[$nouveau['sujet_id']]['temps'] ) ? LU : NON_LU;
		$data[$nouveau['sujet_id']]['type'] = $status;
		$data[$nouveau['sujet_id']]['forum_id'] = $nouveau['forum_id'];
		$data[$nouveau['sujet_id']]['temps'] = $nouveau['dernier_message_temps'];
	}

	return $data;
}

exclut les messages postés par l'utilisateur courant. En cas d'erreur ou d'exclusion des cookies, au moins l'utilisateur ne verra ses propres messages en non lus.
 
Dr DLP
30 Décembre 2004, 18:53
Pour les quotes et code, il faut utiliser les fonctions existantes, et celle là ensuite, après que les balises code et quote aient été transformées.
 
Dr DLP
28 Décembre 2004, 16:55
J'avais fait (fait est très exagéré, c'est entièrement pompé sur le mod bbcode php de Fubonis) un truc du genre pour un système de commentaires :
function color($text)
{
	$matches = array();
	$match_count = preg_match_all("#\[php\](.*?)\[/php\]#si", $text, $matches);
	for ( $i = 0; $i < $match_count; $i ++)
	{
		$before_replace = $matches[1][$i];
		$after_replace = trim($matches[1][$i]);
		$str_to_match = "[php]" . $before_replace . "[/php]";
		$after_replace = str_replace('&lt;', '<', $after_replace);
		$after_replace = str_replace('&gt;', '>', $after_replace);
		$after_replace = str_replace('&amp;', '&', $after_replace);
		$added = FALSE;
		if (preg_match('/^<\?.*?\?>$/si', $after_replace) <= 0)
		{
			$after_replace = "<?php $after_replace ?>";
			$added = TRUE;
		}
		if(strcmp('4.2.0', phpversion()) > 0)
		{
			ob_start();
			highlight_string($after_replace);
			$after_replace = ob_get_contents();
			ob_end_clean();
		}
		else
		{
			$after_replace = highlight_string($after_replace, TRUE);
		}
		if ($added == TRUE)
		{
			$after_replace = str_replace('<font color="#0000BB">&lt;?php ', '<font color="#0000BB">', $after_replace);
			$after_replace = str_replace('<font color="#0000BB">?&gt;</font>', '', $after_replace);
		}
		$after_replace = preg_replace('/<font color="(.*?)">/si', '<span style="color: \\1;">', $after_replace);
		$after_replace = str_replace('</font>', '</span>', $after_replace);
		$after_replace = str_replace("\n", '', $after_replace);
		$replacement .= $after_replace;

		$text = str_replace($str_to_match, $replacement, $text);
	}

	$new_match_count = preg_match_all("#\[blockquote\](.*?)\[/blockquote\]#si", $text, $new_matches);
	for ( $i = 0; $i < $new_match_count; $i ++)
	{
		$ligne = explode("\n",$new_matches[1][$i]);
		reset($ligne);
		while($l = each($ligne)) 
		{
			ereg('^ *',$l[1],$tab);
			$temp_text[$i] .= ereg_replace(' ','&nbsp',$tab[0]);
			$temp_text[$i] .= htmlentities(ereg_replace('^ *','',$l[1]));
			$temp_text[$i] .= "<BR>";
		}
		$oc_to_replace[$i] = "[blockquote]".$new_matches[1][$i]."[/blockquote]";
		$text = str_replace($oc_to_replace[$i],$temp_text[$i],$text);
	}
	return $text;
}

Utilisé avec le traitement suivant :
	$comment = "[blockquote]".$comment."[/blockquote]";
	$comment = str_replace('<?php','[/blockquote][php]',$comment);
	$comment = str_replace('?>','[/php]fin_du_php_125485734[blockquote]',$comment);
	$comment = str_replace('<?','[/blockquote][php]',$comment);
	$comment = color(stripslashes($comment));
	$comment = str_replace('fin_du_php_125485734','&nbsp<font color="#0000BB">?></font>',$comment);

C'est vraiment moche mais fonctionnel.

PS : Les balises php ici ont un souci avec les imbrications d'autres balises php, il faut neutraliser les balises contenues comme avec le bbcode code :)
 
Dr DLP
23 Décembre 2004, 0:33
Le problème est le même que pour le bbcode code, la solution est la même.
Le principe est simple : dans
[b][i][b][b]gras[/b][/b][/i][/b]
il est évident que seul le premier groupe de
[b][/b]
( le plus externe par rapport au texte ) à interêt à être traité.
Il suffit donc de virer les occurences [bbcode][/bbcode] déjà inclus dans un [bbcode][/bbcode].

La fonction récursive suivante s'en occupe :
function parse_bbcode($message, $bbcode)
{
	preg_match_all("`\[$bbcode\](.*?)\[/$bbcode\]`si", $message, $matches);
	$nb_matches = count($matches[1]);
	$bb_length = strlen($bbcode) + 2;
	for ($i = 0; $i < $nb_matches; $i++)
	{
		if ( preg_match_all("`\[$bbcode\](.*?)\[/$bbcode\]`si", $matches[$i][0], $matchs) )
		{
			$nb_matchs = count($matchs[1]);
			$newm = substr($matchs[0][0], $bb_length);
			if ( preg_match("`\[$bbcode\](.*?)\[/$bbcode\]`si", $newm) && $nb_matchs > 0 )
			{
				$new_message = preg_replace("`\[$bbcode\](.*?)\[/$bbcode\]`", "\\1", $newm);
				$new_message = str_replace($newm, $new_message, $message);
				return parse_bbcode($new_message, $bbcode);
			}
		}
	}
	$message = preg_replace("#\[$bbcode\](.*?)\[/$bbcode\]#si", "<$bbcode>\\1</$bbcode>", $message);

	return $message;
}

Et les bbcodes simples sont traités par :
$message = parse_bbcode($message, 'b');
$message = parse_bbcode($message, 'u');
$message = parse_bbcode($message, 'i');
$message = parse_bbcode($message, 'strike');
 
Dr DLP
22 Décembre 2004, 21:23
Finalement, il y a des soucis au niveau de l'imbrication de tous les bbcodes :

Citation
  1. 1
  2. 2
  3. 3
  4. 4



jhrjrjrjrrj



[size=18]hhheeh[/size]


 
Dr DLP
22 Décembre 2004, 20:20
Je n'ai pas vu de traces de listes ordonnées avec type.
Tu peux les rajouter avec ça :
		preg_match_all("`\[list=(.*?)\](.*?)\[/list\]`si", $message, $matches);
		$nb_matches = count($matches);
		for ($i = 0; $i < $nb_matches; $i++)
		{
			$origine = $matches[0][$i];
			$remplacement = $matches[0][$i];
			$remplacement = str_replace('[*]', '<li>', $remplacement);
			$message = str_replace($origine, $remplacement, $message);
		}
		$message = fscode_subparse($message, '(\[list=\])', '(\[/list\])', $theme['fsliste_ouvert'], $theme['fsliste_ferme']);
		$message = preg_replace("`\[list=(.*?)\](.*?)\[/list\]`si", '<ol type="\\1">\\2</ol>', $message);

Et dans les fichiers thèmes :
$theme['fsliste_ouvert'] = '<ol>';
$theme['fsliste_ferme'] = '</ol>';
 
Dr DLP
22 Décembre 2004, 19:27
Il suffit de faire une fonction récursive :=) :
function parse_code($message)
{
	preg_match_all("`\[code\](.*?)\[/code\]`si", $message, $matches);
	$nb_matches = count($matches[1]);
	for ($i = 0; $i < $nb_matches; $i++)
	{
		if ( preg_match_all("`\[code\](.*?)\[/code\]`si", $matches[$i][1], $matchs) )
		{
			$nb_matchs = count($matchs[1]);
			$newm = substr($matchs[0][0], 6);

			if ( preg_match("`\[code\](.*?)\[/code\]`si", $newm) && $nb_matchs > 0 )
			{
				$new_message = preg_replace("`\[code\](.*?)\[/code\]`", fscode2fs('[code]')."\\1".fscode2fs('
'), $newm);
$new_message = str_replace($newm, $new_message, $message);
return parse_code($new_message);
}
}

$origine = $matches[1][$i];
$remplacement = $matches[1][$i];
$remplacement = fscode2fs($remplacement);
$remplacement = str_replace(" ", "&nbsp; ", $remplacement);
$remplacement = str_replace(" ", " &nbsp;", $remplacement);
$remplacement = str_replace("\t", "&nbsp; &nbsp;", $remplacement);
$remplacement = preg_replace("/^ {1}/m", '&nbsp;', $remplacement);
$origine = '
' . $origine . '
';
$remplacement = '
' . $remplacement . '
';
$message = str_replace($origine, $remplacement, $message);
}
$message = preg_replace("`\[code\](.*?)\[/code\]`si", fscode_code('\\1'), $message);

return $message;
}[/code]

J'ai testé avec ton fichier (remplace juste $message par $texte), c'est ok de mon cà´té.

Erf... Evidemment avec le bug... edite mon message pour voir le code :)
 
Dr DLP
22 Décembre 2004, 18:12
Salut :=)

Je suis en train de coder un petit système de forums (nettement moins complexe que celui-ci ou phpbb) et je galère un peu sur les bbcodes... Ces expressions régulières sont une horreur.
Bref; je teste chez les autres pour voir si ça fonctionne.
Ici il y a un bug avec les imbrications du bbcode code : le traitement se fait sur la première balise fermante au lieu de la dernière :
[quote][code][i][b]jktjkkf[/b][/i]
[/quote][/code]

Je n'ai pas vu que ceci a déjà été signalé. Je vais chercher un peu de mon cà´té.
Bon courage :)
 

.