Passed
Push — 4.1 ( 802261...1362b2 )
by
unknown
15:08 queued 06:46
created

DBFieldTest::testPrepValueForDBArrayValue()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 1
nop 3
dl 0
loc 15
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ORM\Tests;
4
5
use SilverStripe\Assets\Image;
6
use SilverStripe\ORM\FieldType\DBBigInt;
7
use SilverStripe\ORM\FieldType\DBBoolean;
8
use SilverStripe\ORM\FieldType\DBCurrency;
9
use SilverStripe\ORM\FieldType\DBDate;
10
use SilverStripe\ORM\FieldType\DBDatetime;
11
use SilverStripe\ORM\FieldType\DBDecimal;
12
use SilverStripe\ORM\FieldType\DBDouble;
13
use SilverStripe\ORM\FieldType\DBEnum;
14
use SilverStripe\ORM\FieldType\DBFloat;
15
use SilverStripe\ORM\FieldType\DBForeignKey;
16
use SilverStripe\ORM\FieldType\DBHTMLText;
17
use SilverStripe\ORM\FieldType\DBHTMLVarchar;
18
use SilverStripe\ORM\FieldType\DBInt;
19
use SilverStripe\ORM\FieldType\DBLocale;
20
use SilverStripe\ORM\FieldType\DBMoney;
21
use SilverStripe\ORM\FieldType\DBMultiEnum;
22
use SilverStripe\ORM\FieldType\DBPercentage;
23
use SilverStripe\ORM\FieldType\DBPolymorphicForeignKey;
24
use SilverStripe\ORM\FieldType\DBPrimaryKey;
25
use SilverStripe\ORM\FieldType\DBString;
26
use SilverStripe\ORM\FieldType\DBTime;
27
use SilverStripe\ORM\FieldType\DBVarchar;
28
use SilverStripe\ORM\FieldType\DBText;
29
use SilverStripe\Dev\SapphireTest;
30
use SilverStripe\ORM\FieldType\DBYear;
31
32
/**
33
 * Tests for DBField objects.
34
 */
