diff --git a/model/DataList.php b/model/DataList.php index ce92b048f..d50f20e13 100644 --- a/model/DataList.php +++ b/model/DataList.php @@ -233,12 +233,24 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab } /** + * Returns true if this DataList can be filtered by the given field. * - * @param string $fieldName + * @param string $fieldName (May be a related field in dot notation like Member.FirstName) * @return boolean */ public function canFilterBy($fieldName) { - if($t = singleton($this->dataClass)->hasDatabaseField($fieldName)){ + $model = singleton($this->dataClass); + $relations = explode(".", $fieldName); + // First validate the relationships + $fieldName = array_pop($relations); + foreach ($relations as $r) { + $relationClass = $model->getRelationClass($r); + if (!$relationClass) return false; + $model = singleton($relationClass); + if (!$model) return false; + } + // Then check field + if ($model->hasDatabaseField($fieldName)){ return true; } return false; diff --git a/tests/model/DataListTest.php b/tests/model/DataListTest.php index 828805502..1a4353127 100755 --- a/tests/model/DataListTest.php +++ b/tests/model/DataListTest.php @@ -533,6 +533,38 @@ class DataListTest extends SapphireTest { $this->assertEquals('Phil', $list->last()->Name, 'Last comment should be from Phil'); } + /** + * Test DataList->canFilterBy() + */ + public function testCanFilterBy() { + // Basic check + $team = DataObjectTest_Team::get(); + $this->assertTrue($team->canFilterBy("Title")); + $this->assertFalse($team->canFilterBy("SomethingElse")); + + // Has one + $this->assertTrue($team->canFilterBy("CaptainID")); + $this->assertTrue($team->canFilterBy("Captain.ShirtNumber")); + $this->assertFalse($team->canFilterBy("SomethingElse.ShirtNumber")); + $this->assertFalse($team->canFilterBy("Captain.SomethingElse")); + $this->assertTrue($team->canFilterBy("Captain.FavouriteTeam.Captain.ShirtNumber")); + + // Has many + $this->assertTrue($team->canFilterBy("Fans.Name")); + $this->assertFalse($team->canFilterBy("SomethingElse.Name")); + $this->assertFalse($team->canFilterBy("Fans.SomethingElse")); + + // Many many + $this->assertTrue($team->canFilterBy("Players.FirstName")); + $this->assertFalse($team->canFilterBy("SomethingElse.FirstName")); + $this->assertFalse($team->canFilterBy("Players.SomethingElse")); + + // Subclasses + $subteam = DataObjectTest_SubTeam::get(); + $this->assertTrue($subteam->canFilterBy("Title")); + $this->assertTrue($subteam->canFilterBy("SubclassDatabaseField")); + } + /** * $list->filter('Name', 'bob'); // only bob in the list */