Skip to content

Commit

Permalink
API-CHANGE: SSF-168 initial rearranging the SS_Report class for use i…
Browse files Browse the repository at this point in the history
…n SS3. Deprecating unnecessary methods, moving code around, rewriting get_reports method and writing unit tests
  • Loading branch information
Julian Seidenberg committed Apr 3, 2012
1 parent fe28058 commit ee220bb
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 111 deletions.
179 changes: 78 additions & 101 deletions code/reports/Report.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -35,19 +35,13 @@
* Showing reports to the user * Showing reports to the user
* =========================== * ===========================
* *
* Right now, all subclasses of SS_Report will be shown in the ReportAdmin. However, we are planning * Right now, all subclasses of SS_Report will be shown in the ReportAdmin. In SS3 there is only
* on adding an explicit registration mechanism, so that you can decide which reports go in the * one place where reports can go, so this class is greatly simplifed from from its version in SS2.
* report admin, and which go elsewhere (such as the side panel in the CMS).
* *
* @package cms * @package cms
* @subpackage reports * @subpackage reports
*/ */
class SS_Report extends ViewableData { 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, * This is the title of the report,
* used by the ReportAdmin templates. * used by the ReportAdmin templates.
Expand All @@ -70,6 +64,22 @@ class SS_Report extends ViewableData {
* Set by overriding in your subclass. * Set by overriding in your subclass.
*/ */
protected $dataClass = 'SiteTree'; 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. * Return the title of this report.
Expand All @@ -93,22 +103,12 @@ function description() {
return $this->description; 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. * Return the {@link SQLQuery} that provides your report data.
*/ */
function sourceQuery($params) { function sourceQuery($params) {
if($this->hasMethod('sourceRecords')) { if($this->hasMethod('sourceRecords')) {
$query = new SS_Report_FakeQuery($this, 'sourceRecords', $params); $query = new SS_Report_FakeQuery($this, 'sourceRecords', $params);
$query->setSortColumnMethod('sortColumns');
return $query; return $query;
} else { } else {
user_error("Please override sourceQuery()/sourceRecords() and columns() or, if necessary, override getReportField()", E_USER_ERROR); user_error("Please override sourceQuery()/sourceRecords() and columns() or, if necessary, override getReportField()", E_USER_ERROR);
Expand All @@ -126,36 +126,75 @@ function records($params) {
} }
} }



/** /**
* Return an map of columns for your report. * Return the data class for this 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() { function dataClass() {
user_error("Please override sourceQuery() and columns() or, if necessary, override getReportField()", E_USER_ERROR); return $this->dataClass;
} }


function sortColumns() {
return array_keys($this->columns());
/**
* @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) {
} }

/** /**
* Return the number of records in this report with no filters applied. * @deprecated 3.0
* All subclasses of SS_Report now appear in the report admin, no need to register or unregister.
*/ */
function count() { static function unregister($list, $reportClass) {
return (int)$this->sourceQuery(array())->unlimitedRowCount(); self::excludeReport($reportClass);
} }

/** /**
* Return the data class for this report * Exclude a certain report class from the list of Reports in the CMS
* @static
* @param $reportClass
*/ */
function dataClass() { static function excludeReport($reportClass) {
return $this->dataClass; 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. * Returns a FieldList with which to create the CMS editing form.
Expand Down Expand Up @@ -273,72 +312,10 @@ function canView($member = null) {
* @return string * @return string
*/ */
function TreeTitle() { 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;
}


} }


Expand Down Expand Up @@ -370,7 +347,7 @@ function __construct($obj, $method, $params) {
$this->method = $method; $this->method = $method;
$this->params = $params; $this->params = $params;
} }

/** /**
* Provide a method that will return a list of columns that can be used to sort. * Provide a method that will return a list of columns that can be used to sort.
*/ */
Expand Down
36 changes: 26 additions & 10 deletions tests/reports/ReportTest.php
Original file line number Original file line Diff line number Diff line change
@@ -1,18 +1,34 @@
<?php <?php


class ReportTest extends SapphireTest { 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() { function testGetReports() {
$reports = SS_Report::get_reports(); $reports = SS_Report::get_reports();
$this->assertNotNull($reports, "Reports returned"); $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');
} }
} }


Expand All @@ -39,12 +55,12 @@ function sort() {


class ReportTest_FakeTest2 extends SS_Report implements TestOnly { class ReportTest_FakeTest2 extends SS_Report implements TestOnly {
function title() { function title() {
return 'Report title'; return 'Report title 2';
} }
function columns() { function columns() {
return array( return array(
"Title" => array( "Title" => array(
"title" => "Page Title" "title" => "Page Title 2"
) )
); );
} }
Expand Down

0 comments on commit ee220bb

Please sign in to comment.