35
class DBFieldTest extends SapphireTest
36
{
37
38
    /**
39
     * Test the nullValue() method on DBField.
40
     */
41
    public function testNullValue()
42
    {
43
        /* Float and Double use 0 for "null" value representation */
44
        $this->assertEquals(0, singleton('Float')->nullValue());
45
        $this->assertEquals(0, singleton('Double')->nullValue());
46
    }
47
48
    /**
49
     * Test the prepValueForDB() method on DBField.
50
     */
51
    public function testPrepValueForDB()
52
    {
53
        /* Float behaviour, asserting we have 0 */
54
        $float = DBFloat::create();
55
        $this->assertEquals(0, $float->prepValueForDB(0));
56
        $this->assertEquals(0, $float->prepValueForDB(null));
57
        $this->assertEquals(0, $float->prepValueForDB(false));
58
        $this->assertEquals(0, $float->prepValueForDB(''));
59
        $this->assertEquals('0', $float->prepValueForDB('0'));
60
61
        /* Double behaviour, asserting we have 0 */
62
        $double = DBDouble::create();
63
        $this->assertEquals(0, $double->prepValueForDB(0));
64
        $this->assertEquals(0, $double->prepValueForDB(null));
65
        $this->assertEquals(0, $double->prepValueForDB(false));
66
        $this->assertEquals(0, $double->prepValueForDB(''));
67
        $this->assertEquals('0', $double->prepValueForDB('0'));
68
69
        /* Integer behaviour, asserting we have 0 */
70
        $int = singleton('Int');
71
        $this->assertEquals(0, $int->prepValueForDB(0));
72
        $this->assertEquals(0, $int->prepValueForDB(null));
73
        $this->assertEquals(0, $int->prepValueForDB(false));
74
        $this->assertEquals(0, $int->prepValueForDB(''));
75
        $this->assertEquals(0, $int->prepValueForDB('0'));
76
77
        /* Integer behaviour, asserting we have 1 */
78
        $this->assertEquals(1, $int->prepValueForDB(true));
79
        $this->assertEquals(1, $int->prepValueForDB(1));
80
        $this->assertEquals(1, $int->prepValueForDB('1'));
81
82
        /* Decimal behaviour, asserting we have 0 */
83
        $decimal = DBDecimal::create();
84
        $this->assertEquals(0, $decimal->prepValueForDB(0));
85
        $this->assertEquals(0.0, $decimal->prepValueForDB(0.0));
86
        $this->assertEquals(0, $decimal->prepValueForDB(null));
87
        $this->assertEquals(0, $decimal->prepValueForDB(false));
88
        $this->assertEquals(0, $decimal->prepValueForDB(''));
89
        $this->assertEquals(0, $decimal->prepValueForDB('0'));
90
        $this->assertEquals(0.0, $decimal->prepValueForDB('0.0'));
91
92
        /* Decimal behaviour, asserting we have 1 */
93
        $this->assertEquals(1, $decimal->prepValueForDB(true));
94
        $this->assertEquals(1, $decimal->prepValueForDB(1));
95
        $this->assertEquals(1.1, $decimal->prepValueForDB(1.1));
96
        $this->assertEquals(1, $decimal->prepValueForDB('1'));
97
        $this->assertEquals(1.1, $decimal->prepValueForDB('1.1'));
98
99
        /* Boolean behaviour, asserting we have 0 */
100
        $boolean = DBBoolean::create();
101
        $this->assertEquals(false, $boolean->prepValueForDB(0));
102
        $this->assertEquals(false, $boolean->prepValueForDB(null));
103
        $this->assertEquals(false, $boolean->prepValueForDB(false));
104
        $this->assertEquals(false, $boolean->prepValueForDB('false'));
105
        $this->assertEquals(false, $boolean->prepValueForDB('f'));
106
        $this->assertEquals(false, $boolean->prepValueForDB(''));
107
        $this->assertEquals(false, $boolean->prepValueForDB('0'));
108
109
        /* Boolean behaviour, asserting we have 1 */
110
        $this->assertEquals(true, $boolean->prepValueForDB(true));
111
        $this->assertEquals(true, $boolean->prepValueForDB('true'));
112
        $this->assertEquals(true, $boolean->prepValueForDB('t'));
113
        $this->assertEquals(true, $boolean->prepValueForDB(1));
114
        $this->assertEquals(true, $boolean->prepValueForDB('1'));
115
116
        // @todo - Revisit Varchar to evaluate correct behaviour of nullifyEmpty
117
118
        /* Varchar behaviour: nullifyifEmpty defaults to true */
119
        $varchar = DBVarchar::create();
120
        $this->assertEquals(0, $varchar->prepValueForDB(0));
121
        $this->assertEquals(null, $varchar->prepValueForDB(null));
122
        $this->assertEquals(null, $varchar->prepValueForDB(false));
123
        $this->assertEquals(null, $varchar->prepValueForDB(''));
124
        $this->assertEquals('0', $varchar->prepValueForDB('0'));
125
        $this->assertEquals(1, $varchar->prepValueForDB(1));
126
        $this->assertEquals(true, $varchar->prepValueForDB(true));
127
        $this->assertEquals('1', $varchar->prepValueForDB('1'));
128
        $this->assertEquals('00000', $varchar->prepValueForDB('00000'));
129
        $this->assertEquals(0, $varchar->prepValueForDB(0000));
130
        $this->assertEquals('test', $varchar->prepValueForDB('test'));
131
        $this->assertEquals(123, $varchar->prepValueForDB(123));
132
133
        /* AllowEmpty Varchar behaviour */
134
        $varcharField = DBVarchar::create("testfield", 50, array("nullifyEmpty"=>false));
135
        $this->assertSame('0', $varcharField->prepValueForDB(0));
136
        $this->assertSame(null, $varcharField->prepValueForDB(null));
137
        $this->assertSame('', $varcharField->prepValueForDB(false));
138
        $this->assertSame('', $varcharField->prepValueForDB(''));
139
        $this->assertSame('0', $varcharField->prepValueForDB('0'));
140
        $this->assertSame('1', $varcharField->prepValueForDB(1));
141
        $this->assertSame('1', $varcharField->prepValueForDB(true));
142
        $this->assertSame('1', $varcharField->prepValueForDB('1'));
143
        $this->assertSame('00000', $varcharField->prepValueForDB('00000'));
144
        $this->assertSame('0', $varcharField->prepValueForDB(0000));
145
        $this->assertSame('test', $varcharField->prepValueForDB('test'));
146
        $this->assertSame('123', $varcharField->prepValueForDB(123));
147
        unset($varcharField);
148
149
        /* Text behaviour */
150
        $text = DBText::create();
151
        $this->assertEquals('0', $text->prepValueForDB(0));
152
        $this->assertEquals(null, $text->prepValueForDB(null));
153
        $this->assertEquals(null, $text->prepValueForDB(false));
154
        $this->assertEquals(null, $text->prepValueForDB(''));
155
        $this->assertEquals('0', $text->prepValueForDB('0'));
156
        $this->assertEquals('1', $text->prepValueForDB(1));
157
        $this->assertEquals('1', $text->prepValueForDB(true));
158
        $this->assertEquals('1', $text->prepValueForDB('1'));
159
        $this->assertEquals('00000', $text->prepValueForDB('00000'));
160
        $this->assertEquals('0', $text->prepValueForDB(0000));
161
        $this->assertEquals('test', $text->prepValueForDB('test'));
162
        $this->assertEquals('123', $text->prepValueForDB(123));
163
164
        /* AllowEmpty Text behaviour */
165
        $textField = DBText::create("testfield", array("nullifyEmpty"=>false));
166
        $this->assertSame('0', $textField->prepValueForDB(0));
167
        $this->assertSame(null, $textField->prepValueForDB(null));
168
        $this->assertSame('', $textField->prepValueForDB(false));
169
        $this->assertSame('', $textField->prepValueForDB(''));
170
        $this->assertSame('0', $textField->prepValueForDB('0'));
171
        $this->assertSame('1', $textField->prepValueForDB(1));
172
        $this->assertSame('1', $textField->prepValueForDB(true));
173
        $this->assertSame('1', $textField->prepValueForDB('1'));
174
        $this->assertSame('00000', $textField->prepValueForDB('00000'));
175
        $this->assertSame('0', $textField->prepValueForDB(0000));
176
        $this->assertSame('test', $textField->prepValueForDB('test'));
177
        $this->assertSame('123', $textField->prepValueForDB(123));
178
        unset($textField);
179
180
        /* Time behaviour */
181
        $time = DBTime::create();
182
        $time->setValue('12:01am');
183
        $this->assertEquals("00:01:00", $time->getValue());
184
        $time->setValue('12:59am');
185
        $this->assertEquals("00:59:00", $time->getValue());
186
        $time->setValue('11:59am');
187
        $this->assertEquals("11:59:00", $time->getValue());
188
        $time->setValue('12:00pm');
189
        $this->assertEquals("12:00:00", $time->getValue());
190
        $time->setValue('12:59am');
191
        $this->assertEquals("00:59:00", $time->getValue());
192
        $time->setValue('1:00pm');
193
        $this->assertEquals("13:00:00", $time->getValue());
194
        $time->setValue('11:59pm');
195
        $this->assertEquals("23:59:00", $time->getValue());
196
        $time->setValue('12:00am');
197
        $this->assertEquals("00:00:00", $time->getValue());
198
        $time->setValue('00:00:00');
199
        $this->assertEquals("00:00:00", $time->getValue());
200
201
        /* BigInt behaviour */
202
        $bigInt = DBBigInt::create();
203
        $bigInt->setValue(PHP_INT_MAX);
204
        $this->assertEquals(PHP_INT_MAX, $bigInt->getValue());
205
    }
206
207
    /**
208
     * @dataProvider dataProviderPrepValueForDBArrayValue
209
     */
210
    public function testPrepValueForDBArrayValue($dbFieldName, $scalarValueOnly, $extraArgs = [])
211
    {
212
        $reflection = new \ReflectionClass($dbFieldName);
213
        /**
214
         * @var DBField
215
         */
216
        $dbField = $reflection->newInstanceArgs($extraArgs);
217
        $dbField->setName('SomeField');
218
        $payload = ['GREATEST(0,?)' => '2'];
219
        $preparedValue = $dbField->prepValueForDB($payload);
220
        $this->assertTrue(
221
            !$scalarValueOnly || !is_array($preparedValue),
222
            '`prepValueForDB` can not return an array if scalarValueOnly is true'
223
        );
224
        $this->assertEquals($scalarValueOnly, $dbField->scalarValueOnly());
225
    }
226
227
    public function dataProviderPrepValueForDBArrayValue()
228
    {
229
        return [
230
            [DBBigInt::class, true],
231
            [DBBoolean::class, true],
232
            [DBCurrency::class, true],
233
            [DBDate::class, true],
234
            [DBDatetime::class, true],
235
            [DBDecimal::class, true],
236
            [DBDouble::class, true],
237
            [DBEnum::class, true],
238
            [DBFloat::class, true],
239
            [DBForeignKey::class, true, ['SomeField']],
240
            [DBHTMLText::class, true],
241
            [DBHTMLVarchar::class, true],
242
            [DBInt::class, true],
243
            [DBLocale::class, true],
244
            [DBMoney::class, false],
245
            [DBMultiEnum::class, true, ['SomeField', ['One', 'Two', 'Three']]],
246
            [DBPercentage::class, true],
247
            [DBPolymorphicForeignKey::class, false, ['SomeField']],
248
            [DBText::class, true],
249
            [DBTime::class, true],
250
            [DBVarchar::class, true],
251
            [DBYear::class, true],
252
        ];
253
    }
254
255
    public function testExists()
256
    {
257
        $varcharField = new DBVarchar("testfield");
258
        $this->assertTrue($varcharField->getNullifyEmpty());
259
        $varcharField->setValue('abc');
260
        $this->assertTrue($varcharField->exists());
261
        $varcharField->setValue('');
262
        $this->assertFalse($varcharField->exists());
263
        $varcharField->setValue(null);
264
        $this->assertFalse($varcharField->exists());
265
266
        $varcharField = new DBVarchar("testfield", 50, array('nullifyEmpty'=>false));
267
        $this->assertFalse($varcharField->getNullifyEmpty());
268
        $varcharField->setValue('abc');
269
        $this->assertTrue($varcharField->exists());
270
        $varcharField->setValue('');
271
        $this->assertFalse($varcharField->exists());
272
        $varcharField->setValue(null);
273
        $this->assertFalse($varcharField->exists());
274
275
        $textField = new DBText("testfield");
276
        $this->assertTrue($textField->getNullifyEmpty());
277
        $textField->setValue('abc');
278
        $this->assertTrue($textField->exists());
279
        $textField->setValue('');
280
        $this->assertFalse($textField->exists());
281
        $textField->setValue(null);
282
        $this->assertFalse($textField->exists());
283
284
        $textField = new DBText("testfield", array('nullifyEmpty'=>false));
285
        $this->assertFalse($textField->getNullifyEmpty());
286
        $textField->setValue('abc');
287
        $this->assertTrue($textField->exists());
288
        $textField->setValue('');
289
        $this->assertFalse($textField->exists());
290
        $textField->setValue(null);
291
        $this->assertFalse($textField->exists());
292
    }
293
294
    public function testStringFieldsWithMultibyteData()
295
    {
296
        $plainFields = array('Varchar', 'Text');
297
        $htmlFields = array('HTMLVarchar', 'HTMLText', 'HTMLFragment');
298
        $allFields = array_merge($plainFields, $htmlFields);
299
300
        $value = 'üåäöÜÅÄÖ';
301
        foreach ($allFields as $stringField) {
302
            $stringField = DBString::create_field($stringField, $value);
303
            for ($i = 1; $i < mb_strlen($value); $i++) {
304
                $expected = mb_substr($value, 0, $i) . '...';
305
                $this->assertEquals($expected, $stringField->LimitCharacters($i));
0 ignored issues
show
Bug introduced by
The method LimitCharacters() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

305
                $this->assertEquals($expected, $stringField->/** @scrutinizer ignore-call */ LimitCharacters($i));
Loading history...
306
            }
307
        }
308
309
        $value = '<p>üåäö&amp;ÜÅÄÖ</p>';
310
        foreach ($htmlFields as $stringField) {
311
            $stringObj = DBString::create_field($stringField, $value);
312
313
            // Converted to plain text
314
            $this->assertEquals('üåäö&ÜÅÄ...', $stringObj->LimitCharacters(8));
315
316
            // But which will be safely cast in templates
317
            $this->assertEquals('üåäö&amp;ÜÅÄ...', $stringObj->obj('LimitCharacters', [8])->forTemplate());
318
        }
319
320
        $this->assertEquals('ÅÄÖ', DBText::create_field('Text', 'åäö')->UpperCase());
0 ignored issues
show
Bug introduced by
The method UpperCase() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

320
        $this->assertEquals('ÅÄÖ', DBText::create_field('Text', 'åäö')->/** @scrutinizer ignore-call */ UpperCase());
Loading history...
321
        $this->assertEquals('åäö', DBText::create_field('Text', 'ÅÄÖ')->LowerCase());
0 ignored issues
show
Bug introduced by
The method LowerCase() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

321
        $this->assertEquals('åäö', DBText::create_field('Text', 'ÅÄÖ')->/** @scrutinizer ignore-call */ LowerCase());
Loading history...
322
        $this->assertEquals('<P>ÅÄÖ</P>', DBHTMLText::create_field('HTMLFragment', '<p>åäö</p>')->UpperCase());
323
        $this->assertEquals('<p>åäö</p>', DBHTMLText::create_field('HTMLFragment', '<p>ÅÄÖ</p>')->LowerCase());
324
    }
325
}
326