Suche mit Berücksichtigung Frontend-Gruppen und Gewichtung

Alles rund um Module und Plugins in CONTENIDO 4.9.
McHubi
Beiträge: 956
Registriert: Do 18. Nov 2004, 23:06
Wohnort: Mettmann
Kontaktdaten:

Suche mit Berücksichtigung Frontend-Gruppen und Gewichtung

Beitrag von McHubi » Di 10. Feb 2015, 16:48

Hallo zusammen,

da die "bordeigene" Suche, zumindest im Moment, nicht so funktioniert wie sie soll (http://forum.contenido.org/viewtopic.php?f=92&t=34513), habe ich mir selbst eine geschneidert. Dabei wird auch Rücksicht genommen auf ggf. nicht für den Suchenden freigegebene Kategorien, ob Artikel on- oder offline sind und ob sie als "suchbar" in den Artikeleigenschaften deklariert wurden. Darüber hinaus besteht die Möglichkeit,
# die Mindestlänge für Suchworte sowie
# maximale Anzahl aufzulistender Suchtreffer und
# die Länge des Textteasers festzulegen (Kommt hier das Suchwort drin vor, wird es gehighlighted)
# eine Gewichtung der Suchtreffer vorzunehmen - je nachdem, ob der Suchstring in einer Headline, in einem Textelement und/oder in den Metaangaben zu keywords und description vorkommt -
# entsprechende Listung und Prozentanzeige im Frontend inklusive.

Ggf. schiebe ich noch eine Pagination und ein Logging der Suchbegriffe mit diversen Filtermodi (alphabetisch, nach Zeitraum, Anzahl der Eingaben, ...) nach.

Wichtig:
  • Alle Korrekturen, Anmerkungen usw. der Folgepostings sind in den Quelltexten dieses Eröffnungsposts berücksichtigt.
  • Wenn Suchbegriffe mit Umlauten nicht gefunden werden sollten, dann bitte in der Zeile
    $conversion=utf8_encode(html_entity_decode(stripslashes(mb_strtolower($array_crawler[value]))));
    utf8_encode rausnehmen:
    $conversion=html_entity_decode(stripslashes(mb_strtolower($array_crawler[value])));
Also, was ist zu tun:

neues Modul "search_sd" anlegen mit diesen Bestandteilen:
Input:

Code: Alles auswählen

/***********************************************
* CONTENIDO MODUL - INPUT
*
* Modulname   :     search_sd
* Author(s)   :     Seamless-Design Markus Hübner
* Copyright   :     Seamless-Design Markus Hübner
* Created     :     05.02.2015
************************************************/

echo mi18n("input - discard hit if category is");
echo '<table>';
echo '<tr><td>'.mi18n("input - offline").'</td>';
echo '<td>';
if ("CMS_VALUE[100]" !="true") echo '<input type="radio" name="CMS_VAR[100]" value="true"> '.mi18n("input - yes"); 
  else echo '<input type="radio" name="CMS_VAR[100]" value="true" checked> '.mi18n("input - yes"); 
if ("CMS_VALUE[100]" != "false") echo '<input type="radio" name="CMS_VAR[100]" value="false"> '.mi18n("input - no"); 
  else echo '<input type="radio" name="CMS_VAR[100]" value="false" checked> '.mi18n("input - no"); 
echo '</td></tr>';
echo '<tr><td>'.mi18n("input - secured").'</td>';
echo '<td>';
if ("CMS_VALUE[110]" !="true") echo '<input type="radio" name="CMS_VAR[110]" value="true"> '.mi18n("input - yes"); 
  else echo '<input type="radio" name="CMS_VAR[110]" value="true" checked> '.mi18n("input - yes"); 
if ("CMS_VALUE[110]" != "false") echo '<input type="radio" name="CMS_VAR[110]" value="false"> '.mi18n("input - no"); 
  else echo '<input type="radio" name="CMS_VAR[110]" value="false" checked> '.mi18n("input - no"); 
echo '</td></tr>';
echo '<tr><td>'.mi18n("input - secured but unlocked for fe-user group").'</td>';
echo '<td>';
if ("CMS_VALUE[120]" !="true") echo '<input type="radio" name="CMS_VAR[120]" value="true"> '.mi18n("input - yes"); 
  else echo '<input type="radio" name="CMS_VAR[120]" value="true" checked> '.mi18n("input - yes"); 
if ("CMS_VALUE[120]" != "false") echo '<input type="radio" name="CMS_VAR[120]" value="false"> '.mi18n("input - no"); 
  else echo '<input type="radio" name="CMS_VAR[120]" value="false" checked> '.mi18n("input - no"); 
echo '</td></tr>';
echo '</table>';
echo '<table>';
echo '<tr><td>'.mi18n("input - maximum length of description").'</td><td><input type="text" name="CMS_VAR[200]" value="CMS_VALUE[200]"/></td></tr>';
echo '<tr><td>'.mi18n("input - maximum amount of hits").'</td><td><input type="text" name="CMS_VAR[300]" value="CMS_VALUE[300]"/></td></tr>';
echo '<tr><td>'.mi18n("input - minimum length of searchstring").'</td><td><input type="text" name="CMS_VAR[400]" value="CMS_VALUE[400]"/></td></tr>';
echo '<tr><td>'.mi18n("input - hints for multiplyers").'</td></tr>';
echo '<tr><td>'.mi18n("input - multiplyer hit in headline").'</td><td><input type="text" name="CMS_VAR[500]" value="CMS_VALUE[500]"/></td></tr>';
echo '<tr><td>'.mi18n("input - multiplyer hit in text").'</td><td><input type="text" name="CMS_VAR[510]" value="CMS_VALUE[510]"/></td></tr>';
echo '<tr><td>'.mi18n("input - multiplyer hit in meta keywords").'</td><td><input type="text" name="CMS_VAR[520]" value="CMS_VALUE[520]"/></td></tr>';
echo '<tr><td>'.mi18n("input - multiplyer hit in meta description").'</td><td><input type="text" name="CMS_VAR[530]" value="CMS_VALUE[530]"/></td></tr>';
echo '</table>';
Output:

Code: Alles auswählen

<?php

/***********************************************
* CONTENIDO MODUL - OUTPUT
*
* Modulname   :     search_sd
* Author(s)   :     Seamless-Design Markus Hübner
* Copyright   :     Seamless-Design Markus Hübner
* Created     :     05.02.2015
************************************************/

/*
TODOs:
# check, if idtype is really used! -> searchstring -> PIFA-Form is found within database - although PIFA-Form is no longer used/online
*/
// assert framework initialization
defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');

/*########## variables begin ##########*/
$do_not_add_if_cat_offline="CMS_VALUE[100]";
$do_not_add_if_cat_secured="CMS_VALUE[110]";
$do_not_add_if_cat_secured_but_unlocked_for_fe_group="CMS_VALUE[120]";
$length_text_max="CMS_VALUE[200]"; // how many letters should be displayed before result is cut
$max_amount_hits_displayed="CMS_VALUE[300]"; // becomes a role after complete data is searched, because of ranking! not the first found articles have to be displayed but the most important ones!
if($max_amount_hits_displayed=="") $max_amount_hits_displayed=10;
if($max_amount_hits_displayed>50) $max_amount_hits_displayed=50;
$searchstring_minimum_length="CMS_VALUE[400]";
/*
for each idtype you can define worth of hit - e.g. a hit within a headline (idtype 1) is worthier than within normal text, so a hit within a headline could be counted twice. Also metadata is being checked, because explicitly mentioned here, the article is normally more important than articles without mentioning
searchstring in metadata. After this, hits are used as a score for ordering search results.
have a look at con_type for idtype-definition!
 */
$hit_multiplier_headline="CMS_VALUE[500]";
if($hit_multiplier_headline=="") $hit_multiplier_headline=2;
$hit_multiplier_text="CMS_VALUE[510]";
if($hit_multiplier_text=="") $hit_multiplier_text=1;
$hit_multiplier_meta_keywords="CMS_VALUE[520]"; // search string is found within keywords or description
if($hit_multiplier_meta_keywords=="") $hit_multiplier_meta_keywords=1.5;
$hit_multiplier_meta_description="CMS_VALUE[530]"; // search string is found within keywords or description
if($hit_multiplier_meta_description=="") $hit_multiplier_meta_description=1.5;

$string_search_input="";
$string_search_input=strip_tags($_POST['searchterm']);

$array_search=array('"','\'','&apos;','"');
$array_replace=array('','','apos','quot');
$string_search_input=str_replace($array_search,$array_replace,$string_search_input);
$string_search=addslashes(strip_tags(mb_strtolower($_POST['searchterm'])));


/****** checking which idcats are allowed for fe-user and if fe-user has global rights begin ******/
if($do_not_add_if_cat_secured=="false" OR $do_not_add_if_cat_secured_but_unlocked_for_fe_group=="false")
  {
  $id_feu=$auth->auth["uid"];
  $query = "SELECT idfrontendgroup FROM con_frontendgroupmembers WHERE idfrontenduser='$id_feu'";
  $result = cRegistry::getDb();
  $result->query($query);
  while($result->nextRecord())
    {
    $arr_fe_groups=$result->toArray();
    }
  $visitor_fe_group=$arr_fe_groups[idfrontendgroup];

  $arr_visitor_fe_group_allowed_cat_ids=array();
  $query = "SELECT item FROM con_frontendpermissions WHERE idfrontendgroup='$visitor_fe_group'";
  $result = cRegistry::getDb();
  $result->query($query);
  while($result->nextRecord())
    {
    $arr_result=$result->toArray();
    $arr_visitor_fe_group_allowed_cat_ids[]=$arr_result[item];
    }
  $fe_user_global_rights="false";
  if(in_array('__GLOBAL__',$arr_visitor_fe_group_allowed_cat_ids))   $fe_user_global_rights="true";
  }
/****** checking which idcats are allowed for fe-user and if fe-user has global rights end ******/
/*########## variables end ##########*/





/*########## functions begin ##########*/
function show_result($show_content_hit_idart,$show_content_lang,$string_search_input,$hits,$hits_maximum,$length_text_max,$hit_number)
  {
  $hit_number++; //delivered number is array-pointer, therefor first hit has number 0. so hit_number has to be increased by 1
  $array_search=array('Ü','Ä','Ö','ü','ä','ö','ß');
  $array_replace=array('&Uuml;','&Auml;','&Ouml;','&uuml;','&auml;','&ouml;','&szlig');
  $article = new cApiArticleLanguage();
  $article->loadByArticleAndLanguageId($show_content_hit_idart,$show_content_lang);
  echo '<div class="s_sd_result">';
    $width_relevance=round(($hits/$hits_maximum)*100,0);
    echo '<div class="s_sd_result_number">'.$hit_number.')</div>';
    echo '<div class="s_sd_relevance">';
      echo '<div class="s_sd_relevance_score" style="width:'.$width_relevance.'%;">';
      echo $width_relevance.'%';
      echo '</div>';
    echo '</div>';
  if($article->getContent('CMS_HTMLHEAD', 1)!="")
    {
   echo '<div class="s_sd_result_headline">'.strip_tags($article->getContent('CMS_HTMLHEAD', 1)).'</div>';
   }
  if($article->getContent('CMS_HTML', 1)!="")
    {
   /*highlighting exact string regarding upper-/lowercase*/
   $string_search_input=str_replace($array_search,$array_replace,$string_search_input);
   $show=str_replace($string_search_input, '<span class="s_sd_highlight_item">'.$string_search_input.'</span>',substr(strip_tags($article->getContent('CMS_HTML', 1)),0,$length_text_max));
   /*highlighting string even if search-string within input-field is written uppercase*/
   $string_search_input_strtolower=strtolower($string_search_input);
   $show=str_replace($string_search_input_strtolower, '<span class="s_sd_highlight_item">'.$string_search_input_strtolower.'</span>',$show);
   /*highlighting string even if first letter of search-string within input-field is written lowercase and string within text begins with first letter uppercase*/
   $string_search_input_ucfirst=ucfirst($string_search_input);
   $show=str_replace($string_search_input_ucfirst, '<span class="s_sd_highlight_item">'.$string_search_input_ucfirst.'</span>',$show);
   echo '<div class="s_sd_result_text">'.$show.'</div>';
   }
  echo '<div class="s_sd_more"><a class="link_text_link" href="front_content.php?idart='.$show_content_hit_idart.'" title="'.mi18n("more").'">'.mi18n("more").'</a></div>';
  echo '</div>';
  }
/*########## functions end ##########*/






/*########## checking if searchstring is at least x letters long begin ##########*/
if(strlen($string_search)<$searchstring_minimum_length)
  {
  $start_search=false;
  echo '<p>'.mi18n("minimum length of word is 3 letters").'</p>';
  }
  else $start_search=true;
/*########## checking if searchstring is at least x letters long end ##########*/




 
/*########## displaying form begin ##########*/
echo '<form method="post" action="">';
echo '<input class="s_sd_input_text" type="text" name="searchterm" value="'.$string_search_input.'"/>';
echo '<input class="s_sd_input_submit" type="submit" value="&nbsp;"/>';
echo '</form>';
/*########## displaying form end ##########*/





/*########## search begin ##########*/
if($start_search==true)
{
$hits_maximum=0; // amount represents 100% for calculating relevance of results
/********** collecting idartlang, idtype and amount of hits begin **********/
// array contains all idtypes with hits, so idartlang might be contained several times
$query = "SELECT idartlang,idtype,value FROM con_content ORDER BY idartlang ASC";
$result = cRegistry::getDb();
$result->query($query);

$array_detections=array();
while($result->nextRecord())
  {
  $array_crawler=$result->toArray();
  $conversion=utf8_encode(html_entity_decode(stripslashes(mb_strtolower($array_crawler[value]))));
  if(strpos(" ".$conversion,$string_search))
    {
   $amount_of_hits=substr_count($conversion,$string_search);
    $array_detections[]=array('idartlang'=>$array_crawler[idartlang],'idtype'=>$array_crawler[idtype],'hits'=>$amount_of_hits);
    }
  }
/********** collecting idartlang, idtype and amount of hits end **********/






if(count($array_detections)>0)
{
/********** summarizing hits of all idtypes to one idartlang begin **********/
$array_detections_to_display=array();
foreach($array_detections AS $element)
  {
  $current_idartlang=$element[idartlang];
  if($current_idartlang==$previous_idartlang)
    {
   $hits_to_increase=$array_detections_to_display[$current_idartlang];
   $add_hits=$element[hits];
   if($element[idtype]==1) $add_hits=$add_hits*$hit_multiplier_headline; // if string is found within a headline, it is x-times worthier
   if($element[idtype]==2) $add_hits=$add_hits*$hit_multiplier_text; // if string is found within a text, it is x-times worthier
   $hits=$hits_to_increase+$add_hits;
   }
    else
     {
     if($element[idtype]==1) $hits=$element[hits]*$hit_multiplier_headline;
     if($element[idtype]==2) $hits=$element[hits]*$hit_multiplier_text;
       else $hits=$element[hits];
/* searchstring contained in metadata begin */
/*
idmetatypes:
3: description
5: keywords
*/
$query_meta_1 = "SELECT idmetatype,metavalue FROM con_meta_tag WHERE idartlang='$current_idartlang'";
$result_meta_1 = cRegistry::getDb();
$result_meta_1->query($query_meta_1);
while($result_meta_1->nextRecord())
  {
  $array_meta=$result_meta_1->toArray();
  if($array_meta[idmetatype]=="3")
    {
   if(strpos(" ".utf8_encode(html_entity_decode(stripslashes(mb_strtolower($array_meta[metavalue])))),$string_search))
     {
     $hits=$hits*$hit_multiplier_meta_description;
     }
   }
  if($array_meta[idmetatype]=="5")
    {
   if(strpos(" ".utf8_encode(html_entity_decode(stripslashes(mb_strtolower($array_meta[metavalue])))),$string_search))
     {
     $hits=$hits*$hit_multiplier_meta_keywords;
     }
   }
  }
/* searchstring contained in metadata end */
     
     }
   
  $array_detections_to_display[$element[idartlang]]=$hits;
  if($hits>$hits_maximum) $hits_maximum=$hits;
  $previous_idartlang=$element[idartlang];
  }
/********** summarizing hits of all idtypes to one idartlang end **********/





/********** building array for collecting search result information begin **********/
arsort($array_detections_to_display); //sorting array by value, descending
$array_data_collection=array();
foreach ($array_detections_to_display as $key => $value)
    {
    if($counter_max_amount_hits<$max_amount_hits_displayed)
    {
   $query = "SELECT idart,idlang FROM con_art_lang WHERE idartlang='$key' AND idlang='$lang' AND online='1' AND searchable='1'";
    $result = cRegistry::getDb();
    $amount_of_rows = $result->num_rows;
    $result->query($query);
    $array_idart_hit=array();
    while($result->nextRecord())
      {
      $array_idart_hit=$result->toArray();
      /* category online or secured begin */   
/*
con_art_lang -> idartlang & idart
idart in con_cat_art -> idcatart & idcat
idcat in con_cat_lang -> visible & public
$query_cat_1: article is placed in which category
$query_cat_2: category's online- and secure-status
*/
     $query_cat_1 = "SELECT idcat FROM con_cat_art WHERE idart='$array_idart_hit[idart]'";
      $result_query_cat_1 = cRegistry::getDb();
      $result_query_cat_1->query($query_cat_1);
      $array_query_cat_1=array();
      while($result_query_cat_1->nextRecord())
        {
        $array_query_cat_1=$result_query_cat_1->toArray();
       $query_cat_2 = "SELECT visible,public FROM con_cat_lang WHERE idcat='$array_query_cat_1[idcat]'";
       $result_query_cat_2 = cRegistry::getDb();
        $result_query_cat_2->query($query_cat_2);
        $array_query_cat_2=array();
       while($result_query_cat_2->nextRecord())
          {
          $array_query_cat_2=$result_query_cat_2->toArray();
         }
        }   
      /* category online or secured end */
      $do_not_add="false";
     if($do_not_add_if_cat_offline=="true" AND $array_query_cat_2['visible']=="0") $do_not_add="true";
     /*if category is secured */
     if($do_not_add_if_cat_secured=="true" AND $array_query_cat_2['public']=="0") $do_not_add="true";
     /*if category is secured but visitor is logged in as fe-user */
     if($do_not_add_if_cat_secured_but_unlocked_for_fe_group=="true" AND $array_query_cat_2['public']=="0") $do_not_add="true";
       elseif($do_not_add!="true" AND $array_query_cat_2['public']=="0" AND $fe_user_global_rights!="true")
         {
	 if(!in_array($array_query_cat_1[idcat],$arr_visitor_fe_group_allowed_cat_ids)) $do_not_add="true";
         }

	 if($do_not_add=="false")
         {
         $counter_max_amount_hits++;
         $array_data_collection[]=array("idart"=>$array_idart_hit[idart],"idartlang"=>$key,"idlang"=>$array_idart_hit[idlang],"hits"=>$value);
         }
      } //while($result->nextRecord())
     } //if($counter_max_amount_hits<$max_amount_hits_displayed)
   }
/********** building array for collecting search result information end **********/




/********** displaying search results begin **********/
$amount_of_hits_finally=count($array_data_collection);
if ($amount_of_hits_finally>0)
  {
  if($max_amount_hits_displayed>$amount_of_hits_finally) $max_amount_hits_displayed=$amount_of_hits_finally;
  echo '<p>'.mi18n("found hits").': ';
    if($max_amount_hits_displayed<$amount_of_hits_finally) echo $max_amount_hits_displayed;
      else echo $amount_of_hits_finally;
  echo '</p>';
  $i=0;
  while($i<$max_amount_hits_displayed)
    {
    show_result($array_data_collection[$i][idart],$lang,$string_search_input,$array_data_collection[$i][hits],$hits_maximum,$length_text_max,$i); //$lang: only show results with matching current chosen language
    $i++;
    }
  }
  else echo '<p>'.mi18n("nothing found").'</p>';

  } //if(count($array_detections)>0)
  elseif($string_search!="") echo '<p>'.mi18n("nothing found").'</p>';
/********** displaying search results end **********/
}
?>
CSS:

Code: Alles auswählen

a.link_text_link {
border: 1px solid #444444;
text-decoration: none;
padding: 0.2em;
}
a.link_text_link:hover {
color: #ff0000;
}
div.s_sd_result {
border: 1px solid #999999;
padding: 0.5em;
margin-bottom: 2em;
}
div.s_sd_relevance {
width: 30%;
border: 1px solid #999999;
padding: 1px;
float: left;
}
div.s_sd_relevance_score {
font-size: 0.6em;
background-color: #999999;
color: #ffffff;
padding: 1px;
}
div.s_sd_result_headline {
clear: both;
font-weight: 900;
font-size: 1.2em;
margin-top: 0.3em;
}
div.s_sd_result_number {
font-weight: 900;
float: left;
margin-right: 0.3em;
}
div.s_sd_result_text {
font-size: 0.8em;
}
span.s_sd_highlight_item {
font-weight: 900;
text-decoration: underline;
}
div.s_sd_more {
text-align: right;
}
div.s_sd_more a {
color: #000000;
}
div.s_sd_more a:hover {
color: #ff0000;
}
input.s_sd_input_text {
width: 80%;
height: 1.8em;
margin-right: 1em;
border: 1px solid #999999;
background-color: #ffffff;
}
input.s_sd_input_submit {
border: 1px solid #999999;
border-radius: 0.3em;
width: 2em;
height: 2em;
background-image: url('MEINPFAD/icon-start-search.png');
background-repeat: no-repeat;
background-size: cover;
background-color: #ffffff;
}
input.s_sd_input_submit:hover {
border: 1px solid #000000;
cursor: pointer;
}
Pfad zum Background-Image muss noch angepasst werden!

lang_de_DE.txt

Code: Alles auswählen

found hits=Suchtreffer
input - discard hit if category is=Suchtreffer nicht berücksichtigen wenn Artikel in Kategorie liegt, die
input - hints for multiplyers=Multiplikatoren, wenn Suchbegriff enthalten ist in
input - maximum amount of hits=Maximale Anzahl aufgelisteter Suchtreffer
input - maximum length of description=Länge des Suchtreffer-Teasers
input - minimum length of searchstring=Minimale Länge des Suchwortes
input - multiplyer hit in headline=Überschrift
input - multiplyer hit in meta description=Meta-Description
input - multiplyer hit in meta keywords=Meta-Keywords
input - multiplyer hit in text=Text
input - no=nein
input - offline=offline ist
input - secured=geschützt ist
input - secured but unlocked for fe-user group=geschützt ist, aber für Frontend-User-Group des Besuchers freigegeben
input - yes=ja
minimum length of word is 3 letters=Bitte geben Sie mindestens drei Zeichen ein.
more=mehr
nothing found=Kein Suchtreffer.
Zusätzliches Modul "search_sd-additional-form" anlegen mit diesen Bestandteilen:
Output:

Code: Alles auswählen

<?php

/***********************************************
* CONTENIDO MODUL - OUTPUT
*
* Modulname   :     search_sd-additional-form
* Author(s)   :     Seamless-Design Markus Hübner
* Copyright   :     Seamless-Design Markus Hübner
* Created     :     05.02.2015
************************************************/

// assert framework initialization
defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');

/*########## variables begin ##########*/
$idart_resultpage=MEINE-IDART;
/*########## variables end ##########*/
  
/*########## displaying form begin ##########*/
echo '<div class="s_sd_af">';
echo '<form method="post" action="front_content.php?idart='.$idart_resultpage.'">';
echo '<input class="s_sd_af_input_text" type="text" name="searchterm" value="'.$string_search_input.'"/>';
echo '<input class="s_sd_af_input_submit" type="submit" value="&nbsp;"/>';
echo '</form>'; 
echo '</div>';
/*########## displaying form end ##########*/
?>
$idart_resultpage am Anfang noch auf eigenen Wert anpassen!

CSS:

Code: Alles auswählen

div.s_sd_af {
margin-top: 1em;
background-color: #ffffff;
border: 1px solid #ffffff;
border-radius: 0.3em;
padding: 0.5em;
}
input.s_sd_af_input_text {
width: 60%;
height: 1.8em;
margin-right: 1em;
border: 1px solid #999999;
background-color: #ffffff;
}
input.s_sd_af_input_submit {
border: 1px solid #999999;
border-radius: 0.3em;
width: 2em;
height: 2em;
background-image: url('MEINPFAD/icon-start-search.png');
background-repeat: no-repeat;
background-size: cover;
background-color: #ffffff;
}
input.s_sd_af_input_submit:hover {
border: 1px solid #000000;
cursor: pointer;
}
Pfad zum Background-Image noch anpassen!

Wer den Aufbau der Suchtreffer anpassen möchte: Das HTML-Markup läuft nicht über smarty, sondern ist in der function "show_result" im Output des Moduls "search_sd" festgelegt. Das Ranking selbst läuft simpel über die Anzahl der Suchtreffer im Artikel. Ein Artikel, bei dem das Suchwort 5 mal vorkommt wird höher gerankt als ein Artikel, bei dem es nur 3 mal vorkommt. Da das Suchwort in einer Headline aber mehr Bedeutung bekommen und zum Beispiel doppelt gewichtet werden sollte, kann hier in der Konfiguration ein entsprechender Multiplikator eingetragen werden. Gleiches gilt für die Metadaten. Ein Treffer in den Keywords bekommt mit dem Multiplikator 3 den - logisch - dreifachen Wert. Ein Treffer in den Keywords hat dann die gleiche Gewichtung wie drei Treffer im Textelement.

Viel Spaß damit! :D
search_sd-screenshot-be-001.jpg
search_sd-screenshot-be-001.jpg (82.16 KiB) 2854 mal betrachtet
search_sd-screenshot-fe-001.jpg
(137.95 KiB) Noch nie heruntergeladen
icon-start-search.png
icon-start-search.png (3.19 KiB) 2857 mal betrachtet
Zuletzt geändert von McHubi am Fr 14. Jul 2017, 22:38, insgesamt 13-mal geändert.
seamless-design.de
"Geht nicht!" wohnt in der "Will nicht!"-Strasse.

Die NEUAUFLAGE des Buchs zur Version 4.9: CONTENIDO für Einsteiger (4.9)

Oldperl
Beiträge: 4014
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Franken, Bayern
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von Oldperl » Mi 11. Feb 2015, 09:24

Moin Markus,

schönes Modul. Hast Du das schon mal in einem System mit viel Content getestet? Ich vermute mal, da es ja jedes Mal direkt auf die DB zugreift, das ihm irgendwann die Puste aus geht.

Gruß aus Franken

Ortwin
ConLite 2.0, alternatives und stabiles Update von Contenido 4.8.x *-* phpBO Search Advanced - das neue Suchwort-Plugin für CONTENIDO 4.9 *-* Mein Entwickler-Blog

McHubi
Beiträge: 956
Registriert: Do 18. Nov 2004, 23:06
Wohnort: Mettmann
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von McHubi » Mi 11. Feb 2015, 11:42

Hallo Ortwin,

hatte es zunächst auf einer rel. kleinen Seite entwickelt und keinerlei Probleme. Auf einer "größeren" Seite kommen bei diversen keywords auch schon mal ohne weiteres Suchergebnise im locker dreistelligen Bereich bei rum und es funktioniert auch innerhalb einer passablen Zeit. Allerdings habe ich bei manchen Keywords auch schon mal eine 500er Fehlermeldung (würde zu Deiner Vermutung passen, ist aber innerhalb von zwei,drei Sekunden schon da) und bei anderen Keywords wird nach dem Sucheingabefeld beim Seitenreload der Seitenaufbau abgebrochen. So, als ob hier ein php-Fehler zuschlägt. Ein Muster kann ich aber nicht erkennen. Vielleicht führt aber das eine oder andere ' oder " im Text selbst zum Abbruch. :motz:

Ob das jetzt tatsächlich mit der Seitengröße zusammenhängt, gute Frage. Ja, der Aufbau der Abfragen gefällt mir selbst auch noch nicht wirklich gut. Da lässt sich sicher noch optimieren. Wäre doch auch ein gutes Praxisbeispiel um näher auf cApiCategoryArticleCollection() (http://forum.contenido.org/viewtopic.ph ... 57#p165643) einzugehen.

Also, Code auseinanderpflücken, an diversen Stellen den Kopf schütteln und das nächste Mal den Kaffe vorher trinken... :wink:

EDIT:
Als erstes hab ich die query im Abschnitt /********** collecting idartlang, idtype and amount of hits begin **********/ etwas "entschlackt".

Dann habe ich mal ein Keyword rausgepickt, was in der Suche über phpMyAdmin ca. 500 Treffer in der con_content hervorbringt. Den o.g. Code für search_sd habe ich dann Stück für Stück "freigeschaltet" und das reine Durchsuchen der con_content (/********** collecting idartlang, idtype and amount of hits begin **********/) klappt wunderbar. Gleiches gilt für das Zusammenfassen von mehreren Treffern für einen Artikel unter /********** summarizing hits of all idtypes to one idartlang begin **********/. Sobald aber der Abschnitt /********** building array for collecting search result information begin **********/ hinzukommt, kracht es.

Da sind wir dann bei den von Dir angesprochenen Zugriffen auf die DB:

1) Über die con_art_lang wird die idart, idlang herausgezogen für die idartlang des Suchtreffers in der passenden Sprache, sofern der Artikel online und suchbar ist.
Aus diesem Array wird dann über die idart
2) aus der con_cat_art die idcat herausgelesen und dann
3) aus der con_cat_lang der Status der Kategorie "sichtbar" und "öffentlich" herausgelesen
Als nächstes kommt dann
4) die Prüfung über die con_frontendpermissions die Prüfung, ob der Seitenbesucher Zugriff auf diese Kategorie hat.

