PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/assets/snippets/ditto/extenders/search.extender.inc.php

https://github.com/good-web-master/modx.evo.custom
PHP | 263 lines | 120 code | 36 blank | 107 comment | 18 complexity | 22eeb6e1d7942de50ec5664a9cbfb8cf MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0, GPL-2.0, MIT, BSD-3-Clause
  1. <?php
  2. /*
  3. * Title: Search Filter for Ditto
  4. * Version: 2.0
  5. * Purpose: Expands Ditto's functionality to include filtering search results,
  6. * using simple text search, regular expressions or php code snippets
  7. * for advanced search functions
  8. *
  9. * License: http://www.gnu.org/copyleft/gpl.html GNU Public License (GPL)
  10. * Author: sam (sam@gmx-topmail.de)
  11. * www: https://github.com/Sammyboy/MODx-Ditto-Extenders
  12. *
  13. * Installation:
  14. * Copy this file into "assets/snippets/ditto/extenders/" of your MODx
  15. * installation folder
  16. *
  17. * Usage:
  18. * [!Ditto? &extenders=`search` &searchString=`my search string` &searchFields=`content,tv1,tv2` &searchOptions=`caseSensitive` ... !]
  19. */
  20. // ---------------------------------------------------
  21. // Search Parameters
  22. // ---------------------------------------------------
  23. $searchFields = isset($searchFields) ?
  24. preg_replace('/[\n|\r|\t]+/', '', $searchFields) :
  25. "content";
  26. /*
  27. Param: searchFields
  28. Purpose: Fields to search in
  29. Options: Comma separated list of document variables and/or template variables
  30. used by Ditto
  31. Default: "content"
  32. */
  33. $searchOptions = isset($searchOptions) ? $searchOptions : "";
  34. /*
  35. Param: searchOptions
  36. Purpose: Search Options
  37. Options:
  38. "caseSensitive": Get case sensitive results only
  39. Example call:
  40. &searchOptions=`caseSensitive`
  41. &searchString=`test`
  42. "regex": Search for regular expressions
  43. Example call:
  44. &searchOptions=`regex`
  45. &searchString=`/test/i`
  46. (case insensitive search for "test")
  47. "snippet": Search use Snippet to get search results
  48. Example call:
  49. &searchOptions=`snippet: mySearchSnippet, param1: value1, param2: value2, paramTree: another value`
  50. &searchString=`test`
  51. The same call using JSON configuration string:
  52. &searchOptions=`{"snippet":"mySearchSnippet","param1":"value1","param2":"value2","paramTree":"another value"}`
  53. &searchString=`test`
  54. Using @FILE for including snippet file:
  55. &searchOptions=`snippet: @FILE assets/snippets/ditto/extenders/searchRule.php, param1: value1, param2: value2`
  56. &searchString=`test`
  57. Or use JSON string:
  58. &searchOptions=`{"snippet":"@FILE assets/snippets/ditto/extenders/searchRule.php","param1":"value1","param2":"value2"}`
  59. &searchString=`test`
  60. Using @EVAL and @CHUNK:
  61. &searchOptions=`@CHUNK dittoSearchOptions`
  62. &searchString=`test`
  63. &searchOptionsSeparators=`{"outer":"||","inner":"::"}`
  64. Content of the chunk "dittoSearchOptions":
  65. snippet::@EVAL return (stripos($searchContent, $searchString) === false) ? false : ((stripos($searchContent, $and_not) === false) ? true : false);||and_not::sub
  66. Or use JSON string:
  67. &searchOptions=`@CHUNK dittoSearchOptions`
  68. &searchString=`test`
  69. Content of the chunk "dittoSearchOptions":
  70. {"snippet":"@EVAL return (stripos($searchContent, $searchString) === false) ? false : ((stripos($searchContent, $and_not) === false) ? true : false);","and_not":"sub"}
  71. */
  72. $searchString = isset($searchString) ? $searchString : "";
  73. /*
  74. Param: searchString
  75. Purpose: JSON string with separators for the options list
  76. Options: Any string or
  77. @FILE - Search for the content of a file
  78. Example call:
  79. &searchOptions=`regex`
  80. &searchString=`@FILE assets/snippets/ditto/extenders/regexSearch.txt`
  81. @CHUNK - Search for the content of a chunk
  82. Example call:
  83. &searchOptions=`regex`
  84. &searchString=`@CHUNK regexSearchChunk`
  85. Default: ""
  86. */
  87. $searchOptionsSeparators = isset($searchOptionsSeparators) ? $searchOptionsSeparators : null;
  88. /*
  89. Param: searchOptionsSeparators
  90. Purpose: JSON string with separators for the options list
  91. Options: Any string
  92. @FILE
  93. @CHUNK
  94. Default: '{"outer":",","inner":"="}'
  95. */
  96. // ---------------------------------------------------
  97. // Search Filter Class
  98. // ---------------------------------------------------
  99. if (!class_exists("searchFilter")) {
  100. class searchFilter {
  101. var $searchFunction;
  102. private $sourceFields, $searchOptions, $searchString, $snippet, $options, $function_code, $source, $separators;
  103. function searchFilter($searchString = "", $sourceFields = "content", $searchOptions = "", $separators = null) {
  104. global $modx;
  105. $functions = array('snippet', 'regex', 'case_sensitive');
  106. $this->searchOptions = $this->getSource($searchOptions);
  107. if (!($this->options = json_decode($this->searchOptions, true))) {
  108. $this->separators = (isset($separators) && ($new_separators = json_decode($this->getSource($separators), true))) ?
  109. $new_separators : array('outer' => ',', 'inner' => ':');
  110. $this->options = $this->parseOptions($this->searchOptions, $this->separators["outer"], $this->separators["inner"]);
  111. }
  112. if ($func = array_intersect_key($this->options, array_flip($functions))) {
  113. $this->searchFunction = key($func);
  114. $this->options[$this->searchFunction] = $this->getSource($this->options[$this->searchFunction]);
  115. if (($this->searchFunction === 'snippet') && isset($this->source))
  116. $this->searchFunction = 'eval';
  117. } else
  118. $this->searchFunction = "default";
  119. $this->searchString = $this->getSource($searchString);
  120. if ($this->searchFunction === 'eval')
  121. $this->function_code = trim($this->options['snippet'], " <>?ph\n\r\t");
  122. elseif ($this->searchFunction === 'snippet') {
  123. $this->snippet = $this->options[$this->searchFunction];
  124. unset($this->options['snippet']);
  125. }
  126. if (($this->searchFunction === 'eval') || ($this->searchFunction === 'snippet')) {
  127. if (!isset($this->options["searchString"]))
  128. $this->options["searchString"] = $this->searchString;
  129. }
  130. $this->sourceFields = explode(",", $this->getSource($sourceFields));
  131. $this->searchFunction = ucfirst($this->searchFunction);
  132. }
  133. private function parseOptions($options) {
  134. $new_options = array();
  135. $options = explode($this->separators['outer'], $options);
  136. foreach ($options as $option) {
  137. list($key, $val) = (($pos = strpos($option, $this->separators['inner'])) === false) ?
  138. array(trim($option), true) :
  139. array(trim(substr($option, 0, $pos)), ltrim(substr($option, $pos + strlen($this->separators['inner']))));
  140. $new_options[$key] = $val;
  141. }
  142. return $new_options;
  143. }
  144. private function getSource($string) {
  145. global $modx;
  146. $this->source = 1;
  147. if (stripos(($string = ltrim($string)), "@file") === 0)
  148. $string = (($content = file_get_contents($name = trim(substr($string, 5), ": "))) === false) ? $name : $content;
  149. elseif (stripos($string, "@chunk") === 0)
  150. $string = (($content = $modx->getChunk($name = trim(substr($string, 6), ": "))) === false) ? $name : $content;
  151. elseif (stripos($string, "@eval") === 0) {
  152. $string = trim(substr($string, 5), ": ");
  153. return $string;
  154. } else {
  155. $this->source = null;
  156. return $string;
  157. }
  158. return $this->getSource($string);
  159. }
  160. function executeSnippet($resource) {
  161. global $modx;
  162. $result = 0;
  163. foreach ($this->sourceFields as $field) {
  164. $this->options["searchContent"] = $resource[$field];
  165. if ($modx->runSnippet($this->custom_function, $this->options))
  166. $result = 1;
  167. }
  168. return $result;
  169. }
  170. function executeEval($resource) {
  171. global $modx;
  172. $result = 0;
  173. extract($this->options);
  174. foreach ($this->sourceFields as $field) {
  175. $searchContent = $resource[$field];
  176. if (eval($this->function_code))
  177. $result = 1;
  178. }
  179. return $result;
  180. }
  181. function executeRegex($resource) {
  182. $result = 0;
  183. foreach ($this->sourceFields as $field) {
  184. if (preg_match($this->searchString, $resource[$field]))
  185. $result = 1;
  186. }
  187. return $result;
  188. }
  189. function executeCase_sensitive($resource) {
  190. $result = 0;
  191. foreach ($this->sourceFields as $field) {
  192. if (strpos($resource[$field], $this->searchString) !== false)
  193. $result = 1;
  194. }
  195. return $result;
  196. }
  197. function executeDefault($resource) {
  198. $result = 0;
  199. foreach ($this->sourceFields as $field) {
  200. if (stripos($resource[$field], $this->searchString) !== false)
  201. $result = 1;
  202. }
  203. return $result;
  204. }
  205. }
  206. }
  207. // ---------------------------------------------------
  208. // Search Filter Execution
  209. // ---------------------------------------------------
  210. if (isset($searchString)) {
  211. $searchFilter = new searchFilter($searchString, $searchFields, $searchOptions, $searchOptionsSeparators);
  212. $filters["custom"]["searchFilter"] = array($searchFields,array($searchFilter,"execute".$searchFilter->searchFunction));
  213. }
  214. ?>