Aller au contenu
Support de Zwii
roger

[Résolu] Module de recherche amélioration

Messages recommandés

Bonjour @Fred ainsi que  @sylvainlelievre

 

Voila ce n'est as vraiment un bug que je relate ici mais plutôt un inconvénient relevé depuis quelque temps déjà et qui concerne la page de recherche d'un Zwii.

 

- En effet lorsque nous lançons une recherche sur un mot précis ou des mots approchants (avec l'option prévue sous la barre de recherche) et bien aucun résultat n 'est retourné si l'un des mots (ou un simple mot) est écrit dans un commentaire posté par exemple dans le blog.

- C'est idem si l'on recherche dans les "Galeries" d'un zwii le module ne trouve pas les noms de galeries crées

 

💡 Il me semble important que le module de recherche soit aussi capable de recherche n'importe quel terme das un  zwii et qui soit à la vue d'un visiteur ou d'un membre enregistré; non?

Si on a un site qui contient énormément de commentaires postés (exemple un zwii de vulgarisation en tutoriel, un zwii transformé en site de vente ou dépannage) les gens aiment y trouver s'ils ont oublié où ils l'ont lu un terme bien précis pour le retrouver dans le contexte....

 

Cet exemple en 4 images:

Un commentaire de base à l'installation du ZwiiCMS rédigé par Rémi dans un article du blog

A.thumb.png.973cc6be0e923a9c1ce1b829fda91240.png

 

Je tape donc dans le formulaire de recherche

B.png.dd6e55f9a995ff9028b28780701fb0d5.png

résultat

C.png.d7c4eed04e7cfe67df3862f80747e94f.png

 

Je recommence avec l'autre option (décocher les mots approchants)

D.png.5fd7ac0e114a0ecad0b82bfe960bb06a.png

résultat

D.png.5fd7ac0e114a0ecad0b82bfe960bb06a.png

 

mais n'ai pas réussi à trouver dans le module search (maintenant incorporé au zwii) les codes à modifier; peur être le développeur à l'origine de ce module @sylvainlelievre pourrait trouver comment remédier à ce petit inconvénient là  🤓

Modifié par roger

Partager ce message


Lien à poster
Partager sur d’autres sites

@roger c'est parce que le module search n'est plus plus vraiment celui de @sylvainlelievre, désormais il fonctionne par expressions régulières.

 

Les lignes 117 - 118, 132 et 133 font l'agrégation du titre de la page et de son contenu, mais jamais du contenu du module dépendant de la page 165 et 1696, sauf pour le blog. 

 

Autrement dit ne sont pas pris en compte :

  • les commentaires
  • les news
  • les galeries
  • les formulaires

C'est un choix volontaire afin de diminuer la complexité de la mise en évidence des résultats gérés par la fonction occurrence :

private function occurrence($url, $titre, $contenu, $motclef, $motentier)
	{
		// Nettoyage de $contenu : on enlève tout ce qui est inclus entre < et >
		$contenu = preg_replace ('/<[^>]*>/', ' ', $contenu);
		// Accentuation
		$contenu = html_entity_decode($contenu);

		// Découper le chaîne en tenant compte des quillemets
		$a = str_getcsv(html_entity_decode($motclef), ' ');

		// Construire la clé de recherche selon options de recherche
		$keywords = '/(';
		foreach ($a as $key => $value) {
			$keywords .= $motentier === true ? $value . '|' : '\b' . $value . '\b|' ;
		}
		$keywords = substr($keywords,0,strlen($keywords) - 1);
		$keywords .= ')/i';
		$keywords = str_replace ('+', ' ',$keywords);

		// Rechercher
		$valid = preg_match_all($keywords,$contenu,$matches,PREG_OFFSET_CAPTURE);
		if ($valid > 0 ) {
			if (($matches[0][0][1]) > 0) {
				$resultat = '<h2><a  href="./?'.$url.'" target="_blank" rel="noopener">' . $titre .  '</a></h2>';
				// Création de l'aperçu
				// Eviter de découper avec une valeur négative
				$d = $matches[0][0][1] - 50 < 0 ? 1 : $matches[0][0][1] - 50;
				// Rechercher l'espace le plus proche
				$d = $d >= 1 ? strpos($contenu,' ',$d) : $d;
				// Découper l'aperçu
				$t = substr($contenu, $d ,$this->getData(['module',$this->getUrl(0),'previewLength']));
				// Applique une mise en évidence
				$t = preg_replace($keywords, '<span class="searchKeyword">\1</span>',$t);
				// Sauver résultat
				$resultat .= '<p class="searchResult">'.$t.'...</p>';
				$resultat .= '<p class="searchTitle">' . count($matches[0]) . (count($matches[0]) === 1 ? ' correspondance<p>' : ' correspondances<p>');
				//}
				return ([
					'matches' => count($matches[0]),
					'preview' => $resultat
				]);
			}
		}
	}

 

et surtout de celle-ci :

 

	public function index() {
		// Création des valeurs de thème par défaut
		if ( $this->getData(['theme', 'search']) === null ) {
			require_once('module/search/ressource/defaultdata.php');
			$this->setData(['theme', 'search', theme::$defaultData]);
		}
		// Création des valeurs de réglage par défaut
		if ( $this->getData(['module', 'search']) === null ) {
			require_once('module/search/ressource/defaultdata.php');
			$this->setData(['module', $this->getUrl(0), data::$defaultData]);
		}

		if($this->isPost())  {
			//Initialisations variables
			$success = true;
			$result = [];
			$notification = '';
			$total='';

			// Récupération du mot clef passé par le formulaire de ...view/index.php, avec caractères accentués
			self::$motclef=$this->getInput('searchMotphraseclef');

			// Récupération de l'état de l'option mot entier passé par le même formulaire
			self::$motentier=$this->getInput('searchMotentier', helper::FILTER_BOOLEAN);

			if (self::$motclef !== '' ) {
				foreach($this->getHierarchy(null,false,null) as $parentId => $childIds) {
					if ($this->getData(['page', $parentId, 'disable']) === false  &&
                        $this->getUser('group') >= $this->getData(['page', $parentId, 'group']) &&
                        $this->getData(['page', $parentId, 'block']) !== 'bar') 	{
						$url = $parentId;
						$titre = $this->getData(['page', $parentId, 'title']);
						$contenu =  ' ' . $titre . ' ' . $this->getData(['page', $parentId, 'content']);
						// Pages sauf pages filles et articles de blog
						$tempData  = $this->occurrence($url, $titre, $contenu, self::$motclef, self::$motentier);
						if (is_array($tempData) ) {
							$result [] = $tempData;
						}
					}

					foreach($childIds as $childId) {
							// Sous page
							if ($this->getData(['page', $childId, 'disable']) === false &&
                                $this->getUser('group') >= $this->getData(['page', $parentId, 'group']) &&
                                $this->getData(['page', $parentId, 'block']) !== 'bar') 	{
                                    $url = $childId;
                                    $titre = $this->getData(['page', $childId, 'title']);
                                    $contenu = ' ' . $titre . ' ' . $this->getData(['page', $childId, 'content']);
                                    //Pages filles
									$tempData  = $this->occurrence($url, $titre, $contenu, self::$motclef, self::$motentier);
									if (is_array($tempData) ) {
										$result [] = $tempData;
									}
							}

							// Articles d'une sous-page blog
							if ($this->getData(['page', $childId, 'moduleId']) === 'blog')
							{
								foreach($this->getData(['module',$childId]) as $articleId => $article) {
									if($this->getData(['module',$childId,$articleId,'state']) === true)  {
										$url = $childId . '/' . $articleId;
										$titre = $article['title'];
										$contenu = ' ' . $titre . ' ' . $article['content'];
										// Articles de sous-page de type blog
										$tempData  = $this->occurrence($url, $titre, $contenu, self::$motclef, self::$motentier);
										if (is_array($tempData) ) {
											$result [] = $tempData;
										}
									}
                                }
							}
                    }

					// Articles d'un blog
					if ($this->getData(['page', $parentId, 'moduleId']) === 'blog' ) {
						foreach($this->getData(['module',$parentId]) as $articleId => $article) {
							if($this->getData(['module',$parentId,$articleId,'state']) === true)
							{
								$url = $parentId. '/' . $articleId;
								$titre = $article['title'];
								$contenu = ' ' . $titre . ' ' . $article['content'];
								// Articles de Blog
								$tempData  = $this->occurrence($url, $titre, $contenu, self::$motclef, self::$motentier);
								if (is_array($tempData) ) {
									$result [] = $tempData;
								}
							}
                        }
					}
				}

				// Message de synthèse de la recherche
				if (count($result) === 0) 	{
					self::$resultTitle = 'Aucun résultat';
					self::$resultError = 'Avez-vous pens&eacute; aux accents ?';
				} else  {
					self::$resultError = '';
					self::$resultTitle = ' Résultat de votre recherche';
					rsort($result);
					foreach ($result as $key => $value) {
						$r [] = $value['preview'];
					}
					// Générer une chaine de caractères
					self::$resultList= implode("", $r);
				}
			}

			// Valeurs en sortie, affichage du résultat
			$this->addOutput([
				'view' => 'index',
				'showBarEditButton' => true,
				'showPageContent' => !$this->getData(['module', $this->getUrl(0),'resultHideContent'])
			]);
		} else {
			// Valeurs en sortie, affichage du formulaire
			$this->addOutput([
				'view' => 'index',
				'showBarEditButton' => true,
				'showPageContent' => true
			]);
		}
	}

Cela dit il y a sûrement moyen de faire mieux et plus court.

 

 

 

 

 

 

 

Partager ce message


Lien à poster
Partager sur d’autres sites
Il y a 18 heures, Fred a dit :

Cela dit il y a sûrement moyen de faire mieux et plus court.

Merci Fred pur cette explication détaillée que tu m'as apporté en réponse à mon interrogation.

Par contre je serais bien incapable moi même de faire mieux et plus court que toi pour coder une telle fonction ou de tels codes où qu'ils soient dans le zwii. Mes qualifications au niveau PHP doivent se situer comme telles: "Roger est un élève assis sur un banc d'école du CE1 et qui essaie d'apprendre ce qu'est ce drôle de langage là qu'est PHP" 😳

 

Plus sérieux si je comprend bien cette valeur dit au module de recherche où il doit aller pour trouver une info qu'il affichera ensuite dans le résultat

Citation

$titre, $content,

le titre d'une page et son contenu à explorer (toutes les pages d'un zwii) susceptible de contenir un mot recherché (par exemple le mot article)

