Compare commits

...

52 Commits
4.7.0 ... 4

Author SHA1 Message Date
github-actions
6942278b41 Merge branch '4.13' into 4 2024-02-09 11:04:20 +00:00
Guy Sartorelli
c9c6c3ff1e
TLN Update translations (#176) 2024-02-08 13:29:26 +13:00
Guy Sartorelli
f5b5daa711
TLN Update translations (#175) 2024-02-07 16:10:59 +13:00
github-actions
aa3d0a3b6a Merge branch '4.13' into 4 2023-09-29 11:04:25 +00:00
Guy Sartorelli
aa085022a1
Merge pull request #169 from heyday/4
FIX broken URL builder when using MultiSelectFields as parameters
2023-09-26 10:35:41 +13:00
Will Rossiter
a25d0432c4
FIX broken URL builder when using MultiSelectFields as parameters 2023-09-21 13:21:46 +12:00
github-actions
030c56777c Merge branch '4.13' into 4 2023-08-25 11:04:27 +00:00
Guy Sartorelli
03869a7535
ENH Update translations (#167) 2023-08-21 12:56:04 +12:00
Steve Boyd
2c3f2ca64d Merge branch '4.13' into 4 2023-06-16 10:39:53 +12:00
Guy Sartorelli
92b5d968da
Merge pull request #164 from creative-commoners/pulls/4.13/tx-1686724792
ENH Update translations
2023-06-15 10:06:10 +12:00
Steve Boyd
f6aee12f07 ENH Update translations 2023-06-14 18:39:52 +12:00
Guy Sartorelli
2db20aba1a
Merge branch '4.13' into 4 2023-04-26 12:44:49 +12:00
Guy Sartorelli
cea17947ea
MNT Revert erroneous dependency changes (#161) 2023-03-28 16:43:12 +13:00
Maxime Rainville
48b103bf97
Merge pull request #160 from creative-commoners/pulls/4/dispatch-ci
MNT Use gha-dispatch-ci
2023-03-23 12:09:00 +13:00
Steve Boyd
454a3df1e7 MNT Use gha-dispatch-ci 2023-03-21 12:16:32 +13:00
Guy Sartorelli
4cb8e8f880
MNT Update development dependencies 2023-03-10 16:30:57 +13:00
Guy Sartorelli
f23076b4cf
MNT Update release dependencies 2023-03-10 16:30:53 +13:00
Guy Sartorelli
2bf6bc1a9c
MNT Update development dependencies 2023-03-10 12:21:27 +13:00
Guy Sartorelli
e88a56243d
Merge pull request #159 from creative-commoners/pulls/4/tx-1678080021
ENH Update translations
2023-03-08 10:32:08 +13:00
Steve Boyd
a75e054b99 ENH Update translations 2023-03-06 18:20:21 +13:00
Steve Boyd
bd74939c14
Merge pull request #154 from creative-commoners/pulls/4/rescue-master-psr12
Rescue Master Branch PR: PSR12 compliance
2022-08-29 18:15:29 +12:00
Robbie Averill
01f2663179
Use Injector to instantiate new base report instances 2022-08-26 13:53:16 +12:00
Robbie Averill
213f7167a6
ENH Fix phpcs violations 2022-08-26 13:53:08 +12:00
Robbie Averill
c5f42d99a3
MNT Update phpcs ruleset to use PSR-12 as a base 2022-08-26 13:48:51 +12:00
Steve Boyd
d21503c88c Merge branch '4.11' into 4 2022-08-02 18:38:12 +12:00
Steve Boyd
eacecdbb56 Merge branch '4.10' into 4.11 2022-08-02 18:38:08 +12:00
Guy Sartorelli
c0bdbc3d3b
Merge pull request #150 from creative-commoners/pulls/4.10/standardise-modules
MNT Standardise modules
2022-08-02 14:29:45 +12:00
Steve Boyd
567124b34a MNT Standardise modules 2022-08-01 15:36:42 +12:00
Guy Sartorelli
bd7fb5a45d Merge branch '4.11' into 4 2022-07-11 11:24:14 +12:00
Guy Sartorelli
f18dd784e5 Merge branch '4.10' into 4.11 2022-07-11 11:24:02 +12:00
Guy Sartorelli
86d338680a
Merge pull request #149 from creative-commoners/pulls/4.10/module-standards
MNT Use GitHub Actions CI
2022-07-05 16:31:12 +12:00
Steve Boyd
fca925673f MNT Use GitHub Actions CI 2022-07-05 16:04:25 +12:00
Guy Sartorelli
8e3d6cb3eb
Merge pull request #148 from creative-commoners/pulls/4/php81
ENH PHP 8.1 compatibility
2022-04-22 16:18:26 +12:00
Steve Boyd
0bceb0903c ENH PHP 8.1 compatibility 2022-04-13 17:39:46 +12:00
Guy Sartorelli
6d565028c8
ENH Prefer dependency injection for GridFieldComponents. (#147)
GridFieldComponents packaged with silverstripe/framework are injectable as of 4.11.0
2022-03-04 10:13:45 +13:00
Maxime Rainville
ede88ee491
Merge pull request #146 from creative-commoners/pulls/4/php74
DEP Set PHP 7.4 as the minimum version
2022-02-18 22:05:50 +13:00
Steve Boyd
013c5d74cf DEP Set PHP 7.4 as the minimum version 2022-02-10 17:31:38 +13:00
GuySartorelli
375c31904f
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...)
2022-01-31 17:20:11 +13:00
Steve Boyd
0cb265434a Merge branch '4.10' into 4 2021-12-22 10:12:27 +13:00
Maxime Rainville
411a98e45b
Merge pull request #143 from creative-commoners/pulls/4.10/dynamic
MNT Rely on dynamic REQUIRE_RECIPE
2021-12-14 10:30:03 +13:00
Steve Boyd
cb71f6b7f2 MNT Rely on dynamic REQUIRE_RECIPE 2021-12-13 11:47:20 +13:00
Maxime Rainville
6dd0627678
Merge pull request #142 from creative-commoners/pulls/4/dms
MNT Remove polyfill
2021-11-09 10:57:04 +13:00
Steve Boyd
1b2a9a8926 MNT Remove polyfill 2021-11-05 13:23:15 +13:00
Maxime Rainville
3ab86f3d0a
Merge pull request #141 from creative-commoners/pulls/4/sapphire-test-nine
API phpunit9 support
2021-10-28 00:00:38 +13:00
Steve Boyd
9f76ec2a43 API phpunit9 support 2021-10-27 17:52:11 +13:00
Steve Boyd
908dc49dca Merge branch '4.9' into 4 2021-09-06 16:08:45 +12:00
Steve Boyd
22839ec8c2
MNT Update REQUIRE_RECIPE 2021-09-06 16:06:23 +12:00
Steve Boyd
8098a7c61f Merge branch '4.8' into 4 2021-05-17 16:34:51 +12:00
Steve Boyd
1d9940aab0 MNT Remove COMPOSER_ROOT_VERSION 2021-05-17 16:34:21 +12:00
Steve Boyd
27288dc508 Update translations 2021-05-17 10:53:21 +12:00
Steve Boyd
e101f1e034
Update build status badge 2021-01-21 16:07:28 +13:00
Steve Boyd
90bdc6f3ce Merge branch '4.7' into 4 2020-11-11 17:02:56 +13:00
27 changed files with 253 additions and 116 deletions

View File

@ -1 +0,0 @@
comment: false

11
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,11 @@
name: CI
on:
push:
pull_request:
workflow_dispatch:
jobs:
ci:
name: CI
uses: silverstripe/gha-ci/.github/workflows/ci.yml@v1

16
.github/workflows/dispatch-ci.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: Dispatch CI
on:
# At 11:00 AM UTC, only on Monday and Tuesday
schedule:
- cron: '0 11 * * 1,2'
jobs:
dispatch-ci:
name: Dispatch CI
# Only run cron on the silverstripe account
if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
runs-on: ubuntu-latest
steps:
- name: Dispatch CI
uses: silverstripe/gha-dispatch-ci@v1

17
.github/workflows/keepalive.yml vendored Normal file
View File

@ -0,0 +1,17 @@
name: Keepalive
on:
workflow_dispatch:
# The 4th of every month at 10:50am UTC
schedule:
- cron: '50 10 4 * *'
jobs:
keepalive:
name: Keepalive
# Only run cron on the silverstripe account
if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
runs-on: ubuntu-latest
steps:
- name: Keepalive
uses: silverstripe/gha-keepalive@v1

View File

@ -1,9 +0,0 @@
inherit: true
checks:
php:
code_rating: true
duplication: true
filter:
paths: [code/*, tests/*]

View File

@ -1,9 +0,0 @@
version: ~> 1.0
import:
- silverstripe/silverstripe-travis-shared:config/provision/standard-jobs-fixed.yml
env:
global:
- COMPOSER_ROOT_VERSION="4.7.x-dev"
- REQUIRE_RECIPE="$COMPOSER_ROOT_VERSION"

View File

@ -1,8 +1,9 @@
[main] [main]
host = https://www.transifex.com host = https://www.transifex.com
[silverstripe-reports.master] [o:silverstripe:p:silverstripe-reports:r:master]
file_filter = lang/<lang>.yml file_filter = lang/<lang>.yml
source_file = lang/en.yml source_file = lang/en.yml
source_lang = en source_lang = en
type = YML type = YML

View File

@ -1,17 +1,17 @@
# Reports # Reports
[![Build Status](https://secure.travis-ci.org/silverstripe/silverstripe-reports.png?branch=master)](http://travis-ci.org/silverstripe/silverstripe-reports) [![CI](https://github.com/silverstripe/silverstripe-reports/actions/workflows/ci.yml/badge.svg)](https://github.com/silverstripe/silverstripe-reports/actions/workflows/ci.yml)
[![SilverStripe supported module](https://img.shields.io/badge/silverstripe-supported-0071C4.svg)](https://www.silverstripe.org/software/addons/silverstripe-commercially-supported-module-list/) [![Silverstripe supported module](https://img.shields.io/badge/silverstripe-supported-0071C4.svg)](https://www.silverstripe.org/software/addons/silverstripe-commercially-supported-module-list/)
## Introduction ## Introduction
This module contains the API's for building Reports that are displayed in the This module contains the API's for building Reports that are displayed in the
SilverStripe backend. This module replaces the built-in reports API from earlier Silverstripe backend. This module replaces the built-in reports API from earlier
versions of SilverStripe (2.4 and 3.0). versions of Silverstripe (2.4 and 3.0).
## Requirements ## Requirements
* SilverStripe 4.0 * Silverstripe 4.0
## Troubleshooting ## Troubleshooting
@ -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)

View File

@ -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;
@ -60,7 +61,8 @@ use SilverStripe\View\ViewableData;
* Right now, all subclasses of SS_Report will be shown in the ReportAdmin. In SS3 there is only * 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 its version in SS2. * one place where reports can go, so this class is greatly simplifed from its version in SS2.
* *
* @method SS_List|DataList sourceRecords($params = [], $sort = null, $limit = null) List of records to show for this report * @method SS_List|DataList sourceRecords($params = [], $sort = null, $limit = null)
* List of records to show for this report
*/ */
class Report extends ViewableData class Report extends ViewableData
{ {
@ -105,6 +107,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.
* *
@ -149,7 +159,8 @@ class Report extends ViewableData
{ {
if (!$this->hasMethod('sourceRecords')) { if (!$this->hasMethod('sourceRecords')) {
throw new \RuntimeException( throw new \RuntimeException(
'Please override sourceQuery()/sourceRecords() and columns() or, if necessary, override getReportField()' 'Please override sourceQuery()/sourceRecords() and columns() or, '
. 'if necessary, override getReportField()'
); );
} }
@ -209,25 +220,53 @@ class Report extends ViewableData
*/ */
protected function sanitiseClassName($class) protected function sanitiseClassName($class)
{ {
return str_replace('\\', '-', $class); return str_replace('\\', '-', $class ?? '');
} }
/** /**
* 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.
@ -249,12 +288,12 @@ class Report extends ViewableData
$reports = ClassInfo::subclassesFor(get_called_class()); $reports = ClassInfo::subclassesFor(get_called_class());
$reportsArray = []; $reportsArray = [];
if ($reports && count($reports) > 0) { if ($reports && count($reports ?? []) > 0) {
$excludedReports = static::get_excluded_reports(); $excludedReports = static::get_excluded_reports();
// Collect reports into array with an attribute for 'sort' // Collect reports into array with an attribute for 'sort'
foreach ($reports as $report) { foreach ($reports as $report) {
// Don't use the Report superclass, or any excluded report classes // Don't use the Report superclass, or any excluded report classes
if (in_array($report, $excludedReports)) { if (in_array($report, $excludedReports ?? [])) {
continue; continue;
} }
$reflectionClass = new ReflectionClass($report); $reflectionClass = new ReflectionClass($report);
@ -316,7 +355,10 @@ class Report extends ViewableData
} }
// Add a search button // Add a search button
$formAction = FormAction::create('updatereport', _t('SilverStripe\\Forms\\GridField\\GridField.Filter', 'Filter')); $formAction = FormAction::create(
'updatereport',
_t('SilverStripe\\Forms\\GridField\\GridField.Filter', 'Filter')
);
$formAction->addExtraClass('btn-primary mb-4'); $formAction->addExtraClass('btn-primary mb-4');
$fields->push($formAction); $fields->push($formAction);
@ -352,12 +394,12 @@ class Report extends ViewableData
$items = $this->sourceRecords($params, null, null); $items = $this->sourceRecords($params, null, null);
$gridFieldConfig = GridFieldConfig::create()->addComponents( $gridFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldButtonRow('before'), GridFieldButtonRow::create('before'),
new GridFieldPrintButton('buttons-before-left'), GridFieldPrintButton::create('buttons-before-left'),
new GridFieldExportButton('buttons-before-left'), GridFieldExportButton::create('buttons-before-left'),
new GridFieldSortableHeader(), GridFieldSortableHeader::create(),
new GridFieldDataColumns(), GridFieldDataColumns::create(),
new GridFieldPaginator() GridFieldPaginator::create()
); );
/** @var GridField $gridField */ /** @var GridField $gridField */
$gridField = GridField::create('Report', null, $items, $gridFieldConfig); $gridField = GridField::create('Report', null, $items, $gridFieldConfig);
@ -447,7 +489,7 @@ class Report extends ViewableData
$results = $this->extend($methodName, $member); $results = $this->extend($methodName, $member);
if ($results && is_array($results)) { if ($results && is_array($results)) {
// Remove NULLs // Remove NULLs
$results = array_filter($results, function ($v) { $results = array_filter($results ?? [], function ($v) {
return !is_null($v); return !is_null($v);
}); });
// If there are any non-NULL responses, then return the lowest one of them. // If there are any non-NULL responses, then return the lowest one of them.

View File

@ -139,7 +139,7 @@ class ReportAdmin extends LeftAndMain implements PermissionProvider
*/ */
protected function unsanitiseClassName($class) protected function unsanitiseClassName($class)
{ {
return str_replace('-', '\\', $class); return str_replace('-', '\\', $class ?? '');
} }
/** /**
@ -155,7 +155,7 @@ class ReportAdmin extends LeftAndMain implements PermissionProvider
*/ */
public static function has_reports() public static function has_reports()
{ {
return sizeof(Report::get_reports()) > 0; return sizeof(Report::get_reports() ?? []) > 0;
} }
/** /**
@ -181,13 +181,13 @@ class ReportAdmin extends LeftAndMain implements PermissionProvider
} }
//build breadcrumb trail to the current report //build breadcrumb trail to the current report
$items->push(new ArrayData(array( $items->push(ArrayData::create([
'Title' => $report->title(), 'Title' => $report->title(),
'Link' => Controller::join_links( 'Link' => Controller::join_links(
$this->Link(), $this->Link(),
'?' . http_build_query(array('q' => $this->request->requestVar('q'))) '?' . http_build_query(['q' => $this->request->requestVar('q')])
) )
))); ]));
} }
return $items; return $items;
@ -230,19 +230,20 @@ class ReportAdmin extends LeftAndMain implements PermissionProvider
// List all reports // List all reports
$fields = new FieldList(); $fields = new FieldList();
$gridFieldConfig = GridFieldConfig::create()->addComponents( $gridFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldSortableHeader(), GridFieldSortableHeader::create(),
new GridFieldDataColumns(), GridFieldDataColumns::create(),
new GridFieldFooter() GridFieldFooter::create()
); );
$gridField = new GridField('Reports', false, $this->Reports(), $gridFieldConfig); $gridField = GridField::create('Reports', false, $this->Reports(), $gridFieldConfig);
/** @var GridFieldDataColumns $columns */ /** @var GridFieldDataColumns $columns */
$columns = $gridField->getConfig()->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDataColumns'); $columns = $gridField->getConfig()
->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDataColumns');
$columns->setDisplayFields(array( $columns->setDisplayFields(array(
'title' => _t('SilverStripe\\Reports\\ReportAdmin.ReportTitle', 'Title'), 'title' => _t('SilverStripe\\Reports\\ReportAdmin.ReportTitle', 'Title'),
)); ));
$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);
@ -250,7 +251,9 @@ class ReportAdmin extends LeftAndMain implements PermissionProvider
$actions = new FieldList(); $actions = new FieldList();
$form = new Form($this, "EditForm", $fields, $actions); $form = new Form($this, "EditForm", $fields, $actions);
$form->addExtraClass('panel panel--padded panel--scrollable cms-edit-form cms-panel-padded' . $this->BaseCSSClasses()); $form->addExtraClass(
'panel panel--padded panel--scrollable cms-edit-form cms-panel-padded' . $this->BaseCSSClasses()
);
$form->loadDataFrom($this->request->getVars()); $form->loadDataFrom($this->request->getVars());
$this->extend('updateEditForm', $form); $this->extend('updateEditForm', $form);

View File

@ -2,6 +2,8 @@
namespace SilverStripe\Reports; namespace SilverStripe\Reports;
use SilverStripe\Core\Injector\Injector;
/** /**
* SS_ReportWrapper is a base class for creating report wappers. * SS_ReportWrapper is a base class for creating report wappers.
* *
@ -21,7 +23,7 @@ abstract class ReportWrapper extends Report
public function __construct($baseReport) public function __construct($baseReport)
{ {
$this->baseReport = is_string($baseReport) ? new $baseReport : $baseReport; $this->baseReport = is_string($baseReport) ? Injector::inst()->create($baseReport) : $baseReport;
$this->dataClass = $this->baseReport->dataClass(); $this->dataClass = $this->baseReport->dataClass();
parent::__construct(); parent::__construct();
} }

View File

@ -11,8 +11,8 @@ use SilverStripe\View\ViewableData;
*/ */
class SideReportView extends ViewableData class SideReportView extends ViewableData
{ {
protected $controller;
protected $controller, $report; protected $report;
protected $parameters; protected $parameters;
public function __construct($controller, $report) public function __construct($controller, $report)
@ -79,9 +79,9 @@ class SideReportView extends ViewableData
// Formatting, a la TableListField // Formatting, a la TableListField
if (!empty($info['formatting'])) { if (!empty($info['formatting'])) {
$format = str_replace('$value', "__VAL__", $info['formatting']); $format = str_replace('$value', "__VAL__", $info['formatting'] ?? '');
$format = preg_replace('/\$([A-Za-z0-9-_]+)/', '$record->$1', $format); $format = preg_replace('/\$([A-Za-z0-9-_]+)/', '$record->$1', $format ?? '');
$format = str_replace('__VAL__', '$val', $format); $format = str_replace('__VAL__', '$val', $format ?? '');
$val = eval('return "' . $format . '";'); $val = eval('return "' . $format . '";');
} }
@ -90,7 +90,7 @@ class SideReportView extends ViewableData
$classClause = ""; $classClause = "";
if (isset($info['title'])) { if (isset($info['title'])) {
$cssClass = preg_replace('/[^A-Za-z0-9]+/', '', $info['title']); $cssClass = preg_replace('/[^A-Za-z0-9]+/', '', $info['title'] ?? '');
$classClause = "class=\"$cssClass\""; $classClause = "class=\"$cssClass\"";
} }

View File

@ -20,7 +20,8 @@
} }
], ],
"require": { "require": {
"silverstripe/framework": "^4.6@dev", "php": "^7.4 || ^8.0",
"silverstripe/framework": "^4.11",
"silverstripe/admin": "^1.6@dev", "silverstripe/admin": "^1.6@dev",
"silverstripe/versioned": "^1.6@dev", "silverstripe/versioned": "^1.6@dev",
"silverstripe/config": "^1.0@dev", "silverstripe/config": "^1.0@dev",
@ -28,7 +29,7 @@
"silverstripe/vendor-plugin": "^1" "silverstripe/vendor-plugin": "^1"
}, },
"require-dev": { "require-dev": {
"sminnee/phpunit": "^5.7", "phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "^3.0" "squizlabs/php_codesniffer": "^3.0"
}, },
"extra": { "extra": {
@ -44,4 +45,4 @@
}, },
"minimum-stability": "dev", "minimum-stability": "dev",
"prefer-stable": true "prefer-stable": true
} }

View File

@ -2,17 +2,32 @@
* File: ReportAdmin.js * File: ReportAdmin.js
*/ */
(function($) { (function ($) {
$.entwine('ss', function($){ $.entwine("ss", function ($) {
$('.ReportAdmin .cms-edit-form').entwine({ $(".ReportAdmin .cms-edit-form").entwine({
onsubmit: function(e) { onsubmit: function (e) {
var url = $.path.parseUrl(document.location.href).hrefNoSearch, let url = $.path.parseUrl(document.location.href).hrefNoSearch;
params = this.find(':input[name^=filters]').serializeArray(); let params = this.find(":input[name^=filters]").serializeArray();
params = $.grep(params, function(param) {return (param.value);}); // filter out empty
if(params) url = $.path.addSearchParams(url, $.param(params)); try {
$('.cms-container').loadPanel(url); params = $.grep(params, function (param) {
return false; // filter out empty
} return param.value;
}); });
});
// convert params to a query string
params = $.param(params);
// append query string to url
url += "?" + params;
$(".cms-container").loadPanel(url);
} catch (err) {
console.error(err);
}
return false;
},
});
});
})(jQuery); })(jQuery);

View File

@ -1,4 +1,8 @@
en: en:
SilverStripe\CMS\Controllers\CMSPageHistoryController:
PREVIEW: 'Website preview'
SilverStripe\Forms\GridField\GridField:
Filter: Filter
SilverStripe\Reports\ReportAdmin: SilverStripe\Reports\ReportAdmin:
MENUTITLE: Reports MENUTITLE: Reports
ReportTitle: Title ReportTitle: Title

View File

@ -1,4 +1,8 @@
eo: eo:
SilverStripe\CMS\Controllers\CMSPageHistoryController:
PREVIEW: 'Retejon antaŭvidi'
SilverStripe\Forms\GridField\GridField:
Filter: Filtrilo
SilverStripe\Reports\ReportAdmin: SilverStripe\Reports\ReportAdmin:
MENUTITLE: Raportoj MENUTITLE: Raportoj
ReportTitle: Titoloj ReportTitle: Titoloj

View File

@ -1,7 +1,9 @@
sk: sk:
SilverStripe\CMS\Controllers\CMSPageHistoryController:
PREVIEW: 'Náhľad webovej stránky'
SilverStripe\Reports\ReportAdmin: SilverStripe\Reports\ReportAdmin:
MENUTITLE: Výkazy MENUTITLE: Správy
ReportTitle: Titulok ReportTitle: Názov
SilverStripe\Reports\SideReport: SilverStripe\Reports\SideReport:
OtherGroupTitle: Iné OtherGroupTitle: Iné
REPEMPTY: 'Výkaz {title} je prázdny.' REPEMPTY: 'Správa {title} je prázdna.'

7
lang/sl.yml Normal file
View File

@ -0,0 +1,7 @@
sl:
SilverStripe\Reports\ReportAdmin:
MENUTITLE: Poročila
ReportTitle: Naslov
SilverStripe\Reports\SideReport:
OtherGroupTitle: Drugo
REPEMPTY: 'Poročilo ''{title}'' je prazno.'

View File

@ -1,4 +1,6 @@
sv: sv:
SilverStripe\CMS\Controllers\CMSPageHistoryController:
PREVIEW: 'Webbplats förhandsvisning'
SilverStripe\Reports\ReportAdmin: SilverStripe\Reports\ReportAdmin:
MENUTITLE: Rapporter MENUTITLE: Rapporter
ReportTitle: Titel ReportTitle: Titel

View File

@ -5,20 +5,9 @@
<file>code</file> <file>code</file>
<file>tests</file> <file>tests</file>
<!-- base rules are PSR-2 --> <!-- base rules are PSR-12 -->
<rule ref="PSR2" > <rule ref="PSR12" >
<!-- Current exclusions --> <!-- Current exclusions -->
<exclude name="PSR1.Methods.CamelCapsMethodName" /> <exclude name="PSR1.Methods.CamelCapsMethodName.NotCamelCaps" />
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols" />
<exclude name="PSR2.Classes.PropertyDeclaration" />
<exclude name="PSR2.ControlStructures.SwitchDeclaration" /> <!-- causes php notice while linting -->
<exclude name="PSR2.ControlStructures.SwitchDeclaration.WrongOpenercase" />
<exclude name="PSR2.ControlStructures.SwitchDeclaration.WrongOpenerdefault" />
<exclude name="PSR2.ControlStructures.SwitchDeclaration.TerminatingComment" />
<exclude name="PSR2.Methods.MethodDeclaration.Underscore" />
<exclude name="Squiz.Scope.MethodScope" />
<exclude name="Squiz.Classes.ValidClassName.NotCamelCaps" />
<exclude name="Generic.Files.LineLength.TooLong" />
<exclude name="PEAR.Functions.ValidDefaultValue.NotAtEnd" />
</rule> </rule>
</ruleset> </ruleset>

View File

@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/silverstripe/framework/tests/bootstrap.php" colors="true"> <phpunit bootstrap="vendor/silverstripe/framework/tests/bootstrap.php" colors="true">
<testsuite name="Default"> <testsuites>
<directory>tests</directory> <testsuite name="Default">
</testsuite> <directory>tests</directory>
</testsuite>
</testsuites>
<filter> <filter>
<whitelist addUncoveredFilesFromWhitelist="true"> <whitelist addUncoveredFilesFromWhitelist="true">

View File

@ -1,4 +1,5 @@
<?php <?php
namespace SilverStripe\Reports\Tests; namespace SilverStripe\Reports\Tests;
use ReflectionClass; use ReflectionClass;
@ -20,15 +21,12 @@ class ReportAdminTest extends SapphireTest
$breadcrumbs = $controller->BreadCrumbs(); $breadcrumbs = $controller->BreadCrumbs();
$this->assertCount(2, $breadcrumbs); $this->assertCount(2, $breadcrumbs);
$map = $breadcrumbs[0]->toMap();
$this->assertSame('Reports', $map['Title']);
$this->assertSame('admin/reports/', $map['Link']);
$this->assertArraySubset([ $map = $breadcrumbs[1]->toMap();
'Title' => 'Reports', $this->assertSame('Fake report', $map['Title']);
'Link' => 'admin/reports/',
], $breadcrumbs[0]->toMap(), true, 'Link to top level reports is within breadcrumbs');
$this->assertArraySubset([
'Title' => 'Fake report'
], $breadcrumbs[1]->toMap(), true, 'Current report is within breadcrumbs');
$extraCrumbs = FakeReport2::create(); $extraCrumbs = FakeReport2::create();
$controller = $this->mockController($extraCrumbs); $controller = $this->mockController($extraCrumbs);
@ -36,19 +34,16 @@ class ReportAdminTest extends SapphireTest
$this->assertCount(3, $breadcrumbs); $this->assertCount(3, $breadcrumbs);
$this->assertArraySubset([ $map = $breadcrumbs[0]->toMap();
'Title' => 'Reports', $this->assertSame('Reports', $map['Title']);
'Link' => 'admin/reports/', $this->assertSame('admin/reports/', $map['Link']);
], $breadcrumbs[0]->toMap(), true, 'Link to top level reports is within breadcrumbs (again)');
$this->assertArraySubset([ $map = $breadcrumbs[1]->toMap();
'Title' => 'Fake report title', $this->assertSame('Fake report title', $map['Title']);
'Link' => 'admin/reports/show/SilverStripe-Reports-Tests-ReportAdminTest-FakeReport', $this->assertSame('admin/reports/show/SilverStripe-Reports-Tests-ReportAdminTest-FakeReport', $map['Link']);
], $breadcrumbs[1]->toMap(), true, 'Custom breadcrumb appears');
$this->assertArraySubset([ $map = $breadcrumbs[2]->toMap();
'Title' => 'Fake report two' $this->assertSame('Fake report two', $map['Title']);
], $breadcrumbs[2]->toMap(), true, 'Current report is still within breadcrumbs');
} }
/** /**

View File

@ -1,4 +1,5 @@
<?php <?php
namespace SilverStripe\Reports\Tests\ReportAdminTest; namespace SilverStripe\Reports\Tests\ReportAdminTest;
use SilverStripe\Dev\TestOnly; use SilverStripe\Dev\TestOnly;

View File

@ -1,4 +1,5 @@
<?php <?php
namespace SilverStripe\Reports\Tests\ReportAdminTest; namespace SilverStripe\Reports\Tests\ReportAdminTest;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;

View File

@ -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());
}
} }

View 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));
}
}

View File

@ -8,7 +8,6 @@ use SilverStripe\Reports\Report;
abstract class FakeTestAbstract extends Report implements TestOnly abstract class FakeTestAbstract extends Report implements TestOnly
{ {
public function title() public function title()
{ {
return 'Report title Abstract'; return 'Report title Abstract';