Completed
Push — namespace-template ( 7967f2...367a36 )
by Sam
10:48
created

DBMoneyTest::testGetName()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 18
rs 9.4285
cc 2
eloc 12
nc 3
nop 0
1
<?php
2
3
use SilverStripe\Model\FieldType\DBMoney;
4
5
/**
6
 * Partially based on Zend_CurrencyTest.
7
 *
8
 * @copyright  Copyright (c) 2006 Zend Technologies USA Inc. (http://www.zend.com)
9
 * @license	http://framework.zend.com/license/new-bsd	 New BSD License
10
 * @version	$Id: CurrencyTest.php 14644 2009-04-04 18:59:08Z thomas $
11
 */
12
13
/**
14
 * @package framework
15
 * @subpackage tests
16
 */
17
class DBMoneyTest extends SapphireTest {
18
19
	protected static $fixture_file = 'MoneyTest.yml';
20
21
	protected $extraDataObjects = array(
22
		'MoneyTest_DataObject',
23
		'MoneyTest_SubClass',
24
	);
25
26
	public function testMoneyFieldsReturnedAsObjects() {
27
		$obj = $this->objFromFixture('MoneyTest_DataObject', 'test1');
28
		$this->assertInstanceOf('SilverStripe\Model\FieldType\DBMoney', $obj->MyMoney);
29
	}
30
31
32
	public function testLoadFromFixture() {
33
		$obj = $this->objFromFixture('MoneyTest_DataObject', 'test1');
34
35
		$this->assertInstanceOf('SilverStripe\Model\FieldType\DBMoney', $obj->MyMoney);
36
		$this->assertEquals($obj->MyMoney->getCurrency(), 'EUR');
37
		$this->assertEquals($obj->MyMoney->getAmount(), 1.23);
38
	}
39
40
	public function testDataObjectChangedFields() {
41
		$obj = $this->objFromFixture('MoneyTest_DataObject', 'test1');
42
43
		// Without changes
44
		$curr = $obj->obj('MyMoney');
0 ignored issues
show
Unused Code introduced by
$curr is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
45
		$changed = $obj->getChangedFields();
46
		$this->assertNotContains('MyMoney', array_keys($changed));
47
48
		// With changes
49
		$this->assertInstanceOf('SilverStripe\Model\FieldType\DBMoney', $obj->MyMoney);
50
		$obj->MyMoney->setAmount(99);
51
		$changed = $obj->getChangedFields();
52
		$this->assertContains('MyMoney', array_keys($changed), 'Field is detected as changed');
53
		$this->assertEquals(2, $changed['MyMoney']['level'], 'Correct change level');
54
	}
55
56
	public function testCanOverwriteSettersWithNull() {
57
		$obj = new MoneyTest_DataObject();
58
59
		$m1 = new DBMoney();
60
		$m1->setAmount(987.65);
61
		$m1->setCurrency('USD');
62
		$obj->MyMoney = $m1;
0 ignored issues
show
Documentation introduced by
The property MyMoney does not exist on object<MoneyTest_DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
63
		$obj->write();
64
65
		$m2 = new DBMoney();
66
		$m2->setAmount(null);
67
		$m2->setCurrency(null);
68
		$obj->MyMoney = $m2;
0 ignored issues
show
Documentation introduced by
The property MyMoney does not exist on object<MoneyTest_DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
69
		$obj->write();
70
71
		$moneyTest = DataObject::get_by_id('MoneyTest_DataObject',$obj->ID);
72
		$this->assertTrue($moneyTest instanceof MoneyTest_DataObject);
73
		$this->assertEquals('', $moneyTest->MyMoneyCurrency);
74
		$this->assertEquals(0.0000, $moneyTest->MyMoneyAmount);
75
	}
76
77
	public function testIsChanged() {
78
		$obj1 = $this->objFromFixture('MoneyTest_DataObject', 'test1');
79
		$this->assertFalse($obj1->isChanged());
80
		$this->assertFalse($obj1->isChanged('MyMoney'));
81
82
		// modify non-db field
83
		$m1 = new DBMoney();
84
		$m1->setAmount(500);
85
		$m1->setCurrency('NZD');
86
		$obj1->NonDBMoneyField = $m1;
0 ignored issues
show
Documentation introduced by
The property NonDBMoneyField does not exist on object<DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
87
		$this->assertFalse($obj1->isChanged()); // Because only detects DB fields
88
		$this->assertTrue($obj1->isChanged('NonDBMoneyField')); // Allow change detection to non-db fields explicitly named
89
90
		// Modify db field
91
		$obj2 = $this->objFromFixture('MoneyTest_DataObject', 'test2');
92
		$m2 = new DBMoney();
93
		$m2->setAmount(500);
94
		$m2->setCurrency('NZD');
95
		$obj2->MyMoney = $m2;
0 ignored issues
show
Documentation introduced by
The property MyMoney does not exist on object<DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
96
		$this->assertTrue($obj2->isChanged()); // Detects change to DB field
97
		$this->assertTrue($obj2->ischanged('MyMoney'));
98
99
		// Modify sub-fields
100
		$obj3 = $this->objFromFixture('MoneyTest_DataObject', 'test3');
101
		$obj3->MyMoneyCurrency = 'USD';
0 ignored issues
show
Documentation introduced by
The property MyMoneyCurrency does not exist on object<DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
102
		$this->assertTrue($obj3->isChanged()); // Detects change to DB field
103
		$this->assertTrue($obj3->ischanged('MyMoneyCurrency'));
104
	}
105
106
	/**
107
	 * Write a Money object to the database, then re-read it to ensure it
108
	 * is re-read properly.
109
	 */
110
	public function testGettingWrittenDataObject() {
111
		$local = i18n::get_locale();
112
		//make sure that the $ amount is not prefixed by US$, as it would be in non-US locale
113
		i18n::set_locale('en_US');
114
115
		$obj = new MoneyTest_DataObject();
116
117
		$m = new DBMoney();
118
		$m->setAmount(987.65);
119
		$m->setCurrency('USD');
120
		$obj->MyMoney = $m;
0 ignored issues
show
Documentation introduced by
The property MyMoney does not exist on object<MoneyTest_DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
121
		$this->assertEquals("$987.65", $obj->MyMoney->Nice(),
122
			"Money field not added to data object properly when read prior to first writing the record."
123
		);
124
125
		$objID = $obj->write();
126
127
		$moneyTest = DataObject::get_by_id('MoneyTest_DataObject',$objID);
128
		$this->assertTrue($moneyTest instanceof MoneyTest_DataObject);
129
		$this->assertEquals('USD', $moneyTest->MyMoneyCurrency);
130
		$this->assertEquals(987.65, $moneyTest->MyMoneyAmount);
131
		$this->assertEquals("$987.65", $moneyTest->MyMoney->Nice(),
132
			"Money field not added to data object properly when read."
133
		);
134
135
		i18n::set_locale($local);
136
	}
137
138
	public function testToCurrency() {
139
		$USD = new DBMoney();
140
		$USD->setLocale('en_US');
141
		$USD->setAmount(53292.18);
142
		$this->assertSame('$53,292.18', $USD->Nice());
143
		$this->assertSame('$ 53.292,18', $USD->Nice(array('format' => 'de_AT')));
144
	}
145
146
	public function testGetSign() {
147
		$SKR = new DBMoney();
148
		$SKR->setValue(array(
149
			'Currency' => 'SKR',
150
			'Amount' => 3.44
151
		));
152
153
		$this->assertSame('€',	$SKR->getSymbol('EUR','de_AT'));
154
		$this->assertSame(null,	$SKR->getSymbol());
155
156
		try {
157
			$SKR->getSymbol('EGP', 'de_XX');
158
			$this->setExpectedException("Exception");
159
		} catch(Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
160
		}
161
162
		$EUR = new DBMoney();
163
		$EUR->setValue(array(
164
			'Currency' => 'EUR',
165
			'Amount' => 3.44
166
		));
167
		$EUR->setLocale('de_DE');
168
		$this->assertSame('€',	$EUR->getSymbol());
169
	}
170
171
	public function testGetName()
172
	{
173
		$m = new DBMoney();
174
		$m->setValue(array(
175
			'Currency' => 'EUR',
176
			'Amount' => 3.44
177
		));
178
		$m->setLocale('ar_EG');
179
180
		$this->assertSame('Estnische Krone', $m->getCurrencyName('EEK','de_AT'));
181
		$this->assertSame('يورو', $m->getCurrencyName());
182
183
		try {
184
			$m->getCurrencyName('EGP', 'xy_XY');
185
			$this->setExpectedException("Exception");
186
		} catch(Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
187
		}
188
	}
189
190
	public function testGetShortName() {
191
		$m = new DBMoney();
192
		$m->setValue(array(
193
			'Currency' => 'EUR',
194
			'Amount' => 3.44
195
		));
196
		$m->setLocale('de_AT');
197
198
		$this->assertSame('EUR', $m->getShortName('Euro',	 'de_AT'));
199
		$this->assertSame('USD', $m->getShortName('US-Dollar','de_AT'));
200
		//$this->assertSame('EUR', $m->getShortName(null, 'de_AT'));
201
		$this->assertSame('EUR', $m->getShortName());
202
203
		try {
204
			$m->getShortName('EUR', 'xy_ZT');
205
			$this->setExpectedException("Exception");
206
		} catch(Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
207
		}
208
	}
209
210
	public function testSetValueAsArray() {
211
		$m = new DBMoney();
212
		$m->setValue(array(
213
			'Currency' => 'EUR',
214
			'Amount' => 3.44
215
		));
216
		$this->assertEquals(
217
			$m->getCurrency(),
218
			'EUR'
219
		);
220
		$this->assertEquals(
221
			$m->getAmount(),
222
			3.44
223
		);
224
	}
225
226
	public function testSetValueAsMoney() {
227
		$m1 = new DBMoney();
228
		$m1->setValue(array(
229
			'Currency' => 'EUR',
230
			'Amount' => 3.44
231
		));
232
		$m2 = new DBMoney();
233
		$m2->setValue($m1);
234
		$this->assertEquals(
235
			$m2->getCurrency(),
236
			'EUR'
237
		);
238
		$this->assertEquals(
239
			$m2->getAmount(),
240
			3.44
241
		);
242
	}
243
244
	public function testExists() {
245
		$m1 = new DBMoney();
246
		$this->assertFalse($m1->exists());
247
248
		$m2 = new DBMoney();
249
		$m2->setValue(array(
250
			'Currency' => 'EUR',
251
			'Amount' => 3.44
252
		));
253
		$this->assertTrue($m2->exists());
254
255
		$m3 = new DBMoney();
256
		$m3->setValue(array(
257
			'Currency' => 'EUR',
258
			'Amount' => 0
259
		));
260
		$this->assertTrue($m3->exists());
261
	}
262
263 View Code Duplication
	public function testLoadIntoDataObject() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
264
		$obj = new MoneyTest_DataObject();
265
266
		$this->assertInstanceOf('SilverStripe\Model\FieldType\DBMoney', $obj->obj('MyMoney'));
267
268
		$m = new DBMoney();
269
		$m->setValue(array(
270
			'Currency' => 'EUR',
271
			'Amount' => 1.23
272
		));
273
		$obj->MyMoney = $m;
0 ignored issues
show
Documentation introduced by
The property MyMoney does not exist on object<MoneyTest_DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
274
275
		$this->assertEquals($obj->MyMoney->getCurrency(), 'EUR');
276
		$this->assertEquals($obj->MyMoney->getAmount(), 1.23);
277
	}
