BuildFormPlainTest.php 37.1 KB
Newer Older
1
<?php
2
/**
3
 * @author Carsten Rose <carsten.rose@math.uzh.ch>
4
 */
5

6
7
8
namespace qfq;

require_once(__DIR__ . '/database/AbstractDatabaseTest.php');
9

10
11
12
/**
 * Class BuildFormPlainTest
 */
13
14
class BuildFormPlainTest extends AbstractDatabaseTest {

15
    /**
Carsten  Rose's avatar
Carsten Rose committed
16
17
18
     * @throws CodeException
     * @throws UserFormException
     * @throws UserReportException
19
     */
20
21
    public function testGetProcessFilter() {

Carsten  Rose's avatar
Carsten Rose committed
22
        $build = new BuildFormPlain([F_DB_INDEX => DB_INDEX_DEFAULT], array(), array(), $this->dbArray);
23
24
25
26

        $this->assertEquals(FORM_ELEMENTS_NATIVE, $build->getProcessFilter());
    }

27
    /**
Carsten  Rose's avatar
Carsten Rose committed
28
29
30
     * @throws CodeException
     * @throws UserFormException
     * @throws UserReportException
31
32
     */
    public function testGetFormId() {
Carsten  Rose's avatar
Carsten Rose committed
33
        $build = new BuildFormPlain([F_DB_INDEX => DB_INDEX_DEFAULT], array(), array(), $this->dbArray);
34
35
36
37
38
39
40
41
42

        $formId1 = $build->getFormId();
        $this->assertRegExp('/qfq-form-[0-9a-f]{13}/', $formId1);

        $formId2 = $build->getFormId();
        $this->assertEquals($formId1, $formId2);

    }

43
    /**
Carsten  Rose's avatar
Carsten Rose committed
44
45
46
     * @throws CodeException
     * @throws UserFormException
     * @throws UserReportException
47
     */
48
    public function testWrapItem() {
Carsten  Rose's avatar
Carsten Rose committed
49
        $build = new BuildFormPlain([F_DB_INDEX => DB_INDEX_DEFAULT], array(), array(), $this->dbArray);
50
51
52
53
54
55
56
57
58
59
60
61
62
63

        $result = $build->wrapItem(WRAP_SETUP_ELEMENT, 'Hello World', false);
        $this->assertEquals('<p>Hello World</p>', $result);

        $result = $build->wrapItem(WRAP_SETUP_ELEMENT, 'Hello World', true);
        $this->assertEquals('<p>Hello World</p>', $result);

        $result = $build->wrapItem(WRAP_SETUP_ELEMENT, '', false);
        $this->assertEquals('<p></p>', $result);

        $result = $build->wrapItem(WRAP_SETUP_ELEMENT, '', true);
        $this->assertEquals('', $result);
    }

64
    /**
Carsten  Rose's avatar
Carsten Rose committed
65
66
67
     * @throws CodeException
     * @throws UserFormException
     * @throws UserReportException
68
     */
69
    public function testBuildLabel() {
Carsten  Rose's avatar
Carsten Rose committed
70
        $build = new BuildFormPlain([F_DB_INDEX => DB_INDEX_DEFAULT], array(), array(), $this->dbArray);
71
72

        $result = $build->buildLabel('myLabel:123', "Hello World");
73
        $this->assertEquals('<label for="myLabel:123" class="control-label" >Hello World</label>', $result);
74
75
    }

76
    /**
Carsten  Rose's avatar
Carsten Rose committed
77
78
79
     * @throws CodeException
     * @throws UserFormException
     * @throws UserReportException
80
     */
81
82
83
    public function testBuildInput() {
        $form = array();
        $formElement = array();
Carsten  Rose's avatar
Carsten Rose committed
84
        $json = array();
85

86
        $this->templateFormNFormElement($form, $formElement);
87

88
        $build = new BuildFormPlain($form, array(), [$formElement], $this->dbArray);
Elias Villiger's avatar
Elias Villiger committed
89
        $formElement[FE_CHECK_TYPE] = SANITIZE_ALLOW_ALL;
Carsten  Rose's avatar
Carsten Rose committed
90
        $formElement[FE_DECIMAL_FORMAT] = '';
91

92
        $label['123-l'][API_ELEMENT_CONTENT] = '<label for="name:1" class="control-label" >Name</label>';
Carsten  Rose's avatar
Carsten Rose committed
93
94
//        $label['123'][API_ELEMENT_ATTRIBUTE] = ['value' => ''];
        $label['123'][API_ELEMENT_ATTRIBUTE] = ['value' => '', 'required' => false, 'hidden' => false];
Carsten  Rose's avatar
Carsten Rose committed
95
        $label['123-r'][API_ELEMENT_ATTRIBUTE] = ['class' => ''];
96

Carsten  Rose's avatar
Carsten Rose committed
97
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
98
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" data-pattern-error="pattern error" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
Carsten  Rose's avatar
Carsten Rose committed
99
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
100

101
        // Min/Max
102
103
        $formElement[FE_MIN] = '1';
        $formElement[FE_MAX] = '10';
Carsten  Rose's avatar
Carsten Rose committed
104
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
105
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="number" value="" data-pattern-error="pattern error" data-required-error="data required" min="1" max="10" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
106
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
107

108
        $formElement[FE_MIN] = '1';
109
110
        $formElement[FE_MAX] = '';
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
111
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" data-pattern-error="pattern error" data-required-error="data required" min="1" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
112
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
113
114

        $formElement[FE_MIN] = '';
115
        $formElement[FE_MAX] = '10';
116
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
117
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" data-pattern-error="pattern error" data-required-error="data required" max="10" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
118
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
119
120
121
122
123
124
125
126
127
128
129
130
131

        $formElement[FE_MIN] = '0';
        $formElement[FE_MAX] = '10';
        $result = $build->buildInput($formElement, 'name:1', '', $json);
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" data-pattern-error="pattern error" data-required-error="data required" min="0" max="10" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);

        $formElement[FE_MIN] = '-5';
        $formElement[FE_MAX] = '0';
        $result = $build->buildInput($formElement, 'name:1', '', $json);
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" data-pattern-error="pattern error" data-required-error="data required" min="-5" max="0" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);

132
133
134
        // reset so they don't interfere with next tests
        $formElement[FE_MIN] = '';
        $formElement[FE_MAX] = '';
135
136

        // CheckType
137
138
        $formElement[FE_CHECK_TYPE] = SANITIZE_ALLOW_PATTERN;
        $formElement[FE_CHECK_PATTERN] = '^[a-z]*$';
Carsten  Rose's avatar
Carsten Rose committed
139
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
140
141
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" pattern="^[a-z]*$" data-pattern-error="pattern error" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
        $label['123'][API_ELEMENT_ATTRIBUTE]['pattern'] = '^[a-z]*$';
142
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
143

144
145
        $formElement[FE_CHECK_TYPE] = SANITIZE_ALLOW_DIGIT;
        $formElement[FE_CHECK_PATTERN] = '';
Carsten  Rose's avatar
Carsten Rose committed
146
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
147
148
149
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" pattern="^[\d]*$" data-pattern-error="Allowed characters: 0...9" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);

        $label['123'][API_ELEMENT_ATTRIBUTE]['pattern'] = '^[\d]*$';
150
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
151

152
153
        $formElement[FE_CHECK_TYPE] = SANITIZE_ALLOW_EMAIL;
        $formElement[FE_CHECK_PATTERN] = '';
Carsten  Rose's avatar
Carsten Rose committed
154
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
155
156
        $label['123'][API_ELEMENT_ATTRIBUTE]['pattern'] = '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$';
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" data-pattern-error="Requested format: string@domain.tld" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
157
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
158

159
        $formElement[FE_CHECK_TYPE] = SANITIZE_ALLOW_ALL;
160
        $formElement[FE_CHECK_PATTERN] = '';
161
162


163
164
165
        // Decimal format
        $formElement[FE_DECIMAL_FORMAT] = '5,2';
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
166
167
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" pattern="^-?[0-9]{0,3}(\.[0-9]{0,2})?$" data-pattern-error="Requested decimal format (mantis,decimal): 5,2" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
        $label['123'][API_ELEMENT_ATTRIBUTE]['pattern'] = '^-?[0-9]{0,3}(\.[0-9]{0,2})?$';
168
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
169
170
171
172
173

        $formElement[FE_DECIMAL_FORMAT] = '';


        // Explicit size
174
175
        $formElement['size'] = 40;
        $formElement['maxLength'] = 40;
Carsten  Rose's avatar
Carsten Rose committed
176
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
177
178
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="40" type="input" size="40" value="" data-pattern-error="pattern error" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
        unset($label['123'][API_ELEMENT_ATTRIBUTE]['pattern']);
179
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
180
181

        // maxlength bigger than physical spec:
182
        $formElement['maxLength'] = 1000;
Carsten  Rose's avatar
Carsten Rose committed
183
        $result = $build->buildInput($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
184
        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="1000" type="input" size="40" value="" data-pattern-error="pattern error" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
185
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
186

187
188
189
190
191
192
        // no size, no maxlength and column not in primary table
        $formElement2 = $formElement;
        $formElement2['maxLength'] = '';
        $formElement2['size'] = '';
        $formElement2['name'] = 'specialname';
        $result = $build->buildInput($formElement2, 'specialname:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
193
        $this->assertEquals('<input id="123" name="specialname:1" class="form-control" type="input" value="" data-pattern-error="pattern error" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
194
195
196
197

        // no size,  given maxlength and column not in primary table
        $formElement2['maxLength'] = '10';
        $result = $build->buildInput($formElement2, 'specialname:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
198
        $this->assertEquals('<input id="123" name="specialname:1" class="form-control" maxlength="10" type="input" value="" data-pattern-error="pattern error" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
199
200
201
202
203

        // size given, no maxlength and column not in primary table
        $formElement2['maxLength'] = '';
        $formElement2['size'] = '10';
        $result = $build->buildInput($formElement2, 'specialname:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
204
        $this->assertEquals('<input id="123" name="specialname:1" class="form-control" type="input" size="10" value="" data-pattern-error="pattern error" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
205
206
207
208
209

        // size given, maxlength given and column not in primary table
        $formElement2['maxLength'] = '20';
        $formElement2['size'] = '10';
        $result = $build->buildInput($formElement2, 'specialname:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
210
        $this->assertEquals('<input id="123" name="specialname:1" class="form-control" maxlength="20" type="input" size="10" value="" data-pattern-error="pattern error" data-required-error="data required" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
211
212
        $formElement2['maxLength'] = '';
        $formElement2['size'] = '';
213

214
        // Explicit: further
215
216
217
        $formElement2['tooltip'] = 'Nice Tooltip';
        $formElement2['placeholder'] = 'Please type a name';
        $result = $build->buildInput($formElement2, 'name:1', 'Hello World', $json);
Carsten  Rose's avatar
Carsten Rose committed
218
219
        $this->assertEquals('<input id="123" name="name:1" class="form-control" type="input" value="Hello World" placeholder="Please type a name" data-pattern-error="pattern error" data-required-error="data required" title="Nice Tooltip" data-hidden="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
        $label['123'][API_ELEMENT_ATTRIBUTE] = ['value' => 'Hello World', 'required' => false, 'hidden' => false];
220
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => 'Hello World', API_ELEMENT_UPDATE => $label], $json);
221
222

        // textarea
223
224
        $formElement2['size'] = '40,10';
        $result = $build->buildInput($formElement2, 'name:1', 'Hello World', $json);
Carsten  Rose's avatar
Carsten Rose committed
225
        $this->assertEquals('<textarea id="123" name="name:1" class="form-control" cols="40" rows="10" placeholder="Please type a name" data-pattern-error="pattern error" data-required-error="data required" title="Nice Tooltip" data-hidden="no" data-required="no" >Hello World</textarea><div class="help-block with-errors hidden"></div>', $result);
226

227
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => 'Hello World', API_ELEMENT_UPDATE => $label], $json);
228

229
230
        $formElement2['size'] = ' 40     , 10 ';
        $result = $build->buildInput($formElement2, 'name:1', 'Hello World', $json);
Carsten  Rose's avatar
Carsten Rose committed
231
        $this->assertEquals('<textarea id="123" name="name:1" class="form-control" cols="40" rows="10" placeholder="Please type a name" data-pattern-error="pattern error" data-required-error="data required" title="Nice Tooltip" data-hidden="no" data-required="no" >Hello World</textarea><div class="help-block with-errors hidden"></div>', $result);
232
        $this->assertEquals(['disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => 'Hello World', API_ELEMENT_UPDATE => $label], $json);
233
234
    }

235
    /**
Carsten  Rose's avatar
Carsten Rose committed
236
237
238
     * @throws CodeException
     * @throws UserFormException
     * @throws UserReportException
239
     */
240
241
242
243
    public function testGetKeyValueListFromSqlEnumSpec() {
        $form = array();
        $formElement = array();

244
        $this->templateFormNFormElement($form, $formElement);
245
246
        $formElement['name'] = 'deleted';

Carsten  Rose's avatar
Carsten Rose committed
247
        $build = new BuildFormPlain($form, array(), [$formElement], $this->dbArray);
248
249
250
251
252
253
254
255
256
257
258
259

        $keys = array();
        $values = array();

        // Spec Enum
        $expect = ['yes', 'no'];
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expect, $keys);
        $this->assertEquals($expect, $values);

        // Spec Enum + emptyItemAtStart
        $expect = ['', 'yes', 'no'];
260
        $formElement[FE_EMPTY_ITEM_AT_START] = '';
261
262
263
264
265
266
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expect, $keys);
        $this->assertEquals($expect, $values);

        // Spec Enum + emptyItemAtEnd
        $expect = ['', 'yes', 'no', ''];
267
        $formElement[FE_EMPTY_ITEM_AT_END] = '';
268
269
270
271
272
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expect, $keys);
        $this->assertEquals($expect, $values);

        // clean
273
274
        unset($formElement[FE_EMPTY_ITEM_AT_START]);
        unset($formElement[FE_EMPTY_ITEM_AT_END]);
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

        // listItem: only value
        $expect = ['a', 'b', 'c'];
        $formElement['itemList'] = 'a,b,c';
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expect, $keys);
        $this->assertEquals($expect, $values);

        // listItem: key/value
        $expectKeys = ['A', 'B', 'C'];
        $expectValues = ['a', 'b', 'c'];
        $formElement['itemList'] = 'A:a,B:b,C:c';
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expectKeys, $keys);
        $this->assertEquals($expectValues, $values);

        // listItem: key/value + emptyItemAtEnd
        $formElement['emptyItemAtEnd'] = '';
        $expectKeys = ['A', 'B', 'C', ''];
        $expectValues = ['a', 'b', 'c', ''];
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expectKeys, $keys);
        $this->assertEquals($expectValues, $values);
        unset($formElement['emptyItemAtEnd']);

300
        // SQL: any content is fine, but should always be the same to do checks
301
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT name FROM Form AS f ORDER BY f.id LIMIT 3');
Carsten  Rose's avatar
Carsten Rose committed
302
//        $expect = ['form', 'formElement', 'phpunit_person'];
303
        $expect = ['form', 'formElement', 'copyForm'];
304
305
306
307
308
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expect, $keys);
        $this->assertEquals($expect, $values);

        // SQL (one column, no keyword) + emptyItemAtStart
309
        $formElement[FE_EMPTY_ITEM_AT_START] = '';
310
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT name FROM Form AS f ORDER BY f.id LIMIT 3');
Carsten  Rose's avatar
Carsten Rose committed
311
//        $expect = ['', 'form', 'formElement', 'phpunit_person'];
312
        $expect = ['', 'form', 'formElement', 'copyForm'];
313
314
315
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expect, $keys);
        $this->assertEquals($expect, $values);
Carsten  Rose's avatar
Carsten Rose committed
316
        unset($formElement[FE_EMPTY_ITEM_AT_START]);
317
318

        // SQL (4 columns, none 'id' nor 'label') - Take the first two columns
319
320
        $expectKeys = ['100', '200', '300'];
        $expectValues = ['basic', 'formelement', 'layout'];
321
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT ord, name, created, modified  FROM FormElement AS fe ORDER BY fe.id LIMIT 3');
322
323
324
325
326
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expectKeys, $keys);
        $this->assertEquals($expectValues, $values);

