From 2f20fe402c0654b1bab06f2a6ec9097ad5cbc61b Mon Sep 17 00:00:00 2001
From: Ryan Cramer
Date: Tue, 8 May 2018 08:48:52 -0400
Subject: [PATCH] Some code cleanup in ProcessPageSearch, plus add a hook for
processwire/processwire-issues#584
---
.../ProcessPageSearch.module | 259 +++++++++++++-----
1 file changed, 198 insertions(+), 61 deletions(-)
diff --git a/wire/modules/Process/ProcessPageSearch/ProcessPageSearch.module b/wire/modules/Process/ProcessPageSearch/ProcessPageSearch.module
index bc04dcaa..8bb29ca4 100644
--- a/wire/modules/Process/ProcessPageSearch/ProcessPageSearch.module
+++ b/wire/modules/Process/ProcessPageSearch/ProcessPageSearch.module
@@ -8,8 +8,10 @@
* For more details about how Process modules work, please see:
* /wire/core/Process.php
*
- * ProcessWire 3.x, Copyright 2016 by Ryan Cramer
+ * ProcessWire 3.x, Copyright 2018 by Ryan Cramer
* https://processwire.com
+ *
+ * @method string findReady($selector)
*
*/
@@ -25,8 +27,18 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
);
}
+ /**
+ * Default operator for text searches
+ *
+ */
const defaultOperator = '%=';
+ /**
+ * Native/system sortable properties
+ *
+ * @var array
+ *
+ */
protected $nativeSorts = array(
'relevance',
'name',
@@ -46,11 +58,36 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
'sortfield',
);
+ /**
+ * Names of all Field objects in PW
+ *
+ * @var array
+ *
+ */
protected $fieldOptions = array();
- protected $customSorts = array();
+
+ /**
+ * All operators where key is operator and value is description
+ *
+ * @var array
+ *
+ */
protected $operators = array();
+
+ /**
+ * Items per pagination
+ *
+ * @var int
+ *
+ */
protected $resultLimit = 25;
- protected $maxLimit = 250;
+
+ /**
+ * Lister instance, when applicable
+ *
+ * @var null|ProcessPageLister
+ *
+ */
protected $lister = null;
/**
@@ -61,7 +98,11 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
*
*/
protected $adminSearchMode = false;
-
+
+ /**
+ * Initialize module
+ *
+ */
public function init() {
foreach($this->fields as $field) {
@@ -74,6 +115,12 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
parent::init();
}
+ /**
+ * Get operators used for searches, where key is operator and value is description
+ *
+ * @return array
+ *
+ */
static public function getOperators() {
$f = __FILE__;
return array(
@@ -105,6 +152,20 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$this->operators = self::getOperators();
}
+ /**
+ * Hookable function to optionally modify selector before it is sent to $pages->find()
+ *
+ * Not applicable when Lister is handling the search/render.
+ *
+ * #pw-hooker
+ *
+ * @param string $selector Selector that will be used to find pages
+ * @return string Must return the selector (optionally modified)
+ *
+ */
+ protected function ___findReady($selector) {
+ return $selector;
+ }
/**
* Perform an interactive search and provide a search form (default)
@@ -140,6 +201,7 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$lister->columns = $this->getDisplayFields();
return $lister->execute();
} else {
+ $selector = $this->findReady($selector);
$matches = $this->pages->find($selector);
return $this->render($matches, $displaySelector);
}
@@ -157,7 +219,6 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$this->fullSetup();
$selector = '';
- $displaySelector = '';
$limit = $this->resultLimit;
$start = 0;
$status = 0;
@@ -314,6 +375,7 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
}
}
+ $selector = $this->findReady($selector);
$items = $this->pages->find($selector);
if(!$superuser && $checkEditAccess) {
@@ -395,12 +457,25 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
/**
* Render the search results
+ *
+ * @param PageArray $matches
+ * @param string $displaySelector
+ * @return string
*
*/
protected function render(PageArray $matches, $displaySelector) {
$out = '';
- if($displaySelector) $this->message(sprintf($this->_n('Found %1$d page using selector: %2$s', 'Found %1$d pages using selector: %2$s', $matches->getTotal()), $matches->getTotal(), $displaySelector));
+
+ if($displaySelector) {
+ $this->message(
+ sprintf(
+ $this->_n('Found %1$d page using selector: %2$s', 'Found %1$d pages using selector: %2$s', $matches->getTotal()),
+ $matches->getTotal(),
+ $displaySelector
+ )
+ );
+ }
// determine what fields will be displayed
$display = array();
@@ -423,7 +498,10 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$class = 'show_options';
}
- $out .= "\n" . $this->renderMatchesTable($matches, $display) . "\n
";
+ $out .=
+ "\n" .
+ $this->renderMatchesTable($matches, $display) .
+ "\n
";
}
return $out;
@@ -431,12 +509,22 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
/**
* Build a selector based upon interactive choices from the search form
+ *
+ * Only used by execute(), not used by executeFor()
+ *
+ * ~~~~~
+ * Returns array(
+ * 0 => $selector, // string, main selector for search
+ * 1 => $displaySelector, // string, selector for display purposes
+ * 2 => $initSelector, // string, selector for initialization in Lister (the part user cannot change)
+ * 3 => $defaultSelector // string default selector used by Lister (the part user can change)
+ * );
+ * ~~~~~
+ * @return array
*
*/
protected function buildSelector() {
$selector = ''; // for regular ProcessPageSearch
- $initSelector = ''; // for Lister, non-changable part of the selector
- $defaultSelector = ''; // for Lister, changeable filters
// search query text
$q = $this->input->whitelist('q');
@@ -485,7 +573,7 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$s = ''; // anything added to this will be populated to both $selector and $initSelector below
// limit results for pagination
- $s = ", limit={$this->resultLimit}";
+ $s .= ", limit={$this->resultLimit}";
$adminRootPage = $this->wire('pages')->get($this->wire('config')->adminRootPageID);
@@ -560,8 +648,12 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$this->input->whitelist('sort', 'relevance');
if($this->input->get->sort) {
$sort = $this->sanitizer->fieldName($this->input->get->sort);
- if($sort && (in_array($sort, $this->nativeSorts) || in_array($sort, $this->fieldOptions))) $this->input->whitelist('sort', $sort);
- if($this->input->get->reverse) $this->input->whitelist('reverse', 1);
+ if($sort && (in_array($sort, $this->nativeSorts) || in_array($sort, $this->fieldOptions))) {
+ $this->input->whitelist('sort', $sort);
+ }
+ if($this->input->get->reverse) {
+ $this->input->whitelist('reverse', 1);
+ }
}
// template
@@ -576,6 +668,10 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
/**
* Is the given field name selectable?
+ *
+ * @param string $name
+ * @param int $level
+ * @return bool
*
*/
protected function isSelectableFieldName($name, $level = 0) {
@@ -618,12 +714,14 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$out = "\n\t";
- $out .= "\n\t
" .
+ $out .=
+ "\n\t
" .
"\n\t" .
"\n\t" .
"\n\t
";
- $out .= "\n\t" .
+ $out .=
+ "\n\t
" .
"\n\t" .
"\n\t" .
+ $out .=
+ "\n\t" .
"\n\t
";
- $out .= "\n\t" .
+ $out .=
+ "\n\t" .
"\n\t" .
"\n\t" .
"\n\t
";
@@ -646,7 +746,8 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$advCollapsed = true;
- $out2 = "\n\t" .
+ $out2 =
+ "\n\t
" .
"\n\t" .
"\n\t" .
+ $out2 .=
+ "\n\t" .
"\n\t
";
- $out2.= "\n\t" .
+ $out2.=
+ "\n\t
" .
"\n\t" .
"\n\t" .
+ $out2 .=
+ "\n\t" .
"\n\t
";
if($sort != 'relevance') {
$reverse = $this->input->whitelist('reverse');
- $out2 .= "\n\t" .
+ $out2 .=
+ "\n\t
" .
"\n\t" .
"\n\t
";
if($reverse) $advCollapsed = false;
}
$display = $this->input->whitelist('display');
- $out2.= "\n\t" .
+ $out2 .=
+ "\n\t
" .
"\n\t" .
"\n\t" .
"\n\t
";
if($display && $display != 'title,path') $advCollapsed = false;
+ /** @var InputfieldSubmit $submit */
$submit = $this->modules->get("InputfieldSubmit");
$submit->attr('name', 'submit');
$submit->attr('value', $this->_x('Search', 'submit')); // Search submit button for advanced search
$out .= "" . $submit->render() . "
";
+ /** @var InputfieldForm $form */
$form = $this->modules->get("InputfieldForm");
$form->attr('id', 'ProcessPageSearchOptionsForm');
$form->method = 'get';
$form->action = './';
+ /** @var InputfieldMarkup $field */
$field = $this->modules->get("InputfieldMarkup");
$field->label = $this->_("Search Options");
$field->value = $out;
@@ -719,7 +828,7 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$form->add($field);
- /* Remove temporarily
+ /* no longer in use
$field = $this->modules->get("InputfieldMarkup");
$field->id = 'ProcessPageSearchShortcuts';
$field->collapsed = true;
@@ -733,46 +842,22 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
}
- protected function renderShortcuts() {
- $out = '';
- $links = array(
- 'Quick Links',
- "All by creation date" => '?q=&submit=Search&display=title+path+created&sort=created&reverse=1' ,
- "All by latest edit date" => '?q=&submit=Search&display=title+path+created&sort=modified&reverse=1',
- "Users by creation date" => '?q=&template=user&submit=Search&operator=~%3D&display=name+email+created&sort=created&reverse=1',
- 'New pages by template',
- );
-
- foreach($this->templates as $template) {
- // Quick links only for content with more than one page
- // if($template->getNumPages() < 2) continue;
-
- // Users get own quick link earlier, others are rather irrelevant
- if($template->flags & Template::flagSystem) continue;
-
- $links[$template->name] = "?q=&template={$template->name}&submit=Search&operator=~%3D&display=title+path+created&sort=created&reverse=1";
- }
-
- foreach($links as $label => $value) {
- if(is_int($label)) {
- $out .= "$value
";
- } else {
- $value .= "&show_options=1";
- $value = htmlspecialchars($value);
- $out .= "$label";
- }
- }
-
- return $out;
- }
-
- protected function renderMatchesTable(PageArray $matches, array $display, $id = 'ProcessPageSearchResultsList') {
+ /**
+ * Render a table of matches
+ *
+ * @param PageArray $matches
+ * @param array $display Fields to display (from getDisplayFields method)
+ * @return string
+ *
+ */
+ protected function renderMatchesTable(PageArray $matches, array $display) {
if(!count($display)) $display = array('path');
$out = '';
if(!count($matches)) return $out;
+ /** @var MarkupAdminDataTable $table */
$table = $this->modules->get("MarkupAdminDataTable");
$table->setSortable(false);
$table->setEncodeEntities(false);
@@ -817,7 +902,7 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
*
* Applicable to adminSearchMode only.
*
- * @param $q Text to find
+ * @param string $q Text to find
* @return array Array of matches
*
*/
@@ -872,8 +957,9 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
* Render the provided matches as a JSON string for AJAX use
*
* @param PageArray $matches
- * @param array Array of fields to display, or display format associative array
+ * @param array $display Array of fields to display, or display format associative array
* @param string $selector
+ * @return string
*
*/
protected function renderMatchesAjax(PageArray $matches, $display, $selector) {
@@ -964,6 +1050,9 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
* Convert object to an array where possible, otherwise convert to a string
*
* For use by renderMatchesAjax
+ *
+ * @param Page|WireData|WireArray|Wire|object $o
+ * @return array
*
*/
protected function setupObjectMatch($o) {
@@ -985,6 +1074,9 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
* Filter an array converting any indexes containing objects to arrays or strings
*
* For use by renderMatchesAjax
+ *
+ * @param array $a
+ * @return array
*
*/
protected function setupArrayMatch(array $a) {
@@ -995,6 +1087,13 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
return $a;
}
+ /**
+ * Render search for that submits to this process
+ *
+ * @param string $placeholder Value for placeholder attribute in search input
+ * @return string
+ *
+ */
public function renderSearchForm($placeholder = '') {
$q = substr($this->input->get->q, 0, 128);
@@ -1008,9 +1107,10 @@ class ProcessPageSearch extends Process implements ConfigurableModule {
$placeholder = '';
}
- $out = "\n