We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 3098
    • 37 Posts
    Hello,


    I’ve developed an improved version of the FlexSearchForm snippet and I would like to create a new snippet to keep the original code clear.
    But, I’ve got some problems to share variables between my snippet and the FlexSearchForm snippet.

    So my goal is to use the advanced search code into the FlexSearchForm snippet.

    I’ve tried the "runSnippet" method to run my snippet from the FlexSearchForm snippet but it doesn’t work well.

    My idea was to create different functions in my snippet and to call them from a "switch" that would receive the value from the FlexSearchForm.
    The "switch" works well, I receive the value from the FlexSearchForm but I don’t know how to access FlexSearchForm variables.


    Please tell me if you have any other (better) ideas.

    Thanks.
      • 17883
      • 1,039 Posts
      Hi Benjamin,

      why not copy the whole FlexFormSearch snippet and rename it? Then insert your improvements and call your new snippet directly. After sharing your improvements the developers sure would like to view the improvements and put them in the original snippet if they are useful. Otherwise we can look for a seperate solution, but therefore we would need some code smiley

      Marc
      • Advanced searching algorithms would be very much appreciated and I’d like to commit these to the repository for the next release.
          Ryan Thrash, MODX Co-Founder
          Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
          • 3098
          • 37 Posts
          Here it is.

          So what’s new ?

          • searching by templates, parent folders (*), document groups and web groups
          • management of a stopwords list (blacklist stored in a chunk)
          • advanced search :[list][li]use of quotation marks for searching groups of words
          • use of ’+’ to bypass the stopwords test
          • use of ’-’ to exclude words from the search
          example : [ "Lorem ipsum" -dolor +sit amet ]
          [/li][/list]
          (*) search will include subfolders automatically


          Comments in the code are in French for now. Sorry.

          There are 3 different portions of code added to the original FlexSearchForm code :

          • Declaration of the new variables
          • Construction of the DB request
          • Message if stopwords have been found

          HyperFlexSearchForm code :
          // ----------------------------
          // Snippet: HyperFlexSearchForm
          // ----------------------------
          // Version: 0.1a
          // Date: 2006.04.06
          // [email protected]
          //
          // This snippet was designed to create a search form
          // that is highly flexible in how it is presented. It
          // can be used as both a small, subtle, persistent
          // search field element, as well as present the search
          // results. All elements are branded with classes
          // for easy CSS styling.
          
          // CONFIGURE
          
            // MAIN SNIPPET SETUP OPTIONS
            // --------------------------
          
             // $searchStyle [ 'relevance' | 'partial' ]
             // This option allows you to decide to use a faster,
             // relevance sorted search ('relevance') which WILL NOT
             // inlclude partial matches. Or use a slower, but
             // more inclusive search ('partial') that will include
             // partial matches. Results will NOT be sorted based on
             // relevance.
             //
             // This option contributed by Rich from Snappy Graffix Media to 
             // allow partial matching and LIKE matching of the search term.
             // [email protected]
             $searchStyle = 'relevance';
             
             // $useAllWords [ true | false ]
             // If you want only documents which contain ALL words in the 
             // search string, set to true. Otherwise, the search will return
             // all pages with ONE or more of the search words (which can be 
             // a LOT more pages).
             $useAllWords = true;
          
             // $showSearchWithResults [1 | 0]
             // If you would like to turn off the search
             // form when showing results you can set
             // this to false. Can also be set in template
             // by using the snippet variable: FSF_showForm
             // like this (1=true, 0=false):
             // [[FlexSearchForm?FSF_showForm=0]]
             $showSearchWithResults = 1;
          
             // $resultsPage [int]
             // The default behavior is to show the results on
             // the current page, but you may define the results
             // page any way you like. The priority is:
             //
             // 1- snippet variable - set in page template like this:
             //    [[FlexSearchForm?FSF_landing=int]]
             //    where int is the page id number of the page you want
             //    your results on
             // 2- querystring variable FSF_form
             // 3- variable set here
             // 4- use current page
             //
             // This is VERY handy when you want to put the search form in
             // a discrete and/or small place on your page- like a side
             // column, but don't want all your results to show up there!
             // Set to results page or leave 0 as default
             $resultsPage = 0;
          
             // $showResults [1 | 0] (as passed in snippet variable ONLY)
             // You can define whether this snippet will show the results
             // of the search with it. Do this by assigning the snippet
             // variable FSF_showResults as:
             // [[FlexSearchForm?FSF_showResults=0]]
             //
             // This is useful in situations where you want to show the
             // search results in a different place than the search form.
             // In that type of situation, you would include two of these
             // snippets on the same page, one showing results, and one
             // showing the form.
             //
             // Default is true.
          
             // $grabMax [ int ]   
             // Set to the max number of records you would like on
             // each page. Set to 0 if unlimited.
             $grabMax = 10;
          
             // $pageLinkSeparator [ string ]
             // What you want, if anything, between your page link numbers
             $pageLinkSeparator = " | ";
          
             // $stripHTML [ true | false ]
             // Allow HTML characters in the search? Probably not.
             $stripHTML = true;
          		
             // $stripSnip [ true | false ]
             // Strip out snippet calls etc from the search string?
             $stripSnip = true;
             
             // $stripSnippets [ true | false ]
             // Strip out snippet names so users will not be able to "search"
             // to see what snippets are used in your content. This is a 
             // security benefit, as users will not be able to search for what pages
             // use specific snippets.
             $stripSnippets = true;
             
             // $xhtmlStrict [ true | false ]
             // If you want this form to validate as XHTML Strict compliance, then
             // this needs to be true, but IE has a fieldset bug that I don't know
             // a workaround for. So you can set this to false to avoid it.
             $xhtmlStrict = false;
          
             // $minChars [ int ]
             // Minimum number of characters to require for a word to be valid for
             // searching. MySQL will typically NOT search for words with less than
             // 4 characters (relevance mode). If you have $useAllWords = true and
             // a three or fewer word appears in the search string, the results will
             // always be 0. Setting this drops those words from the search in THAT
             // CIRCUMSTANCE ONLY (relevance mode, useAllWords=true).
             $minChars = 4;
          
          
            // LANGUAGE AND LABELS
            // --------------------------
          
             // $resultsIntroFailure
             // If nothing is found for the search. You should give the user
             // some indication that the search was a failure.
             $resultsIntroFailure = 'There were no search results. Please try using more general terms to get more results.';
          
             // $searchButtonText [string]
             // Label the search button what
             // you wish
             $searchButtonText = 'Go!';
             
             // $boxText [ string ]
             // What, if anything, you want to have in the search box when the
             // form first loads. When clicked, it will disappear. This uses 
             // JavaScript. If you don't want this feature or the JavaScript,
             // just set to empty string: ''
             $boxText = 'Search here...';
          
             // $introMessage [ string ]
             // This is the text that will show up if the person arrives
             // at the search page without having done a search first.
             // You can leave this as an empty string if you like.
             $introMessage = 'Please enter a search term to begin your search.';
             
             // $resultsFoundTextSingle, $resultsFoundTextMultiple [ string patttern ]
             // The string that will tell the user how many results were found.
             // two variables will be provided at runtime:
             // %d    The number of results found (integer)
             // %s    The search string itself.
             $resultsFoundTextSingle = '%d result found for "%s".';
             $resultsFoundTextMultiple = '%d results found for "%s".';
             
             // $paginationTextSinglePage and $paginationTextMultiplePages [ string ]
             // The text that comes before the links to other pages. In this
             // example, "Result pages: " was the $paginationTextMultiplePages:
             // Result pages: 1 | 2 | 3 | 4
             // Page numbers will only appear if there is more than one page.
             $paginationTextSinglePage = '';
             $paginationTextMultiplePages = 'Result pages: ';
          
            /* BEGIN HACK by Benjamin Toussaint [Hypernovae] */
          
            // SEARCH IMPROVEMENTS
            // --------------------------
             
             // Separator used in the comma-separated lists
             $hyperSeparator = ',';
             
             // Name of the chunk containing the stopwords
             $hyperChunk = 'stopWordList';
             
             // Idea from xyzvisual ([email protected])
             // $templateSearch [ csv ]
             // Allow searching by templates
             $templateSearch = '';
           
             // $templateSearchMode [ 0 | 1 ]
             // Indicates whether we exclude or include the templates list
             $templateSearchMode = 1;
             
             // Idea from Wendy Novianto
             // $parentSearch [ csv ]
             // Allow parent categories to be searched in
             $parentSearch = '';
             
             // $parentSearchMode [ 0 | 1 ]
             // Indicates whether we exclude or include the parent categories list
             $parentSearchMode = 1;
             
             // $documentgroupSearch [ csv ]
             // Allow searching by documentgroups
             $documentgroupSearch = '';
           
             // $documentgroupSearchMode [ 0 | 1 ]
             // Indicates whether we exclude or include the documentgroups list
             $documentgroupSearchMode = 1;
          
             // $webgroupSearch [ csv ]
             // Allow searching by webgroups
             $webgroupSearch = '';
           
             // $webgroupSearchMode [ 0 | 1 ]
             // Indicates whether we exclude or include the webgroups list
             $webgroupSearchMode = 1;
             
             // $stopWords [ csv ] (from chunk)
             // List of the words to exclude of the search string
             $stopWords = implode(",", explode("\n", $modx->getChunk($hyperChunk)) );
                
             /* END HACK by Benjamin Toussaint [Hypernovae] */
             
          // Styles
          // These styles are included in this snippet:
          //
          // .FSF_form{}
          // .FSF_input {}
          // .FSF_submit {}
          //
          // .FSF_SearchResults {}
          // .FSF_resultsIntroFailure{}
          // .FSF_result {}
          // .FSF_resultLink {}
          // .FSF_resultDescription {}
          // .FSF_pagination
          // .FSF_intro
          
          // -------------
          // End configure
          // -------------
          
          // establish whether to show the form or not
          $showSearchWithResults = (isset($FSF_showForm))? $FSF_showForm : $showSearchWithResults;
          
          // establish whether to show the results or not
          $showResults = (isset($FSF_showResults))? $FSF_showResults : true;
          
          // establish results page
          if (isset($FSF_landing)){ // set in snippet
            $searchAction = "[~".$FSF_landing."~]";
          } elseif ($resultsPage > 0){ // locally set
            $searchAction = "[~".$resultsPage."~]";
          }  else { //otherwise
            $searchAction = "[~".$modx->documentIdentifier."~]";
          }
          
          // Set newline variable
          $newline = "\n";
          
          // Initialize search string
          $searchString = '';
          
          // CLEAN SEARCH STRING
          if ( isset($_POST['search']) || isset($_GET['FSF_search']) ){
            // Prefer post to get
            $searchString = (isset($_POST['search']))? $_POST['search'] : urldecode($_GET['FSF_search']) ;
            // block sensitive search patterns
            $searchString =
            (
            $searchString != "{{" &&
            $searchString != "[[" &&
            $searchString != "[!" &&
            $searchString != "[(" &&
            $searchString != "[~" &&
            $searchString != "[*" 
            )
            ?
            $searchString : "" ;
          
            // Remove dangerous tags and such
          
            // Strip HTML too
            if ($stripHTML){
              $searchString = strip_tags($searchString);
            }
          
            // Regular expressions of things to remove from search string
            $modRegExArray[] = '~\[\[(.*?)\]\]~';   // [[snippets]]
            $modRegExArray[] = '~\[!(.*?)!\]~';     // [!noCacheSnippets!]
            $modRegExArray[] = '!\[\~(.*?)\~\]!is'; // [~links~]
            $modRegExArray[] = '~\[\((.*?)\)\]~';   // [(settings)]
            $modRegExArray[] = '~{{(.*?)}}~';       // {{chunks}}
            $modRegExArray[] = '~\[\*(.*?)\*\]~';   // [*attributes*]
            
            // Remove modx sensitive tags
            if ($stripSnip){
              foreach ($modRegExArray as $mReg){
                $searchString = preg_replace($mReg,'',$searchString);
              }
            }
          
            // Remove snippet names
            if ($stripSnippets && $searchString != ''){
              // get all the snippet names
              $tbl = $modx->dbConfig['dbase'] . "." . $modx->dbConfig['table_prefix'] . "site_snippets";
              $snippetSql = "SELECT $tbl.name FROM $tbl;";
              $snippetRs = $modx->dbQuery($snippetSql);
              $snippetCount = $modx->recordCount($snippetRs);
              $snippetNameArray = array();
              for ($s = 0; $s < $snippetCount; $s++){
                $thisSnippetRow = $modx->fetchRow($snippetRs);
                $snippetNameArray[] = strtolower($thisSnippetRow['name']);
              }
              // Split search into strings
              $searchWords = explode(' ',$searchString);
              $cleansedWords = '';
              foreach($searchWords as $word){
                if ($word != '' && 
                    !in_array(strtolower($word),$snippetNameArray) &&
                      ((!$useAllWords) ||
                      ($searchStyle == 'partial') ||
                      (strlen($word) >= $minChars && $useAllWords && $searchStyle == 'relevance'))
                   ){
                  $cleansedWords .= $word.' ';
                }
              }
              // Remove last space
              $cleansedWords = substr($cleansedWords,0,(strlen($cleansedWords)-1));
              
              $searchString = $cleansedWords;
            }
          
          } // End cleansing search string
          
          // check querystring
          $validSearch = ($searchString != '')? true : false ;
          
          //check for offset
          $offset = (isset($_GET['FSF_offset']))? $_GET['FSF_offset'] : 0;
          
          // initialize output
          $SearchForm = '';
          
          // establish form
          if (($validSearch && ($showSearchWithResults)) || $showSearchWithResults){
            $SearchForm .= '<form class="FSF_form" action="'.$searchAction.'" method="post">';
            $SearchForm .= ($xhtmlStrict)? '<fieldset><legend>Search</legend>' : '' ;
            // decide what goes in search box
            $searchBoxVal = ($searchString == '' && $boxText != '')? $boxText : $searchString ;
            $SearchForm .= '<input class="FSF_input" type="text" name="search" value="'.$searchBoxVal.'"  ';
            $SearchForm .= ($boxText)? 'onfocus="this.value=(this.value==\''.$boxText.'\')? \'\' : this.value ;" />' : '/>';
            $SearchForm .= '<input class="FSF_submit" type="submit" name="sub" value="'.$searchButtonText.'" />';
            $SearchForm .= ($xhtmlStrict)? '</fieldset>' : '';
            $SearchForm .= '</form>'.$newline;
          }
          
          if ($showResults) {
            if($validSearch) {
              /*$search = explode(" ", $searchString);
              $tbl = $modx->dbConfig['dbase'] . "." . $modx->dbConfig['table_prefix'] . "site_content";
          
              if ($searchStyle == 'partial'){
                $sql = "SELECT id, pagetitle, description ";
                $sql .= "FROM $tbl ";
                $sql .= "WHERE ";
                if (count($search)>1 && $useAllWords){
                  foreach ($search as $searchTerm){
                    $sql .= "(pagetitle LIKE '%$searchString%' OR description LIKE '%$searchString%' OR content LIKE '%$searchTerm%') AND ";
                  }
                } else {
                  $sql .= "(pagetitle LIKE '%$searchString%' OR description LIKE '%$searchString%' OR content LIKE '%$searchString%') AND ";
                }
                $sql .= "$tbl.published = 1 AND $tbl.searchable=1 AND $tbl.deleted=0;";
              } else {
                $sql = "SELECT id, pagetitle, description ";
                $sql .= "FROM $tbl WHERE ";
                if (count($search)>1 && $useAllWords){
                  foreach ($search as $searchTerm){
                    $sql .= "MATCH (pagetitle, description, content) AGAINST ('$searchTerm') AND ";
                  }
                } else {
                  $sql .= "MATCH (pagetitle, description, content) AGAINST ('$searchString') AND ";
                }
                $sql .= "$tbl.published = 1 AND $tbl.searchable=1 AND $tbl.deleted=0;";
              }*/
          
          	/* BEGIN HACK by Benjamin Toussaint [Hypernovae] */
          	
          	# nettoyage de la chaîne de recherche
          	
          	# caractères à remplacer
          	$input  = "ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ";
          	# caractères de remplacement
          	$output = "aaaaaaaaaaaaooooooooooooeeeeeeeecciiiiiiiiuuuuuuuuynn";
          	# suppression des accents et passage en minuscules
          	$searchString = strtolower( strtr($searchString, $input, $output) );
          	
          	# gestion des guillemets dans la chaîne de recherche
          	
          	# on extrait les segments entre guillemets
          	$mask = '`(")(.*?)((?<!\\\)("))`s';
          	preg_match_all($mask, $searchString, $array);
          	# boucle sur toutes les occurences trouvées
          	foreach ($array[0] as $result)
          	{
          		# on cherche la position de la chaîne trouvée
          	    $pos = @strpos($searchString, $result);
          	    # on calcule sa longueur
          		$length = strlen($result);
          		# on supprimer la chaîne trouvée de la chaîne de recherche
          		$searchString = substr_replace($searchString, "", $pos, $length);
          		# on récupère ce qu'il y a entre les guillemets
          		$tmp = substr($result, 1, $length-2);
          		# si la chaîne trouvée n'est pas vide, on l'ajoute à la liste
          		if(!empty($tmp)) $keywords[] = $tmp;
          	}
          	
          	$words = $stopWords;
          	
          	if (!empty($words))
          	{
          		# nettoyage de la liste des mots à exclure
          		$clean = create_function('&$item','$item = trim(strtolower($item));');
          		array_walk(&$words, $clean);
          		
          		# boucle sur chaque mot de la chaîne de recherche
          		foreach (explode(" ", $searchString) as $searchTerm)
          		{
          			# suppression des espaces dans le mot
          			$searchTerm = trim($searchTerm);
          			# si la chaîne est vide, on boucle
          			if (empty($searchTerm)) continue;
          			
          			# on vérifie si le mot est à exclure
          			$test = array_search($searchTerm, $words);
          			
          			# null et false pour des raisons de compatibilité PHP
          			# le + devant un mot permet de le garder même s'il est dans la liste noire
          			if ( $test === null || $test === false || $searchTerm{0} == "+" )
          			{
          				# si le mot commence par un +
          				if ($searchTerm{0} == "+")
          				{
          					# on supprime ce +
          					$searchTerm = substr($searchTerm, 1);
          				}
          				# et on ajoute le mot à la liste
          				$keywords[] = $searchTerm;
          			}
          			# si le mot est à exclure
          			elseif ( is_int($test) )
          			{
          				# on l'ajoute à la liste noire
          				$stopwords[] = $searchTerm;
          			}
          		}
          		
          		# si la liste des mots est vide
          		if (!$keywords)
          		{
          			# on récupère la chaîne de départ
          			$keywords = explode(" ", $searchString);
          			$searchWarning = '';
          		}
          		# sinon, si la liste noire n'est pas vide
          		elseif ($stopwords)
          		{
          			# si cette liste contient in seul mot
          			if (count($stopwords) == 1)
          			{
          				# construction du message d'avertissement
          				$searchWarning = '<strong>"'.$stopwords[0].'"</strong> étant un mot très courant, il a été ignoré lors de cette recherche.';
          			}
          			# si plusieurs mots
          			else
          			{
          				# construction du message d'avertissement
          				$searchWarning = 'Les termes suivants étant très courants, ils ont été ignorés lors de cette recherche : <strong>'.implode(" ", $stopwords).'</strong>.';
          			}
          		}
          	}
          	
          	# noms des différentes tables pour la requête
          	
          	$tbl = $modx->dbConfig['dbase'] . ".`" . $modx->dbConfig['table_prefix'];
          	$tbl_cnt = $tbl . "site_content`";
          	$tbl_dgp = $tbl . "document_groups`";
          	$tbl_dgn = $tbl . "documentgroup_names`";
          	$tbl_wga = $tbl . "webgroup_access`";
          	$tbl_wgn = $tbl . "webgroup_names`";
          	$tbl_tpl = $tbl . "site_templates`";
          	
          	# recherche dans les répertoires parents
          	
          	# si la liste des catégorie à cherche n'est pas vide
          	if ( !empty($parentSearch) )
          	{
          	
          		# construction de la requête sur les répertoires parents
          		
          		$sql  = "SELECT `id`, `parent`, `isfolder`, `pagetitle` FROM `modx_site_content` WHERE `parent` <> '0' OR `isfolder` = '1'";
          		$rs = $modx->dbQuery($sql);
          		
          		$folders = array();
          		while ( $doc = mysql_fetch_object($rs) )
          		{
          			# on regroupe les résultats par id de dossier parent
          			$folders[$doc->parent][] = array("id" => $doc->id, "isfolder" => $doc->isfolder);
          		}
          	
          		# fonction qui renvoit la liste des sous-dossiers
          		
          		$list = array();
          		
          		# id du dossier parent, liste générée plus haut
          		function getSubfolders($parentId, $folders)
          		{
          			global $list;
          	
          			# si le dossier contient des sous-dossiers
          			if (is_array($folders[$parentId]))
          			{
          				# boucle sur chaque sous-dossier
          				foreach ($folders[$parentId] as $item)
          				{
          					# si le sous-dossier n'est pas vide
          					if ($item["isfolder"])
          					{
          						# on récupère l'id du sous-dossier
          						$list[] = (int) $parentId;
          						# et on fait une nouvelle recherche avec cet id
          						getSubfolders($item["id"], $folders);
          					}
          				}
          				
          				# liste des sous-dossiers
          				$list[] = (int) $parentId;
          			}
          			
          			# on renvoit la liste des sous-dossiers
          			return $list;
          		}
          		
          		# recherche des sous-dossiers
          		
          		# boucle sur chaque id dans la liste à chercher
          		foreach (explode($hyperSeparator, $parentSearch) as $parentId)
          		{
          			$parentId = (int) $parentId;
          			# on recherche les sous-dossiers de chaque répertoire
          			$subfolders[] = getSubfolders($parentId, $folders);
          		}
          		
          		# suppression des doublons dans la liste reçue
          		$parentSearchArr = array_unique($subfolders);
          	
          	}
          	
          	# construction de la requête de base
          	
          	$sql  = "SELECT ";
          	$sql .= "cnt.`id`, cnt.`pagetitle`, cnt.`description`";
          	
          	# si le liste des templates n'est pas vide
          	if ( !empty($templateSearch) )
          	{
          		$sql .= ", cnt.`parent`";
          	}
          	
          	# si le liste des groupes de documents ou celle des groupes web n'est pas vide
          	if ( ( !empty($documentgroupSearch) ) || ( !empty($webgroupSearch) ) )
          	{
          		$sql .= ", dgn.`name` AS documentgroup";
          		
          		# si la liste des groupes web n'est pas vide
          		if ( !empty($webgroupSearch) )
          		{
          			$sql .= ", wgn.`name` AS webgroup";
          		}
          	}
          	
          	# si la liste des templates n'est pas vide
          	if ( !empty($templateSearch) )
          	{
          		$sql .= ", stm.`templatename` AS template";
          	}
          	
          	$sql .= " FROM $tbl_cnt AS cnt";
          
          	# si le liste des groupes de documents ou celle des groupes web n'est pas vide	
          	if ( ( !empty($documentgroupSearch) ) || ( !empty($webgroupSearch) ) )
          	{
          		$sql .= " LEFT JOIN $tbl_dgp AS dgp ON cnt.`id` = dgp.`document`";
          		$sql .= " LEFT JOIN $tbl_dgn AS dgn ON dgp.`document_group` = dgn.`id`";
          		
          		# si la liste des groupes web n'est pas vide
          		if ( !empty($webgroupSearch) )
          		{
          			$sql .= " LEFT JOIN $tbl_wga AS wga ON dgn.`id` = wga.`documentgroup`";
          			$sql .= " LEFT JOIN $tbl_wgn AS wgn ON wga.`webgroup` = wgn.`id`";
          		}
          	}
          	
          	# si la liste des templates n'est pas vide
          	if ( ( !empty($templateSearch) ) )
          	{
          		$sql .= " LEFT JOIN $tbl_tpl AS stm ON cnt.`template` = stm.`id`";
          	}
          	
          	$sql .= " WHERE ";
          	
          	# filtres de base
          	
          	$sql .= "cnt.`published` = '1' AND cnt.`searchable` = '1' AND cnt.`deleted` = '0'";
          	
          	# fonction qui construit la requête sur base de la liste (csv)
          	
          	# nom du champ, liste, mode de recherche
          	function csvToQuery($name, $csv, $mode)
          	{
          		# paramètres variables selon le mode (inclusion ou exclusion)
          		$compStr = ($mode) ? "=" : "<>";
          		$joinStr = ($mode) ? "OR" : "AND";
          		# boucle sur chaque éléments de la liste
          		foreach (explode($hyperSeparator, $csv) as $val)
          		{
          			$group = trim($val);
          			# requête brute
          			$q[] = "$name $compStr '$val'";
          		}
          		# requête finale
          		$sql = " AND (" . implode(" $joinStr ", $q) . ") ";
          		
          		# on renvoit le segment de requête
          		return $sql;
          	}
          	
          	# filtre sur les templates
          	
          	# si la liste des templates n'est pas vide
          	if ( !empty($templateSearch) )
          	{
          		# on construit la requête
          		$sql .= csvToQuery("template", $templateSearch, $templateSearchMode);	
          	}
          	
          	# filtre sur les dossiers parents
          	
          	# si la liste des dossiers parents n'est pas vide
          	if ( !empty($parentSearch) )
          	{
          		# on récupère les id des dossiers et sous-dossiers
          		$parentSearch = implode(",", $parentSearchArr);
          		# on construit la requête
          		$sql .= csvToQuery("parent", $parentSearch, $parentSearchMode);
          	}
          		
          	# filtre sur les groupes de documents
          
          	# si la liste de groupes de documents n'est pas vide	
          	if ( !empty($documentgroupSearch) )
          	{
          		# on construit la requête
          		$sql .= csvToQuery("documentgroup", $documentgroupSearch, $documentgroupSearchMode);
          	}
          	
          	# filtre sur les groupes web
          	
          	# si la liste des groupes web n'est pas vide
          	if ( !empty($webgroupSearch) )
          	{
          		# on construit la requête
          		$sql .= csvToQuery("webgroup", $webgroupSearch, $webgroupSearchMode);
          	}
          	
          	# filtre sur le mots-clés (pour finir en beauté)
          	
          	# fontion qui protège les valeurs reçues
          	function smartEscape($value)
          	{
          		if (get_magic_quotes_gpc())
          		{
          			# suppression des antislashs
          			$value = stripslashes($value);
          		}
          
          		if (!is_numeric($value))
          		{
          			# protection de la chaîne
          		    $value = "'". mysql_real_escape_string($value) . "'";
          		}
          		
          		# on renvoit la chaîne protégée
          		return $value;
          	}
          
          	# boucle sur chaque mot
          	foreach ($keywords as $searchTerm)
          	{
          		# si le mot est précédé d'un - (moins)
          		if ( $searchTerm{0} == "-" )
          		{
          			# paramètre variable selon le style de recherche
          			$compStr = ($searchStyle == 'partial') ? "NOT LIKE" : "<>" ;
          			$joinStr = "AND";
          			# on supprime le - en début de mot
          			$searchTerm = substr($searchTerm, 1);
          		}
          		# s'il n'est pas précédé d'un -
          		else
          		{
          			# paramètre variable selon le style de recherche			
          			$compStr = ($searchStyle == 'partial') ? "LIKE" : "=";
          			$joinStr = "OR";
          		}
          		
          		# selon le style de recherche, on inclut le mot entre %		
          		$searchTerm = ($searchStyle == 'partial') ? "%" . $searchTerm . "%" : $searchTerm ;
          		
          		# on protège la chaîne pour la requête
          		$searchTerm = smartEscape($searchTerm);
          		
          		# construction de la reqûete
          		$q[] = " (LOWER(cnt.`pagetitle`) $compStr $searchTerm $joinStr LOWER(cnt.`description`) $compStr $searchTerm $joinStr LOWER(cnt.`content`) $compStr $searchTerm) ";
          	}
          	
          	# paramètre variable selon l'option choisie			
          	$joinStr = ($useAllWords) ? "AND" : "OR" ;
          	
          	# dans le cas où il n'y a qu'un seul mot
          	if (count($q) == 1)
          	{
          		$sql .= " AND (" . $q[0] . ") ";
          	}
          	# si plusieurs mots
          	elseif (count($q) > 1)
          	{
          		$sql .= " AND (" . implode(" $joinStr ", $q) . ") ";
          	}
          	
          	/* END HACK by Benjamin Toussaint [Hypernovae] */
          	
              $rs = $modx->dbQuery($sql);
              $limit = $modx->recordCount($rs);
          
              if($limit>0) {
                $SearchForm .= '<div class="FSF_searchResults">'.$newline;
          
                // pagination
                if ($grabMax > 0){
                  $numResultPages = ceil($limit/$grabMax);
                  $resultPageLinks = '<span class="FSF_pages">';
                  $resultPageLinks .= ($limit>$grabMax)? $paginationTextMultiplePages : $paginationTextSinglePage ;
                  $resultPageLinkNumber = 1;
                  for ($nrp=0;$nrp<$limit && $limit > $grabMax;$nrp+=$grabMax){
                    if($offset == ($resultPageLinkNumber-1)*$grabMax){
                      $resultPageLinks .= $resultPageLinkNumber;
                    } else {
                      $resultPageLinks .= '<a href="[~' . $modx->documentObject['id'] . '~]&FSF_offset=' . $nrp . '&FSF_search=' . urlencode($searchString) . '">' . $resultPageLinkNumber . '</a>';
                    }
                    $resultPageLinks .= ($nrp+$grabMax < $limit)? $pageLinkSeparator : '' ;
                    $resultPageLinkNumber++;
                  }
                  $resultPageLinks .= "</span>".$newline;
                  $SearchForm .= '<p class="FSF_pagination">';
                  $resultsFoundText = ($limit > 1)? $resultsFoundTextMultiple : $resultsFoundTextSingle ;
                  $SearchForm .= sprintf($resultsFoundText,$limit,$searchString);
                  
                  /* BEGIN HACK by Benjamin Toussaint [Hypernovae] */
          		
          		# on affiche l'avertissement sur les mots exclus de la recherche
                  $SearchForm .= '<br /><span class="FSF_Warning">'.$hyperSearchWarning.'</span>';
                  
                  /* END HACK by Benjamin Toussaint [Hypernovae] */        
                  
                  $SearchForm .= '<br />'.$resultPageLinks."</p>".$newline;
                } // end if grabMax
          
                // search results
                $useLimit = ($grabMax > 0)? $offset+$grabMax : $limit;
                for ($y = $offset; ($y < $useLimit) && ($y<$limit); $y++) {
                  $moveToRow = mysql_data_seek($rs,$y);
                  $SearchFormsrc=$modx->fetchRow($rs);
                  $SearchForm.='<div class="FSF_result">'.$newline;
                  $SearchForm.='<a class="FSF_resultLink" href="[~'.$SearchFormsrc['id'].'~]" title="' . $SearchFormsrc['pagetitle'] . '">' . $SearchFormsrc['pagetitle'] . "</a>".$newline;
                  $SearchForm.=$SearchFormsrc['description']!='' ? '<span class="FSF_resultDescription">' . $SearchFormsrc['description'] . "</span>".$newline : "" ;
                  $SearchForm.='</div><!--end FlexSearchResult-->'.$newline;
                }
                $SearchForm.='<p class="FSF_pagination">'.$resultPageLinks.'</p>';
                $SearchForm.='</div><!--end FlexSearchResults-->'.$newline;
              } else {
                $SearchForm.='<p class="FSF_resultsIntroFailure">'.$resultsIntroFailure.'</p>';
              } // end if records found
          
            } else if (!$validSearch && isset($_POST['sub'])) {
          
              // message to show if search was performed but for something invalid
              $SearchForm .= '<p class="FSF_resultsIntroFailure">'.$resultsIntroFailure.'</p>';
              
            } else { // end if validSearch
          
              $SearchForm .= '<p class="FSF_intro">'.$introMessage.'</p>';
          
            } // end if not validSearch
          } // end if showResults
          
          return $SearchForm;
          
            • 32241
            • 1,495 Posts
            I think searching by document groups will be one of those great enchancement that I would like to have in my MODx framework installation wink

            Btw, you can use GLOBAL variables to share parameter between snippet, but remember the order of your snippet calling. Another workaround will be to use setPlaceholder API, but it works the same way as having a GLOBAL variables defined in your previous snippet, before being used by the second snippet.

            Hope that will help you to improve the snippet into a more versatile tool that can be included in our arsenal.
              Wendy Novianto
              [font=Verdana]PT DJAMOER Technology Media
              [font=Verdana]Xituz Media
            • Quote from: Djamoer at Apr 06, 2006, 06:10 PM

              Btw, you can use GLOBAL variables to share parameter between snippet, but remember the order of your snippet calling. Another workaround will be to use setPlaceholder API, but it works the same way as having a GLOBAL variables defined in your previous snippet, before being used by the second snippet.

              Hope that will help you to improve the snippet into a more versatile tool that can be included in our arsenal.

              This is why I used a plugin for the ShopX project. The plugin takes care of managing the "global" values that the various snippets need to have in order to function. It is set to capture the first possible event, then processes the GPCS so everything is all set up for the snippets when the parser gets to them. This way the developer can use the snippets and TVs in any way he pleases without having to worry about it.
                Studying MODX in the desert - http://sottwell.com
                Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                Join the Slack Community - http://modx.org
                • 6726
                • 7,075 Posts
                This is great Benjamin !

                One thing I *really* would like to see is all the enhancement brought by to FlexSearchForm into one search snippet laugh

                Quote from: Djamoer at Apr 06, 2006, 06:10 PM
                I think searching by document groups will be one of those great enchancement that I would like to have in my MODx framework installation wink

                So is keyword searching...
                  .: COO - Commerce Guys - Community Driven Innovation :.


                  MODx est l&#39;outil id