Et c'est sous cette forme dans le fichier "page.json" dans le data:

Citation

""blog":

"content": "<p>Cette page contient une instance du module de blog. Cliquez sur un article afin de le lire et de poster des commentaires.<\/p>",

 

Idem pour la page d'un article, le module search regardera alors dans le fichier module.json cela pour afficher ensuite un possible résultat

Citation

"mon-premier-article":

"content": "<p>Je retrouve ici le mot Article que je recherche<\/p>",

 

Alors que pour un commentaire posté dans un article "content": est lui remplacé (pour le contenu) par "comment":

Citation

"comment": {
                    "58e11d09e5aff": {
                        "author": "Rémi",
                        "content": "Article bien rédigé et très pertinent, bravo !",
                        "createdOn": 1421748000,
                        "userId": ""
                    }

 

Si j'ajoutais en plus de "content" dans la valeur de l'endroit à rechercher ceci: "comment" et modifiais un tant soi peu les autres parties situées dans ta réponse (notamment pour le resultat de recherche à afficher ):

Citation

private function occurrence($url, $titre, $content, $comment, $motclef, $motentier)
	

 

 

🤓 Aurais je une chance d'aboutir à un début de solution pour rechercher aussi dans les commentaires d'un article ou est ce voué à l'échec et ne mérite pas que je me penche sur cette modification là à essayer chez moi?

Partager ce message


Lien à poster
Partager sur d’autres sites
il y a 1 minute, roger a dit :

🤓 Aurais je une chance d'aboutir à un début de solution pour rechercher aussi dans les commentaires d'un article ou est ce voué à l'échec et ne mérite pas que je me penche sur cette modification là à essayer chez moi?

En effet,

Mais la manière dont est écrit l’algorithme va alourdir l'écriture en multipliant les foreach. Il faudrait effectuer le travail en deux fois :

1. construire un tableau avec les id des pages

2. lire le tableau et faire un switch sur les modules pour aller chercher les données.

Mais comme tu veux répertorier les commentaires, il y aura une autre boucle. Comme les commentaires sont modérés dans 10400 il faudra également appliquer ce filtre.

Ce que tu peux lire :

formulaire : nom des champs

news : texte des news

blog : les commentaire publiés

galerie : les légendes

Ça fait quand même beaucoup de taf !

  • J'aime 1
  • Merci 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Merci Fred 👍, ta réponse me laisse entrevoir l'espoir que c'est possible et ce malgré, comme tu le précises à juste titre, l'énormité de la tache à accomplir dans le code à modifier (ssurtout pour la future 10400. Ce sera sans doute ma prochaine "marotte" d'essais lors de la sortie de cette version.

Je marque "Résolu" en haut car j'ai donc les réponses au sujet (qui n'est pas un bug en effet et que j'avais d'ailleurs signalé en début de sujet comme étant "plutôt un inconvénient") et si j'arrive de mon coté à un résultat, promis j'en ferais profiter le plus grand nombre 😀

 

  • J'aime 1

Partager ce message


Lien à poster
Partager sur d’autres sites

×
×
  • Créer...