Und hier kam es dann zum Abbruch, da JEDE Kategorie geprüft wurde - auch, wenn sie öffentlich war. Ich hab hier jetzt die Bedingung etwas erweitert mit
elseif($do_not_add!="true" AND $array_query_cat_2['public']=="0")
so dass die Rechteprüfung nur dann durchgeführt wird, wenn die Kategorie tatsächlich geschützt ist.

Jetzt läuft die Suche durch. Das ist aber vermutlich auch nicht der Weisheit letzter Schluss, denn wenn eine Website zig tausende geschützte Kategorien hat, dann kracht es wieder wg. der hohen Anzahl Abfragen. Denke mal es macht mehr Sinn, vorher in einer Einzel-query die für die Gruppe des Seitenbesuchers freigegebenen Kategorien in einem Array zu sammeln. Das Ganze ist in der Tat viel zu verschachtelt.

Die hier im EDIT beschriebenen Anpassungen im im Code des Eröffnungspostings angepasst.

VG,

Markus
seamless-design.de
"Geht nicht!" wohnt in der "Will nicht!"-Strasse.

Die NEUAUFLAGE des Buchs zur Version 4.9: CONTENIDO für Einsteiger (4.9)

Oldperl
Beiträge: 4014
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Franken, Bayern
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von Oldperl » Mi 11. Feb 2015, 13:10

