wsclient_rest.inc in Web service client 7
Web service client REST - include file.
File
wsclient_rest/wsclient_rest.incView source
<?php
/**
* @file
* Web service client REST - include file.
*/
/**
* A remote endpoint type for invoking REST services.
*/
class WSClientRESTEndpoint extends WSClientEndpoint {
/**
* @var HttpClient
*/
protected $client;
public function __construct(WSClientServiceDescription $service) {
$this->service = $service;
$this->url = $service->url;
}
/**
* {@inheritdoc}
* @return HttpClient
*/
public function client() {
if (!isset($this->client)) {
$settings = $this->service->settings;
// Determine which type of authentication to use.
$authentication = NULL;
if (isset($settings['authentication'])) {
// Handle each type of authentication.
foreach ($settings['authentication'] as $auth => $auth_settings) {
// @todo Remove this check once multiple authentications are
// implemented.
if ($auth == 'type') {
continue;
}
// @todo Remove this check once multiple authentications are
// implemeted. For now the switch would cause the last configured
// authentication type to be taken.
if ($auth == $settings['authentication']['type']) {
// @todo Allow multiple authentications by implementing and using
// HttpClientCompositeAuth.
switch ($auth) {
// OAuth v2 support using the http_client module.
case 'oauth2':
$authentication = new HttpClientOAuth2($auth_settings);
break;
// Default authentication options from the http_client module.
case 'basic':
case 'wss':
default:
$username = $auth_settings['username'];
$password = $auth_settings['password'];
$authentication = new HttpClientBasicAuth($username, $password);
break;
}
}
}
}
if (wsclient_rest_has_old_formatter($settings)) {
$formatter = new $settings['formatter']();
$this->client = new HttpClient($authentication, $formatter, $this);
}
else {
$formatters = array();
foreach (array(
'send_formatter',
'receive_formatter',
) as $formatter_type) {
// Settings could be missing.
$formatter_settings = !empty($settings[$formatter_type]['settings']) ? $settings[$formatter_type]['settings'] : array();
$formatters[$formatter_type] = new $settings[$formatter_type]['class']($formatter_settings);
}
$formatter = new HttpClientCompositeFormatter($formatters['send_formatter'], $formatters['receive_formatter']);
$this->client = new HttpClient($authentication, $formatter, $this);
}
// Pass through additional curl options.
if (!empty($settings['curl options'])) {
$this->client->options['curlopts'] = $settings['curl options'];
}
}
return $this->client;
}
/**
* Calls the REST service.
*
* @param string $operation_name
* The name of the operation to execute.
* @param array $arguments
* Arguments to pass to the service with this operation.
*/
public function call($operation_name, $arguments) {
$operation = $this->service->operations[$operation_name];
$operation_url = isset($operation['url']) ? $operation['url'] : '';
// Replace argument patterns in the operation URL.
foreach ($arguments as $key => $value) {
if (strpos($operation_url, '@' . $key) !== FALSE) {
$operation_url = str_replace('@' . $key, $value, $operation_url);
unset($arguments[$key]);
}
}
$client = $this
->client();
$type = isset($operation['type']) ? $operation['type'] : 'GET';
$data = NULL;
if (isset($operation['data'])) {
$data = $arguments[$operation['data']];
unset($arguments[$operation['data']]);
}
// Services module compliance: post fields should be in the $data array
// instead of $arguments.
if ($type == 'POST' || $type == 'PUT') {
$data = array_merge((array) $data, $arguments);
if (empty($data)) {
unset($data);
}
unset($arguments);
}
try {
$response = $client
->execute(new HttpClientRequest($this->service->url . $operation_url, array(
'method' => $type,
'parameters' => $arguments,
'data' => $data,
)));
return $response;
} catch (HttpClientException $e) {
throw new WSClientException('Error invoking the REST service %name, operation %operation: %error', array(
'%name' => $this->service->label,
'%operation' => $operation_name,
'%error' => $e
->getMessage(),
));
}
}
/**
* Adds options to the Web Service config form specific to the REST service.
*
* Allows the user to choose which formatter (JSO, PHP, XML) to use for
* requesting or parsing
*
* @see WSClientEndpoint::formAlter($form, $form_state)
*/
public function formAlter(&$form, &$form_state) {
$service = $form_state['service'];
$options = wsclient_rest_formatters_as_options();
switch ($form_state['form']) {
case 'main':
$default_formatter = NULL;
foreach (array(
'send_formatter',
'receive_formatter',
) as $formatter_type) {
if (wsclient_rest_has_custom_formatter($service->settings, $formatter_type)) {
$default_formatter = 'custom';
}
else {
$default_formatter = isset($service->settings[$formatter_type]['class']) ? $service->settings[$formatter_type]['class'] : 'WsclientRestJSONFormatter';
}
switch ($formatter_type) {
case 'send_formatter':
$title = t('Request formatter (send_formatter)');
$description = t('Choose how to serialize the request.');
$weight = 50;
break;
case 'receive_formatter':
$title = t('Response formatter (receive_formatter)');
$description = t('Choose how to parse the response.');
$weight = 55;
break;
}
$form['settings'][$formatter_type] = array(
'#type' => 'fieldset',
'#title' => $title,
'#tree' => TRUE,
'#weight' => $weight,
);
$form['settings'][$formatter_type]['class'] = array(
'#type' => 'select',
'#title' => t('Formatter'),
'#default_value' => $default_formatter,
'#description' => $description,
'#options' => $options,
);
}
break;
case 'operation':
$operation = $form_state['operation'];
$form['type'] = array(
'#type' => 'select',
'#title' => t('HTTP Method'),
'#default_value' => isset($operation['type']) ? $operation['type'] : 'GET',
'#description' => t('Specify the HTTP request method used for this operation.'),
'#options' => array(
'GET' => 'GET',
'POST' => 'POST',
'PUT' => 'PUT',
'DELETE' => 'DELETE',
),
'#weight' => -5,
);
$form['url'] = array(
'#type' => 'textfield',
'#title' => t('Path'),
'#default_value' => isset($operation['url']) ? $operation['url'] : '',
'#description' => t('The path to append to the services base URL. In order to construct the path using parameter values make use of replacements in the form "@parameter-name". E.g. the path "node/@nid" together with a "nid" parameter could be used to construct the path to a Drupal node.'),
'#weight' => -5,
);
break;
}
// Allow formatters to alter the form.
foreach ($options as $options_groupped) {
foreach (array_keys($options_groupped) as $formatter_class) {
if ($formatter_class == 'custom') {
// Skip custom.
continue;
}
$formatter = new $formatter_class();
if (method_exists($formatter, 'formAlter')) {
$formatter
->formAlter($form, $form_state);
}
}
}
$form['#submit'][] = 'wsclient_rest_form_submit';
}
/**
* Alters the given request.
*
* The public alterRequest method supported by Hugo Wetterberg's HttpClient.
* The request to be altered is passed to drupal_alter() with the service
* definition as a context.
*
* @param HttpClientRequest $request
* The request to be altered.
*
* @see HttpClient
* @see hook_wsclient_rest_request_alter()
*/
public function alterRequest($request) {
drupal_alter('wsclient_rest_request', $request, $this->service);
}
}
class WsclientRestFormFormatter extends HttpClientBaseFormatter {
public function __construct() {
parent::__construct(self::FORMAT_FORM);
}
}
class WsclientRestJSONFormatter extends HttpClientBaseFormatter {
public function __construct() {
parent::__construct(self::FORMAT_JSON);
}
}
class WsclientRestPHPFormatter extends HttpClientBaseFormatter {
public function __construct() {
parent::__construct(self::FORMAT_PHP);
}
}
class WsclientRestXMLFormatter extends HttpClientXMLFormatter {
public function __construct($settings = array()) {
parent::__construct(!empty($settings['default_root']) ? $settings['default_root'] : NULL, !empty($settings['adaptive_root']) ? $settings['adaptive_root'] : NULL);
$this->settings = $settings;
}
public function formAlter(&$form, &$form_state) {
switch ($form_state['form']) {
case 'main':
$service = $form_state['service'];
$info = module_invoke_all('wsclient_rest_formatter_info');
$default_formatter_settings = $info['WsclientRestXMLFormatter']['settings'];
foreach (array(
'send_formatter',
'receive_formatter',
) as $formatter_type) {
// Alias for such long nested path.
$formatter_settings = !empty($service->settings[$formatter_type]['settings']) ? $service->settings[$formatter_type]['settings'] : array();
// UI for settings.
$form['settings'][$formatter_type]['settings']['default_root'] = array(
'#type' => 'textfield',
'#title' => t('Default root'),
'#default_value' => isset($formatter_settings['default_root']) ? $formatter_settings['default_root'] : $default_formatter_settings['default_root'],
'#description' => t('Default root for created XML documents.'),
'#states' => array(
'visible' => array(
'select[name="settings[' . $formatter_type . '][class]"]' => array(
'value' => 'WsclientRestXMLFormatter',
),
),
),
);
$form['settings'][$formatter_type]['settings']['adaptive_root'] = array(
'#type' => 'checkbox',
'#title' => t('Adaptive root'),
'#default_value' => isset($formatter_settings['adaptive_root']) ? $formatter_settings['adaptive_root'] : $default_formatter_settings['adaptive_root'],
'#description' => t('If it is set to TRUE and the source data has a single root attribute the formatter will use that attribute as root. The object %foo_object would be serialized to %foo_wrapped instead of %foo_wrapped_result.', array(
'%foo_object' => '{"foo":"bar"}',
'%foo_wrapped' => '<foo>bar</foo>',
'%foo_wrapped_result' => '<result><foo>bar</foo></result>',
)),
'#states' => array(
'visible' => array(
'select[name="settings[' . $formatter_type . '][class]"]' => array(
'value' => 'WsclientRestXMLFormatter',
),
),
),
);
}
break;
}
}
public function formSubmit($form, &$form_state) {
switch ($form_state['form']) {
case 'main':
// Remove XML settings from the formatters that are not XML.
foreach (array(
'send_formatter',
'receive_formatter',
) as $formatter_type) {
if (empty($form_state['values']['settings'][$formatter_type]['formatter'])) {
continue;
}
if ($form_state['values']['settings'][$formatter_type]['formatter'] != 'WsclientRestXMLFormatter') {
foreach (array(
'default_root',
'adaptive_root',
) as $setting) {
unset($form_state['values']['settings'][$formatter_type]['settings'][$setting]);
}
}
}
break;
}
}
}
Classes
Name | Description |
---|---|
WSClientRESTEndpoint | A remote endpoint type for invoking REST services. |
WsclientRestFormFormatter | |
WsclientRestJSONFormatter | |
WsclientRestPHPFormatter | |
WsclientRestXMLFormatter |