        // SQL (4 columns, none 'id', one 'label' ) - Take the first and the fourth two columns
327
328
        $expectKeys = ['100', '200', '300'];
        $expectValues = ['basic',  'formelement', 'layout'];
329
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT ord, created, modified, name AS label FROM FormElement AS fe ORDER BY fe.id LIMIT 3');
330
331
332
333
334
335
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expectKeys, $keys);
        $this->assertEquals($expectValues, $values);

        // SQL (4 columns, none 'id', one 'label' ) - Take the first and the fourth two columns
        $expectKeys = ['1', '2', '3'];
336
        $expectValues = ['basic',  'formelement', 'layout'];
337
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT ord, created, modified, name AS label, id FROM FormElement AS fe ORDER BY fe.id LIMIT 3');
338
339
340
341
342
343
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
        $this->assertEquals($expectKeys, $keys);
        $this->assertEquals($expectValues, $values);
    }

    /**
Carsten  Rose's avatar
Carsten Rose committed
344
     * @expectedException \qfq\UserFormException
345
     *
Carsten  Rose's avatar
Carsten Rose committed
346
347
348
     * @throws CodeException
     * @throws UserFormException
     * @throws UserReportException
349
350
351
352
353
     */
    public function testGetKeyValueListFromSqlEnumSpecException() {
        $form = array();
        $formElement = array();

354
        $this->templateFormNFormElement($form, $formElement);
355

Carsten  Rose's avatar
Carsten Rose committed
356
        $build = new BuildFormPlain($form, array(), [$formElement], $this->dbArray);
357
358

        $formElement['name'] = 'noteInternal';
359
360
        $keys = array();
        $values = array();
361
362
363
        $build->getKeyValueListFromSqlEnumSpec($formElement, $keys, $values);
    }

