From 3ab48a2fbddff464ab3fc696fa1f2675a8696982 Mon Sep 17 00:00:00 2001 From: Michael Nowina-Krowicki Date: Fri, 8 Nov 2024 00:06:45 +1030 Subject: [PATCH] ENH GridFieldExportButton improvement --- src/Forms/GridField/GridFieldExportButton.php | 97 ++++++++++++++++++- .../GridField/GridFieldExportButtonTest.php | 82 ++++++++++++++-- 2 files changed, 169 insertions(+), 10 deletions(-) diff --git a/src/Forms/GridField/GridFieldExportButton.php b/src/Forms/GridField/GridFieldExportButton.php index 710b0e20757..2686d5d1f8c 100644 --- a/src/Forms/GridField/GridFieldExportButton.php +++ b/src/Forms/GridField/GridFieldExportButton.php @@ -6,6 +6,7 @@ use LogicException; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; +use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Config\Config; use SilverStripe\ORM\DataList; use SilverStripe\ORM\ArrayList; @@ -42,6 +43,16 @@ class GridFieldExportButton extends AbstractGridFieldComponent implements GridFi */ protected $targetFragment; + /** + * Export file name + */ + protected $exportFileName = '[classname]-export-[timestamp].csv'; + + /** + * Export file name timestamp format + */ + protected $timeStampFormat = 'Y-m-d-H-i'; + /** * Set to true to disable XLS sanitisation * [SS-2017-007] Ensure all cells with leading [@=+] have a leading tab @@ -54,11 +65,25 @@ class GridFieldExportButton extends AbstractGridFieldComponent implements GridFi /** * @param string $targetFragment The HTML fragment to write the button into * @param array $exportColumns The columns to include in the export + * @param string $exportFileName Export file name + * @param string $timeStampFormat Export file name timestamp format */ - public function __construct($targetFragment = "after", $exportColumns = null) - { + public function __construct( + $targetFragment = 'after', + $exportColumns = null, + $exportFileName = null, + $timeStampFormat = null + ) { $this->targetFragment = $targetFragment; $this->exportColumns = $exportColumns; + + if ($exportFileName) { + $this->exportFileName = $exportFileName; + } + + if ($timeStampFormat) { + $this->timeStampFormat = $timeStampFormat; + } } /** @@ -128,8 +153,7 @@ public function getURLHandlers($gridField) */ public function handleExport($gridField, $request = null) { - $now = date("d-m-Y-H-i"); - $fileName = "export-$now.csv"; + $fileName = $this->getExportFileName($gridField); if ($fileData = $this->generateExportFileData($gridField)) { return HTTPRequest::send_file($fileData, $fileName, 'text/csv'); @@ -351,4 +375,69 @@ public function setCsvHasHeader($bool) $this->csvHasHeader = $bool; return $this; } + + /** + * @param string $exportFileName + * + * @return $this + */ + public function setExportFileName($exportFileName): GridFieldExportButton + { + $this->exportFileName = $exportFileName; + + return $this; + } + + /** + * @param GridField $gridField + * + * @return string + */ + public function getExportFileName(GridField $gridField): string + { + $exportFileName = $this->exportFileName; + + if (!$exportFileName) { + return null; + } + + if (str_contains($exportFileName, '[classname]')) { + $className = strtolower( + preg_replace( + '/(?getModelClass() + ) + ) + ); + $exportFileName = str_replace( + '[classname]', + $className, + $exportFileName + ); + } + + if (str_contains($exportFileName, '[timestamp]')) { + $exportFileName = str_replace( + '[timestamp]', + date($this->timeStampFormat), + $exportFileName + ); + } + + return $exportFileName; + } + + /** + * @param string $timeStampFormat + * + * @return $this + */ + public function setTimeStampFormat($timeStampFormat): GridFieldExportButton + { + $this->timeStampFormat = $timeStampFormat; + + return $this; + } } diff --git a/tests/php/Forms/GridField/GridFieldExportButtonTest.php b/tests/php/Forms/GridField/GridFieldExportButtonTest.php index 2f4c9078c59..105c88b4c7b 100644 --- a/tests/php/Forms/GridField/GridFieldExportButtonTest.php +++ b/tests/php/Forms/GridField/GridFieldExportButtonTest.php @@ -9,13 +9,13 @@ use SilverStripe\Forms\Tests\GridField\GridFieldExportButtonTest\Team; use SilverStripe\ORM\DataList; use SilverStripe\ORM\ArrayList; -use SilverStripe\ORM\DataObject; use SilverStripe\Dev\SapphireTest; use SilverStripe\Forms\GridField\GridFieldConfig; use SilverStripe\Forms\GridField\GridFieldExportButton; use SilverStripe\Forms\GridField\GridField; use SilverStripe\Forms\GridField\GridFieldDataColumns; use SilverStripe\Forms\GridField\GridFieldPaginator; +use SilverStripe\ORM\FieldType\DBDatetime; use SilverStripe\ORM\FieldType\DBField; use SilverStripe\View\ArrayData; @@ -32,6 +32,16 @@ class GridFieldExportButtonTest extends SapphireTest */ protected $gridField; + /** + * @var GridFieldConfig + */ + protected $gridFieldConfig; + + /** + * @var GridFieldExportButton + */ + protected $exportButton; + protected static $fixture_file = 'GridFieldExportButtonTest.yml'; protected static $extra_dataobjects = [ @@ -45,8 +55,10 @@ protected function setUp(): void $this->list = new DataList(Team::class); $this->list = $this->list->sort('Name'); - $config = GridFieldConfig::create()->addComponent(new GridFieldExportButton()); - $this->gridField = new GridField('testfield', 'testfield', $this->list, $config); + $this->gridFieldConfig = GridFieldConfig::create()->addComponent( + $this->exportButton = new GridFieldExportButton() + ); + $this->gridField = new GridField('testfield', 'testfield', $this->list, $this->gridFieldConfig); } public function testCanView() @@ -161,8 +173,8 @@ public function testArrayListInput() $button = new GridFieldExportButton(); $columns = new GridFieldDataColumns(); $columns->setDisplayFields(['ID' => 'ID']); - $this->gridField->getConfig()->addComponent($columns); - $this->gridField->getConfig()->addComponent(new GridFieldPaginator()); + $this->gridFieldConfig->addComponent($columns); + $this->gridFieldConfig->addComponent(new GridFieldPaginator()); //Create an ArrayList 1 greater the Paginator's default 15 rows $arrayList = new ArrayList(); @@ -203,7 +215,7 @@ public function testGetExportColumnsForGridFieldThrowsException() { $component = new GridFieldExportButton(); $gridField = new GridField('dummy', 'dummy', new ArrayList()); - $gridField->getConfig()->removeComponentsByType(GridFieldDataColumns::class); + $gridFieldConfig->removeComponentsByType(GridFieldDataColumns::class); $modelClass = ArrayData::class; $gridField->setModelClass($modelClass); @@ -218,6 +230,64 @@ public function testGetExportColumnsForGridFieldThrowsException() $reflectionMethod->invoke($component, $gridField); } + public function testSetExportFileName() + { + $this->exportButton->setExportFileName('export.csv'); + + $this->assertEquals( + 'export.csv', + $this->exportButton->getExportFileName() + ); + + $this->exportButton->setExportFileName('[classname]-export.csv'); + + $this->assertEquals( + 'team-export.csv', + $this->exportButton->getExportFileName() + ); + + $mockDate = '2024-12-31 22:10:59'; + DBDatetime::set_mock_now($mockDate); + + $this->exportButton->setExportFileName('export-[timestamp].csv'); + + $this->assertEquals( + 'export-2024-12-31-22-10.csv', + $this->exportButton->getExportFileName() + ); + + $this->exportButton->setExportFileName('[classname]-export-[timestamp].csv'); + + $this->assertEquals( + 'team-export-2024-12-31-22-10.csv', + $this->exportButton->getExportFileName() + ); + + DBDatetime::clear_mock_now(); + } + + public function testSetTimeStampFormat() + { + $mockDate = '2024-12-31 22:10:59'; + DBDatetime::set_mock_now($mockDate); + + $this->exportButton->setTimeStampFormat('Ymd-Hi'); + + $this->assertEquals( + 'export-20241231-2210.csv', + $this->exportButton->getExportFileName() + ); + + $this->exportButton->setTimeStampFormat('d-m-Y'); + + $this->assertEquals( + 'team-export-31-12-2024.csv', + $this->exportButton->getExportFileName() + ); + + DBDatetime::clear_mock_now(); + } + protected function createReader($string) { $reader = Reader::createFromString($string);