Nun Markus, es ist eigentlich aus Performance-Sicht ein No-Go jedes Mal bei der Suche die komplette DB nach dem Suchwort zu durchwühlen, zumindest eine Art Caching wäre hier angebracht. Da ist die grundsätzliche Lösung der Core-Suche mit einer DB-Tabelle für Suchworte schon effektiver.
Daher habe ich ja auch mein Plugin phpBO Search Advanced auf die vorhandene DB-Tabelle aufgebaut, wobei ich da schon überlege die komplette SuchIndexierung incl. FE-Modul nachzubauen, dabei aber eine eigene Tabelle für das Plugin zu nutzen, da ich an die CoreTabelle leider per PIM nicht ran komme und momentan Änderungen daran im Vorlauf des 1. Aufrufes des Plugin-Backends mache.
Falls du Interesse hast am Modul dafür mitzumachen könnte ich Dir das Plugin ja mal geben, wollte mich eh nochmal mit Dir zusammen unterhalten wegen meinem Plugin-Buch zur 4.9er.

Gruß aus Franken

Ortwin
ConLite 2.0, alternatives und stabiles Update von Contenido 4.8.x *-* phpBO Search Advanced - das neue Suchwort-Plugin für CONTENIDO 4.9 *-* Mein Entwickler-Blog

