Textpattern PHP Cross Reference Content Management Systems

Source: /textpattern/vendors/Textpattern/Search/Method.php - 293 lines - 8091 bytes - Summary - Text - Print

Description: Admin-side search method.

   1  <?php
   2  
   3  /*
   4   * Textpattern Content Management System
   5   * https://textpattern.com/
   6   *
   7   * Copyright (C) 2020 The Textpattern Development Team
   8   *
   9   * This file is part of Textpattern.
  10   *
  11   * Textpattern is free software; you can redistribute it and/or
  12   * modify it under the terms of the GNU General Public License
  13   * as published by the Free Software Foundation, version 2.
  14   *
  15   * Textpattern is distributed in the hope that it will be useful,
  16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18   * GNU General Public License for more details.
  19   *
  20   * You should have received a copy of the GNU General Public License
  21   * along with Textpattern. If not, see <https://www.gnu.org/licenses/>.
  22   */
  23  
  24  /**
  25   * Admin-side search method.
  26   *
  27   * A container for packaging search criteria into a cohesive set of SQL
  28   * statements suitable for the WHERE clause of a query.
  29   *
  30   * Supports aliasing of criteria so many user input values equates to a single
  31   * value to be compared in the DB (e.g. 'true', 'yes', or '1' can all be used to
  32   * check for a '1' in a boolean field).
  33   *
  34   * @since   4.6.0
  35   * @package Search
  36   */
  37  
  38  namespace Textpattern\Search;
  39  
  40  class Method
  41  {
  42      /**
  43       * The method's unique reference -- usually the form-submitted variable name.
  44       *
  45       * @var string
  46       */
  47  
  48      protected $id;
  49  
  50      /**
  51       * The database column names against which a search should be performed.
  52       *
  53       * @var array
  54       */
  55  
  56      protected $columns;
  57  
  58      /**
  59       * The method's human friendly name.
  60       *
  61       * @var string
  62       */
  63  
  64      protected $label;
  65  
  66      /**
  67       * The method's data type.
  68       *
  69       * Determines if the method is compared as string, integer, etc.
  70       *
  71       * @var string
  72       */
  73  
  74      protected $type;
  75  
  76      /**
  77       * The method's options.
  78       *
  79       * @var array
  80       */
  81  
  82      protected $options;
  83  
  84      /**
  85       * Criteria aliases: values that are equivalent to the actual DB value.
  86       *
  87       * @var array
  88       */
  89  
  90      protected $aliases;
  91  
  92      /**
  93       * General constructor for search methods.
  94       *
  95       * @param string $key  The unique reference to this Method
  96       * @param array  $atts Attributes such as the DB column(s) to which the method applies, its label or data type
  97       */
  98  
  99      public function __construct($key, $atts)
 100      {
 101          $this->id = $key;
 102          $options = array();
 103  
 104          foreach ($atts as $attribute => $value) {
 105              switch ($attribute) {
 106                  case 'column':
 107                      $this->columns = (array) $value;
 108                      break;
 109                  case 'label':
 110                      $this->label = (string) $value;
 111                      break;
 112                  case 'type':
 113                      $this->type = (string) $value;
 114                      break;
 115                  case 'options':
 116                      $options = (array) $value;
 117                      break;
 118              }
 119          }
 120  
 121          $this->setOptions($options);
 122      }
 123  
 124      /**
 125       * Sets method's options.
 126       *
 127       * Valid options are:
 128       *  -> always_like: treat the criteria as SQL LIKE, regardless if it is "in quotes".
 129       *  -> can_list: the criteria can be a comma-separated list of values to retrieve.
 130       *  -> case_sensitive: the criteria is case sensitive.
 131       *
 132       * @param array $options Array of options
 133       */
 134  
 135      public function setOptions($options = array())
 136      {
 137          $this->options = lAtts(array(
 138              'always_like'    => false,
 139              'can_list'       => false,
 140              'case_sensitive' => false,
 141          ), (array) $options);
 142      }
 143  
 144      /**
 145       * Gets methods options.
 146       *
 147       * @param array $options Array of options
 148       */
 149  
 150      public function getOptions($keys = array())
 151      {
 152          $out = array();
 153  
 154          if (empty($keys)) {
 155              $keys = array_keys($this->options);
 156          }
 157  
 158          foreach ((array) $keys as $key) {
 159              if (isset($this->options[$key])) {
 160                  $out[] = $this->options[$key];
 161              }
 162          }
 163  
 164          return $out;
 165      }
 166  
 167      /**
 168       * Sets method aliases.
 169       *
 170       * An alias' key is the literal value that is passed to the database as search criteria
 171       * if the user-supplied criteria matches any of the aliases. Useful for computed,
 172       * define()d or boolean fields. For example, allowing anyone to use the (localised)
 173       * words 'draft', 'hidden' or 'live' in a search box as aliases for the numeric
 174       * values 1, 2, and 4 respectively.
 175       *
 176       * @param string $column  DB column to which the aliases should be applied.
 177       * @param string $key     DB value that is returned if the criteria matches.
 178       * @param array  $aliases Criteria values that are equivalent to the key.
 179       */
 180  
 181      public function setAlias($column, $key, $aliases)
 182      {
 183          $this->aliases[$column][$key] = $aliases;
 184      }
 185  
 186      /**
 187       * Searches aliases for a partial match.
 188       *
 189       * @param string $needle   The thing to look for
 190       * @param array  $haystack The place to look in
 191       * @param string $type     $needle's type, which affects the way the alias is interpreted
 192       */
 193  
 194      private function findAlias($needle, $haystack, $type = '')
 195      {
 196          foreach ($haystack as $key => $value) {
 197              if ($type === 'numeric') {
 198                  if ($value == $needle) {
 199                      return $key;
 200                  }
 201              } else {
 202                  if (strpos($value, $needle) !== false) {
 203                      return $key;
 204                  }
 205              }
 206          }
 207  
 208          return false;
 209      }
 210  
 211      /**
 212       * Gets an item from the object.
 213       *
 214       * @param string $item The thing to retrieve
 215       */
 216  
 217      public function getInfo($item)
 218      {
 219          $out = null;
 220  
 221          switch ($item) {
 222              case 'column':
 223                  $out = $this->columns;
 224                  break;
 225              case 'label':
 226                  $out = $this->label;
 227                  break;
 228              case 'type':
 229                  $out = $this->type;
 230                  break;
 231          }
 232  
 233          return $out;
 234      }
 235  
 236      /**
 237       * Gets an SQL clause for this method based on the criteria.
 238       *
 239       * @todo Case-sensitive searches
 240       *
 241       * @param string $search_term The value to search for
 242       * @param int    $verbatim    Whether the search term is in quotes (1) or not (0)
 243       */
 244  
 245      public function getCriteria($search_term, $verbatim)
 246      {
 247          $clause = array();
 248  
 249          foreach ($this->columns as $column) {
 250              if (isset($this->aliases[$column])) {
 251                  foreach ($this->aliases[$column] as $dbval => $aliases) {
 252                      $terms = do_list($search_term);
 253  
 254                      foreach ($terms as $idx => $term) {
 255                          if ($this->findAlias($term, $aliases, $this->type) !== false) {
 256                              $terms[$idx] = $dbval;
 257                          }
 258                      }
 259  
 260                      $search_term = join(',', $terms);
 261                  }
 262              }
 263  
 264              if ($this->options['case_sensitive']) {
 265                  $column = 'BINARY '.$column;
 266              }
 267  
 268              if ($this->options['can_list']) {
 269                  $operator = ' in ';
 270                  $value = '('.join(',', quote_list(do_list($search_term))).')';
 271              } elseif ($this->type === 'boolean') {
 272                  $clause[] = "convert(".$column.", char) = '".$search_term."'";
 273                  continue;
 274              } elseif ($verbatim && !$this->options['always_like']) {
 275                  $operator = ' = ';
 276                  $value = doQuote($search_term);
 277              } elseif ($this->type === 'find_in_set') {
 278                  $clause[] = "find_in_set('".$search_term."', ".$column." )";
 279                  continue;
 280              } elseif ($this->type === 'numeric') {
 281                  $clause[] = "convert(".$column.", char) = '".$search_term."'";
 282                  continue;
 283              } else {
 284                  $operator = ' like ';
 285                  $value = doQuote("%$search_term%");
 286              }
 287  
 288              $clause[] = join($operator, array($column, $value));
 289          }
 290  
 291          return $clause;
 292      }
 293  }

title

Description

title

Description

title

Description

title

title

Body