Skip to content

Commit

Permalink
API CHANGE: Added DataObject::relField(), which pushes the "relation …
Browse files Browse the repository at this point in the history
…dot syntax" code of TableListField/GridField back to the model.

BUGFIX: Made DataObject::relObject() more flexible; allowable thanks to new ORM.
  • Loading branch information
Sam Minnee committed Mar 24, 2012
1 parent 1b24437 commit 2576944
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 13 deletions.
50 changes: 37 additions & 13 deletions model/DataObject.php
Expand Up @@ -2397,22 +2397,22 @@ public function dbObject($fieldName) {
* @return DBField
*/
public function relObject($fieldPath) {
$parts = explode('.', $fieldPath);
$fieldName = array_pop($parts);
$component = $this;
foreach($parts as $relation) {
if ($rel = $component->has_one($relation)) {
$component = singleton($rel);
} elseif ($rel = $component->has_many($relation)) {
$component = singleton($rel);
} elseif ($rel = $component->many_many($relation)) {
$component = singleton($rel[1]);
} elseif($className = $this->castingClass($relation)) {
$component = $className;
if(strpos($fieldPath, '.') !== false) {
$parts = explode('.', $fieldPath);
$fieldName = array_pop($parts);

// Traverse dot syntax
$component = $this;
foreach($parts as $relation) {
$component = $component->$relation();
}

$object = $component->dbObject($fieldName);

} else {
$object = $this->dbObject($fieldPath);
}

$object = $component->dbObject($fieldName);

if (!($object instanceof DBField) && !($object instanceof DataList)) {
// Todo: come up with a broader range of exception objects to describe differnet kinds of errors programatically
Expand All @@ -2421,6 +2421,30 @@ public function relObject($fieldPath) {
return $object;
}

/**
* Traverses to a field referenced by relationships between data objects, returning the value
* The path to the related field is specified with dot separated syntax (eg: Parent.Child.Child.FieldName)
*
* @param $fieldPath string
* @return string
*/
public function relField($fieldPath) {
if(strpos($fieldPath, '.') !== false) {
$parts = explode('.', $fieldPath);
$fieldName = array_pop($parts);

// Traverse dot syntax
$component = $this;
foreach($parts as $relation) {
$component = $component->$relation();
}

return $component->$fieldName;
} else {
return $this->$fieldPath;
}
}

/**
* Temporary hack to return an association name, based on class, to get around the mangle
* of having to deal with reverse lookup of relationships to determine autogenerated foreign keys.
Expand Down
27 changes: 27 additions & 0 deletions tests/model/DataObjectTest.php
Expand Up @@ -1007,6 +1007,33 @@ function testIsEmpty() {
$this->assertFalse($objEmpty->isEmpty(), 'Zero value in attribute considered non-empty');
}

function testRelField() {
$captain = $this->objFromFixture('DataObjectTest_Player', 'captain1');
// Test traversal of a single has_one
$this->assertEquals("Team 1", $captain->relField('FavouriteTeam.Title'));
// Test direct field access
$this->assertEquals("Captain", $captain->relField('FirstName'));

$player = $this->objFromFixture('DataObjectTest_Player', 'player2');
// Test that we can traverse more than once, and that arbitrary methods are okay
$this->assertEquals("Team 1", $player->relField('Teams.First.Title'));
}

function testRelObject() {
$captain = $this->objFromFixture('DataObjectTest_Player', 'captain1');
// Test traversal of a single has_one
$this->assertInstanceOf("Varchar", $captain->relObject('FavouriteTeam.Title'));
$this->assertEquals("Team 1", $captain->relObject('FavouriteTeam.Title')->getValue());
// Test direct field access
$this->assertInstanceOf("Boolean", $captain->relObject('IsRetired'));
$this->assertEquals(1, $captain->relObject('IsRetired')->getValue());

$player = $this->objFromFixture('DataObjectTest_Player', 'player2');
// Test that we can traverse more than once, and that arbitrary methods are okay
$this->assertInstanceOf("Varchar", $player->relObject('Teams.First.Title'));
$this->assertEquals("Team 1", $player->relObject('Teams.First.Title')->getValue());
}


}

Expand Down

1 comment on commit 2576944

@halkyon
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sminnee I found a SearchContext test failure from a change on line 2410 of DataObject. $component->dbObject() is being called on a HasManyList, but dbObject isn't defined.

Search Context Test::test Relationship Objects Linked In Search
Object->__call(): the method 'dbobject' does not exist on 'HasManyList'
<ul>Object->__call(dbObject,Array)
DataObject.php:2410

HasManyList->dbObject(SolutionArea)
DataObject.php:2410

DataObject->relObject(Actions.SolutionArea)
DataObject.php:1790

DataObject->scaffoldSearchFields()
DataObject.php:1736

DataObject->getDefaultSearchContext()
SearchContextTest.php:101

Please sign in to comment.