McHubi
Beiträge: 956
Registriert: Do 18. Nov 2004, 23:06
Wohnort: Mettmann
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von McHubi » Mi 11. Feb 2015, 14:53

So. Problem eingegrenzt. Es kommt nur dann zum Abbruch, wenn zu viele Suchtreffer generiert und im $array_data_collection gesammelt werden. Ich habe den Code jetzt so angepasst, dass dieses finale Array für die Ausgabe der Suchtreffer nur bis zum Erreichen der in der Konfiguration gesetzten Trefferobergrenze gefüllt wird. Bisher war es so, dass das Array bis zum St. Nimmerlein mit allen - nach Prüfung ob online usw. - in Frage kommenden Treffern gefüllt wurde. Ein Array-Element besteht aus:

Code: Alles auswählen

[0] => Array ( [idart] => 429 [idartlang] => 429 [idlang] => 1 [hits] => 34 )
Das dann 500 Mal z. B. wird irgendwann wohl zu viel. Auch ein print_r($array_data_collection) wollte nicht mehr.

Die Ausgabe der Suchtreffer sollte ursprünglich also z. B. die Plätze 1 bis 50 abspulen und dann abbrechen, die folgenden Elemente 51 bis 500 des Arrays nicht mehr berücksichtigen - was zum Fehler führte. Das Array wird deshalb jetzt nur noch bis zur festgelegten Obergrenze für die Suchtreffer gefüllt. Bei meiner aktuellen Testseite sind z. B. 100 Treffer überhaupt kein Thema. Im oben nochmals angepassten Output hab ich dennoch den Maximalwert auf 50 festgelegt.
es ist eigentlich aus Performance-Sicht ein No-Go jedes Mal bei der Suche die komplette DB nach dem Suchwort zu durchwühlen,
Ja, da hast Du recht. Ist die Frage, ab wann die Wartezeit nicht mehr akzeptabel ist. Bei meinem Test dauert der komplette Seitenaufbau der Suchanfrage mit Begrenzung auf 100 Treffer knapp sechs Sekunden (50 Treffer/ vier Sekunden) bei einer Gesamtseitenzahl von durchsuchten 422 Artikeln (891 Datensätze in der con_content). Nehme ich einen Suchbegriff, der nur selten vorkommt, geht es nochmals schneller. Am zeitintensivsten scheint also nicht das eigentliche Sammeln und Ranken der Treffer zu sein sondern lediglich die Ausgabe selbst - bei der auf $article = new cApiArticleLanguage(); zurückgegriffen wird. Kann trotzdem sehr gerne schneller gehen. :wink: Wäre mal interessant, die onboard-Suche (wenn sie denn auch Textelemente durchsuchen würde :motz: ) hier gegenlaufen zu lassen und zu schauen, welche Zeiten hier bei rum kommen. Aber hat die auch ein Ranking und Filterung nach Gruppenrechten? Ich meine nicht.
auf die vorhandene DB-Tabelle aufgebaut
Halt mich nicht für bekloppt, aber: Welche genau meinst Du?
wollte mich eh nochmal mit Dir zusammen unterhalten wegen meinem Plugin-Buch zur 4.9er.
Klar, gerne. Da würde ich durchaus auch selbst von profitieren. :D
seamless-design.de
"Geht nicht!" wohnt in der "Will nicht!"-Strasse.