364
365

    /**
Carsten  Rose's avatar
Carsten Rose committed
366
367
368
369
     * @throws CodeException
     * @throws DbException
     * @throws UserFormException
     * @throws UserReportException
370
371
372
373
374
375
376
     */
    public function testBuildSubrecord() {
        $form = array();
        $formElement = array();
        $json = array();

        $this->templateFormNFormElement($form, $formElement);
Carsten  Rose's avatar
Carsten Rose committed
377
        $formElement = Support::setFeDefaults($formElement);
Carsten  Rose's avatar
Carsten Rose committed
378

379
        // CheckType
Carsten  Rose's avatar
Carsten Rose committed
380
        $build = new BuildFormPlain($form, array(), [$formElement], $this->dbArray);
381
382

        // id: 1, firstName: John, name: Doe
383
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id, name, firstName FROM Person ORDER BY id LIMIT 2');
Carsten  Rose's avatar
Carsten Rose committed
384
        $formElement[SUBRECORD_PARAMETER_FORM] = 'Person';
Carsten  Rose's avatar
Carsten Rose committed
385
        $formElement[FE_SUBRECORD_OPTION] = '';
Carsten  Rose's avatar
Carsten Rose committed
386

387
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
388
        $this->assertEquals('<table class="table table-hover qfq-subrecord-table" ><thead><tr><th>id</th><th>name</th><th>firstName</th></tr></thead><tbody ><tr class="record" ><td><span class="text-muted">1</span></td><td>Doe</td><td>John</td></tr><tr class="record" ><td><span class="text-muted">2</span></td><td>Smith</td><td>Jane</td></tr></tbody></table>', $result);
389
390

        $this->store->setStore(['id' => 1], STORE_RECORD, true);
391
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
392
        $this->assertEquals('<table class="table table-hover qfq-subrecord-table" ><thead><tr><th>id</th><th>name</th><th>firstName</th></tr></thead><tbody ><tr class="record" ><td><span class="text-muted">1</span></td><td>Doe</td><td>John</td></tr><tr class="record" ><td><span class="text-muted">2</span></td><td>Smith</td><td>Jane</td></tr></tbody></table>', $result);
393
394

        // _id: 1, name: Doe,
395
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name FROM Person ORDER BY id LIMIT 2');
396
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
397
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>name</th></tr></thead><tbody ><tr class="record" ><td>Doe</td></tr><tr class="record" ><td>Smith</td></tr></tbody></table>', $result);
398

399
        // _id: 1, name: Doe,title=''
400
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name AS "title=" FROM Person ORDER BY id LIMIT 2');
401
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
402
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th></th></tr></thead><tbody ><tr class="record" ><td>Doe</td></tr><tr class="record" ><td>Smith</td></tr></tbody></table>', $result);
403
404

        // _id: 1, name: Doe, column: _Person
405
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name AS "unused|width=2|title=_Person", firstName  FROM Person ORDER BY id LIMIT 2');
406
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
407
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>firstName</th></tr></thead><tbody ><tr class="record" ><td>John</td></tr><tr class="record" ><td>Jane</td></tr></tbody></table>', $result);
408

409
        // _id: 1, name: Doe, title: PERSON
410
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name AS "PERSON" FROM Person ORDER BY id LIMIT 2');
411
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
412
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>PERSON</th></tr></thead><tbody ><tr class="record" ><td>Doe</td></tr><tr class="record" ><td>Smith</td></tr></tbody></table>', $result);
413
414

        // _id: 1, "This is a much longer text than necessary": Default max:20
415
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", "This is a much longer text than necessary" FROM Person ORDER BY id LIMIT 1');
416
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
417
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>This is a much longe</th></tr></thead><tbody ><tr class="record" ><td>This is a much longe</td></tr></tbody></table>', $result);
418
419

        // _id: 1, name: Jo (width:2)
420
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name AS "2" FROM Person ORDER BY id LIMIT 2');
421
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
422
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th></th></tr></thead><tbody ><tr class="record" ><td>Do</td></tr><tr class="record" ><td>Sm</td></tr></tbody></table>', $result);
423
424

        // _id: 1, name: Jo (width:2)
425
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name AS "2|PERSON" FROM Person ORDER BY id LIMIT 2');
426
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
427
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>PE</th></tr></thead><tbody ><tr class="record" ><td>Do</td></tr><tr class="record" ><td>Sm</td></tr></tbody></table>', $result);
428
429

        // _id: 1, name: Doe ('width':3)
430
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name AS "Name|width=3" FROM Person ORDER BY id LIMIT 2');
431
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
432
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>Nam</th></tr></thead><tbody ><tr class="record" ><td>Doe</td></tr><tr class="record" ><td>Smi</td></tr></tbody></table>', $result);
433
434

        // _id: 1, name: Doe (width:3, title:PERSON)
435
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name AS "3|title=PERSON" FROM Person ORDER BY id LIMIT 2');
436
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
437
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>PER</th></tr></thead><tbody ><tr class="record" ><td>Doe</td></tr><tr class="record" ><td>Smi</td></tr></tbody></table>', $result);
438
439

        // _id: 1, name: <b>Doe</b>
440
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", CONCAT("<b>", name, "</b>") AS "Name" FROM Person ORDER BY id LIMIT 2');
441
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
442
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>Name</th></tr></thead><tbody ><tr class="record" ><td>Doe</td></tr><tr class="record" ><td>Smith</td></tr></tbody></table>', $result);
443

444
        // _id: 1, name: <b>Doe</b>, width=2
445
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", CONCAT("<b>", name, "</b>") AS "Name|2" FROM Person ORDER BY id LIMIT 2');
446
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
447
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>Na</th></tr></thead><tbody ><tr class="record" ><td>Do</td></tr><tr class="record" ><td>Sm</td></tr></tbody></table>', $result);
448

449
        // _id: 1, name: <b>Doe</b> , nostrip
450
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", CONCAT("<b>", name, "</b>") AS "Name|nostrip" FROM Person ORDER BY id LIMIT 2');
451
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
452
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>Name</th></tr></thead><tbody ><tr class="record" ><td><b>Doe</b></td></tr><tr class="record" ><td><b>Smith</b></td></tr></tbody></table>', $result);
453
454

        // _id: 1, icon: bullet-green.gif
455
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", "bullet-green.gif" AS "Status|icon" FROM Person ORDER BY id LIMIT 2');
456
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
457
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>Status</th></tr></thead><tbody ><tr class="record" ><td><image src=\'typo3conf/ext/qfq/Resources/Public/icons/bullet-green.gif\'></td></tr><tr class="record" ><td><image src=\'typo3conf/ext/qfq/Resources/Public/icons/bullet-green.gif\'></td></tr></tbody></table>', $result);
458
459

        // _id: 1, mailto: john@doe.com