278
279
	public function testWriteToDataObject() {
280
		$obj = new MoneyTest_DataObject();
281
		$m = new DBMoney();
282
		$m->setValue(array(
283
			'Currency' => 'EUR',
284
			'Amount' => 1.23
285
		));
286
		$obj->MyMoney = $m;
0 ignored issues
show
Documentation introduced by
The property MyMoney does not exist on object<MoneyTest_DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
287
		$obj->write();
288
289
		$this->assertEquals(
290
			'EUR',
291
			DB::query(sprintf(
292
				'SELECT "MyMoneyCurrency" FROM "MoneyTest_DataObject" WHERE "ID" = %d',
293
				$obj->ID
294
			))->value()
295
		);
296
		$this->assertEquals(
297
			'1.23',
298
			DB::query(sprintf(
299
				'SELECT "MyMoneyAmount" FROM "MoneyTest_DataObject" WHERE "ID" = %d',
300
				$obj->ID
301
			))->value()
302
		);
303
	}
304
305
	public function testMoneyLazyLoading() {
306
		// Get the object, ensuring that MyOtherMoney will be lazy loaded
307
		$id = $this->idFromFixture('MoneyTest_SubClass', 'test2');
308
		$obj = MoneyTest_DataObject::get()->byID($id);
309
310
		$this->assertEquals('£2.46', $obj->obj('MyOtherMoney')->Nice());
311
	}