Die NEUAUFLAGE des Buchs zur Version 4.9: CONTENIDO für Einsteiger (4.9)

Oldperl
Beiträge: 4014
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Franken, Bayern
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von Oldperl » Mi 11. Feb 2015, 17:27

Also sollten wir mal teflonieren oder Skypen, sofern du Skype hast. :wink:

Also im Core wird jeder Artikel beim Anlegen oder Ändern indexiert. Das Ergebnis wandert in die Tabelle con_keywords (womit dann auch die Tabelle benannt wäre :mrgreen: ).
Mein Plugin arbeitet auch mit dieser Tabelle, wobei ich vorher ein paar Modifikationen vornehme. Das Ergebnis bleibt trotzdem abwärts-kompatible zur Core-Indexierung. Nur mit der original-Tabelle aufwärts das hat nicht funktioniert, da die Core-Klasse teilweise Mist in die Tabelle schreibt, weswegen mein Plugin bei der erstmaligen Installation diese auch leert.

Wir sollten mal schauen ob wir nicht irgendwo eine Muster-DB mit ein wenig (mehr) Inhalten auftreiben, dann könnte man mal irgendwo auf einem/meinem Server eine Spielwiese einrichten. Ich würde dann da mein Plugin in der stand-alone Version installieren und dann könnte man mal testen. Es macht halt keinen wirklichen Sinn so etwas mit den bisserl Daten des Demomandanten zu testen. Vielleicht hat ja Jemand eine umfangreichere Seite deren DB er zur Verfügung stellen würde (ich weiß das ist immer schwierig :roll: )

