From 4f22c8202a88af471739a1bafd36b746ba631004 Mon Sep 17 00:00:00 2001 From: Bournwog Date: Thu, 18 Apr 2024 09:43:54 +0300 Subject: [PATCH 1/2] Update search processor like modx 3.x --- .../modx/processors/search/search.class.php | 401 ++++++------------ 1 file changed, 124 insertions(+), 277 deletions(-) diff --git a/core/model/modx/processors/search/search.class.php b/core/model/modx/processors/search/search.class.php index 276280a33f2..a8f25be6c2d 100644 --- a/core/model/modx/processors/search/search.class.php +++ b/core/model/modx/processors/search/search.class.php @@ -14,141 +14,75 @@ **/ class modSearchProcessor extends modProcessor { - public $maxResults = 5; - public $actionToken = ':'; - private $actions = array(); + const TYPE_TEMPLATE = 'template'; + const TYPE_TV = 'tv'; + const TYPE_CHUNK = 'chunk'; + const TYPE_SNIPPET = 'snippet'; + const TYPE_PLUGIN = 'plugin'; + + const TYPE_USER = 'user'; + const TYPE_RESOURCE = 'resource'; protected $query; + public $results = array(); - public function checkPermissions() { + /** + * @return bool + */ + public function checkPermissions() + { return $this->modx->hasPermission('search'); } /** - * @return string JSON formatted results + * Returns max records per search request + * @return int */ - public function process() + protected function getMaxResults() { - $this->query = $this->getProperty('query'); - if (!empty($this->query)) { - if (strpos($this->query, ':') === 0) { - // upcoming "launch actions" - //$this->searchActions(); - } else { - // Search elements & resources - if ($this->modx->hasPermission('edit_document')) { - $this->searchResources(); - } - if ($this->modx->hasPermission('edit_chunk')) { - $this->searchChunks(); - } - if ($this->modx->hasPermission('edit_template')) { - $this->searchTemplates(); - } - if ($this->modx->hasPermission('edit_tv')) { - $this->searchTVs(); - } - if ($this->modx->hasPermission('edit_snippet')) { - $this->searchSnippets(); - } - if ($this->modx->hasPermission('edit_plugin')) { - $this->searchPlugins(); - } - if ($this->modx->hasPermission('edit_user')) { - $this->searchUsers(); - } - } - } - - return $this->outputArray($this->results); + return (int)$this->modx->getOption('quick_search_result_max', null, 10); } /** - * Dummy method to micmic actions search + * @return bool */ - public function searchActions() + protected function searchInContent() { - $type = 'actions'; - - $query = ltrim($this->query, $this->actionToken); - $this->actions = array( - array( - 'name' => 'Welcome', - '_action' => 'welcome', - 'description' => 'Go back home', - 'type' => $type, - 'perms' => array(), - ), - array( - 'name' => 'Error log', - '_action' => 'system/event', - 'description' => 'View error log', - 'type' => $type, - 'perms' => array(), - ), - array( - 'name' => 'Clear cache', - '_action' => 'system/refresh_site', - 'description' => 'Refresh the cache', - 'type' => $type, - 'perms' => array(), - ), - array( - 'name' => 'Edit chunk', - '_action' => 'element/chunk/update', - 'description' => 'Edit the given chunk', - 'type' => $type, - 'perms' => array(), - ), - ); - - return $this->filterActions($query); -// $class = 'modMenu'; -// $c = $this->modx->newQuery($class); -// $c->where(array( -// 'action:LIKE' => '%' . $this->query . '%', -// )); -// $c->limit($this->maxResults); -// -// $collection = $this->modx->getCollection($class, $c); -// /** @var modMenu $record */ -// foreach ($collection as $record) { -// $output[] = array( -// 'name' => $record->get('text'), -// 'action' => $record->get('action'), -// 'description' => $record->get('description'), -// 'type' => 'Actions', -// ); -// } + return (boolean)$this->modx->getOption('quick_search_in_content', null, true); } - private function filterActions($query) + /** + * @return string JSON formatted results + */ + public function process() { - // source : http://stackoverflow.com/questions/5808923/filter-values-from-an-array-similar-to-sql-like-search-using-php - $query = preg_quote($query, '~'); - $names = array(); -// $actions = array(); -// $descriptions = array(); - foreach ($this->actions as $idx => $action) { - $names[$idx] = $action['name']; -// $actions[$idx] = $action['action']; -// $descriptions[$idx] = $action['description']; - } - $results = preg_grep('~' . $query . '~', $names); -// $results = array_merge($results, preg_grep('~' . $this->query . '~', $actions)); -// $results = array_merge($results, preg_grep('~' . $this->query . '~', $descriptions)); - - //$output = array(); - if ($results) { - foreach ($results as $idx => $field) { - $this->results[] = $this->actions[$idx]; + $this->query = trim($this->getProperty('query')); + if (!empty($this->query)) { + if ($this->modx->hasPermission('edit_document')) { + $this->searchResources(); + } + if ($this->modx->hasPermission('edit_chunk')) { + $this->searchElements('modChunk', static::TYPE_CHUNK, 'name', 'description', 'snippet'); + } + if ($this->modx->hasPermission('edit_template')) { + $this->searchElements('modTemplate', static::TYPE_TEMPLATE, 'templatename', 'description', 'content'); + } + if ($this->modx->hasPermission('edit_tv')) { + $this->searchElements('modTemplateVar', static::TYPE_TV, 'name', 'caption', 'default_text'); + } + if ($this->modx->hasPermission('edit_snippet')) { + $this->searchElements('modSnippet', static::TYPE_SNIPPET, 'name', 'description', 'snippet'); + } + if ($this->modx->hasPermission('edit_plugin')) { + $this->searchElements('modPlugin', static::TYPE_PLUGIN, 'name', 'description', 'plugincode'); + } + if ($this->modx->hasPermission('edit_user')) { + $this->searchUsers(); } } - //$output = array_unique($output); - - //return $output; + return $this->outputArray($this->results); } /** @@ -156,13 +90,10 @@ private function filterActions($query) * * @return void */ - public function searchResources() + protected function searchResources() { - $type = 'resources'; - $typeLabel = $this->modx->lexicon('search_resulttype_' . $type); - - $contextKeys = array(); - $contexts = $this->modx->getCollection('modContext', array('key:!=' => 'mgr')); + $contextKeys = []; + $contexts = $this->modx->getIterator('modContext', ['key:!=' => 'mgr']); foreach ($contexts as $context) { $contextKeys[] = $context->get('key'); } @@ -170,199 +101,115 @@ public function searchResources() $c = $this->modx->newQuery('modResource'); $c->leftJoin('modTemplate', 'modTemplate', 'modResource.template = modTemplate.id'); $c->select($this->modx->getSelectColumns('modResource', 'modResource')); - $c->select("modTemplate.icon as icon"); - $c->where(array( - array( - 'modResource.pagetitle:LIKE' => '%' . $this->query .'%', - 'OR:modResource.longtitle:LIKE' => '%' . $this->query .'%', - 'OR:modResource.alias:LIKE' => '%' . $this->query .'%', - 'OR:modResource.description:LIKE' => '%' . $this->query .'%', - 'OR:modResource.introtext:LIKE' => '%' . $this->query .'%', - 'OR:modResource.id:=' => $this->query, - ), - array( - 'modResource.context_key:IN' => $contextKeys, - ) - )); + $c->select('modTemplate.icon as icon'); + + $querySearch = [ + 'modResource.pagetitle:LIKE' => '%' . $this->query .'%', + 'OR:modResource.longtitle:LIKE' => '%' . $this->query .'%', + 'OR:modResource.alias:LIKE' => '%' . $this->query .'%', + 'OR:modResource.description:LIKE' => '%' . $this->query .'%', + 'OR:modResource.introtext:LIKE' => '%' . $this->query .'%', + ]; + if ($this->searchInContent()) { + $querySearch['OR:modResource.content:LIKE'] = '%' . $this->query .'%'; + } + $querySearch['OR:modResource.id:='] = $this->query; + $queryContext = [ + 'modResource.context_key:IN' => $contextKeys, + ]; + $c->where($querySearch, $queryContext); + $c->sortby('IF(`modResource`.`pagetitle` = ' . $this->modx->quote($this->query) . ', 0, 1)'); $c->sortby('modResource.createdon', 'DESC'); - $c->limit($this->maxResults); + $c->limit($this->getMaxResults()); - $collection = $this->modx->getCollection('modResource', $c); + $collection = $this->modx->getIterator('modResource', $c); /** @var modResource $record */ foreach ($collection as $record) { - $this->results[] = array( - 'name' => $this->modx->hasPermission('tree_show_resource_ids') ? $record->get('pagetitle') . ' (' . $record->get('id') . ')' : $record->get('pagetitle'), + $this->results[] = [ + 'name' => $this->modx->hasPermission('tree_show_resource_ids') + ? $record->get('pagetitle') . ' (' . $record->get('id') . ')' + : $record->get('pagetitle'), '_action' => 'resource/update&id=' . $record->get('id'), 'description' => $record->get('description'), - 'type' => $type, + 'type' => static::TYPE_RESOURCE . 's', 'class' => $record->get('class_key'), - 'type_label' => $typeLabel, 'icon' => str_replace('icon-', '', $record->get('icon')) - ); - } - } - - public function searchSnippets() - { - $type = 'snippets'; - - $c = $this->modx->newQuery('modSnippet'); - $c->where(array( - 'name:LIKE' => '%' . $this->query . '%', - 'OR:description:LIKE' => '%' . $this->query .'%', - 'OR:id:=' => $this->query, - )); - $c->sortby('IF(`name` = ' . $this->modx->quote($this->query) . ', 0, 1)'); - $c->limit($this->maxResults); - - $collection = $this->modx->getCollection('modSnippet', $c); - /** @var modSnippet $record */ - foreach ($collection as $record) { - $this->results[] = array( - 'name' => $record->get('name'), - '_action' => 'element/snippet/update&id=' . $record->get('id'), - 'description' => $record->get('description'), - 'type' => $type, - ); + ]; } } - public function searchChunks() + /** + * Searches elements - chunks, snippets, tvs, templates, plugins + * @param $class + * @param string $type + * @param string $nameField + * @param string $descriptionField + * @param string $contentField + */ + protected function searchElements($class, $type = '', $nameField = 'name', $descriptionField = 'description', $contentField = '') { - $type = 'chunks'; - - $class = 'modChunk'; $c = $this->modx->newQuery($class); - $c->where(array( - 'name:LIKE' => '%' . $this->query . '%', - 'OR:description:LIKE' => '%' . $this->query .'%', - 'OR:id:=' => $this->query, - )); - $c->sortby('IF(`name` = ' . $this->modx->quote($this->query) . ', 0, 1)'); - $c->limit($this->maxResults); - - $collection = $this->modx->getCollection($class, $c); - /** @var modChunk $record */ - foreach ($collection as $record) { - $this->results[] = array( - 'name' => $record->get('name'), - '_action' => 'element/chunk/update&id=' . $record->get('id'), - 'description' => $record->get('description'), - 'type' => $type, - ); + $querySearch = [ + $nameField . ':LIKE' => '%' . $this->query . '%', + 'OR:' . $descriptionField . ':LIKE' => '%' . $this->query .'%', + ]; + if ($this->searchInContent() && !empty($contentField)) { + $querySearch['OR:' . $contentField . ':LIKE'] = '%' . $this->query .'%'; } - } - - public function searchTemplates() - { - $type = 'templates'; + $querySearch['OR:id:='] = $this->query; + $c->where($querySearch); - $class = 'modTemplate'; - $c = $this->modx->newQuery($class); - $c->where(array( - 'templatename:LIKE' => '%' . $this->query . '%', - 'OR:description:LIKE' => '%' . $this->query .'%', - 'OR:id:=' => $this->query, - )); - $c->sortby('IF(`templatename` = ' . $this->modx->quote($this->query) . ', 0, 1)'); - $c->limit($this->maxResults); + $c->sortby('IF(`' . $nameField . '` = ' . $this->modx->quote($this->query) . ', 0, 1)'); - $collection = $this->modx->getCollection($class, $c); - /** @var modTemplate $record */ - foreach ($collection as $record) { - $this->results[] = array( - 'name' => $record->get('templatename'), - '_action' => 'element/template/update&id=' . $record->get('id'), - 'description' => $record->get('description'), - 'type' => $type, - ); - } - } + $c->limit($this->getMaxResults()); - public function searchPlugins() - { - $type = 'plugins'; + $collection = $this->modx->getIterator($class, $c); - $class = 'modPlugin'; - $c = $this->modx->newQuery($class); - $c->where(array( - 'name:LIKE' => '%' . $this->query . '%', - 'OR:description:LIKE' => '%' . $this->query .'%', - 'OR:id:=' => $this->query, - )); - $c->sortby('IF(`name` = ' . $this->modx->quote($this->query) . ', 0, 1)'); - $c->limit($this->maxResults); - - $collection = $this->modx->getCollection($class, $c); - /** @var modPlugin $record */ + /** @var modElement $record */ foreach ($collection as $record) { - $this->results[] = array( - 'name' => $record->get('name'), - '_action' => 'element/plugin/update&id=' . $record->get('id'), - 'description' => $record->get('description'), - 'type' => $type, - ); + $this->results[] = [ + 'name' => $record->get($nameField), + 'description' => $record->get($descriptionField), + '_action' => 'element/' . $type . '/update&id=' . $record->get('id'), + 'type' => $type . 's' + ]; } } - public function searchTVs() - { - $type = 'tvs'; - - $class = 'modTemplateVar'; - $c = $this->modx->newQuery($class); - $c->where(array( - 'name:LIKE' => '%' . $this->query . '%', - 'OR:caption:LIKE' => '%' . $this->query .'%', - 'OR:id:=' => $this->query, - )); - $c->sortby('IF(`name` = ' . $this->modx->quote($this->query) . ', 0, 1)'); - $c->limit($this->maxResults); - - $collection = $this->modx->getCollection($class, $c); - /** @var modTemplate $record */ - foreach ($collection as $record) { - $this->results[] = array( - 'name' => $record->get('name'), - '_action' => 'element/tv/update&id=' . $record->get('id'), - 'description' => $record->get('caption'), - 'type' => $type, - ); - } - } - - public function searchUsers() + /** + * Searches users registered in the system + */ + protected function searchUsers() { - $type = 'users'; - - $class = 'modUser'; - $c = $this->modx->newQuery($class); - $c->select(array( - $this->modx->getSelectColumns($class, $class), - $this->modx->getSelectColumns('modUserProfile', 'Profile', ''), - )); - $c->leftJoin('modUserProfile', 'Profile'); - $c->where(array( + $c = $this->modx->newQuery('modUser'); + $c->select([ + $this->modx->getSelectColumns('modUser', 'modUser'), + $this->modx->getSelectColumns('modUserProfile', 'Profile'), + ]); + $c->leftJoin(modUserProfile::class, 'Profile'); + $c->where([ 'username:LIKE' => '%' . $this->query . '%', 'OR:Profile.fullname:LIKE' => '%' . $this->query .'%', 'OR:Profile.email:LIKE' => '%' . $this->query .'%', 'OR:id:=' => $this->query, - )); + ]); + $c->sortby('IF(`username` = ' . $this->modx->quote($this->query) . ', 0, 1)'); - $c->limit($this->maxResults); + + $c->limit($this->getMaxResults()); /** @var modUserProfile[] $collection */ - $collection = $this->modx->getCollection($class, $c); + $collection = $this->modx->getIterator('modUser', $c); foreach ($collection as $record) { - $this->results[] = array( + $this->results[] = [ 'name' => $record->get('username'), - '_action' => 'security/user/update&id=' . $record->get('internalKey'), 'description' => $record->get('fullname') .' / '. $record->get('email'), - 'type' => $type, - ); + '_action' => 'security/user/update&id=' . $record->get('internalKey'), + 'type' => static::TYPE_USER . 's', + ]; } } } From 83a6aa5b7e38445aa8342e72b7dd6413f6cdb2a9 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 26 Aug 2024 15:03:30 +0300 Subject: [PATCH 2/2] en lexicon --- _build/data/transport.core.system_settings.php | 18 ++++++++++++++++++ core/lexicon/en/setting.inc.php | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/_build/data/transport.core.system_settings.php b/_build/data/transport.core.system_settings.php index 73d8559e3ba..3a2397ed537 100644 --- a/_build/data/transport.core.system_settings.php +++ b/_build/data/transport.core.system_settings.php @@ -1477,6 +1477,24 @@ 'area' => 'file', 'editedon' => null, ), '', true, true); +$settings['quick_search_in_content']= $xpdo->newObject('modSystemSetting'); +$settings['quick_search_in_content']->fromArray(array ( + 'key' => 'quick_search_in_content', + 'value' => true, + 'xtype' => 'combo-boolean', + 'namespace' => 'core', + 'area' => 'manager', + 'editedon' => null, +), '', true, true); +$settings['quick_search_result_max']= $xpdo->newObject('modSystemSetting'); +$settings['quick_search_result_max']->fromArray(array ( + 'key' => 'quick_search_result_max', + 'value' => 10, + 'xtype' => 'numberfield', + 'namespace' => 'core', + 'area' => 'manager', + 'editedon' => null, +), '', true, true); $settings['request_controller']= $xpdo->newObject('modSystemSetting'); $settings['request_controller']->fromArray(array ( 'key' => 'request_controller', diff --git a/core/lexicon/en/setting.inc.php b/core/lexicon/en/setting.inc.php index 466fe9255d2..62fcaf60351 100644 --- a/core/lexicon/en/setting.inc.php +++ b/core/lexicon/en/setting.inc.php @@ -620,6 +620,12 @@ $_lang['setting_rb_base_url_desc'] = 'Enter the virtual path to resource directory. This setting is usually automatically generated. If you\'re using IIS, however, MODX may not be able to work the URL out on its own, causing the Resource Browser to show an error. In that case, you can enter the URL to the images directory here (the URL as you\'d enter it on Internet Explorer).'; $_lang['setting_rb_base_url_err'] = 'Please state the resource browser base URL.'; +$_lang['setting_quick_search_in_content'] = 'Allow search in content'; +$_lang['setting_quick_search_in_content_desc'] = 'If \'Yes\', then the content of the element (resource, template, chunk, etc.) will also be available for quick search.'; + +$_lang['setting_quick_search_result_max'] = 'Number of items in search result'; +$_lang['setting_quick_search_result_max_desc'] = 'Maximum number of elements for each type (resource, template, chunk, etc.) in the quick search result.'; + $_lang['setting_request_controller'] = 'Request Controller Filename'; $_lang['setting_request_controller_desc'] = 'The filename of the main request controller from which MODX is loaded. Most users can leave this as index.php.';