assertTrue($obj->hasDatabaseField('MyMoneyAmount')); $this->assertTrue($obj->hasDatabaseField('MyMoneyCurrency')); $this->assertFalse($obj->hasDatabaseField('MyMoney')); // Check that nested fields are exposed properly $this->assertTrue($obj->dbObject('MyMoney')->hasField('Amount')); $this->assertTrue($obj->dbObject('MyMoney')->hasField('Currency')); // Test getField accessor $this->assertTrue($obj->MyMoney instanceof DBMoney); $this->assertTrue($obj->MyMoney->hasField('Amount')); $obj->MyMoney->Amount = 100.00; $this->assertEquals(100.00, $obj->MyMoney->Amount); $this->assertEquals(100.00, $obj->MyMoneyAmount); // Not strictly correct $this->assertFalse($obj->dbObject('MyMoney')->hasField('MyMoneyAmount')); $this->assertFalse($obj->dbObject('MyMoney')->hasField('MyMoneyCurrency')); $this->assertFalse($obj->dbObject('MyMoney')->hasField('MyMoney')); } /** * Test DataObject::composite_fields() and DataObject::is_composite_field() */ public function testCompositeFieldMetaDataFunctions() { $schema = DataObject::getSchema(); $this->assertEquals('Money', $schema->compositeField(DBCompositeTest\TestObject::class, 'MyMoney')); $this->assertNull($schema->compositeField(DBCompositeTest\TestObject::class, 'Title')); $this->assertEquals( [ 'MyMoney' => 'Money', 'OverriddenMoney' => 'Money', 'DoubleMoney' => DBCompositeTest\DBDoubleMoney::class ], $schema->compositeFields(DBCompositeTest\TestObject::class) ); $this->assertEquals('Money', $schema->compositeField(DBCompositeTest\SubclassedDBFieldObject::class, 'MyMoney')); $this->assertEquals('Money', $schema->compositeField(DBCompositeTest\SubclassedDBFieldObject::class, 'OtherMoney')); $this->assertNull($schema->compositeField(DBCompositeTest\SubclassedDBFieldObject::class, 'Title')); $this->assertNull($schema->compositeField(DBCompositeTest\SubclassedDBFieldObject::class, 'OtherField')); $this->assertEquals( [ 'MyMoney' => 'Money', 'OtherMoney' => 'Money', 'OverriddenMoney' => 'Money', 'DoubleMoney' => DBCompositeTest\DBDoubleMoney::class ], $schema->compositeFields(DBCompositeTest\SubclassedDBFieldObject::class) ); } /** * Tests that changes to the fields affect the underlying dataobject, and vice versa */ public function testFieldBinding() { $object = new DBCompositeTest\TestObject(); $object->MyMoney->Currency = 'NZD'; $object->MyMoney->Amount = 100.0; $this->assertEquals('NZD', $object->MyMoneyCurrency); $this->assertEquals(100.0, $object->MyMoneyAmount); $object->write(); $object2 = DBCompositeTest\TestObject::get()->byID($object->ID); $this->assertEquals('NZD', $object2->MyMoney->Currency); $this->assertEquals(100.0, $object2->MyMoney->Amount); $object2->MyMoneyCurrency = 'USD'; $this->assertEquals('USD', $object2->MyMoney->Currency); $object2->MyMoney->setValue(['Currency' => 'EUR', 'Amount' => 200.0]); $this->assertEquals('EUR', $object2->MyMoneyCurrency); $this->assertEquals(200.0, $object2->MyMoneyAmount); } /** * Ensures that composite fields are assigned to the correct tables */ public function testInheritedTables() { $object1 = new DBCompositeTest\TestObject(); $object2 = new DBCompositeTest\SubclassedDBFieldObject(); $this->assertEquals('DBCompositeTest_DataObject', $object1->dbObject('MyMoney')->getTable()); $this->assertEquals('DBCompositeTest_DataObject', $object1->dbObject('OverriddenMoney')->getTable()); $this->assertEquals('DBCompositeTest_DataObject', $object2->dbObject('MyMoney')->getTable()); $this->assertEquals('DBCompositeTest_SubclassedDBFieldObject', $object2->dbObject('OtherMoney')->getTable()); $this->assertEquals('DBCompositeTest_SubclassedDBFieldObject', $object2->dbObject('OverriddenMoney')->getTable()); } /* Uncomment this for SS5 public function testSetFieldDynamicPropertyException() { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage(implode(' ', [ 'Field abc does not exist.', 'If this was accessed via a dynamic property then call setDynamicData() instead.' ])); $object = new DBCompositeTest\TestObject(); $object->MyMoney->abc = 'def'; } */ public function testWriteToManipuationIsCalledWhenWritingDataObject() { $obj = DBCompositeTest\TestObject::create(); $obj->DoubleMoney = ['Amount' => 10, 'Currency' => 'CAD']; $moneyField = $obj->dbObject('DoubleMoney'); $this->assertEquals(10, $moneyField->getAmount()); $obj->write(); // Custom money class should double the amount before writing $this->assertEquals(20, $moneyField->getAmount()); // Note: these would fail since dbObject will return a new instance // of the DoubleMoney field based on the initial values // $this->assertSame($moneyField, $obj->dbObject('DoubleMoney')); // $this->assertEquals(20, $obj->dbObject('DoubleMoney')->getAmount()); } }