Gruß aus Franken

Ortwin
ConLite 2.0, alternatives und stabiles Update von Contenido 4.8.x *-* phpBO Search Advanced - das neue Suchwort-Plugin für CONTENIDO 4.9 *-* Mein Entwickler-Blog

McHubi
Beiträge: 956
Registriert: Do 18. Nov 2004, 23:06
Wohnort: Mettmann
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von McHubi » Mi 11. Feb 2015, 18:18

Das Ergebnis wandert in die Tabelle con_keywords
Die hab ich jetzt nicht ernst genommen. Die dort hinterlegten Daten der Spalte keywords sind für meinen Geschmack nicht wirklich nachvollziehbar zusammengestellt. Da dauert ein Komplettdurchsuchen der con_content zwar länger, ist aber garantiert ergiebiger und zuverlässiger.
Also sollten wir mal teflonieren oder Skypen, sofern du Skype hast.
Beides. Lass uns nächste Woche mal schauen. Entweder ich oder Du schickst halt mal ne PN.
Muster-DB mit ein wenig (mehr) Inhalten
Ich denke, da kann ich mal mit einem Kunden von mir sprechen. Dann hätten wir die DB mit den >400 Artikeln aus meinem Test weiter oben. :D
seamless-design.de
"Geht nicht!" wohnt in der "Will nicht!"-Strasse.

