mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
ENHANCEMENT: Significant speed up for SiteTree Filter
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/branches/2.3@76944 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
ddbf2e2e99
commit
f27e284f5f
115
code/CMSMain.php
115
code/CMSMain.php
@ -183,7 +183,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
public function getfilteredsubtree() {
|
public function getfilteredsubtree() {
|
||||||
// Get the tree
|
// Get the tree
|
||||||
$tree = $this->getSiteTreeFor($this->stat('tree_class'), $_REQUEST['ID'], null, 'cmsMainMarkingFilterFunction');
|
$tree = $this->getSiteTreeFor($this->stat('tree_class'), $_REQUEST['ID'], null, array(new CMSMainMarkingFilter(), 'mark'));
|
||||||
|
|
||||||
// Trim off the outer tag
|
// Trim off the outer tag
|
||||||
$tree = ereg_replace('^[ \t\r\n]*<ul[^>]*>','', $tree);
|
$tree = ereg_replace('^[ \t\r\n]*<ul[^>]*>','', $tree);
|
||||||
@ -1220,75 +1220,72 @@ JS;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$filterCache = array();
|
class CMSMainMarkingFilter {
|
||||||
|
|
||||||
// TODO: Find way to put this in a class
|
function __construct() {
|
||||||
function cmsMainMarkingFilterFunction($node) {
|
$this->ids = array();
|
||||||
global $filterCache;
|
$this->expanded = array();
|
||||||
// Expand all nodes
|
|
||||||
// $node->markingFinished();
|
|
||||||
|
|
||||||
$failed_filter = false;
|
$where = array();
|
||||||
// First check for the generic search term in the URLSegment, Title, MenuTitle, & Content
|
|
||||||
if (!empty($_REQUEST['SiteTreeSearchTerm'])) {
|
// Match against URLSegment, Title, MenuTitle & Content
|
||||||
// For childless nodes, show only those matching the filter
|
if (isset($_REQUEST['SiteTreeSearchTerm'])) {
|
||||||
$filter = strtolower($_REQUEST['SiteTreeSearchTerm']);
|
$term = Convert::raw2sql($_REQUEST['SiteTreeSearchTerm']);
|
||||||
if ( strpos( strtolower($node->URLSegment) , $filter) === false
|
$where[] = "`URLSegment` LIKE '%$term%' OR `Title` LIKE '%$term%' OR `MenuTitle` LIKE '%$term%' OR `Content` LIKE '%$term%'";
|
||||||
&& strpos( strtolower($node->Title) , $filter) === false
|
|
||||||
&& strpos( strtolower($node->MenuTitle) , $filter) === false
|
|
||||||
&& strpos( strtolower($node->Content) , $filter) === false) {
|
|
||||||
$failed_filter = true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Check the 'Edited Since' date
|
|
||||||
if (!empty($_REQUEST['SiteTreeFilterDate'])) {
|
|
||||||
$edited_since = mktime(0, 0, 0, substr($_REQUEST['SiteTreeFilterDate'], 3, 2),
|
|
||||||
substr($_REQUEST['SiteTreeFilterDate'], 0, 2), substr($_REQUEST['SiteTreeFilterDate'], 6, 4));
|
|
||||||
if ( strtotime($node->LastEdited) < $edited_since ) {
|
|
||||||
$failed_filter = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check the ClassName
|
|
||||||
if (!empty($_REQUEST['ClassName']) && $_REQUEST['ClassName'] != 'Any') {
|
|
||||||
if ($node->ClassName != $_REQUEST['ClassName']) $failed_filter = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now check if a specified Criteria attribute matches
|
// Match against date
|
||||||
foreach (CMSMain::T_SiteTreeFilterOptions() as $key => $value)
|
if (isset($_REQUEST['SiteTreeFilterDate'])) {
|
||||||
{
|
$date = $_REQUEST['SiteTreeFilterDate'];
|
||||||
if (!empty($_REQUEST[$key])) {
|
$date = ((int)substr($date,6,4)) . '-' . ((int)substr($date,3,2)) . '-' . ((int)substr($date,0,2));
|
||||||
$parameterName = $key;
|
$where[] = "`LastEdited` > '$date'";
|
||||||
$filter = strtolower($_REQUEST[$key]);
|
|
||||||
// Show node only if the filter string exists anywere in the filter paramater (ignoring case)
|
|
||||||
if (strpos( strtolower($node->$parameterName) , $filter) === false) {
|
|
||||||
$failed_filter = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Each filter must match or it fails
|
|
||||||
if (true == $failed_filter) {
|
|
||||||
// Don't ever hide nodes with children, because otherwise if one of their children matches the search, it wouldn't be shown.
|
|
||||||
if($node->AllChildrenIncludingDeleted()->count() > 0) {
|
|
||||||
// Open all nodes with children so it is easy to see any children that match the search.
|
|
||||||
|
|
||||||
foreach($node->AllChildrenIncludingDeleted() as $childNode) {
|
// Match against exact ClassName
|
||||||
if(cmsMainMarkingFilterFunction($childNode)) {
|
if (isset($_REQUEST['ClassName']) && $_REQUEST['ClassName'] != 'All') {
|
||||||
$node->markOpened();
|
$klass = Convert::raw2sql($_REQUEST['ClassName']);
|
||||||
$filterCache[$node->ID] = true;
|
$where[] = "`ClassName` = '$klass'";
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
// 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%'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$filterCache[$node->ID] = false;
|
$where = empty($where) ? '' : 'WHERE (' . implode(') AND (',$where) . ')';
|
||||||
return false;
|
|
||||||
} else {
|
$parents = array();
|
||||||
if($node->AllChildrenIncludingDeleted()->count() > 0) {
|
|
||||||
$node->markOpened();
|
/* Do the actual search */
|
||||||
|
$res = DB::query('SELECT `ParentID`, `ID` FROM SiteTree '.$where);
|
||||||
|
if (!$res) return;
|
||||||
|
|
||||||
|
/* And keep a record of parents we don't need to get parents of themselves, as well as IDs to mark */
|
||||||
|
foreach($res as $row) {
|
||||||
|
if ($row['ParentID']) $parents[$row['ParentID']] = true;
|
||||||
|
$this->ids[$row['ID']] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$filterCache[$node->ID] = true;
|
/* We need to recurse up the tree, finding ParentIDs for each ID until we run out of parents */
|
||||||
return true;
|
while (!empty($parents)) {
|
||||||
|
$res = DB::query('SELECT `ParentID`, `ID` FROM SiteTree WHERE `ID` in ('.implode(',',array_keys($parents)).')');
|
||||||
|
$parents = array();
|
||||||
|
|
||||||
|
foreach($res as $row) {
|
||||||
|
if ($row['ParentID']) $parents[$row['ParentID']] = true;
|
||||||
|
$this->ids[$row['ID']] = true;
|
||||||
|
$this->expanded[$row['ID']] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mark($node) {
|
||||||
|
$id = $node->ID;
|
||||||
|
if (array_key_exists($id, $this->expanded)) $node->markOpened();
|
||||||
|
return array_key_exists($id, $this->ids) ? $this->ids[$id] : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user