From 09ad6dcaa69b795e08402f937bf73b1c85d0abe8 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Fri, 22 Apr 2011 23:32:10 +1200 Subject: [PATCH] ENHANCEMENT Showing full CMS search form (instead of toggling fields individually), removing metadata search fields (limiting to fields applicable in new designs) API CHANGE Renamed CMSMain->SearchTreeForm() to SearchForm(), CMSMain->doSearchTree() to doSearch() (search can be used for list and gallery views as well) API CHANGE Removed CMSMain->SiteTreeFilterOptions() and CMSMain::$site_tree_filter_options, moved to CMSMain->SearchForm() --- code/controller/CMSMain.php | 244 ++++++------------------- code/controller/CMSSiteTreeFilter.php | 15 +- javascript/CMSMain.js | 84 +-------- tests/search/CMSMainSearchFormTest.php | 6 +- 4 files changed, 72 insertions(+), 277 deletions(-) diff --git a/code/controller/CMSMain.php b/code/controller/CMSMain.php index 0018acd2..166622f9 100755 --- a/code/controller/CMSMain.php +++ b/code/controller/CMSMain.php @@ -47,35 +47,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr 'VersionsForm', 'EditForm', 'AddForm', - 'SearchTreeForm', + 'SearchForm', 'SiteTreeAsUL', 'getshowdeletedsubtree', 'getfilteredsubtree', 'batchactions', ); - /** - * SiteTree Columns that can be filtered using the the Site Tree Search button - */ - static $site_tree_filter_options = array( - 'Title' => array('CMSMain.TITLE', 'Title'), - 'MenuTitle' => array('CMSMain.MENUTITLE', 'Navigation Label'), - 'ClassName' => array('CMSMain.PAGETYPE', 'Page Type'), - 'Status' => array('CMSMain.STATUS', 'Status'), - 'MetaDescription' => array('CMSMain.METADESC', 'Description'), - 'MetaKeywords' => array('CMSMain.METAKEYWORDS', 'Keywords') - ); - - static function T_SiteTreeFilterOptions(){ - return array( - 'Title' => _t('CMSMain.TITLEOPT', 'Title', 0, 'The dropdown title in CMSMain left SiteTreeFilterOptions'), - 'MenuTitle' => _t('CMSMain.MENUTITLEOPT', 'Navigation Label', 0, 'The dropdown title in CMSMain left SiteTreeFilterOptions'), - 'Status' => _t('CMSMain.STATUSOPT', 'Status', 0, "The dropdown title in CMSMain left SiteTreeFilterOptions"), - 'MetaDescription' => _t('CMSMain.METADESCOPT', 'Description', 0, "The dropdown title in CMSMain left SiteTreeFilterOptions"), - 'MetaKeywords' => _t('CMSMain.METAKEYWORDSOPT', 'Keywords', 0, "The dropdown title in CMSMain left SiteTreeFilterOptions") - ); - } - public function init() { // set reading lang if(Object::has_extension('SiteTree', 'Translatable') && !$this->isAjax()) { @@ -159,75 +137,66 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr return $this->getSiteTreeFor($this->stat('tree_class')); } - /** - * Use a CMSSiteTreeFilter to only get certain nodes - * - * @return string - */ - public function getfilteredsubtree() { - // Sanity and security checks - if (!isset($_REQUEST['filter'])) die('No filter passed'); - if (!ClassInfo::exists($_REQUEST['filter'])) die ('That filter class does not exist'); - if (!is_subclass_of($_REQUEST['filter'], 'CMSSiteTreeFilter')) die ('That is not a valid filter'); + function SearchForm() { + // get all page types in a dropdown-compatible format + $pageTypes = SiteTree::page_type_classes(); + array_unshift($pageTypes, 'All'); + $pageTypes = array_combine($pageTypes, $pageTypes); + asort($pageTypes); - // Do eeet! - $filter = new $_REQUEST['filter'](); - return $filter->getTree(); - } - - /** - * Returns a list of batch actions - */ - function SiteTreeFilters() { + // get all filter instances $filters = ClassInfo::subclassesFor('CMSSiteTreeFilter'); + $filterMap = array(); + // remove base class array_shift($filters); - $doSet = new DataObjectSet(); - $doSet->push(new ArrayData(array( - 'ClassName' => 'all', - 'Title' => _t('CMSSiteTreeFilter.ALL', 'All items') - ))); + // add filters to map foreach($filters as $filter) { - if (call_user_func(array($filter, 'showInList'))) { - $doSet->push(new ArrayData(array( - 'ClassName' => $filter, - 'Title' => call_user_func(array($filter, 'title')) - ))); - } + $filterMap[$filter] = call_user_func(array($filter, 'title')); } - return $doSet; + // ensure that 'all pages' filter is on top position + uasort($filterMap, + create_function('$a,$b', 'return ($a == "CMSSiteTreeFilter_Search") ? 1 : -1;') + ); + + $fields = new FieldSet( + new TextField('Term', _t('CMSSearch.FILTERLABELTEXT', 'Content')), + $dateFrom = new DateField('LastEditedFrom', _t('CMSSearch.FilterDateFrom', 'from')), + $dateTo = new DateField('LastEditedTo', _t('CMSSearch.FilterDateFrom', 'to')), + new DropdownField( + 'FilterClass', + _t('CMSMain.SearchTreeFormPagesDropdown', 'Pages'), + $filterMap + ), + new DropdownField( + 'ClassName', + _t('CMSMain.PAGETYPEOPT','Page Type', PR_MEDIUM, 'Dropdown for limiting search to a page type'), + $pageTypes, + null, + null, + _t('CMSMain.PAGETYPEANYOPT','Any') + ) + // new TextField('MetaTags', _t('CMSMain.SearchMetaTags', 'Meta tags')) + ); + $dateFrom->setConfig('showcalendar', true); + $dateTo->setConfig('showcalendar', true); + + $actions = new FieldSet( + $resetAction = new ResetFormAction('clear', _t('CMSMain_left.ss.CLEAR', 'Clear')), + $searchAction = new FormAction('doSearch', _t('CMSMain_left.ss.SEARCH', 'Search')) + ); + $resetAction->addExtraClass('ss-ui-action-minor'); + + $form = new Form($this, 'SearchForm', $fields, $actions); + $form->setFormMethod('GET'); + $form->disableSecurityToken(); + $form->unsetValidator(); + + return $form; } - /** - * Returns the SiteTree columns that can be filtered using the the Site Tree Search button as a DataObjectSet - */ - public function SiteTreeFilterOptions() { - $filter_options = new DataObjectSet(); - foreach(self::T_SiteTreeFilterOptions() as $key => $value) { - $record = array( - 'Column' => $key, - 'Title' => $value, - ); - $filter_options->push(new ArrayData($record)); - } - return $filter_options; + function doSearch($data, $form) { + return $this->getsubtree($this->request); } - public function SiteTreeFilterDateField() { - $dateField = new DateField('SiteTreeFilterDate'); - - // TODO Enabling this means we load jQuery UI by default in the CMS, - // which is a pretty big performance hit in 2.4 (where the library isn't used for other parts - // of the interface). - // $dateField->setConfig('showcalendar', true); - - return $dateField->Field(); - } - public function SiteTreeFilterPageTypeField() { - $types = SiteTree::page_type_classes(); array_unshift($types, 'All'); - $source = array_combine($types, $types); - asort($source); - $optionsetField = new DropdownField('ClassName', 'ClassName', $source, 'Any'); - return $optionsetField->Field(); - } public function generateDataTreeHints() { $classes = ClassInfo::subclassesFor( $this->stat('tree_class') ); @@ -1304,98 +1273,7 @@ JS; return $form; } - - /** - * Form used to filter the sitetree. It can only be used via javascript for now. - * - * @return Form - */ - function SearchTreeForm() { - // get all page types in a dropdown-compatible format - $pageTypes = SiteTree::page_type_classes(); - array_unshift($pageTypes, 'All'); - $pageTypes = array_combine($pageTypes, $pageTypes); - asort($pageTypes); - - // get all filter instances - $filters = ClassInfo::subclassesFor('CMSSiteTreeFilter'); - $filterMap = array(); - // remove base class - array_shift($filters); - // add filters to map - foreach($filters as $filter) { - $filterMap[$filter] = call_user_func(array($filter, 'title')); - } - // ensure that 'all pages' filter is on top position - uasort($filterMap, - create_function('$a,$b', 'return ($a == "CMSSiteTreeFilter_Search") ? 1 : -1;') - ); - - $showDefaultFields = array(); - $form = new Form( - $this, - 'SearchTreeForm', - new FieldSet( - $showDefaultFields[] = new DropdownField( - 'FilterClass', - _t('CMSMain.SearchTreeFormPagesDropdown', 'Pages'), - $filterMap - ), - $showDefaultFields[] = new TextField( - 'Title', - _t('CMSMain.TITLEOPT', 'Title') - ), - new TextField('Content', _t('CMSMain.TEXTOPT','Text', PR_MEDIUM, 'Text field for fulltext search in page content')), - new DateField('EditedSince', _t('CMSMain_left.ss.EDITEDSINCE','Edited Since')), - new DropdownField( - 'ClassName', - _t('CMSMain.PAGETYPEOPT','Page Type', PR_MEDIUM, 'Dropdown for limiting search to a page type'), - $pageTypes, - null, - null, - _t('CMSMain.PAGETYPEANYOPT','Any') - ), - new TextField( - 'MenuTitle', - _t('CMSMain.MENUTITLEOPT', 'Navigation Label') - ), - new TextField( - 'Status', - _t('CMSMain.STATUSOPT', 'Status') - ), - new TextField( - 'MetaDescription', - _t('CMSMain.METADESCOPT', 'Description') - ), - new TextField( - 'MetaKeywords', - _t('CMSMain.METAKEYWORDSOPT', 'Keywords') - ) - ), - new FieldSet( - new ResetFormAction( - 'clear', - _t('CMSMain_left.ss.CLEAR', 'Clear') - ), - new FormAction( - 'doSearchTree', - _t('CMSMain_left.ss.SEARCH', 'Search') - ) - ) - ); - $form->setFormMethod('GET'); - $form->disableSecurityToken(); - $form->unsetValidator(); - - foreach($showDefaultFields as $f) $f->addExtraClass('show-default'); - - return $form; - } - function doSearchTree($data, $form) { - return $this->getsubtree($this->request); - } - /** * Helper function to get page count */ @@ -1626,14 +1504,14 @@ class CMSMainMarkingFilter { $where = array(); // Match against URLSegment, Title, MenuTitle & Content - if (isset($_REQUEST['SiteTreeSearchTerm'])) { - $term = Convert::raw2sql($_REQUEST['SiteTreeSearchTerm']); + if (isset($_REQUEST['Term'])) { + $term = Convert::raw2sql($_REQUEST['Term']); $where[] = "\"URLSegment\" LIKE '%$term%' OR \"Title\" LIKE '%$term%' OR \"MenuTitle\" LIKE '%$term%' OR \"Content\" LIKE '%$term%'"; } // Match against date - if (isset($_REQUEST['SiteTreeFilterDate'])) { - $date = $_REQUEST['SiteTreeFilterDate']; + if (isset($_REQUEST['LastEdited'])) { + $date = $_REQUEST['LastEdited']; $date = ((int)substr($date,6,4)) . '-' . ((int)substr($date,3,2)) . '-' . ((int)substr($date,0,2)); $where[] = "\"LastEdited\" > '$date'"; } @@ -1644,14 +1522,6 @@ class CMSMainMarkingFilter { $where[] = "\"ClassName\" = '$klass'"; } - // Partial string match against a variety of fields - foreach (CMSMain::T_SiteTreeFilterOptions() as $key => $value) { - if (!empty($_REQUEST[$key])) { - $match = Convert::raw2sql($_REQUEST[$key]); - $where[] = "\"$key\" LIKE '%$match%'"; - } - } - $where = empty($where) ? '' : 'WHERE (' . implode(') AND (',$where) . ')'; $parents = array(); diff --git a/code/controller/CMSSiteTreeFilter.php b/code/controller/CMSSiteTreeFilter.php index 1a77357b..d6c6bfaf 100644 --- a/code/controller/CMSSiteTreeFilter.php +++ b/code/controller/CMSSiteTreeFilter.php @@ -184,16 +184,15 @@ class CMSSiteTreeFilter_Search extends CMSSiteTreeFilter { foreach($SQL_params as $name => $val) { switch($name) { // Match against URLSegment, Title, MenuTitle & Content - case 'SiteTreeSearchTerm': + case 'Term': $where[] = "\"URLSegment\" LIKE '%$val%' OR \"Title\" LIKE '%$val%' OR \"MenuTitle\" LIKE '%$val%' OR \"Content\" LIKE '%$val%'"; break; // Match against date - case 'SiteTreeFilterDate': - // TODO Date Parsing - $val = ((int)substr($val,6,4)) - . '-' . ((int)substr($val,3,2)) - . '-' . ((int)substr($val,0,2)); - $where[] = "\"LastEdited\" > '$val'"; + case 'LastEditedFrom': + if($val) $where[] = "\"LastEdited\" >= '$val'"; + break; + case 'LastEditedTo': + if($val) $where[] = "\"LastEdited\" <= '$val'"; break; // Match against exact ClassName case 'ClassName': @@ -209,7 +208,7 @@ class CMSSiteTreeFilter_Search extends CMSSiteTreeFilter { } } $q->where(empty($where) ? '' : '(' . implode(') AND (',$where) . ')'); - + foreach($q->execute() as $row) { $ids[] = array('ID'=>$row['ID'],'ParentID'=>$row['ParentID']); } diff --git a/javascript/CMSMain.js b/javascript/CMSMain.js index 921067e0..77c5c3e5 100644 --- a/javascript/CMSMain.js +++ b/javascript/CMSMain.js @@ -5,18 +5,13 @@ $.entwine('ss', function($){ /** - * Class: #Form_SearchTreeForm + * Class: #Form_SearchForm * * Control the site tree filter. * Toggles search form fields based on a dropdown selection, * similar to "Smart Search" criteria in iTunes. */ - $('#Form_SearchTreeForm').entwine({ - /** - * Variable: SelectEl - * {DOMElement} - */ - SelectEl: null, + $('#Form_SearchForm').entwine({ /** * Constructor: onmatch @@ -24,24 +19,6 @@ onmatch: function() { var self = this; - // only the first field should be visible by default - this.find('.field').not('.show-default').hide(); - - // generate the field dropdown - this.setSelectEl($('') - .appendTo(this.find('fieldset:first')) - .bind('change', function(e) {self._addField(e);}) - ); - - this._setOptions(); - - // special case: we can't use CMSSiteTreeFilter together with other options - this.find('select[name=FilterClass]').change(function(e) { - var others = self.find('.field').not($(this).parents('.field')).find(':input,select'); - if(e.target.value == 'CMSSiteTreeFilter_Search') others.removeAttr('disabled'); - else others.attr('disabled','disabled'); - }); - // Reset binding through entwine doesn't work in IE this.bind('reset', function(e) { self._onreset(e); @@ -50,31 +27,6 @@ this._super(); }, - /** - * Function: _setOptions - */ - _setOptions: function() { - var self = this; - - // reset existing elements - self.getSelectEl().find('option').remove(); - - // add default option - // TODO i18n - jQuery( - '' - ).appendTo(self.getSelectEl()); - - // populate dropdown values from existing fields - this.find('.field').not(':visible').each(function() { - $('