312
313
	public function testHasAmount() {
314
		$obj = new MoneyTest_DataObject();
315
		$m = new DBMoney();
316
		$obj->MyMoney = $m;
0 ignored issues
show
Documentation introduced by
The property MyMoney does not exist on object<MoneyTest_DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
317
318
		$m->setValue(array('Amount' => 1));
319
		$this->assertTrue($obj->MyMoney->hasAmount());
320
321
		$m->setValue(array('Amount' => 1.00));
322
		$this->assertTrue($obj->MyMoney->hasAmount());
323
324
		$m->setValue(array('Amount' => 1.01));
325
		$this->assertTrue($obj->MyMoney->hasAmount());
326
327
		$m->setValue(array('Amount' => 0.99));
328
		$this->assertTrue($obj->MyMoney->hasAmount());
329
330
		$m->setValue(array('Amount' => 0.01));
331
		$this->assertTrue($obj->MyMoney->hasAmount());
332
333
		$m->setValue(array('Amount' => 0));
334
		$this->assertFalse($obj->MyMoney->hasAmount());
335
336
		$m->setValue(array('Amount' => 0.0));
337
		$this->assertFalse($obj->MyMoney->hasAmount());
338
339
		$m->setValue(array('Amount' => 0.00));
340
		$this->assertFalse($obj->MyMoney->hasAmount());
341
	}
342
343
}
344
345
/**
346
 * @package framework
347
 * @subpackage tests
348
 */
349
class MoneyTest_DataObject extends DataObject implements TestOnly {
350
	private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
351
		'MyMoney' => 'Money',
352
		//'MyOtherMoney' => 'Money',
353
	);
354
}
355
356
/**
357
 * @package framework
358
 * @subpackage tests
359
 */
360
class MoneyTest_SubClass extends MoneyTest_DataObject implements TestOnly {
361
362
	private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
363
		'MyOtherMoney' => 'Money',
364
	);
365
366
}
367