mirror of
https://github.com/silverstripe/silverstripe-reports
synced 2024-10-22 11:05:53 +02:00
ENH Add configuration to cap report counts for large datasets. (#139)
Opted not to return the result from `getCount()` directly since the PHPDoc says this returns an int (even though it technically already returns a string if the report isn't set up correctly...)
This commit is contained in:
parent
0cb265434a
commit
375c31904f
10
README.md
10
README.md
@ -20,6 +20,16 @@ The reports section will not show up in the CMS if:
|
|||||||
* There are no reports to show
|
* There are no reports to show
|
||||||
* The logged in user does not have permission to view any reports
|
* The logged in user does not have permission to view any reports
|
||||||
|
|
||||||
|
For large datasets, the reports section may take a long time to load, since each report is getting a count of the items it contains to display next to the title.
|
||||||
|
|
||||||
|
To mitigate this issue, there is a cap on the number of items that will be counted per report. This is set at 10,000 items by default, but can be configured using the `limit_count_in_overview` configuration variable. Setting this to `null` will result in showing the actual count regardless of how many items there are.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
SilverStripe\Reports\Report:
|
||||||
|
limit_count_in_overview: 500
|
||||||
|
```
|
||||||
|
Note that some reports may have overridden the `getCount` method, and for those reports this may not apply.
|
||||||
|
|
||||||
## Links ##
|
## Links ##
|
||||||
|
|
||||||
* [License](./LICENSE)
|
* [License](./LICENSE)
|
||||||
|
@ -25,6 +25,7 @@ use SilverStripe\ORM\ArrayList;
|
|||||||
use SilverStripe\ORM\CMSPreviewable;
|
use SilverStripe\ORM\CMSPreviewable;
|
||||||
use SilverStripe\ORM\DataList;
|
use SilverStripe\ORM\DataList;
|
||||||
use SilverStripe\ORM\DataQuery;
|
use SilverStripe\ORM\DataQuery;
|
||||||
|
use SilverStripe\ORM\Limitable;
|
||||||
use SilverStripe\ORM\SS_List;
|
use SilverStripe\ORM\SS_List;
|
||||||
use SilverStripe\Security\Member;
|
use SilverStripe\Security\Member;
|
||||||
use SilverStripe\Security\Permission;
|
use SilverStripe\Security\Permission;
|
||||||
@ -105,6 +106,14 @@ class Report extends ViewableData
|
|||||||
SideReportWrapper::class,
|
SideReportWrapper::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of items to include in the count in the reports overview
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
* @var int|null
|
||||||
|
*/
|
||||||
|
private static $limit_count_in_overview = 10000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the title of this report.
|
* Return the title of this report.
|
||||||
*
|
*
|
||||||
@ -216,18 +225,46 @@ class Report extends ViewableData
|
|||||||
/**
|
/**
|
||||||
* counts the number of objects returned
|
* counts the number of objects returned
|
||||||
* @param array $params - any parameters for the sourceRecords
|
* @param array $params - any parameters for the sourceRecords
|
||||||
|
* @param int|null $limit - the maximum number of records to count
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getCount($params = array())
|
public function getCount($params = array(), $limit = null)
|
||||||
{
|
{
|
||||||
$sourceRecords = $this->sourceRecords($params, null, null);
|
$sourceRecords = $this->sourceRecords($params, null, $limit);
|
||||||
if (!$sourceRecords instanceof SS_List) {
|
if (!$sourceRecords instanceof SS_List) {
|
||||||
user_error(static::class . "::sourceRecords does not return an SS_List", E_USER_NOTICE);
|
user_error(static::class . "::sourceRecords does not return an SS_List", E_USER_NOTICE);
|
||||||
return "-1";
|
return "-1";
|
||||||
}
|
}
|
||||||
|
// Some reports may not use the $limit parameter in sourceRecords since it isn't actually
|
||||||
|
// used anywhere else - so make sure we limit record counts if possible.
|
||||||
|
if ($sourceRecords instanceof Limitable) {
|
||||||
|
$sourceRecords = $sourceRecords->limit($limit);
|
||||||
|
}
|
||||||
return $sourceRecords->count();
|
return $sourceRecords->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts the number of objects returned up to a configurable limit.
|
||||||
|
*
|
||||||
|
* Large datasets can cause performance issues for some reports if allowed to count all records.
|
||||||
|
* To mitigate this, you can set the limit_count_in_overview config variable to the maximum number
|
||||||
|
* of items you wish to count to. Counts will be limited to this value, and any counts that hit
|
||||||
|
* this limit will be displayed with a plus, e.g. "500+"
|
||||||
|
*
|
||||||
|
* The default is to have no limit.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCountForOverview(): string
|
||||||
|
{
|
||||||
|
$limit = $this->config()->get('limit_count_in_overview');
|
||||||
|
$count = $this->getCount([], $limit);
|
||||||
|
if ($limit && $count == $limit) {
|
||||||
|
$count = "$count+";
|
||||||
|
}
|
||||||
|
return "$count";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of excluded reports. That is, reports that will not be included in
|
* Return an array of excluded reports. That is, reports that will not be included in
|
||||||
* the list of reports in report admin in the CMS.
|
* the list of reports in report admin in the CMS.
|
||||||
|
@ -242,7 +242,7 @@ class ReportAdmin extends LeftAndMain implements PermissionProvider
|
|||||||
));
|
));
|
||||||
|
|
||||||
$columns->setFieldFormatting(array(
|
$columns->setFieldFormatting(array(
|
||||||
'title' => '<a href=\"$Link\" class=\"grid-field__link-block\">$value ($Count)</a>'
|
'title' => '<a href=\"$Link\" class=\"grid-field__link-block\">$value ($CountForOverview)</a>'
|
||||||
));
|
));
|
||||||
$gridField->addExtraClass('all-reports-gridfield');
|
$gridField->addExtraClass('all-reports-gridfield');
|
||||||
$fields->push($gridField);
|
$fields->push($gridField);
|
||||||
|
@ -114,4 +114,20 @@ class ReportTest extends SapphireTest
|
|||||||
$titleContent
|
$titleContent
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCountForOverview()
|
||||||
|
{
|
||||||
|
$report = new ReportTest\FakeTest3();
|
||||||
|
|
||||||
|
// Count is limited to 10000 by default
|
||||||
|
$this->assertEquals('10000+', $report->getCountForOverview());
|
||||||
|
|
||||||
|
// Count is limited as per configuration
|
||||||
|
Config::modify()->set(ReportTest\FakeTest3::class, 'limit_count_in_overview', 15);
|
||||||
|
$this->assertEquals('15+', $report->getCountForOverview());
|
||||||
|
|
||||||
|
// A null limit displays the full count
|
||||||
|
Config::modify()->set(ReportTest\FakeTest3::class, 'limit_count_in_overview', null);
|
||||||
|
$this->assertEquals('15000', $report->getCountForOverview());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
15
tests/ReportTest/FakeTest3.php
Normal file
15
tests/ReportTest/FakeTest3.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\Reports\Tests\ReportTest;
|
||||||
|
|
||||||
|
use SilverStripe\Dev\TestOnly;
|
||||||
|
use SilverStripe\ORM\ArrayList;
|
||||||
|
use SilverStripe\Reports\Report;
|
||||||
|
|
||||||
|
class FakeTest3 extends Report implements TestOnly
|
||||||
|
{
|
||||||
|
public function sourceRecords($params, $sort, $limit)
|
||||||
|
{
|
||||||
|
return new ArrayList(range(1, 15000));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user