On March 26, 2019 we launched new MODX Forums. Please join us at the new MODX Community Forums.
Subscribe: RSS
  • What I'm trying to achieve is similar to the issue raised here:
    http://forums.modx.com/thread/47821/revo-simplesearch-ids-parameter-not-working

    I have a parent resource (with id 47) on which I have the search form call:

    [[!SimpleSearchForm? &tpl=`DocSearchBOX` &landing=`50`]]

    50 is the search result resource id. The parent (47) has some child resources and the search is intended to be only about the child resources. Here is the call on the result page:

    [[!SimpleSearch &ids=`[[!GetIds? &ids=`c47`]]`]]


    (GetID is a snippet call. The snippet help get the ids of the child child resources.
    http://modx.com/extras/package/getids)

    Without any property to the [[!SimpleSearch]] call results show up (but only show content limited to the parent). With the property (or any other property for that matter I get no results (just blank).

    Please kindly advise.
    • You can try, if this does work for you:

      Create a new file under simplesearch/model/drivers/simplesearchdriverresourcescustom.class.php

      with:

      <?php
      
      /**
       * SimpleSearch
       *
       * Copyright 2010-11 by Shaun McCormick <shaun+sisea@modx.com>
       *
       * This file is part of SimpleSearch, a simple search component for MODx
       * Revolution. It is loosely based off of AjaxSearch for MODx Evolution by
       * coroico/kylej, minus the ajax.
       *
       * SimpleSearch is free software; you can redistribute it and/or modify it under
       * the terms of the GNU General Public License as published by the Free Software
       * Foundation; either version 2 of the License, or (at your option) any later
       * version.
       *
       * SimpleSearch is distributed in the hope that it will be useful, but WITHOUT
       * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
       * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
       * details.
       *
       * You should have received a copy of the GNU General Public License along with
       * SimpleSearch; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
       * Suite 330, Boston, MA 02111-1307 USA
       *
       * @package simplesearch
       */
      require_once dirname(__file__) . '/simplesearchdriver.class.php';
      /**
       * Standard sql-based search driver for SimpleSearch
       * 
       * @package simplesearch
       */
      class SimpleSearchDriverResourcesCustom extends SimpleSearchDriver {
          public $searchString;
      
          public function initialize() {
              return true;
          }
          public function index(array $fields) {
              return true;
          }
          public function removeIndex($id) {
              return true;
          }
      
          public function search($str, array $scriptProperties = array()) {
              if (!empty($str))
                  $this->searchString = strip_tags($this->modx->sanitizeString($str));
      
              $joins = $this->modx->fromJson($this->modx->getOption('joins', $scriptProperties, ''));
              $where = $this->modx->fromJson($this->modx->getOption('where', $scriptProperties, ''));
      
              $ids = $this->modx->getOption('ids', $scriptProperties, '');
              $exclude = $this->modx->getOption('exclude', $scriptProperties, '');
              $useAllWords = $this->modx->getOption('useAllWords', $scriptProperties, false);
              $searchStyle = $this->modx->getOption('searchStyle', $scriptProperties, 'partial');
              $hideMenu = $this->modx->getOption('hideMenu', $scriptProperties, 2);
              $maxWords = $this->modx->getOption('maxWords', $scriptProperties, 7);
              $andTerms = $this->modx->getOption('andTerms', $scriptProperties, true);
              $matchWildcard = $this->modx->getOption('matchWildcard', $scriptProperties, true);
              $docFields = explode(',', $this->modx->getOption('docFields', $scriptProperties, 'pagetitle,longtitle,alias,description,introtext,content'));
      
              $relevanceFields = explode(',', $this->modx->getOption('relevanceFields', $scriptProperties, ''));
      
              $c = $this->modx->newQuery('modResource');
              $c->leftJoin('modTemplateVarResource', 'TemplateVarResources');
              
              $classname = 'modResource';
              
              $c->select($this->modx->getSelectColumns($classname, $classname, ''));
      
              $this->prepareJoins($classname, $joins, $c);
      
              /* if using customPackages, add here */
              $customPackages = array();
              if (!empty($scriptProperties['customPackages'])) {
                  $packages = explode('||', $scriptProperties['customPackages']);
                  if (is_array($packages) && !empty($packages)) {
                      $searchArray = array(
                          '{core_path}',
                          '{assets_path}',
                          '{base_path}',
                          );
                      $replacePaths = array(
                          $this->modx->getOption('core_path', null, MODX_CORE_PATH),
                          $this->modx->getOption('assets_path', null, MODX_ASSETS_PATH),
                          $this->modx->getOption('base_path', null, MODX_BASE_PATH),
                          );
                      foreach ($packages as $package) {
                          /* 0: class name, 1: field name(s) (csl), 2: package name, 3: package path, 4: criteria */
                          $package = explode(':', $package);
                          if (!empty($package[4])) {
                              $package[3] = str_replace($searchArray, $replacePaths, $package[3]);
                              $this->modx->addPackage($package[2], $package[3]);
                              $c->leftJoin($package[0], $package[0], $package[4]);
                              $customPackages[] = $package;
                          }
                      }
                  }
              }
      
              /* process conditional clauses */
              $whereGroup = 1;
              if ($searchStyle == 'partial' || $this->modx->config['dbtype'] == 'sqlsrv') {
                  $wildcard = ($matchWildcard) ? '%' : '';
                  $whereArray = array();
                  if (empty($useAllWords)) {
                      $i = 1;
                      foreach ($this->search->searchArray as $term) {
                          if ($i > $maxWords)
                              break;
                          $term = $wildcard . $term . $wildcard;
                          foreach ($docFields as $field) {
                              $whereArray[] = array(
                                  $field . ':LIKE',
                                  $term,
                                  xPDOQuery::SQL_OR,
                                  $whereGroup);
                          }
                          $whereArray[] = array(
                              'TemplateVarResources.value:LIKE',
                              $term,
                              xPDOQuery::SQL_OR,
                              $whereGroup);
                          if (is_array($customPackages) && !empty($customPackages)) {
                              foreach ($customPackages as $package) {
                                  $fields = explode(',', $package[1]);
                                  foreach ($fields as $field) {
                                      $whereArray[] = array(
                                          $package[0] . '.' . $field . ':LIKE',
                                          $term,
                                          xPDOQuery::SQL_OR,
                                          $whereGroup);
                                  }
                              }
                          }
                          if ($andTerms)
                              $whereGroup++;
                          $i++;
                      }
                  } else {
                      $term = $wildcard . $this->searchString . $wildcard;
                      foreach ($docFields as $field) {
                          $whereArray[] = array(
                              $field . ':LIKE',
                              $term,
                              xPDOQuery::SQL_OR,
                              $whereGroup);
                      }
                      $whereArray[] = array(
                          'TemplateVarResources.value:LIKE',
                          $term,
                          xPDOQuery::SQL_OR,
                          $whereGroup);
                      if (is_array($customPackages) && !empty($customPackages)) {
                          foreach ($customPackages as $package) {
                              $fields = explode(',', $package[1]);
                              foreach ($fields as $field) {
                                  $whereArray[] = array(
                                      $package[0] . '.' . $field . ':LIKE',
                                      $term,
                                      xPDOQuery::SQL_OR,
                                      $whereGroup);
                              }
                          }
                      }
                  }
                  $prevWhereGrp = 0;
                  foreach ($whereArray as $clause) {
                      // The following works, but i consider it a hack, and should be fixed. -oori
                      $c->where(array($clause[0] => $clause[1]), $clause[2], null, $clause[3]);
                      if ($clause[3] > $prevWhereGrp)
                          $c->andCondition(array('AND:id:!=' => ''), null, $prevWhereGrp); // hack xpdo to prefix the whole thing with AND
                      $prevWhereGrp = $clause[3];
                      if ($andTerms)
                          $whereGroup++;
                  }
                  $c->andCondition(array('AND:id:!=' => ''), null, $whereGroup - 1); // xpdo hack: pad last condition...
      
              } else {
                  $fields = $this->modx->getSelectColumns('modResource', '', '', $docFields);
                  if (is_array($customPackages) && !empty($customPackages)) {
                      foreach ($customPackages as $package) {
                          $fields .= (!empty($fields) ? ',' : '') . $this->modx->getSelectColumns($package[0], $package[0], '', explode(',', $package[1]));
                          if (!empty($package[4])) {
                              $c->where($package[4]);
                          }
                      }
                  }
                  $wildcard = ($matchWildcard) ? '*' : '';
                  $relevancyTerms = array();
                  if (empty($useAllWords)) {
                      $i = 0;
                      foreach ($this->search->searchArray as $term) {
                          if ($i > $maxWords)
                              break;
                          $relevancyTerms[] = $this->modx->quote($term . $wildcard);
                          $i++;
                      }
                  } else {
                      $relevancyTerms[] = $this->modx->quote($str . $wildcard);
                  }
                  $this->addRelevancyCondition($c, array(
                      'class' => 'modResource',
                      'fields' => $fields,
                      'terms' => $relevancyTerms));
              }
              if (!empty($ids)) {
                  $idType = $this->modx->getOption('idType', $this->config, 'parents');
                  $depth = $this->modx->getOption('depth', $this->config, 10);
                  $ids = $this->processIds($ids, $idType, $depth);
                  $f = $this->modx->getSelectColumns('modResource', 'modResource', '', array('id'));
                  $c->where(array("{$f}:IN" => $ids), xPDOQuery::SQL_AND, null, $whereGroup);
              }
              if (!empty($exclude)) {
                  $exclude = $this->cleanIds($exclude);
                  $f = $this->modx->getSelectColumns('modResource', 'modResource', '', array('id'));
                  $c->where(array("{$f}:NOT IN" => explode(',', $exclude)), xPDOQuery::SQL_AND, null, 2);
              }
              $c->where(array('published:=' => 1), xPDOQuery::SQL_AND, null, $whereGroup);
              $c->where(array('searchable:=' => 1), xPDOQuery::SQL_AND, null, $whereGroup);
              $c->where(array('deleted:=' => 0), xPDOQuery::SQL_AND, null, $whereGroup);
      
              if (is_array($where) && count($where) > 0) {
                  $c->where($where, xPDOQuery::SQL_AND, null, $whereGroup);
              }
      
              /* restrict to either this context or specified contexts */
              $ctx = !empty($this->config['contexts']) ? $this->config['contexts'] : $this->modx->context->get('key');
              $f = $this->modx->getSelectColumns('modResource', 'modResource', '', array('context_key'));
              $c->where(array("{$f}:IN" => explode(',', $ctx)), xPDOQuery::SQL_AND, null, $whereGroup);
              if ($hideMenu != 2) {
                  $c->where(array('hidemenu' => $hideMenu == 1 ? true : false));
              }
              $total = $this->modx->getCount('modResource', $c);
              $c->query['distinct'] = 'DISTINCT';
      
              if (count($relevanceFields) > 0) {
                  foreach ($relevanceFields as $field) {
                      if (!empty($field)) {
                          $wildcard = '%';
                          $i = 1;
                          foreach ($this->search->searchArray as $term) {
                              if ($i > $maxWords)
                                  break;
                              $fieldalias = str_replace('.', '_', $field . '_' . $term . '_match');
                              $term = $wildcard . $term . $wildcard;
      
                              $c->select(array("IF({$field} LIKE '{$term}',1,0) as {$fieldalias}"));
                              $c->sortby($fieldalias, 'DESC');
                              $i++;
                          }
                      }
                  }
              }
      
              if (!empty($scriptProperties['sortBy'])) {
                  $sortDir = $this->modx->getOption('sortDir', $scriptProperties, 'DESC');
                  $sortDirs = explode(',', $sortDir);
                  $sortBys = explode(',', $scriptProperties['sortBy']);
                  $dir = 'desc';
                  for ($i = 0; $i < count($sortBys); $i++) {
                      if (isset($sortDirs[$i])) {
                          $dir = $sortDirs[$i];
                      }
                      $c->sortby('modResource.' . $sortBys[$i], strtoupper($dir));
                  }
              }
      
              /* set limit */
              $perPage = $this->modx->getOption('perPage', $this->config, 10);
              if (!empty($perPage)) {
                  $offset = $this->modx->getOption('start', $this->config, 0);
                  $offsetIndex = $this->modx->getOption('offsetIndex', $this->config, 'sisea_offset');
                  if (isset($_REQUEST[$offsetIndex]))
                      $offset = (int)$_REQUEST[$offsetIndex];
                  $c->limit($perPage, $offset);
              }
      
              $c->prepare();
              //echo $c->toSql();
              //die();
      
              $resources = $this->modx->getCollection('modResource', $c);
              /*
              if (empty($scriptProperties['sortBy'])) {
                  $resources = $this->sortResults($resources, $scriptProperties);
              }
              */
              $includeTVs = $this->modx->getOption('includeTVs', $scriptProperties, '');
              $processTVs = $this->modx->getOption('processTVs', $scriptProperties, '');
              $list = array();
              /**
               @var modResource $resource */
              foreach ($resources as $resource) {
                  if (!$resource->checkPolicy('list'))
                      continue;
                  $resourceArray = $resource->toArray();
      
                  if (!empty($includeTVs)) {
                      $templateVars = &$resource->getMany('TemplateVars');
                      /**
                       @var modTemplateVar $templateVar */
                      foreach ($templateVars as $tvId => $templateVar) {
                          $resourceArray[$templateVar->get('name')] = !empty($processTVs) ? $templateVar->renderOutput($resource->get('id')) : $templateVar->get('value');
                      }
                  }
                  $list[] = $resourceArray;
              }
      
              //print_r($list);
      
              return array(
                  'total' => $total,
                  'results' => $list,
                  );
          }
      
          /**
           * add relevancy search criteria to query
           *
           * @param xPDOQuery $query
           * @param array $options
           * @param string $options['class'] class name (not currently used but may be needed with custom classes)
           * @param string $options['fields'] query-ready list of fields to search for the terms
           * @param array $options['terms'] search terms (will only be one array member if useAllWords parameter is set)
           * @return boolean
           */
          public function addRelevancyCondition(&$query, $options) {
              $class = $this->modx->getOption('class', $options, 'modResource');
              $fields = $this->modx->getOption('fields', $options, '');
              $terms = $this->modx->getOption('terms', $options, array());
              if (!empty($fields)) {
                  foreach ($terms as $term) {
                      $query->where("MATCH ( {$fields} ) AGAINST ( {$term} IN BOOLEAN MODE )");
                  }
              }
              return true;
          }
      
          public function prepareJoins($classname, $joins, &$c, $forcounting = false) {
              global $modx;
      
              if (is_array($joins)) {
                  foreach ($joins as $join) {
                      $jalias = $modx->getOption('alias', $join, '');
                      $joinclass = $modx->getOption('classname', $join, '');
                      $on = $modx->getOption('on', $join, null);
                      if (!empty($jalias)) {
                          if (empty($joinclass) && $fkMeta = $modx->getFKDefinition($classname, $jalias)) {
                              $joinclass = $fkMeta['class'];
                          }
                          if (!empty($joinclass)) {
                              $selectfields = $modx->getOption('selectfields', $join, '');
      
                              /*
                              if ($joinFkMeta = $modx->getFKDefinition($joinclass, 'Resource')){
                              $localkey = $joinFkMeta['local'];
                              }
                              */
                              $c->leftjoin($joinclass, $jalias, $on);
                              $selectfields = !empty($selectfields) ? explode(',', $selectfields) : null;
                              if ($forcounting) {
      
                              } else {
                                  $c->select($modx->getSelectColumns($joinclass, $jalias, $jalias . '_', $selectfields));
                              }
                          }
                      }
                  }
              }
          }
      
      }
      
      


      and try:

      [[!SimpleSearch? 
      &where=`{"parent":"47"}`
      &sisea.driver_class=`simplesearchdriverresourcescustom`
      &sisea.driver_db_specific=`0`
      ]]
        -------------------------------

        you can buy me a beer, if you like MIGX

        http://webcmsolutions.de/migx.html

        Thanks!
      • As always, thanks Bruno.

        I tried this, I always get
        "There were no search results for the search "search". Please try using more general terms to get more results." Which really is some progression away from the blank page I got previously.

        I was expecting to show the resource title and content extract. And for the "There were no search results for the search "search"" I should be better to indicate the search term that was used rather than "search"

        Without
        &where=`{"parent":"47"}`
        &sisea.driver_class=`simplesearchdriverresourcescustom`
        &sisea.driver_db_specific=`0`

        OR
        &where=`{"parent":"47"}`
        I get results but they are limited to the parent resource (47) and the search result page (50), both of which I don't want to show in the search results. I want to search among the child resources of 47 only. [ed. note: ojchris last edited this post 5 years, 9 months ago.]
        • do I understand you correctly, that you only want search in direct children of resource 47?

          I didn't try my driver directly with the simpleSearch - snippet but have it running inside a custom-snippet, but I think it should work together with the simpleSearch-snipptet.

          Will try that later.
            -------------------------------

            you can buy me a beer, if you like MIGX

            http://webcmsolutions.de/migx.html

            Thanks!
          • this is working for me. I also get the correct search-term in:

            4 Results found for "angular"

            or

            There were no search results for the search "angularjs". Please try using more general terms to get more results.


            what is the code of your DocSearchBOX?
              -------------------------------

              you can buy me a beer, if you like MIGX

              http://webcmsolutions.de/migx.html

              Thanks!
            • Parent resource (with id 47) has child resources (unlimited number). I want the search to be restricted to looking amongst those child resources.

              Here is DocSearchBOX (this guy is a suspect):
              <form id="searchForm" action="[[~[[+landing:default=`[[*id]]`]]]]" method="[[+method:default=`get`]]">
              		        <input type="text"  id="searchbox" name="searchbox" class="tftextinput" placeholder="Enter document terms"  size="21" maxlength="120" onchange="revertBackWidth()" /><input type="submit" value="search" name="search" id="search" class="tfbutton" />
              		
              <input type="hidden" name="id" value="[[+landing:default=[[*id]]]]" />
              
              </form>


              Appreciate your patience.
              • <input type="text"  id="searchbox" name="searchbox" class="tftextinput" placeholder="Enter document terms"  size="21" maxlength="120" onchange="revertBackWidth()" />
                <input type="submit" value="search" name="search" id="search" class="tfbutton" />


                you are allways searching for the word "search" here, because of '&search=search' in your form

                the name of your text-input should be 'search':
                <input type="text"  name="search"


                and the submit-button without a name or something different

                <input type="submit" value="Search" class="tfbutton" />






                  -------------------------------

                  you can buy me a beer, if you like MIGX

                  http://webcmsolutions.de/migx.html

                  Thanks!
                • Now that is it. Thank you. Grateful!
                  • Hi, this is an old thread I know, but I've been using this script and it's been working perfectly up until upgrading Modx Cloud to PHP 7.1, and now it has broken (all I get is a blank search results page). The error log shows a message:

                    [2018-05-17 18:41:27] (ERROR @ /paas/cXXXX/www/core/model/modx/modparser.class.php : 540) Could not find snippet with name GetIds=1,c1,2,c2,3,c3,4,c4,5,c5,6,c6,24,25.
                    [2018-05-17 18:41:27] (ERROR @ /paas/cXXXX/www/core/model/modx/modparser.class.php : 540) Could not find snippet with name GetIds=337,c337.


                    If I remove the request for the custom driver then Simple Search works.

                    I'm using Revo 2.6.3-pl on MODX Cloud. Is anyone able to offer a fix - I guess the customer driver need to be updated for PHP 7.1 but no idea where it's going wrong?
                    • FYI I found a solution on another thread. The post here https://forums.modx.com/thread/96176/simplesearch-exclude-parameter-not-working by rainbowtiger worked so the custom driver isn't needed.

                      Quote from: atype at May 18, 2018, 03:08 AM
                      Hi, this is an old thread I know, but I've been using this script and it's been working perfectly up until upgrading Modx Cloud to PHP 7.1, and now it has broken (all I get is a blank search results page). The error log shows a message:

                      [2018-05-17 18:41:27] (ERROR @ /paas/cXXXX/www/core/model/modx/modparser.class.php : 540) Could not find snippet with name GetIds=1,c1,2,c2,3,c3,4,c4,5,c5,6,c6,24,25.
                      [2018-05-17 18:41:27] (ERROR @ /paas/cXXXX/www/core/model/modx/modparser.class.php : 540) Could not find snippet with name GetIds=337,c337.


                      If I remove the request for the custom driver then Simple Search works.

                      I'm using Revo 2.6.3-pl on MODX Cloud. Is anyone able to offer a fix - I guess the customer driver need to be updated for PHP 7.1 but no idea where it's going wrong?