460
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", "john@doe.com" AS "EMail|mailto" FROM Person ORDER BY id LIMIT 2');
461
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
462
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>EMail</th></tr></thead><tbody ><tr class="record" ><td><a href="mailto:john@doe.com" >john@doe.com</a></td></tr><tr class="record" ><td><a href="mailto:john@doe.com" >john@doe.com</a></td></tr></tbody></table>', $result);
463
464

        // _id: 1, url: www.uzh.ch
465
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", "www.uzh.ch" AS "URL|url" FROM Person ORDER BY id LIMIT 2');
466
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
467
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>URL</th></tr></thead><tbody ><tr class="record" ><td><a href="www.uzh.ch" >www.uzh.ch</a></td></tr><tr class="record" ><td><a href="www.uzh.ch" >www.uzh.ch</a></td></tr></tbody></table>', $result);
468
469

        // _id: 1, name: Doe, _rowclass (text)
470
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name, IF(id=1,"text-warning", "text-danger") AS _rowClass FROM Person ORDER BY id LIMIT 2');
471
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
472
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>name</th></tr></thead><tbody ><tr class="record text-warning" ><td>Doe</td></tr><tr class="record text-danger" ><td>Smith</td></tr></tbody></table>', $result);
473
474

        // _id: 1, name: Doe, _rowClass (text & background)