Die NEUAUFLAGE des Buchs zur Version 4.9: CONTENIDO für Einsteiger (4.9)

Oldperl
Beiträge: 4014
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Franken, Bayern
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von Oldperl » Mi 11. Feb 2015, 18:29

McHubi hat geschrieben:Die hab ich jetzt nicht ernst genommen. Die dort hinterlegten Daten der Spalte keywords sind für meinen Geschmack nicht wirklich nachvollziehbar zusammengestellt.
Nicht nur das war ein Grund für mein Plugin , auch sind die Daten die dort bei größeren Seiten hinterlegt werden inkonsistent bzw. bei Sonderzeichen zerstört bzw. unvollständig. Auch hat mein Plugin bereits eine BadWord-Liste, so dass gängige Worte wie "dass", "der", etc. erst gar nicht in der DB aufschlagen.
Das mit der Muster-DB wäre gut, wobei es sicherlich noch besser wäre die DB vom Demo irgendwann mal aufzubohren in Richtung GROßE Seite(n) mit vieeeeeeeel Inhalt, mehrsprachig und evtl. sogar mit mehr als nur einem Mandanten - quasi eine Big-Demo-DB zum Testen für Entwickler.

Gruß aus Franken

Ortwin
ConLite 2.0, alternatives und stabiles Update von Contenido 4.8.x *-* phpBO Search Advanced - das neue Suchwort-Plugin für CONTENIDO 4.9 *-* Mein Entwickler-Blog

McHubi
Beiträge: 956
Registriert: Do 18. Nov 2004, 23:06
Wohnort: Mettmann
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von McHubi » Fr 13. Feb 2015, 11:54

Es tut sich was...

Bisher war es so, dass nach der Grundzusammenstellung von Suchtreffern jeder Treffer darauf geprüft wurde, ob der Artikel in einer geschützten Kategorie liegt. Die Prüfung selbst wurde mit Hilfe zweier sql-queries für jeden Artikel vorgenommen. Das läuft jetzt anders:

# Ganz am Anfang wird die FE-User-ID nur dann ermittelt, wenn die Berücksichtigung von Artikeln in geschützten Kategorien nicht generell ausgeschlossen sind.
# Nur dann, wenn auch Suchtreffer aus geschützten Kategorien berücksichtigt werden können, ist eine Prüfung der Rechte auf geschützte idcats erforderlich. Also erfolgt auch nur dann eine DB-Abfrage. Da reicht jetzt eine sql-query statt der bisherigen zwei. -> Die so ermittelte Sammlung der für den FE-User freigegebenen idcats wird in einem Array hinterlegt, was im späteren Verlauf nach der aktuellen idcat des zu prüfenden Artikels durchsucht wird. Das sollte gerade in der while-Schleife schneller sein als die alte Methode per doppelter sql-query. Dieses Durchsuchen des Arrays kommt zusätzlich auch nur dann zustande, wenn der FE-User nicht die Rechte "__GLOBAL__" eingeräumt bekommen hat.

Das Ganze ist jetzt also eine Ecke fixer unterwegs als die ersten Versionen... :wink:

Die Quelltexte im Eröffnungsposting sind - wie immer - bereits auf dem neuesten Stand.
seamless-design.de
"Geht nicht!" wohnt in der "Will nicht!"-Strasse.

Die NEUAUFLAGE des Buchs zur Version 4.9: CONTENIDO für Einsteiger (4.9)

benja
Beiträge: 168
Registriert: Mi 31. Aug 2005, 10:54
Wohnort: Köln
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von benja » Fr 17. Apr 2015, 22:25

Hallo, wäre es auch möglich die Suche nur auf eine Kategorie (oder mehrere) zu beschränken? Ich würde sie gerne 2x einsetzten, einmal zum durchsuchen von Kategorie A und einmal von Kategorie B.

Liebe Grüsse
Benja

