API-CHANGE: SSF-168 initial rearranging the SS_Report class for use in SS3. Deprecating unnecessary methods, moving code around, rewriting get_reports method and writing unit tests

This commit is contained in:
Julian Seidenberg 2012-04-03 18:06:35 +12:00
parent fe2805834a
commit ee220bbcce
2 changed files with 108 additions and 115 deletions

View File

@ -35,19 +35,13 @@
* Showing reports to the user
* ===========================
*
* Right now, all subclasses of SS_Report will be shown in the ReportAdmin. However, we are planning
* on adding an explicit registration mechanism, so that you can decide which reports go in the
* report admin, and which go elsewhere (such as the side panel in the CMS).
* Right now, all subclasses of SS_Report will be shown in the ReportAdmin. In SS3 there is only
* one place where reports can go, so this class is greatly simplifed from from its version in SS2.
*
* @package cms
* @subpackage reports
*/
class SS_Report extends ViewableData {
/**
* Report registry populated by {@link SS_Report::register()}
*/
private static $registered_reports = array();
/**
* This is the title of the report,
* used by the ReportAdmin templates.
@ -70,6 +64,22 @@ class SS_Report extends ViewableData {
* Set by overriding in your subclass.
*/
protected $dataClass = 'SiteTree';
/**
* A field that specifies the sort order of this report
* @var int
*/
protected $sort = 0;
/**
* Reports which should not be collected and returned in get_reports
* @var array
*/
public static $excluded_reports = array(
'SS_Report',
'SS_ReportWrapper',
'SideReportWrapper'
);
/**
* Return the title of this report.
@ -93,22 +103,12 @@ class SS_Report extends ViewableData {
return $this->description;
}
/**
* Return a FieldList specifying the search criteria for this report.
*
* Override this method to define search criteria.
*/
function parameterFields() {
return null;
}
/**
* Return the {@link SQLQuery} that provides your report data.
*/
function sourceQuery($params) {
if($this->hasMethod('sourceRecords')) {
$query = new SS_Report_FakeQuery($this, 'sourceRecords', $params);
$query->setSortColumnMethod('sortColumns');
return $query;
} else {
user_error("Please override sourceQuery()/sourceRecords() and columns() or, if necessary, override getReportField()", E_USER_ERROR);
@ -126,29 +126,7 @@ class SS_Report extends ViewableData {
}
}
/**
* Return an map of columns for your report.
* - The map keys will be the source columns for your report (in TableListField dot syntax)
* - The values can either be a string (the column title), or a map containing the following
* column parameters:
* - title: The column title
* - formatting: A formatting string passed to {@link TableListField::setFieldFormatting()}
*/
function columns() {
user_error("Please override sourceQuery() and columns() or, if necessary, override getReportField()", E_USER_ERROR);
}
function sortColumns() {
return array_keys($this->columns());
}
/**
* Return the number of records in this report with no filters applied.
*/
function count() {
return (int)$this->sourceQuery(array())->unlimitedRowCount();
}
/**
* Return the data class for this report
*/
@ -157,6 +135,67 @@ class SS_Report extends ViewableData {
}
/**
* @deprecated 3.0
* All subclasses of SS_Report now appear in the report admin, no need to register or unregister.
*
* Register a report.
* @param $list The list to add the report to: "ReportAdmin" or "SideReports"
* @param $reportClass The class of the report to add.
* @param $priority The priority. Higher numbers will appear furhter up in the reports list.
* The default value is zero.
*/
static function register($list, $reportClass, $priority = 0) {
}
/**
* @deprecated 3.0
* All subclasses of SS_Report now appear in the report admin, no need to register or unregister.
*/
static function unregister($list, $reportClass) {
self::excludeReport($reportClass);
}
/**
* Exclude a certain report class from the list of Reports in the CMS
* @static
* @param $reportClass
*/
static function excludeReport($reportClass) {
self::$excluded_reports[] = $reportClass; //add to the excluded reports, so this report doesn't get used
}
/**
* Return the SS_Report objects making up the given list.
* @return An array of SS_Report objects
*/
static function get_reports() {
$reports = ClassInfo::subclassesFor(get_called_class());
$reportsArray = array();
if ($reports && count($reports) > 0) {
//collect reports into array with an attribute for 'sort'
foreach($reports as $report) {
if (in_array($report, self::$excluded_reports)) continue; //don't use the SS_Report superclass
$reportObj = new $report;
if (method_exists($reportObj,'sort')) $reportObj->sort = $reportObj->sort(); //use the sort method to specify the sort field
$reportsArray[] = $reportObj;
}
}
//convert array into ArrayList
$list = ArrayList::create($reportsArray);
//sort
$list->sort('sort');
return $list;
}
/////////////////////// UI METHODS ///////////////////////
/**
* Returns a FieldList with which to create the CMS editing form.
* You can use the extend() method of FieldList to create customised forms for your other
@ -273,72 +312,10 @@ class SS_Report extends ViewableData {
* @return string
*/
function TreeTitle() {
return $this->title();/* . ' (' . $this->count() . ')'; - this is too slow atm */
return $this->title();
}
/**
* Return the ID of this Report class.
* Because it doesn't have a number, we
* use the class name as the ID.
*
* @return string
*/
function ID() {
return $this->class;
}
/////////////////////////////////////////////////////////////////////////////////////////////
/**
* Register a report.
* @param $list The list to add the report to: "ReportAdmin" or "SideReports"
* @param $reportClass The class of the report to add.
* @param $priority The priority. Higher numbers will appear furhter up in the reports list.
* The default value is zero.
*/
static function register($list, $reportClass, $priority = 0) {
if(strpos($reportClass, '(') === false && (!class_exists($reportClass) || !is_subclass_of($reportClass,'SS_Report'))) {
user_error("SS_Report::register(): '$reportClass' is not a subclass of SS_Report", E_USER_WARNING);
return;
}
self::$registered_reports[$list][$reportClass] = $priority;
}
/**
* Unregister a report, removing it from the list
*/
static function unregister($list, $reportClass) {
unset(self::$registered_reports[$list][$reportClass]);
}
/**
* Return the SS_Report objects making up the given list.
* @return An array of SS_Report objects
*/
static function get_reports($list) {
$output = array();
if(isset(self::$registered_reports[$list])) {
$listItems = self::$registered_reports[$list];
// Sort by priority, preserving internal order of items with the same priority
$groupedItems = array();
foreach($listItems as $k => $v) {
$groupedItems[$v][] = $k;
}
krsort($groupedItems);
$sortedListItems = call_user_func_array('array_merge', $groupedItems);
foreach($sortedListItems as $report) {
if(strpos($report,'(') === false) $reportObj = new $report;
else $reportObj = eval("return new $report;");
$output[$reportObj->ID()] = $reportObj;
}
}
return $output;
}
}
@ -370,7 +347,7 @@ class SS_Report_FakeQuery extends SQLQuery {
$this->method = $method;
$this->params = $params;
}
/**
* Provide a method that will return a list of columns that can be used to sort.
*/

View File

@ -1,18 +1,34 @@
<?php
class ReportTest extends SapphireTest {
function testCanSortBy() {
$report = new SSReportTest_FakeTest();
$this->assertTrue($report->sourceQuery(array())->canSortBy('Title ASC'));
$this->assertTrue($report->sourceQuery(array())->canSortBy('Title DESC'));
$this->assertTrue($report->sourceQuery(array())->canSortBy('Title'));
}
function testGetReports() {
$reports = SS_Report::get_reports();
$this->assertNotNull($reports, "Reports returned");
Debug::Show($reports);
$previousSort = 0;
foreach($reports as $report) {
$this->assertGreaterThanOrEqual($previousSort, $report->sort, "Reports are in correct sort order");
$previousSort = $report->sort;
}
}
function testExcludeReport() {
$reports = SS_Report::get_reports();
$reportNames = array();
foreach($reports as $report) {
$reportNames[] = $report->class;
}
$this->assertContains('ReportTest_FakeTest',$reportNames,'ReportTest_FakeTest is in reports list');
//excluse one report
SS_Report::excludeReport('ReportTest_FakeTest');
$reports = SS_Report::get_reports();
$reportNames = array();
foreach($reports as $report) {
$reportNames[] = $report->class;
}
$this->assertNotContains('ReportTest_FakeTest',$reportNames,'ReportTest_FakeTest is NOT in reports list');
}
}
@ -39,12 +55,12 @@ class ReportTest_FakeTest extends SS_Report implements TestOnly {
class ReportTest_FakeTest2 extends SS_Report implements TestOnly {
function title() {
return 'Report title';
return 'Report title 2';
}
function columns() {
return array(
"Title" => array(
"title" => "Page Title"
"title" => "Page Title 2"
)
);
}