Passed
Pull Request — 4.10 (#10202)
by Steve
08:06
created

GridFieldExportButtonTest::testFormatting()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 18
nc 1
nop 0
dl 0
loc 25
rs 9.6666
c 1
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Forms\Tests\GridField;
4
5
use League\Csv\Reader;
6
use SilverStripe\Forms\Tests\GridField\GridFieldExportButtonTest\NoView;
7
use SilverStripe\Forms\Tests\GridField\GridFieldExportButtonTest\Team;
8
use SilverStripe\ORM\DataList;
9
use SilverStripe\ORM\ArrayList;
10
use SilverStripe\ORM\DataObject;
11
use SilverStripe\Dev\SapphireTest;
12
use SilverStripe\Forms\GridField\GridFieldConfig;
13
use SilverStripe\Forms\GridField\GridFieldDataColumns;
14
use SilverStripe\Forms\GridField\GridFieldExportButton;
15
use SilverStripe\Forms\GridField\GridField;
16
use SilverStripe\Forms\GridField\GridFieldPaginator;
17
use SilverStripe\ORM\FieldType\DBField;
18
19
class GridFieldExportButtonTest extends SapphireTest
20
{
21
22
    /**
23
     * @var DataList
24
     */
25
    protected $list;
26
27
    /**
28
     * @var GridField
29
     */
30
    protected $gridField;
31
32
    protected static $fixture_file = 'GridFieldExportButtonTest.yml';
33
34
    protected static $extra_dataobjects = [
35
        Team::class,
36
        NoView::class,
37
    ];
38
39
    protected function setUp(): void
40
    {
41
        parent::setUp();
42
43
        $this->list = new DataList(Team::class);
44
        $this->list = $this->list->sort('Name');
45
        $config = GridFieldConfig::create()->addComponent(new GridFieldExportButton());
46
        $this->gridField = new GridField('testfield', 'testfield', $this->list, $config);
47
    }
48
49
    public function testCanView()
50
    {
51
        $list = new DataList(NoView::class);
52
53
        $button = new GridFieldExportButton();
54
        $button->setExportColumns(['Name' => 'My Name']);
55
56
        $config = GridFieldConfig::create()->addComponent(new GridFieldExportButton());
57
        $gridField = new GridField('testfield', 'testfield', $list, $config);
58
59
        $csvReader = $this->createReader($button->generateExportFileData($gridField));
60
        $bom = $csvReader->getInputBOM();
61
62
        $this->assertEquals(
63
            "$bom\"My Name\"\r\n",
64
            (string) $csvReader
65
        );
66
    }
67
68
    public function testGenerateFileDataBasicFields()
69
    {
70
        $button = new GridFieldExportButton();
71
        $button->setExportColumns(['Name' => 'My Name']);
72
73
        $csvReader = $this->createReader($button->generateExportFileData($this->gridField));
74
        $bom = $csvReader->getInputBOM();
75
76
        $this->assertEquals(
77
            $bom . '"My Name"' . "\r\n" . 'Test' . "\r\n" . 'Test2' . "\r\n",
78
            (string) $csvReader
79
        );
80
    }
81
82
    public function testXLSSanitisation()
83
    {
84
        // Create risky object
85
        $object = new Team();
86
        $object->Name = '=SUM(1, 2)';
0 ignored issues
show
Bug Best Practice introduced by
The property Name does not exist on SilverStripe\Forms\Tests...ldExportButtonTest\Team. Since you implemented __set, consider adding a @property annotation.
Loading history...
87
        $object->write();
88
89
        // Export
90
        $button = new GridFieldExportButton();
91
        $button->setExportColumns(['Name' => 'My Name']);
92
93
        $csvReader = $this->createReader($button->generateExportFileData($this->gridField));
94
        $bom = $csvReader->getInputBOM();
95
96
        $this->assertEquals(
97
            "$bom\"My Name\"\r\n\"\t=SUM(1, 2)\"\r\nTest\r\nTest2\r\n",
98
            (string) $csvReader
99
        );
100
    }
101
102
    public function testGenerateFileDataAnonymousFunctionField()
103
    {
104
        $button = new GridFieldExportButton();
105
        $button->setExportColumns([
106
            'Name' => 'Name',
107
            'City' => function (DBField $obj) {
108
                return $obj->getValue() . ' city';
109
            }
110
        ]);
111
112
        $csvReader = $this->createReader($button->generateExportFileData($this->gridField));
113
        $bom = $csvReader->getInputBOM();
114
115
        $this->assertEquals(
116
            $bom . 'Name,City' . "\r\n" . 'Test,"City city"' . "\r\n" . 'Test2,"Quoted ""City"" 2 city"' . "\r\n",
117
            (string) $csvReader
118
        );
119
    }
120
121
    public function testBuiltInFunctionNameCanBeUsedAsHeader()
122
    {
123
        $button = new GridFieldExportButton();
124
        $button->setExportColumns([
125
            'Name' => 'Name',
126
            'City' => 'strtolower',
127
        ]);
128
129
        $csvReader = $this->createReader($button->generateExportFileData($this->gridField));
130
        $bom = $csvReader->getInputBOM();
131
132
        $this->assertEquals(
133
            $bom . 'Name,strtolower' . "\r\n" . 'Test,City' . "\r\n" . 'Test2,"Quoted ""City"" 2"' . "\r\n",
134
            (string) $csvReader
135
        );
136
    }
137
138
    public function testNoCsvHeaders()
139
    {
140
        $button = new GridFieldExportButton();
141
        $button->setExportColumns([
142
            'Name' => 'Name',
143
            'City' => 'City',
144
        ]);
145
        $button->setCsvHasHeader(false);
146
147
        $csvReader = $this->createReader($button->generateExportFileData($this->gridField));
148
        $bom = $csvReader->getInputBOM();
149
150
        $this->assertEquals(
151
            $bom . 'Test,City' . "\r\n" . 'Test2,"Quoted ""City"" 2"' . "\r\n",
152
            (string) $csvReader
153
        );
154
    }
155
156
    public function testArrayListInput()
157
    {
158
        $button = new GridFieldExportButton();
159
        $this->gridField->getConfig()->addComponent(new GridFieldPaginator());
160
161
        //Create an ArrayList 1 greater the Paginator's default 15 rows
162
        $arrayList = new ArrayList();
163
        for ($i = 1; $i <= 16; $i++) {
164
            $dataobject = new DataObject(['ID' => $i]);
165
            $arrayList->add($dataobject);
166
        }
167
        $this->gridField->setList($arrayList);
168
169
        $exportData = $button->generateExportFileData($this->gridField);
170
171
        $csvReader = $this->createReader($exportData);
172
        $bom = $csvReader->getInputBOM();
173
174
        $this->assertEquals(
175
            $bom . "ID\r\n" . "1\r\n" . "2\r\n" . "3\r\n" . "4\r\n" . "5\r\n" . "6\r\n" . "7\r\n" . "8\r\n" . "9\r\n" . "10\r\n" . "11\r\n" . "12\r\n" . "13\r\n" . "14\r\n" . "15\r\n" . "16\r\n",
176
            (string) $csvReader
177
        );
178
    }
179
180
    public function testZeroValue()
181
    {
182
        $button = new GridFieldExportButton();
183
        $button->setExportColumns([
184
            'RugbyTeamNumber' => 'Rugby Team Number'
185
        ]);
186
187
        $csvReader = $this->createReader($button->generateExportFileData($this->gridField));
188
        $bom = $csvReader->getInputBOM();
189
190
        $this->assertEquals(
191
            "$bom\"Rugby Team Number\"\r\n2\r\n0\r\n",
192
            (string) $csvReader
193
        );
194
    }
195
196
    protected function createReader($string)
197
    {
198
        $reader = Reader::createFromString($string);
199
200
        // Explicitly set the output BOM in league/csv 9
201
        if (method_exists($reader, 'getContent')) {
202
            $reader->setOutputBOM(Reader::BOM_UTF8);
203
        }
204
205
        return $reader;
206
    }
207
208
    public function testFormatting()
209
    {
210
        $list = new DataList(Team::class);
211
        $config = GridFieldConfig::create();
212
        $button = new GridFieldExportButton();
213
        $button->setExportColumns([
214
            'Name' => 'Name',
215
            'City' => 'City',
216
            'RugbyTeamNumber' => 'Rugby team number'
217
        ]);
218
        $columns = new GridFieldDataColumns();
219
        $columns->setFieldFormatting([
220
            // anonymous function
221
            'City' => function ($value, $item) {
222
                return 'CITY: ' . $value . ' - ' . $item->Name;
223
            },
224
            // class method
225
            'RugbyTeamNumber' => [$this, 'formatRugbyTeamNumber']
226
        ]);
227
        $config->addComponent($button);
228
        $config->addComponent($columns);
229
        $gridField = new GridField('testfield', 'testfield', $list, $config);
230
        $export = $button->generateExportFileData($gridField);
231
        $str = 'Test2,"CITY: Quoted ""City"" 2 - Test2","RUGBY_TEAM_NUMBER: 0 - Test2"';
232
        $this->assertNotFalse(strpos($export, $str));
233
    }
234
235
    public function formatRugbyTeamNumber($value, $item)
236
    {
237
        return 'RUGBY_TEAM_NUMBER: ' . $value . ' - ' . $item->Name;
238
    }
239
}
240