diff --git a/src/DataFormatter/JSONDataFormatter.php b/src/DataFormatter/JSONDataFormatter.php index cd4840c..725ca40 100644 --- a/src/DataFormatter/JSONDataFormatter.php +++ b/src/DataFormatter/JSONDataFormatter.php @@ -2,6 +2,7 @@ namespace SilverStripe\RestfulServer\DataFormatter; +use SilverStripe\RestfulServer\RestfulServer; use SilverStripe\View\ArrayData; use SilverStripe\Core\Convert; use SilverStripe\RestfulServer\DataFormatter; @@ -124,6 +125,8 @@ class JSONDataFormatter extends DataFormatter } foreach ($obj->hasMany() + $obj->manyMany() as $relName => $relClass) { + $relClass = RestfulServer::parseRelationClass($relClass); + //remove dot notation from relation names $parts = explode('.', $relClass); $relClass = array_shift($parts); diff --git a/src/DataFormatter/XMLDataFormatter.php b/src/DataFormatter/XMLDataFormatter.php index ffc74db..8908ff9 100644 --- a/src/DataFormatter/XMLDataFormatter.php +++ b/src/DataFormatter/XMLDataFormatter.php @@ -10,6 +10,7 @@ use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObjectInterface; use SilverStripe\Control\Director; use SilverStripe\ORM\SS_List; +use SilverStripe\RestfulServer\RestfulServer; /** * Formats a DataObject's member fields into an XML string @@ -196,6 +197,8 @@ class XMLDataFormatter extends DataFormatter } foreach ($obj->manyMany() as $relName => $relClass) { + $relClass = RestfulServer::parseRelationClass($relClass); + //remove dot notation from relation names $parts = explode('.', $relClass); $relClass = array_shift($parts); diff --git a/src/RestfulServer.php b/src/RestfulServer.php index 35a59c0..cda2bdc 100644 --- a/src/RestfulServer.php +++ b/src/RestfulServer.php @@ -122,6 +122,32 @@ class RestfulServer extends Controller return str_replace('-', '\\', $className); } + /** + * Parse many many relation class (works with through array syntax) + * + * @param string|array $class + * @return string|array + */ + public static function parseRelationClass($class) + { + // detect many many through syntax + if (is_array($class) + && array_key_exists('through', $class) + && array_key_exists('to', $class) + ) { + $toRelation = $class['to']; + + $hasOne = Config::inst()->get($class['through'], 'has_one'); + if (empty($hasOne) || !is_array($hasOne) || !array_key_exists($toRelation, $hasOne)) { + return $class; + } + + return $hasOne[$toRelation]; + } + + return $class; + } + /** * This handler acts as the switchboard for the controller. * Since no $Action url-param is set, all requests are sent here. @@ -802,6 +828,8 @@ class RestfulServer extends Controller $relations = (array)$obj->hasOne() + (array)$obj->hasMany() + (array)$obj->manyMany(); if ($relations) { foreach ($relations as $relName => $relClass) { + $relClass = static::parseRelationClass($relClass); + //remove dot notation from relation names $parts = explode('.', $relClass); $relClass = array_shift($parts); diff --git a/tests/unit/RestfulServerTest.php b/tests/unit/RestfulServerTest.php index d04202a..02266d6 100644 --- a/tests/unit/RestfulServerTest.php +++ b/tests/unit/RestfulServerTest.php @@ -2,6 +2,7 @@ namespace SilverStripe\RestfulServer\Tests; +use SilverStripe\RestfulServer\RestfulServer; use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestComment; use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestExceptionThrown; use SilverStripe\RestfulServer\Tests\Stubs\RestfulServerTestSecretThing; @@ -701,4 +702,17 @@ class RestfulServerTest extends SapphireTest $responseArr = Convert::xml2array($response->getBody()); $this->assertEquals(\Exception::class, $responseArr['type']); } + + public function testParseClassName() + { + $manyMany = RestfulServerTestAuthor::config()->get('many_many'); + + // simple syntax (many many standard) + $className = RestfulServer::parseRelationClass($manyMany['RelatedPages']); + $this->assertEquals(RestfulServerTestPage::class, $className); + + // array syntax (many many through) + $className = RestfulServer::parseRelationClass($manyMany['SortedPages']); + $this->assertEquals(RestfulServerTestPage::class, $className); + } } diff --git a/tests/unit/Stubs/AuthorSortedPageRelation.php b/tests/unit/Stubs/AuthorSortedPageRelation.php new file mode 100644 index 0000000..3b10f42 --- /dev/null +++ b/tests/unit/Stubs/AuthorSortedPageRelation.php @@ -0,0 +1,29 @@ + RestfulServerTestAuthor::class, + 'SortedPage' => RestfulServerTestPage::class, + ]; + + /** + * @var array + */ + private static $db = [ + 'Sort' => 'Int', + ]; +} diff --git a/tests/unit/Stubs/RestfulServerTestAuthor.php b/tests/unit/Stubs/RestfulServerTestAuthor.php index 0145f03..c400809 100644 --- a/tests/unit/Stubs/RestfulServerTestAuthor.php +++ b/tests/unit/Stubs/RestfulServerTestAuthor.php @@ -18,11 +18,17 @@ class RestfulServerTestAuthor extends DataObject implements TestOnly private static $many_many = array( 'RelatedPages' => RestfulServerTestPage::class, 'RelatedAuthors' => RestfulServerTestAuthor::class, + 'SortedPages' => [ + 'through' => AuthorSortedPageRelation::class, + 'from' => 'Parent', + 'to' => 'SortedPage', + ], ); private static $has_many = array( 'PublishedPages' => RestfulServerTestPage::class, 'Ratings' => RestfulServerTestAuthorRating::class, + 'SortedPagesRelation' => AuthorSortedPageRelation::class . '.Parent', ); public function canView($member = null)