abstract class EntityShareServerRestAbstract in Entity Share 7
Abstract Class to manage the EntityShare Rest server.
Hierarchy
Expanded class hierarchy of EntityShareServerRestAbstract
File
- modules/
entity_share_server/ includes/ entity_share_server.rest.abstract.inc, line 11 - Class for handling Entity Share Rest Server request.
View source
abstract class EntityShareServerRestAbstract {
/**
* Http request.
*
* @var array
* The HTTP request.
*/
protected $request;
/**
* Http response.
*
* @var array
* The HTTP response.
*/
protected $response;
/**
* Http headers.
*
* @var array
* The HTTP headers.
*/
protected $headers = array();
/**
* Result.
*
* @var array
* The results.
*/
protected $result;
/**
* Error.
*
* @var mixed
* The error.
*/
protected $error;
const STATUS_ERROR = 'KO';
const STATUS_OK = 'OK';
const HOOK_PREFIX = 'es_server_rest_';
const WATCHDOG_TYPE = 'entity_share_server_rest';
const IP_RESTRICTED_VARIABLE = 'entity_share_server_allowed_ips';
/**
* Constructor. Initialize properties.
*/
public function __construct() {
$this
->parseRequest();
}
/**
* Get the parameter value.
*
* @param string $name
* Name of th parameter.
*
* @return mixed|null
* The parameter value, NULL otherwise.
*/
public function getParam($name) {
return isset($this->request[$name]) ? $this->request[$name] : NULL;
}
/**
* Get the Request.
*
* @return array|null
* The HTTP request.
*/
public function getRequest() {
return $this->request;
}
/**
* Get the method of the request.
*
* @return string
* The HTTP request method (GET, POST etc.).
*/
public function getRequestMethod() {
return $_SERVER['REQUEST_METHOD'];
}
/**
* Get the result of the action.
*
* @return mixed
* The results.
*/
public function getResult() {
return $this->result;
}
/**
* Set the result of the action.
*
* @param mixed $result
* The result to set.
*
* @return EntityShareServerRestAbstract
* The current class instance.
*/
protected function setResult($result) {
$this->result = $result;
return $this;
}
/**
* Get the error of the action.
*
* @return mixed
* The potential error.
*/
public function getError() {
return $this->error;
}
/**
* Set the error of the action.
*
* @param string $error
* The potential error to set.
* @param string $status
* The http error status.
*
* @return EntityShareServerRestAbstract
* The current class instance.
*/
protected function setError($error, $status = '400 Bad Request') {
$this->error = $error;
$this
->setHeader('Status', $status);
return $this;
}
/**
* Handle the server.
*/
public function handle() {
try {
// Security.
if (!$this
->isRequestAllowed()) {
$this
->setHeader('Status', '403 Forbidden');
$this
->sendHeaders();
return;
}
switch ($this
->getParam('type')) {
case 'login':
switch ($this
->getRequestMethod()) {
case 'POST':
// Manage login.
$this
->doLogin();
break;
default:
$this
->setError('HTTP Method not managed');
}
break;
default:
// HTTP_METHOD.
switch ($this
->getRequestMethod()) {
case 'GET':
// Read an entity.
$this
->handleGet();
break;
case 'POST':
// Create a new entity.
$this
->handlePost();
break;
case 'PUT':
// Update an entity.
$this
->handlePut();
break;
case 'DELETE':
// Delete an entity.
$this
->handleDelete();
break;
default:
$this
->setError('HTTP Method not managed');
}
}
} catch (Exception $e) {
$this
->setError('Internal error', '500 Internal Server Error');
}
$this
->outputResponse();
}
/**
* Handle the GET method action.
*
* Read an entity.
*/
protected abstract function handleGet();
/**
* Handle the POST method action.
*
* Create a new entity.
*/
protected abstract function handlePost();
/**
* Handle the PUT method action.
*
* Update an entity.
*/
protected abstract function handlePut();
/**
* Handle the DELETE method action.
*
* Delete an entity.
*/
protected abstract function handleDelete();
/**
* Default request parameters.
*
* @return array
* The request parameters.
*/
protected function getDefaultRequest() {
$menu_item = menu_get_item();
$menu_path = $menu_item['path'];
// Parse the request path to get args passed to entity share rest api.
$short_path = request_path();
$pos = strpos($short_path, $menu_path);
if ($pos !== FALSE) {
$short_path = substr($short_path, $pos + strlen($menu_path));
}
if (substr($short_path, 0, 1) == '/') {
$short_path = substr($short_path, 1);
}
$args = arg(NULL, $short_path);
// Ex: /node/{id} or node.
$request = array(
'type' => $args[0],
'id' => isset($args[1]) ? $args[1] : NULL,
);
return $request;
}
/**
* Parse the request.
*
* @return bool
* TRUE if the request is valid, FALSE otherwise.
*/
protected function parseRequest() {
$request = $this
->getDefaultRequest();
switch ($this
->getRequestMethod()) {
case 'POST':
case 'PUT':
$raw_data = file_get_contents('php://input');
if (strstr($_SERVER['CONTENT_TYPE'], 'application/json')) {
$request['datas'] = (object) drupal_json_decode($raw_data);
}
else {
return FALSE;
}
break;
case 'GET':
case 'DELETE':
break;
default:
$this
->setError('HTTP Method not managed');
return FALSE;
}
$this->request = $request;
return TRUE;
}
/**
* Format the response in function of the accept header.
*/
protected function formatResponse() {
$result = array(
'result' => $this
->getResult(),
'error' => $this
->getError(),
'status' => !$this
->getError() ? self::STATUS_OK : self::STATUS_ERROR,
);
// Default formatters.
$formatter = array(
'application/json' => function ($result, $server) {
return drupal_json_encode($result);
},
);
drupal_alter(self::HOOK_PREFIX . 'response_formatter', $formatter);
// Call the formatter matching the request.
foreach ($formatter as $http_accept => $callback) {
if (strstr($_SERVER['HTTP_ACCEPT'], $http_accept)) {
if (is_callable($callback)) {
$this
->setHeader('Content-Type', $http_accept);
$this->response = call_user_func_array($callback, array(
$result,
$this,
));
break;
}
else {
// Watchdog.
watchdog(self::WATCHDOG_TYPE, 'The Content Type %type callback is not valid', array(
'%type' => $http_accept,
), WATCHDOG_ERROR);
}
}
}
if (is_null($this->response)) {
$this->response = t('HTTP_ACCEPT "@accept" not managed', array(
'@accept' => $_SERVER['HTTP_ACCEPT'],
));
}
}
/**
* Output the response to the client.
*/
protected function outputResponse() {
$this
->formatResponse();
$this
->sendHeaders();
print $this->response;
// Do not let this output.
drupal_page_footer();
exit;
}
/**
* Set a header (but not send it).
*
* @param string $name
* Header name.
* @param string $value
* Header value.
*/
public function setHeader($name, $value) {
$this->headers[$name] = $value;
}
/**
* Send headers to the response.
*/
protected function sendHeaders() {
foreach ($this->headers as $name => $value) {
drupal_add_http_header($name, $value);
}
}
/**
* Security control.
*
* To allow the call, you have to authorize the ip of the calling server in
* the "entity_share_server_allowed_ips" variable.
*
* @return bool
* TRUE if the request can be performed, FALSE otherwise.
*/
protected function isRequestAllowed() {
// IP address allowed.
$allowed_ips = variable_get(self::IP_RESTRICTED_VARIABLE, array());
if (!in_array(ip_address(), $allowed_ips)) {
watchdog(self::WATCHDOG_TYPE, 'The IP %ip is not allowed', array(
'%ip' => ip_address(),
), WATCHDOG_ERROR);
return FALSE;
}
// Do not check user if we are in the login step.
if ($this
->getParam('type') != 'login') {
// User connected and have the correct permissions.
if (!(user_is_logged_in() && user_access('access entityshare server'))) {
watchdog(self::WATCHDOG_TYPE, 'The user is not allowed', array(), WATCHDOG_ERROR);
return FALSE;
}
}
return TRUE;
}
/**
* Authenticate the user.
*/
protected function doLogin() {
// Get the login and password.
$login = $this
->getParam('datas')->login;
$password = $this
->getParam('datas')->password;
// Authenticate user in drupal.
global $user;
$account = user_authenticate($login, $password);
if (!$account) {
$this
->setError('Invalid user');
return;
}
// Update the drupal loaded user.
$user = user_load($account, TRUE);
// Regenerate the session for security reason.
drupal_session_regenerate();
// Get the session informations.
$session_name = session_name();
$session_id = session_id();
if (!empty($session_name) && !empty($session_id)) {
$this
->setResult(array(
'session_name' => $session_name,
'session_id' => $session_id,
));
}
else {
$this
->setError('User session invalid');
}
}
}