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()
This commit is contained in:
Ingo Schommer 2011-04-22 23:32:10 +12:00
parent be6f56ad3c
commit 09ad6dcaa6
4 changed files with 72 additions and 277 deletions

View File

@ -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();

View File

@ -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']);
}

View File

@ -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($('<select name="options" class="options"></select>')
.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(
'<option value="0">' +
ss.i18n._t('CMSMAIN.AddSearchCriteria') +
'</option>'
).appendTo(self.getSelectEl());
// populate dropdown values from existing fields
this.find('.field').not(':visible').each(function() {
$('<option />').appendTo(self.getSelectEl())
.val(this.id)
.text($(this).find('label').text());
});
},
/**
* Function: onsubmit
*
@ -89,10 +41,10 @@
data[el.name] = el.value;
});
// Disable checkbox tree controls that currently don't work with search.
// TODO Disable checkbox tree controls that currently don't work with search.
this.find('.checkboxAboveTree :checkbox').attr('disabled', 'disabled');
// disable buttons to avoid multiple submission
// TODO disable buttons to avoid multiple submission
//this.find(':submit').attr('disabled', true);
this.find(':submit[name=action_doSearchTree]').addClass('loading');
@ -109,40 +61,14 @@
* (Event) e
*/
_onreset: function(e) {
this.find('.field :input').clearFields();
this.find('.field').not('.show-default').hide();
// Enable checkbox tree controls
// TODO Enable checkbox tree controls
this.find('.checkboxAboveTree :checkbox').attr('disabled', 'false');
// reset all options, some of the might be removed
this._setOptions();
this._reloadSitetree();
return false;
},
/**
* Function: _addField
*
* Parameters:
* (Event) e
*/
_addField: function(e) {
var $select = $(e.target);
// show formfield matching the option
this.find('#' + $select.val()).show();
// remove option from dropdown, each field should just exist once
this.find('option[value=' + $select.val() + ']').remove();
// jump back to default entry
$select.val(0);
return false;
},
/**
* Function: _reloadSitetree
*/

View File

@ -1,5 +1,5 @@
<?php
class CMSMainSearchTreeFormTest extends FunctionalTest {
class CMSMainSearchFormTest extends FunctionalTest {
static $fixture_file = '../controller/CMSMainTest.yml';
@ -9,11 +9,11 @@ class CMSMainSearchTreeFormTest extends FunctionalTest {
$this->session()->inst_set('loggedInAs', $this->idFromFixture('Member', 'admin'));
$response = $this->get(
'admin/SearchTreeForm/?' .
'admin/SearchForm/?' .
http_build_query(array(
'Title' => 'Page 10',
'FilterClass' => 'CMSSiteTreeFilter_Search',
'action_doSearchTree' => true
'action_doSearch' => true
))
);