McHubi
Beiträge: 956
Registriert: Do 18. Nov 2004, 23:06
Wohnort: Mettmann
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von McHubi » So 19. Apr 2015, 18:40

Hallo Benja,

das sollte klappen. Auf die Schnelle würde ich bei der query

Code: Alles auswählen

$query_cat_1 = "SELECT idcat FROM con_cat_art WHERE idart='$array_idart_hit[idart]'";
ansetzen und die Variable $do_not_add auf "true" setzen, falls die ermittelte idcat nicht der von Dir gewünschten entspricht.
seamless-design.de
"Geht nicht!" wohnt in der "Will nicht!"-Strasse.

Die NEUAUFLAGE des Buchs zur Version 4.9: CONTENIDO für Einsteiger (4.9)

thorn
Beiträge: 6
Registriert: Di 24. Aug 2004, 12:09
Wohnort: Berlin
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von thorn » Di 4. Aug 2015, 17:20

Hallo,

habe gerade die Suche eingebaut und getestet, nachdem ich mit dem Suchindex der "Original"-Contenido-Suche Schwierigkeiten hatte. Funktioniert ganz gut, bis auf einen Punkt, der für mich sehr wichtig ist: Die Anzeige von Headline und Text in den Suchergebnissen scheint hart kodiert. Es werden also nur die Texte jener Headlines angezeigt, die "CMS_HTMLHEAD[1]" sind, weitere Indexnummern für "CMS_HTMLHEAD" werden nicht angezeigt, obwohl sie von der Suche gefunden werden. Gleiches gilt für die Inhaltstexte, - auch hier nur die Texte mit "CMS_HTML[1]". Alle anderen Funde enthalten eine leere Ergebnisanzeige mit Prozentanzeige für Relevanz und dem Link auf den Artikel.
Das ist ungünstig für mich, da ich die Kontent-Typen mit unterschiedlichen Indizes verwende, - also z.B. "CMS_HTML[1]", "CMS_HTML[2]", usw. für Einleitung, Hauptinhalt, weiterführende Angaben, etc.
Da ich nicht im Code herumfuhrwerken will, meine Bitte: Wäre es möglich die Funktion "show_result()" dahingehend zu überarbeiten/korrigieren, dass auch jene Texte angezeigt werden, die nicht die Indexnummer 1 haben? Ich denke, dies wäre auch für andere Forennutzer von Wert. Für Tipps oder Code bin ich sehr dankbar.

Danke
Woldemar

Oldperl
Beiträge: 4014
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Franken, Bayern
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von Oldperl » Di 4. Aug 2015, 18:25

Servus,

also für die Headline von 1-10 könnte das etwa so aussehen:
Ersetze

Code: Alles auswählen

if($article->getContent('CMS_HTMLHEAD', 1)!="") {
    echo '<div class="s_sd_result_headline">'.strip_tags($article->getContent('CMS_HTMLHEAD', 1)).'</div>';
}
Durch

Code: Alles auswählen

$i=1;
while($i <= 10) {
    if($article->getContent('CMS_HTMLHEAD', $i)!="") {
        echo '<div class="s_sd_result_headline">'.strip_tags($article->getContent('CMS_HTMLHEAD', $i)).'</div>';
    }
    $i++;
}
Entsprechend kann man mit der Ausgabe für CMS_HTML verfahren. Man kann natürlich auch die Ausgabe beim 1. gefunden Inhalt eines der CMS-Typen abbrechen, oder die Ausgabe aller Ergebnisse in einem umschließenden div-Tag schachteln.

Bedenken sollte man aber beim Einsatz des Suchmodules, dass hier Alles direkt gesucht und angezeigt wird. Es gibt keinen Puffer, keine Datenbank speziell für die Suche. Das kann bei Seiten mit viel Inhalt massiv den Resourcenverbrauch erhöhen, da bei der Suche der gesamte Inhalt (con_content) für jeden Artikel aus der Datenbank geholt wird um ihn zu bewerten. Und das sowohl Sprach- als auch Mandanten-übergreifend.
Als Verbesserungsvorschlag würde ich empfehlen einen SQL-JOIN über die Tabelle con_art_lang bei der SQL-Abfrage

Code: Alles auswählen

$query = "SELECT idartlang,idtype,value FROM con_content ORDER BY idartlang ASC";
zu machen. Somit könnte man die Suche im Content auf die aktuelle Sprache, und damit indirekt auch auf den Mandanten, begrenzen, was für mehrsprachige bzw. Mehrmandaten-System die Auslastung drastisch reduzieren könnte.

Gruß aus Franken

Ortwin
ConLite 2.0, alternatives und stabiles Update von Contenido 4.8.x *-* phpBO Search Advanced - das neue Suchwort-Plugin für CONTENIDO 4.9 *-* Mein Entwickler-Blog

thorn
Beiträge: 6
Registriert: Di 24. Aug 2004, 12:09
Wohnort: Berlin
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von thorn » Di 4. Aug 2015, 20:05

Super, das ging ja schnell!
Zugegeben, auf die while-Schleife hätte ich selbst auch kommen können... :oops:

Danke und auch Grüße nach Franken
Woldemar

Freddy
Beiträge: 230
Registriert: Fr 6. Mai 2005, 21:01
Wohnort: Gummersbach
Kontaktdaten:

Re: Suche mit Berücksichtigung Frontend-Gruppen und Gewichtu

Beitrag von Freddy » Mi 12. Okt 2016, 10:12

Hallo McHubi,
benutze dein Suchmodul. Funktioniert auch soweit ganz gut aber es werden nicht alle möglichen Ergebnisse angezeigt. Was genau wird berücksichtigt??
Mögliche Suchworte aus anderen Module die nicht in CMS_HTML stehen werden z.B. nicht angezeigt. Deswegen habe ich relevante Suchbegriffe in den Meta-Keywords eingegeben. Diese werden aber nicht in der Suche berücksichtigt. Meta-Keywords werden wohl nur für die Wertung des Suchwortes berücksichtigt wenn diese vorher im CMS_HTML stand.
Kann man das Modul soweit umbauen, dass wenn das Suchwort nur in den Meta-Keywords steht auch in den Suchergebniss auftaucht??

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste