diff --git a/code/Report.php b/code/Report.php index dad52df2..5eee3d0c 100644 --- a/code/Report.php +++ b/code/Report.php @@ -29,6 +29,7 @@ use SilverStripe\ORM\SS_List; use SilverStripe\Security\Member; use SilverStripe\Security\Permission; use SilverStripe\Security\Security; +use SilverStripe\View\ArrayData; use SilverStripe\View\ViewableData; /** @@ -345,12 +346,7 @@ class Report extends ViewableData */ public function getReportField() { - $params = []; - if (Injector::inst()->has(HTTPRequest::class)) { - /** @var HTTPRequest $request */ - $request = Injector::inst()->get(HTTPRequest::class); - $params = $request->param('filters') ?: $request->requestVar('filters') ?: []; - } + $params = $this->getSourceParams(); $items = $this->sourceRecords($params, null, null); $gridFieldConfig = GridFieldConfig::create()->addComponents( @@ -464,10 +460,8 @@ class Report extends ViewableData /** - * Return the name of this report, which - * is used by the templates to render the - * name of the report in the report tree, - * the left hand pane inside ReportAdmin. + * Return the name of this report, which is used by the templates to render the name of the report in the report + * tree, the left hand pane inside ReportAdmin. * * @return string */ @@ -475,4 +469,33 @@ class Report extends ViewableData { return $this->title(); } + + /** + * Return additional breadcrumbs for this report. Useful when this report is a child of another. + * + * @return ArrayData[] + */ + public function getBreadcrumbs() + { + return []; + } + + /** + * Get source params for the report to filter by + * + * @return array + */ + protected function getSourceParams() + { + $params = []; + if (Injector::inst()->has(HTTPRequest::class)) { + /** @var HTTPRequest $request */ + $request = Injector::inst()->get(HTTPRequest::class); + $params = $request->param('filters') ?: $request->requestVar('filters') ?: []; + } + + $this->extend('updateSourceParams', $params); + + return $params; + } } diff --git a/code/ReportAdmin.php b/code/ReportAdmin.php index 8173681e..b18a1d9f 100644 --- a/code/ReportAdmin.php +++ b/code/ReportAdmin.php @@ -172,11 +172,21 @@ class ReportAdmin extends LeftAndMain implements PermissionProvider // Uses session state for current record otherwise. $items[0]->Link = singleton('SilverStripe\\Reports\\ReportAdmin')->Link(); - if ($this->reportObject) { + if ($report = $this->reportObject) { + $breadcrumbs = $report->getBreadcrumbs(); + if (!empty($breadcrumbs)) { + foreach ($breadcrumbs as $crumb) { + $items->push($crumb); + } + } + //build breadcrumb trail to the current report $items->push(new ArrayData(array( - 'Title' => $this->reportObject->title(), - 'Link' => Controller::join_links($this->Link(), '?' . http_build_query(array('q' => $this->request->requestVar('q')))) + 'Title' => $report->title(), + 'Link' => Controller::join_links( + $this->Link(), + '?' . http_build_query(array('q' => $this->request->requestVar('q'))) + ) ))); } diff --git a/tests/ReportAdminTest.php b/tests/ReportAdminTest.php new file mode 100644 index 00000000..97e5b49c --- /dev/null +++ b/tests/ReportAdminTest.php @@ -0,0 +1,75 @@ +mockController($noExtraCrumbs); + $breadcrumbs = $controller->BreadCrumbs(); + + $this->assertCount(2, $breadcrumbs); + + $this->assertArraySubset([ + 'Title' => 'Reports', + '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(); + $controller = $this->mockController($extraCrumbs); + $breadcrumbs = $controller->Breadcrumbs(); + + $this->assertCount(3, $breadcrumbs); + + $this->assertArraySubset([ + 'Title' => 'Reports', + 'Link' => 'admin/reports/', + ], $breadcrumbs[0]->toMap(), true, 'Link to top level reports is within breadcrumbs (again)'); + + $this->assertArraySubset([ + 'Title' => 'Fake report title', + 'Link' => 'admin/reports/show/SilverStripe-Reports-Tests-ReportAdminTest-FakeReport', + ], $breadcrumbs[1]->toMap(), true, 'Custom breadcrumb appears'); + + $this->assertArraySubset([ + 'Title' => 'Fake report two' + ], $breadcrumbs[2]->toMap(), true, 'Current report is still within breadcrumbs'); + } + + /** + * @param Report $report + * @return ReportAdmin + * @throws \ReflectionException + */ + protected function mockController(Report $report) + { + $reflector = new ReflectionClass($controller = ReportAdmin::create()); + + $reportClass = $reflector->getProperty('reportClass'); + $reportClass->setAccessible(true); + $reportClass->setValue($controller, get_class($report)); + + $reportObject = $reflector->getProperty('reportObject'); + $reportObject->setAccessible(true); + $reportObject->setValue($controller, $report); + + $controller->setRequest(Controller::curr()->getRequest()); + + return $controller; + } +} diff --git a/tests/ReportAdminTest/FakeReport.php b/tests/ReportAdminTest/FakeReport.php new file mode 100644 index 00000000..c0a377c8 --- /dev/null +++ b/tests/ReportAdminTest/FakeReport.php @@ -0,0 +1,13 @@ + 'Fake report title', + 'Link' => FakeReport::singleton()->getLink() + ])]; + } +}