/**
  * Checks that api access config check works
  */
 public function testDataObjectAPIEnaled()
 {
     Config::inst()->update('RESTfulAPI', 'access_control_policy', 'ACL_CHECK_CONFIG_ONLY');
     // ----------------
     // Method Calls
     // Disabled by default
     $enabled = RESTfulAPI::api_access_control('ApiTest_Author');
     $this->assertFalse($enabled, 'Access control should return FALSE by default');
     // Enabled
     Config::inst()->update('ApiTest_Author', 'api_access', true);
     $enabled = RESTfulAPI::api_access_control('ApiTest_Author');
     $this->assertTrue($enabled, 'Access control should return TRUE when api_access is enbaled');
     // Method specific
     Config::inst()->update('ApiTest_Author', 'api_access', 'GET,POST');
     $enabled = RESTfulAPI::api_access_control('ApiTest_Author');
     $this->assertTrue($enabled, 'Access control should return TRUE when api_access is enbaled with default GET method');
     $enabled = RESTfulAPI::api_access_control('ApiTest_Author', 'POST');
     $this->assertTrue($enabled, 'Access control should return TRUE when api_access match HTTP method');
     $enabled = RESTfulAPI::api_access_control('ApiTest_Author', 'PUT');
     $this->assertFalse($enabled, 'Access control should return FALSE when api_access does not match method');
     // ----------------
     // API Calls
     /*
     // Access authorised
     $response = Director::test('api/ApiTest_Author/1', null, null, 'GET'); 
     $this->assertEquals(
       $response->getStatusCode(),
       200
     );
     
     // Access denied
     Config::inst()->update('ApiTest_Author', 'api_access', false);
     $response = Director::test('api/ApiTest_Author/1', null, null, 'GET');
     $this->assertEquals(
       $response->getStatusCode(),
       403
     );
     
     // Access denied
     Config::inst()->update('ApiTest_Author', 'api_access', 'POST');
     $response = Director::test('api/ApiTest_Author/1', null, null, 'GET');
     $this->assertEquals(
       $response->getStatusCode(),
       403
     );
     */
 }
 /**
  * Constructor....
  */
 public function __construct()
 {
     parent::__construct();
     //save current instance in static var
     self::$instance = $this;
 }
 /**
  * Delete object of Class $model and ID $id
  *
  * @todo  Respond with a 204 status message on success?
  * 
  * @param  string          $model     Model class
  * @param  integer 				 $id        Model ID
  * @param  SS_HTTPRequest  $request   Model ID
  * @return NULL|array                 NULL if successful or array with error detail              
  */
 function deleteModel($model, $id, SS_HTTPRequest $request)
 {
     if ($id) {
         $object = DataObject::get_by_id($model, $id);
         if ($object) {
             if (!RESTfulAPI::api_access_control($object, $request->httpMethod())) {
                 return new RESTfulAPI_Error(403, "API access denied.");
             }
             $object->delete();
         } else {
             return new RESTfulAPI_Error(404, "Record not found.");
         }
     } else {
         //shouldn't happen but just in case
         return new RESTfulAPI_Error(400, "Invalid or missing ID. Received '{$id}'.");
     }
     return NULL;
 }
 /**
  * Format a DataObject keys and values
  * ready to be turned into JSON
  * 
  * @param  DataObject $dataObject The data object to format
  * @return array|null              The formatted array map representation of the DataObject or null is permission denied
  */
 protected function formatDataObject(DataObject $dataObject)
 {
     // api access control
     if (!RESTfulAPI::api_access_control($dataObject, 'GET')) {
         return null;
     }
     if (method_exists($dataObject, 'onBeforeSerialize')) {
         $dataObject->onBeforeSerialize();
     }
     $dataObject->extend('onBeforeSerialize');
     // setup
     $formattedDataObjectMap = array();
     // get DataObject config
     $db = Config::inst()->get($dataObject->ClassName, 'db');
     $has_one = Config::inst()->get($dataObject->ClassName, 'has_one');
     $has_many = Config::inst()->get($dataObject->ClassName, 'has_many');
     $many_many = Config::inst()->get($dataObject->ClassName, 'many_many');
     $belongs_many_many = Config::inst()->get($dataObject->ClassName, 'belongs_many_many');
     //$many_many_extraFields = $dataObject->many_many_extraFields();
     $many_many_extraFields = $dataObject->stat('many_many_extraFields');
     // setup ID (not included in $db!!)
     $serializedColumnName = $this->serializeColumnName('ID');
     $formattedDataObjectMap[$serializedColumnName] = $dataObject->getField('ID');
     // iterate over simple DB fields
     if (!$db) {
         $db = array();
     }
     foreach ($db as $columnName => $fieldClassName) {
         $serializedColumnName = $this->serializeColumnName($columnName);
         $formattedDataObjectMap[$serializedColumnName] = $dataObject->getField($columnName);
     }
     // iterate over has_one relations
     if (!$has_one) {
         $has_one = array();
     }
     foreach ($has_one as $columnName => $fieldClassName) {
         $serializedColumnName = $this->serializeColumnName($columnName);
         // convert foreign ID to integer
         $relationID = intVal($dataObject->{$columnName . 'ID'});
         // skip empty relations
         if ($relationID === 0) {
             continue;
         }
         // check if this should be embedded
         if ($this->isEmbeddable($dataObject->ClassName, $columnName)) {
             // get the relation's record ready to embed
             $embedData = $this->getEmbedData($dataObject, $columnName);
             // embed the data if any
             if ($embedData !== null) {
                 $formattedDataObjectMap[$serializedColumnName] = $embedData;
             }
         } else {
             // save foreign ID
             $formattedDataObjectMap[$serializedColumnName] = $relationID;
         }
     }
     // combine defined '_many' relations into 1 array
     $many_relations = array();
     if (is_array($has_many)) {
         $many_relations = array_merge($many_relations, $has_many);
     }
     if (is_array($many_many)) {
         $many_relations = array_merge($many_relations, $many_many);
     }
     if (is_array($belongs_many_many)) {
         $many_relations = array_merge($many_relations, $belongs_many_many);
     }
     // iterate '_many' relations
     foreach ($many_relations as $relationName => $relationClassname) {
         //get the DataList for this realtion's name
         $dataList = $dataObject->{$relationName}();
         //if there actually are objects in the relation
         if ($dataList->count()) {
             // check if this relation should be embedded
             if ($this->isEmbeddable($dataObject->ClassName, $relationName)) {
                 // get the relation's record(s) ready to embed
                 $embedData = $this->getEmbedData($dataObject, $relationName);
                 // embed the data if any
                 if ($embedData !== null) {
                     $serializedColumnName = $this->serializeColumnName($relationName);
                     $formattedDataObjectMap[$serializedColumnName] = $embedData;
                 }
             } else {
                 // set column value to ID list
                 $idList = $dataList->map('ID', 'ID')->keys();
                 $serializedColumnName = $this->serializeColumnName($relationName);
                 $formattedDataObjectMap[$serializedColumnName] = $idList;
             }
         }
     }
     if ($many_many_extraFields) {
         $extraFieldsData = array();
         // loop through extra fields config
         foreach ($many_many_extraFields as $relation => $fields) {
             $manyManyDataObjects = $dataObject->{$relation}();
             $relationData = array();
             // get the extra data for each object in the relation
             foreach ($manyManyDataObjects as $manyManyDataObject) {
                 $data = $manyManyDataObjects->getExtraData($relation, $manyManyDataObject->ID);
                 // format data
                 foreach ($data as $key => $value) {
                     // clear empty data
                     if (!$value) {
                         unset($data[$key]);
                         continue;
                     }
                     $newKey = $this->serializeColumnName($key);
                     if ($newKey != $key) {
                         unset($data[$key]);
                         $data[$newKey] = $value;
                     }
                 }
                 // store if there is any real data
                 if ($data) {
                     $relationData[$manyManyDataObject->ID] = $data;
                 }
             }
             // add individual DO extra data to the relation's extra data
             if ($relationData) {
                 $key = $this->serializeColumnName($relation);
                 $extraFieldsData[$key] = $relationData;
             }
         }
         // save the extrafields data
         if ($extraFieldsData) {
             $key = $this->serializeColumnName('ManyManyExtraFields');
             $formattedDataObjectMap[$key] = $extraFieldsData;
         }
     }
     if (method_exists($dataObject, 'onAfterSerialize')) {
         $dataObject->onAfterSerialize($formattedDataObjectMap);
     }
     $dataObject->extend('onAfterSerialize', $formattedDataObjectMap);
     return $formattedDataObjectMap;
 }