mirror of
https://github.com/silverstripe/silverstripe-reports
synced 2024-10-22 11:05:53 +02:00
ENHANCEMENT sitetree filters now show up in a dropdown, and you can add your own by extending CMSSiteTreeFilter
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@83674 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
07a61a19a5
commit
6a0f21ca05
@ -57,6 +57,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
||||
'SiteTreeAsUL',
|
||||
'getshowdeletedsubtree',
|
||||
'getfilteredsubtree',
|
||||
'getawesomesubtree',
|
||||
'batchactions'
|
||||
);
|
||||
|
||||
@ -152,31 +153,43 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
||||
|
||||
return $this->getSiteTreeFor("SiteTree");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a subtree underneath the request param 'ID', of the tree that includes deleted pages.
|
||||
* If ID = 0, then get the whole tree.
|
||||
* Use a CMSSiteTreeFilter to only get certain nodes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getshowdeletedsubtree() {
|
||||
// Get the tree
|
||||
$tree = $this->getSiteTreeFor($this->stat('tree_class'), $_REQUEST['ID'], "AllHistoricalChildren");
|
||||
|
||||
// Trim off the outer tag
|
||||
$tree = ereg_replace('^[ \t\r\n]*<ul[^>]*>','', $tree);
|
||||
$tree = ereg_replace('</ul[^>]*>[ \t\r\n]*$','', $tree);
|
||||
|
||||
return $tree;
|
||||
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');
|
||||
|
||||
// Do eeet!
|
||||
$filter = new $_REQUEST['filter']();
|
||||
return $filter->getTree();
|
||||
}
|
||||
|
||||
public function getfilteredsubtree() {
|
||||
// Get the tree
|
||||
$tree = $this->getSiteTreeFor($this->stat('tree_class'), $_REQUEST['ID'], null, array(new CMSMainMarkingFilter(), 'mark'));
|
||||
|
||||
// Trim off the outer tag
|
||||
$tree = ereg_replace('^[ \t\r\n]*<ul[^>]*>','', $tree);
|
||||
$tree = ereg_replace('</ul[^>]*>[ \t\r\n]*$','', $tree);
|
||||
|
||||
return $tree;
|
||||
/**
|
||||
* Returns a list of batch actions
|
||||
*/
|
||||
function SiteTreeFilters() {
|
||||
$filters = ClassInfo::subclassesFor('CMSSiteTreeFilter');
|
||||
array_shift($filters);
|
||||
$doSet = new DataObjectSet();
|
||||
$doSet->push(new ArrayData(array(
|
||||
'ClassName' => 'all',
|
||||
'Title' => 'All items'
|
||||
)));
|
||||
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'))
|
||||
)));
|
||||
}
|
||||
}
|
||||
return $doSet;
|
||||
}
|
||||
|
||||
/**
|
||||
|
136
code/CMSSiteTreeFilter.php
Normal file
136
code/CMSSiteTreeFilter.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/**
|
||||
* Base class for filtering the subtree for certain node statuses
|
||||
* @package cms
|
||||
* @subpackage content
|
||||
*/
|
||||
abstract class CMSSiteTreeFilter extends Object {
|
||||
abstract function getTree();
|
||||
static abstract function title();
|
||||
|
||||
static function showInList() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class CMSSiteTreeFilter_DeletedPages extends CMSSiteTreeFilter {
|
||||
static function title() {
|
||||
return "Deleted pages";
|
||||
}
|
||||
|
||||
function getTree() {
|
||||
$leftAndMain = new LeftAndMain();
|
||||
$tree = $leftAndMain->getSiteTreeFor('SiteTree', isset($_REQUEST['ID']) ? $_REQUEST['ID'] : 0, "AllHistoricalChildren");
|
||||
|
||||
// Trim off the outer tag
|
||||
$tree = ereg_replace('^[ \t\r\n]*<ul[^>]*>','', $tree);
|
||||
$tree = ereg_replace('</ul[^>]*>[ \t\r\n]*$','', $tree);
|
||||
|
||||
return $tree;
|
||||
}
|
||||
}
|
||||
|
||||
class CMSSiteTreeFilter_ChangedPages extends CMSSiteTreeFilter {
|
||||
static function title() {
|
||||
return "Changed pages";
|
||||
}
|
||||
|
||||
function getTree() {
|
||||
$search = new CMSSitetreeFilter_Search();
|
||||
$search->data = array('Status' => 'Saved');
|
||||
return $search->getTree();
|
||||
}
|
||||
}
|
||||
|
||||
class CMSSiteTreeFilter_Search extends CMSSiteTreeFilter {
|
||||
protected $ids = null;
|
||||
protected $expanded = array();
|
||||
public $data;
|
||||
|
||||
|
||||
function __construct() {
|
||||
$this->data = $_REQUEST;
|
||||
}
|
||||
|
||||
static function showInList() { return false; }
|
||||
|
||||
static function title() {
|
||||
return "Search";
|
||||
}
|
||||
|
||||
function populateIds($data) {
|
||||
$this->ids = array();
|
||||
$this->expanded = array();
|
||||
|
||||
$where = array();
|
||||
|
||||
// Match against URLSegment, Title, MenuTitle & Content
|
||||
if (isset($data['SiteTreeSearchTerm'])) {
|
||||
$term = Convert::raw2sql($data['SiteTreeSearchTerm']);
|
||||
$where[] = "\"URLSegment\" LIKE '%$term%' OR \"Title\" LIKE '%$term%' OR \"MenuTitle\" LIKE '%$term%' OR \"Content\" LIKE '%$term%'";
|
||||
}
|
||||
|
||||
// Match against date
|
||||
if (isset($data['SiteTreeFilterDate'])) {
|
||||
$date = $data['SiteTreeFilterDate'];
|
||||
$date = ((int)substr($date,6,4)) . '-' . ((int)substr($date,3,2)) . '-' . ((int)substr($date,0,2));
|
||||
$where[] = "\"LastEdited\" > '$date'";
|
||||
}
|
||||
|
||||
// Match against exact ClassName
|
||||
if (isset($data['ClassName']) && $data['ClassName'] != 'All') {
|
||||
$klass = Convert::raw2sql($data['ClassName']);
|
||||
$where[] = "\"ClassName\" = '$klass'";
|
||||
}
|
||||
|
||||
// Partial string match against a variety of fields
|
||||
foreach (CMSMain::T_SiteTreeFilterOptions() as $key => $value) {
|
||||
if (!empty($data[$key])) {
|
||||
$match = Convert::raw2sql($data[$key]);
|
||||
$where[] = "\"$key\" LIKE '%$match%'";
|
||||
}
|
||||
}
|
||||
|
||||
$where = empty($where) ? '' : 'WHERE (' . implode(') AND (',$where) . ')';
|
||||
|
||||
$parents = array();
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* We need to recurse up the tree, finding ParentIDs for each ID until we run out of parents */
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function includeInTree($page) {
|
||||
if ($this->ids === null) $this->populateIds($this->data);
|
||||
return isset($this->ids[$page->ID]) && $this->ids[$page->ID] ? true : false;
|
||||
}
|
||||
|
||||
function getTree() {
|
||||
$leftAndMain = new LeftAndMain();
|
||||
$tree = $leftAndMain->getSiteTreeFor('SiteTree', isset($_REQUEST['ID']) ? $_REQUEST['ID'] : 0, null, array($this, 'includeInTree'));
|
||||
|
||||
// Trim off the outer tag
|
||||
$tree = ereg_replace('^[ \t\r\n]*<ul[^>]*>','', $tree);
|
||||
$tree = ereg_replace('</ul[^>]*>[ \t\r\n]*$','', $tree);
|
||||
|
||||
return $tree;
|
||||
}
|
||||
}
|
@ -286,6 +286,7 @@ class LeftAndMain extends Controller {
|
||||
'cms/javascript/Upload.js',
|
||||
'sapphire/javascript/TreeSelectorField.js',
|
||||
'cms/javascript/ThumbnailStripField.js',
|
||||
'cms/javascript/FilterSiteTree.js',
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -118,18 +118,16 @@ searchclass.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show deleted pages checkbox
|
||||
*/
|
||||
ShowDeletedPagesAction = Class.create();
|
||||
ShowDeletedPagesAction.applyTo('#showdeletedpages');
|
||||
ShowDeletedPagesAction.prototype = {
|
||||
SiteTreeFilter = Class.create();
|
||||
SiteTreeFilter.applyTo('#siteTreeFilterList');
|
||||
SiteTreeFilter.prototype = {
|
||||
initialize: function () {
|
||||
},
|
||||
|
||||
onclick : function() {
|
||||
if(this.checked) {
|
||||
$('sitetree').setCustomURL(SiteTreeHandlers.controller_url+'/getshowdeletedsubtree');
|
||||
onchange : function() {
|
||||
var value = this.options[this.selectedIndex].value;
|
||||
|
||||
if(value != 'all') {
|
||||
$('sitetree').setCustomURL(SiteTreeHandlers.controller_url+'/getfilteredsubtree?filter='+escape(value));
|
||||
} else {
|
||||
$('sitetree').clearCustomURL();
|
||||
}
|
||||
@ -140,14 +138,14 @@ ShowDeletedPagesAction.prototype = {
|
||||
$('sitetree').stopBeingDraggable();
|
||||
__makeDraggableAfterUpdate = true;
|
||||
}
|
||||
|
||||
var indicator = $('checkboxActionIndicator');
|
||||
indicator.style.display = 'block';
|
||||
|
||||
|
||||
var indicator = $('siteTreeFilterActionIndicator');
|
||||
indicator.style.display = 'inline';
|
||||
|
||||
$('sitetree').reload({
|
||||
onSuccess: function() {
|
||||
if(__makeDraggableAfterUpdate) $('sitetree').makeDraggable();
|
||||
indicator.style.display = 'none';
|
||||
if(__makeDraggableAfterUpdate) $('sitetree').makeDraggable();
|
||||
},
|
||||
onFailure: function(response) {
|
||||
errorMessage('Could not update tree', response);
|
||||
@ -155,34 +153,6 @@ ShowDeletedPagesAction.prototype = {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show only drafts checkbox click action
|
||||
*/
|
||||
showonlydrafts = Class.create();
|
||||
showonlydrafts.applyTo('#publishpage_show_drafts');
|
||||
showonlydrafts.prototype = {
|
||||
onclick : function() {
|
||||
if(this.checked) {
|
||||
$('sitetree').setCustomURL(SiteTreeHandlers.controller_url+'/getfilteredsubtree', {Status:'Saved'});
|
||||
} else {
|
||||
$('sitetree').clearCustomURL();
|
||||
}
|
||||
|
||||
$('sitetree').reload({
|
||||
onSuccess: function() {
|
||||
statusMessage(ss.i18n._t('CMSMAIN.FILTEREDTREE'),'good');
|
||||
},
|
||||
onFailure: function(response) {
|
||||
errorMessage(ss.i18n.sprintf(
|
||||
ss.i18n._t('CMSMAIN.ERRORFILTERPAGES'),
|
||||
response.responseText
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Control the site tree filter
|
||||
*/
|
||||
|
@ -81,20 +81,19 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="checkboxAboveTree" style="border-bottom:none">
|
||||
Show: <select id="siteTreeFilterList">
|
||||
<% control SiteTreeFilters %>
|
||||
<option value="$ClassName">$Title</option>
|
||||
<% end_control %>
|
||||
</select> <img id="siteTreeFilterActionIndicator" style="display:none" src="cms/images/network-save.gif">
|
||||
</div>
|
||||
<div class="checkboxAboveTree">
|
||||
<img id="checkboxActionIndicator" src="cms/images/network-save.gif">
|
||||
<div>
|
||||
<input type="checkbox" id="sortitems" />
|
||||
<label for="sortitems"><% _t('ENABLEDRAGGING','Allow drag & drop reordering', PR_HIGH) %></label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" id="publishpage_show_drafts" />
|
||||
<label for="publishpage_show_drafts"><% _t('SHOWONLYCHANGED','Show only changed pages') %></label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" id="showdeletedpages" />
|
||||
<label for="showdeletedpages"><% _t('SHOW_DELETED_PAGES','Show deleted pages', PR_HIGH) %></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if IsTranslatableEnabled %>
|
||||
|
Loading…
Reference in New Issue
Block a user