475
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name, IF(id=1,"text-warning active", "text-danger success") AS _rowClass FROM Person ORDER BY id LIMIT 2');
476
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
477
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>name</th></tr></thead><tbody ><tr class="record text-warning active" ><td>Doe</td></tr><tr class="record text-danger success" ><td>Smith</td></tr></tbody></table>', $result);
478
479

        // _id: 1, name: Doe, _rowTitle
480
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name, firstName AS _rowTitle FROM Person ORDER BY id LIMIT 2');
481
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
482
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>name</th></tr></thead><tbody ><tr class="record" title="John" ><td>Doe</td></tr><tr class="record" title="Jane" ><td>Smith</td></tr></tbody></table>', $result);
483
484

        // _id: 1, name: Doe, title, width, nostrip
485
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name, "<b>This again is a very long text</b>" AS "title=Important|width=10|nostrip" FROM Person ORDER BY id LIMIT 2');
486
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
487
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>name</th><th>Important</th></tr></thead><tbody ><tr class="record" ><td>Doe</td><td><b>This again is a very long text</b></td></tr><tr class="record" ><td>Smith</td><td><b>This again is a very long text</b></td></tr></tbody></table>', $result);
488
489

        // _id: 1, name: Doe, link
490
        $formElement['sql1'] = $this->dbArray[DB_INDEX_DEFAULT]->sql('SELECT id AS "_id", name, CONCAT("s:1|p:form&form=person&r=" , id , "|t:", name) AS "link" FROM Person ORDER BY id LIMIT 2');
491
        $result = $build->buildSubrecord($formElement, 'name:1', '', $json);
Carsten  Rose's avatar
Carsten Rose committed
492
        $this->assertEquals('<table class="' . SUBRECORD_TABLE_CLASS_DEFAULT . '" ><thead><tr><th>name</th><th></th></tr></thead><tbody ><tr class="record" ><td>Doe</td><td><a href="index.php?id=form&s=badcaffee1234" >Doe</a></td></tr><tr class="record" ><td>Smith</td><td><a href="index.php?id=form&s=badcaffee1234" >Smith</a></td></tr></tbody></table>', $result);
493
494
    }

495
    /**
496
497
     * @param array $form
     * @param array $formElement
498
499
500
     */
    private function templateFormNFormElement(array &$form, array &$formElement) {
        $form = [
Carsten  Rose's avatar
Carsten Rose committed
501
502
503
504
505
506
507
            'id' => '1',
            'name' => 'form',
            'title' => 'Form Editor: {{SELECT id, " / ", title FROM Form WHERE id => {{recordId:S0}}}}',
            'noteInternal' => 'Please secure the form',
            'tableName' => 'Form',
            'permitNew' => 'always',
            'permitEdit' => 'always',
508
            'permitUrlParameter' => '',
Carsten  Rose's avatar
Carsten Rose committed
509
510
511
            'render' => 'bootstrap',
            'multiMode' => 'none',
            'multiSql' => '',
512
513
            'multiDetailForm' => '',
            'multiDetailFormParameter' => '',
Carsten  Rose's avatar
Carsten Rose committed
514
515
516
517
518
519
520
            F_FORWARD_MODE => 'auto',
            F_FORWARD_PAGE => '',
            'bsLabelColumns' => '',
            'bsInputColumns' => '',
            'bsNoteColumns' => '',
            'parameter' => 'maxVisiblePill=>3',
            'deleted' => 'no',
Carsten  Rose's avatar
Carsten Rose committed
521
            F_DB_INDEX => DB_INDEX_DEFAULT,
522
523
524
        ];

        $formElement = [
Carsten  Rose's avatar
Carsten Rose committed
525
            'id' => 123,
Carsten  Rose's avatar
Carsten Rose committed
526
            FE_FORM_ID => 1,
527
528
            FE_ID_CONTAINER => 0,
            FE_DYNAMIC_UPDATE => 'no',
Carsten  Rose's avatar
Carsten Rose committed
529
530
531
532
            'enabled' => 'yes',
            FE_NAME => 'name',
            FE_LABEL => 'Name',
            FE_MODE => 'show',
Carsten  Rose's avatar
Carsten Rose committed
533
            FE_MODE_SQL => '',
Carsten  Rose's avatar
Carsten Rose committed
534
535
536
537
538
539
540
541
542
543
544
545
            'class' => 'native',
            FE_TYPE => 'input',
            'value' => '',
            'sql1' => '',
            'parameter' => '',
            'debug' => 'no',
            'deleted' => 'no',
            'size' => '',
            'maxLength' => '255',
            'tooltip' => '',
            'placeholder' => '',
            FE_CHECK_TYPE => '',
546
            FE_CHECK_PATTERN => '',
Carsten  Rose's avatar
Carsten Rose committed
547
548
            FE_HTML_ID => '123',
            FE_HIDE_ZERO => '0',
Carsten  Rose's avatar
Carsten Rose committed
549
            FE_DATA_REFERENCE => '',
550

Carsten  Rose's avatar
Carsten Rose committed
551
            'tabindex' => 0,
552
553
554
555
556
557
558
559
560
561
562
563
564
        ];

    }

//    /**
//     * @throws Exception
//     */
//    protected function setUp() {
//        parent::setUp();
//
//        $this->executeSQLFile(__DIR__ . '/fixtures/Generic.sql', true);
//    }

565
566
567
568
569
    /**
     */
    protected function setUp() {
        $_GET['form'] = 'phpunit_person';

570
571
        try {
            parent::setUp();
572

573
574
575
576
            // Use always the latest (production) FormEditor: played during QuickFormQuery()
            $this->dbArray[DB_INDEX_DEFAULT]->sql("DROP TABLE IF EXISTS `Form`");
            $this->dbArray[DB_INDEX_DEFAULT]->sql("DROP TABLE IF EXISTS `FormElement`");
            $this->executeSQLFile(__DIR__ . '/../../../Source/sql/formEditor.sql', true);
577

578
579
580
            $this->store->unsetStore(STORE_ADDITIONAL_FORM_ELEMENTS);
            $this->executeSQLFile(__DIR__ . '/database/fixtures/Generic.sql', true);
            $this->executeSQLFile(__DIR__ . '/database/fixtures/TestForm.sql', true);
581

582
583
584
            // Defaults
            $this->store->setVar('name', 'varchar(255)', STORE_TABLE_COLUMN_TYPES, true);
            $this->store->setVar('deleted', "enum('yes','no')", STORE_TABLE_COLUMN_TYPES, true);
585
586
587
//        $this->store->setVar(SYSTEM_DB_INDEX_DATA, DB_INDEX_DEFAULT, true);
//        $this->store->setVar(SYSTEM_DB_INDEX_QFQ, DB_INDEX_DEFAULT, true);

588

589
            $GLOBALS["TSFE"] = new FakeTSFEBuildPlain();
590

591
            $form = new QuickFormQuery(['bodytext' => "form=form\nr=3", 'uid' => 1234], true);
Carsten  Rose's avatar
Carsten Rose committed
592

593
594
595
596
597
598
            // After instantiating QuickFormQuery, the latest updates will be played. The SIP is by default activated which breaks current tests.
            $this->dbArray[DB_INDEX_DEFAULT]->sql("UPDATE Form SET permitNew='always', permitEdit='always' WHERE name='form' ");
            $form->process();
        } catch (\Exception $e) {
            echo 'unhandled exception';
        }
599
600
    }
}
601

602
603
604
/**
 * Class FakeTSFEBuildPlain
 */
605
class FakeTSFEBuildPlain {
606
    public $id = 1;
607
608
    public $type = 1;
    public $sys_language_uid = 1;
609
610
}

611

612