abstract class EventHandler in Services Client 7.2
Event handler plugin.
Hierarchy
- class \ServicesClientPlugin implements ServicesClientConfigurableInterface
- class \EventHandler
Expanded class hierarchy of EventHandler
1 string reference to 'EventHandler'
- services_client_services_client_event_handler in ./
services_client.plugins.inc - List availalable event handler plugins.
File
- include/
event.inc, line 6
View source
abstract class EventHandler extends ServicesClientPlugin {
/**
* Holds connection to remote server.
*
* @var ServicesClientConnection
*/
protected $connection;
/**
* Initialized plugin classes.
*
* @var array
*/
protected $plugin_instances;
/**
* Processed drupal entity in event.
*
* @var stdClass
*/
protected $entity;
/**
* Stores tags assigned to event.
*
* @var array
*/
protected $tags = array();
public function __construct($event, $config) {
parent::__construct($event, $config);
if (empty($this->config)) {
$this->config = $this
->getDefaultConfiguration();
}
}
/**
* Retrieve event definition.
*
* @return ServicesClientEvent
* Event object wrapped by current handler.
*/
public function getEvent() {
$this->event->config = $this
->getConfiguration();
return $this->event;
}
/**
* Save current event configuration to database.
*
* @return bool
* Save result. @see ctools_export_crud_save
*/
public function save() {
$event = $this
->getEvent();
ctools_export_crud_save('services_client_connection_event', $event);
return $event;
}
/**
* Retrieve default event configuration.
*
* @return array
* Default configuration.
*/
protected function getDefaultConfiguration() {
return array(
'condition' => array(),
'uuid_version' => 'alpha1',
'uuid_resource' => '',
'resource' => '',
'debug' => ServicesClientLogLevel::INFO,
'auto_triggered' => TRUE,
);
}
/**
* Retrieves event connection to remote site.
*
* @return ServicesClientConnection
* Initialized services client connection client.
*/
protected function getConnection() {
if ($this->connection == NULL) {
$this->connection = services_client_connection_get($this->event->connection);
}
return $this->connection;
}
/**
* Retrieve remote connection id.
*
* @return string
* Remote connection id if exists.
*/
protected function getConnectionId() {
$connection = services_client_connection_load($this->event->connection);
return isset($connection->services_client_id) ? $connection->services_client_id : NULL;
}
/**
* Set new connection to remote site.
*
* @param ServicesClientConnection $connection
* Initialized SC Connection client.
*
* @return EventHandler
*/
public function setConnection($connection) {
$this->connection = $connection;
return $this;
}
/**
* Add configuration plugin.
*
* @param string $type
* Plugin type. I.e. 'condition'
*
* @param string $name
* Name of the plugin handler - class.
*/
public function addPlugin($type, $name) {
$uuid = $this
->generateUuid();
$this->config[$type][$uuid] = array(
'type' => $name,
'config' => array(),
);
return $uuid;
}
/**
* Retrieve existing plugin.
*
* @param string $type
* Plugin type.
*
* @param string $uuid
* Plugin identifier.
*
* @return ServicesClientPlugin
* Plugin instance.
*/
public function getPlugin($type, $uuid) {
$plugin = isset($this->config[$type][$uuid]) ? $this->config[$type][$uuid] : NULL;
if ($plugin) {
return $this
->getPluginInstance($plugin['type'], $plugin['config'], $uuid);
}
else {
throw new Exception("Missing plugin {$type}:{$uuid}");
}
}
/**
* Update plugin configuration. This does is not saved to DB until save() method is called.
*
* @param string $type
* Plugin type.
*
* @param string $uuid
* Plugin identifier.
*
* @param array $config
* Plugin configuration.
*/
public function setPluginConfig($type, $uuid, $config) {
$this->config[$type][$uuid]['config'] = $config;
}
/**
* Remove existing plugin from configuration. This does is not saved to DB until save() method is called.
*
* @param string $type
* Plugin type, i.e. 'mapping', 'condition'.
*
* @param string $uuid
* Plugin identifier.
*/
public function removePlugin($type, $uuid) {
unset($this->config[$type][$uuid]);
}
/**
* Retrieve plugin instance by name and configuration.
*
* @param string $name
* Class name.
*
* @param array $config
* Plugin configuration array.
*
* @return object
* Plugin instance.
*/
protected function getPluginInstance($name, $config, $uuid) {
if (isset($this->plugin_instances[$uuid])) {
return $this->plugin_instances[$uuid];
}
else {
if (!class_exists($name)) {
throw new Exception(t("Missing class @name when initializing plugin.", array(
'@name' => $name,
)));
}
$reflection = new ReflectionClass($name);
$plugin = $reflection
->newInstanceArgs(array(
$this->event,
$config,
));
$this->plugin_instances[$uuid] = $plugin;
return $plugin;
}
}
/**
* Configuration form.
*/
public function configForm(&$form, &$form_state) {
// Show conditions
$conditions = array();
foreach ($this->config['condition'] as $uuid => $plugin) {
try {
$handler = $this
->getPluginInstance($plugin['type'], $plugin['config'], $uuid);
$conditions[] = array(
$handler
->getSummary(),
implode(' | ', array(
l(t('Edit'), $this
->getUrl('plugin/condition/' . $uuid . '/edit')),
l(t('Remove'), $this
->getUrl('plugin/condition/' . $uuid . '/remove'), array(
'query' => array(
'token' => drupal_get_token($uuid),
),
)),
)),
);
} catch (Exception $e) {
watchdog_exception('services_client', $e);
}
}
$form['condition']['title'] = array(
'#markup' => '<h2>' . t('Conditions') . '</h2>',
);
$form['condition']['table'] = array(
'#theme' => 'table',
'#header' => array(
t('Name'),
t('Actions'),
),
'#rows' => $conditions,
'#empty' => t('There are no conditions added'),
);
$form['condition']['add_condition'] = array(
'#theme_wrappers' => array(
'container',
),
'#markup' => l('+ ' . t('Add condition'), $this
->getUrl('add_plugin/condition')),
);
$form['remote'] = array(
'#type' => 'fieldset',
'#title' => t('Remote configuration'),
'#tree' => FALSE,
'#weight' => 100,
);
$form['remote']['uuid_version'] = array(
'#type' => 'select',
'#title' => t('UUID version'),
'#description' => t('UUID version on remote site.'),
'#options' => array(
'alpha1' => t('7.0 alpha-1'),
'alpha3+' => t('7.0 alpha-3 and higher'),
),
'#default_value' => $this->config['uuid_version'],
);
$form['remote']['uuid_resource'] = array(
'#type' => 'textfield',
'#title' => t('UUID resource'),
'#description' => t('Name of the uuid resource that should be searched.'),
'#default_value' => $this->config['uuid_resource'],
);
$form['remote']['resource'] = array(
'#type' => 'textfield',
'#title' => t('Remote resource name'),
'#description' => t("Provide remote resource name i.e. 'node_raw'."),
'#default_value' => $this->config['resource'],
);
$form['event'] = array(
'#type' => 'fieldset',
'#title' => t('Event configuration'),
'#tree' => FALSE,
'#weight' => 200,
);
$form['event']['auto_triggered'] = array(
'#type' => 'checkbox',
'#title' => t('Automatically triggered'),
'#description' => t('This event will be triggered automatically when event happens in Drupal. I.e. on node_save call.'),
'#default_value' => $this->config['auto_triggered'],
);
$form['event']['queue'] = array(
'#type' => 'checkbox',
'#title' => t('Queue execution'),
'#description' => t('Queue execution of this event in all cases.'),
'#default_value' => isset($this->config['queue']) ? $this->config['queue'] : NULL,
'#states' => array(
'visible' => array(
':input[name="auto_triggered"]' => array(
'checked' => TRUE,
),
),
),
);
$form['event']['debug'] = array(
'#type' => 'select',
'#title' => t('Logging level'),
'#description' => t('Select level of debugging information sent to log.'),
'#options' => ServicesClientLogLevel::getLevels(),
'#default_value' => $this->config['debug'],
);
}
/**
* Submit handler; Store plugin configuration.
*/
public function configFormSubmit(&$form, &$form_state) {
$this->config['uuid_version'] = $form_state['values']['uuid_version'];
$this->config['uuid_resource'] = $form_state['values']['uuid_resource'];
$this->config['resource'] = $form_state['values']['resource'];
$this->config['debug'] = $form_state['values']['debug'];
$this->config['auto_triggered'] = $form_state['values']['auto_triggered'];
$this->config['queue'] = $form_state['values']['queue'];
}
/**
* Execute syncing of entity.
*
* @return result
*/
public abstract function execute();
/**
* Determine wheather entity is matching event conditions.
*
* @return boolean
* TRUE if etnity matches all conditions.
*/
public function isMatching() {
// If no entity is provided return FALSE
$entity = $this
->getEntity();
if (empty($entity)) {
return FALSE;
}
// Go through each plugin and check if entity matches conditions.
foreach ($this->config['condition'] as $uuid => $plugin) {
try {
$handler = $this
->getPluginInstance($plugin['type'], $plugin['config'], $uuid);
if (!$handler
->match($this
->getEntity())) {
return FALSE;
}
} catch (Exception $e) {
watchdog_exception('services_client', $e);
}
}
// All conditions were matched.
return TRUE;
}
/**
* Set entity for current event.
*
* @param stdClass $entity
* Drupal entity object like node or user.
*
* @return EntityHandler
* Reference to itself.
*/
public function setEntity($entity) {
$this->entity = $entity;
return $this;
}
/**
* Retrieve current event entity.
*
* @return stdClass
* Drupal entity.
*/
public function getEntity() {
return $this->entity;
}
/**
* Retrieve entity ID.
*
* @return int
* Retrieve local entity id.
*/
public function getEntityId() {
if ($this
->getEntity()) {
list($entity_id) = entity_extract_ids($this->event->entity_type, $this
->getEntity());
return $entity_id;
}
return NULL;
}
/**
* Get path prefixed with event specific URL.
*
* @param string $path
* Path that should be appended to URL, i.e.
*
* @return string
* Full path prefixed with event URL.
*/
public function getUrl($path = '') {
return $this
->getBaseUrl() . (!empty($path) ? '/' . $path : '');
}
/**
* Retrieve UI base url for event.
*
* @return string
* Event specific URL.
*/
public function getBaseUrl() {
return 'admin/structure/services_client/list/' . $this->event->name;
}
/**
* Retrieve instance of object initialized with object cache.
*
* @return self
*/
public function objectCached() {
// If object is not edit locked put it to object cache.
if (!$this
->getEditLock()) {
$class = get_class($this);
$item = $this
->getObjectCacheOrCache();
return new $this($item, $item->config);
}
return $this;
}
/**
* Retrieve object cached version of event.
*
* @return stdClass
* Cached version if exists, otherwise event.
*/
public function getObjectCache() {
ctools_include('object-cache');
return ctools_object_cache_get('ctui_services_client', $this->event->name . '::configure');
}
/**
* Retrieve current object from cache. If not currently in object cache adds object to
* object cache.
*
* @return stdClass
* Event object.
*/
public function getObjectCacheOrCache() {
$event = $this
->getObjectCache();
if (empty($event)) {
$this
->setObjectCache();
return $this
->getEvent();
}
return $event;
}
/**
* Store current object state to object cache.
*/
public function setObjectCache() {
$event = $this
->getEvent();
ctools_object_cache_set('ctui_services_client', $event->name . '::configure', $event);
}
/**
* Clear current object cache.
*/
public function clearObjectCache() {
ctools_object_cache_clear('ctui_services_client', $this->event->name . '::configure');
}
/**
* Determine weather object has been changed by editing configuration and not
* which isn't stored in permanent storage.
*
* @return bool
* TRUE if is changed.
*/
public function isChanged() {
$item = $this
->getEvent();
return md5(json_encode($item)) !== md5(json_encode(services_client_get_event($item->name)
->getEvent()));
}
/**
* Retrieve edit lock if exists (other user is editing same event).
*
* @return stdClass
* UID and timestamp of user which is editing.
*/
public function getEditLock() {
ctools_include('object-cache');
return ctools_object_cache_test('ctui_services_client', $this->event->name . '::configure');
}
/**
* Break any edit lock for current event.
*/
public function breakEditLock() {
ctools_object_cache_clear_all('ctui_services_client', $this->event->name . '::configure');
}
/**
* Generates a UUID v4 using PHP code.
*
* Based on code from @see http://php.net/uniqid#65879 , but corrected.
*/
protected function generateUuid() {
// The field names refer to RFC 4122 section 4.1.2.
return sprintf('%04x%04x-%04x-4%03x-%04x-%04x%04x%04x', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 4095), bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '10', 0, 2)), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
}
/**
* Retrieve printed version of any variable. Should be used
* for logging.
*
* @param mixed $object
* Data that should be converted.
*
* @return string
* Printable version of data.
*/
protected function debugObject($object) {
return print_r($object, TRUE);
}
/**
* Retrieve controll data for current entity.
*
* @return ServicesClientControl
*/
protected function getControlData() {
if ($this
->getEntity()) {
$remote_id = $this
->getConnectionId();
return new ServicesClientControl($this
->getEntity(), services_client_get_id(), $remote_id);
}
return NULL;
}
/**
* Retrieve remote entity ID.
*
* @return mixed|NULL
* If no remote entity exists returns NULL
*
* @throws ServicesClientConnectionResponseException
*/
public function getRemoteEntityId() {
// For entities that don't provide UUID don't search for remote match.
if (!isset($this
->getEntity()->uuid)) {
$this
->log(ServicesClientLogLevel::ERROR, "MISSING ENTITY UUID; entity : <pre>@entity</pre>", array(
'@entity' => $this
->debugObject($this
->getEntity()),
));
return NULL;
}
// Default result.
$result = $this
->getRemoteIdByUUID($this
->getEntity()->uuid, $this->config['uuid_resource'], $this->config['uuid_resource']);
// Log remote id.
if (!empty($result)) {
$this
->log(ServicesClientLogLevel::DEVEL, "FOUND ID; local uuid : @local_uuid, remote id : @remote_id", array(
'@local_uuid' => $this
->getEntity()->uuid,
'@remote_id' => $result,
));
}
else {
$this
->log(ServicesClientLogLevel::DEVEL, "NOT FOUND ID; local uuid : @local_uuid", array(
'@local_uuid' => $this
->getEntity()->uuid,
'@remote_id' => $result,
));
}
return $result;
}
/**
* Load remote ID by UUID based on remote UUID configuration.
*
* @param string $uuid
* UUID identifier.
*
* @param string $a1_resource
* UUID module Alpha 1 version resource name. ('user', 'node')
*
* @param string $a3_resource
* UUID module Alpha 3+ version resource name. ('user', 'node')
*
* @param string $a3_attribute
* Alpha 3+ attribute that should be searched in retrieved object.
*
* @return int
* Remote ID if found, otherwise NULL.
*
* @throws ServicesClientConnectionResponseException
*/
protected function getRemoteIdByUUID($uuid, $a1_resource, $a3_resource, $a3_attribute = 'uuid') {
// By UUID version decide what type of remote id is requested.
if ($this->config['uuid_version'] == 'alpha1') {
$result = $this
->getConnection()
->get('uuid', $a1_resource, array(
'uuid' => $uuid,
));
// Make sure we're getting scalar value
if (is_array($result) && count($result) == 1 && isset($result[0])) {
$result = $result[0];
}
}
else {
try {
$result = $this
->getConnection()
->get($a3_resource, $uuid);
if (!empty($result) && isset($result[$a3_attribute])) {
$result = $result[$a3_attribute];
}
else {
$result = NULL;
}
} catch (ServicesClientConnectionResponseException $e) {
// Only log error different than 404, which means that entity doens't exists
// on remote server.
if ($e
->getErrorCode() != 404) {
$e
->log();
throw $e;
}
$result = NULL;
}
}
return $result;
}
/**
* Allow plugin to react on before sync event.
*
* @param stdClass $object
* Mapped object that will be sent to remote site.
*/
protected function beforeSync($object) {
}
/**
* Allow plugin to react on before sync event.
*
* @param stdClass $object
* Mapped object that will be sent to remote site.
*/
protected function afterSync($object, ServicesClientEventResult $result) {
}
/**
* Make actual request to remote site to sync object.
*
* @param stdClass $object
* Mapped object that will be sent to remote site.
*
* @return stdClass
* Response from ServicesClientConnection
*/
protected abstract function doSync($object);
/**
* Log messages to Drupal watchdog.
*
* @param int $level
* Log level. @see ServicesClientLogLevel
*
* @param string $message
* Message that should be logged.
*
* @param array $data
* Watchdog data param.
*
* @param int $severity
* Watchdog severity param.
*/
protected function log($level, $message, $data, $severity = WATCHDOG_NOTICE) {
if ($level && $level <= $this->config['debug']) {
watchdog('services_client', $message, $data, $severity);
}
}
/**
* Log error result from services client operation.
*
* @param ServicesClientEventResult $result
* Result of services client operation.
*/
protected function logErrorResult($result) {
// Don't log loops as this is special error type.
if (!$result
->success() && $result->error_type != ServicesClientErrorType::LOOP) {
$this
->log(ServicesClientLogLevel::ERROR, "ERROR: error_message : @error_message, error_type : @error_type, error_code : @error_code, entity_type : @entity_type, entity_id : @entity_id, uuid : @uuid", array(
'@error_message' => $result->error_message,
'@error_type' => !empty($result->error_type) ? ServicesClientErrorType::getTypeName($result->error_type) : ServicesClientErrorType::getTypeName(ServicesClientErrorType::UNKNOWN),
'@error_code' => !empty($result->error_code) ? $result->error_code : '',
'@entity_type' => $this->event->entity_type,
'@entity_id' => $this
->getEntityId(),
'@uuid' => isset($this
->getEntity()->uuid) ? $this
->getEntity()->uuid : NULL,
), WATCHDOG_ERROR);
}
}
/**
* Determine weather event should be fired automatically on drupal object action like node_save or node_delete.
*
* @return boolean
* TRUE if should be triggered.
*/
public function isAutoTriggered() {
return !empty($this->config['auto_triggered']);
}
/**
* Return TRUE if this entity shouldn't be send automatically to all connections.
*
* @return bool
* TRUE if shoudln't be auto synced.
*/
public function skipAutosync() {
if (!empty($this
->getEntity()->_services_client_exclude)) {
return TRUE;
}
foreach (module_implements('services_client_skip_autosync') as $module) {
$function = $module . '_services_client_skip_autosync';
$result = call_user_func_array($function, array(
$this,
$this
->getEntity(),
$this->event->entity_type,
));
if ($result === TRUE) {
return TRUE;
}
}
return FALSE;
}
/**
* Enqueue item if should be queue.
*
* @param bool $force
* Force enqueueing.
*
* @return bool
* TRUE if queued.
*/
public function enqueue($force = FALSE) {
if ($this
->getEntity()) {
if ($force || !empty($this->config['queue']) || $this
->getControlData()
->shouldQueue()) {
$this
->log(ServicesClientLogLevel::INFO, "QUEUE; entity_type : @entity_type, entity_id : @entity_id, uuid : @uuid", array(
'@entity_type' => $this->event->entity_type,
'@entity_id' => $this
->getEntityId(),
'@uuid' => isset($this
->getEntity()->uuid) ? $this
->getEntity()->uuid : NULL,
));
return $this
->enqueueEntity();
}
}
return FALSE;
}
/**
* Put current entity to queue.
*
* @return bool
* TRUE if item was created.
*/
protected function enqueueEntity() {
$data = array(
'version' => 2,
'entity' => $this
->getEntity(),
'event' => $this
->getEvent()->name,
);
// Get queue
$queue = DrupalQueue::get('services_client_sync', TRUE);
// Enqueue data
return $queue
->createItem($data);
}
/**
* Add event tag.
*
* @param string $tag
* Tag that should be added to event.
*
* @return EventHandler
*/
public function addTag($tag) {
if (!$this
->hasTag($tag)) {
$this->tags[] = $tag;
}
return $this;
}
/**
* Check if event has specific tag.
*
* @param string $tag
* Tag name.
*
* @return bool
* TRUE if event has tag.
*/
public function hasTag($tag) {
return in_array($tag, $this->tags);
}
/**
* Remove tag from event.
*
* @param string $tag
* Tag name.
*/
public function removeTag($tag) {
if ($this
->hasTag($tag)) {
$this->tags = array_diff($this->tags, array(
$tag,
));
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
EventHandler:: |
protected | property | Holds connection to remote server. | |
EventHandler:: |
protected | property | Processed drupal entity in event. | |
EventHandler:: |
protected | property | Initialized plugin classes. | |
EventHandler:: |
protected | property | Stores tags assigned to event. | |
EventHandler:: |
public | function | Add configuration plugin. | |
EventHandler:: |
public | function | Add event tag. | |
EventHandler:: |
protected | function | Allow plugin to react on before sync event. | |
EventHandler:: |
protected | function | Allow plugin to react on before sync event. | 2 |
EventHandler:: |
public | function | Break any edit lock for current event. | |
EventHandler:: |
public | function | Clear current object cache. | |
EventHandler:: |
public | function |
Configuration form. Overrides ServicesClientPlugin:: |
1 |
EventHandler:: |
public | function |
Submit handler; Store plugin configuration. Overrides ServicesClientPlugin:: |
2 |
EventHandler:: |
protected | function | Retrieve printed version of any variable. Should be used for logging. | |
EventHandler:: |
abstract protected | function | Make actual request to remote site to sync object. | 2 |
EventHandler:: |
public | function | Enqueue item if should be queue. | |
EventHandler:: |
protected | function | Put current entity to queue. | |
EventHandler:: |
abstract public | function | Execute syncing of entity. | 2 |
EventHandler:: |
protected | function | Generates a UUID v4 using PHP code. | |
EventHandler:: |
public | function | Retrieve UI base url for event. | |
EventHandler:: |
protected | function | Retrieves event connection to remote site. | |
EventHandler:: |
protected | function | Retrieve remote connection id. | |
EventHandler:: |
protected | function | Retrieve controll data for current entity. | |
EventHandler:: |
protected | function | Retrieve default event configuration. | 1 |
EventHandler:: |
public | function | Retrieve edit lock if exists (other user is editing same event). | |
EventHandler:: |
public | function | Retrieve current event entity. | |
EventHandler:: |
public | function | Retrieve entity ID. | |
EventHandler:: |
public | function | Retrieve event definition. | |
EventHandler:: |
public | function | Retrieve object cached version of event. | |
EventHandler:: |
public | function | Retrieve current object from cache. If not currently in object cache adds object to object cache. | |
EventHandler:: |
public | function | Retrieve existing plugin. | |
EventHandler:: |
protected | function | Retrieve plugin instance by name and configuration. | |
EventHandler:: |
public | function | Retrieve remote entity ID. | 1 |
EventHandler:: |
protected | function | Load remote ID by UUID based on remote UUID configuration. | |
EventHandler:: |
public | function | Get path prefixed with event specific URL. | |
EventHandler:: |
public | function | Check if event has specific tag. | |
EventHandler:: |
public | function | Determine weather event should be fired automatically on drupal object action like node_save or node_delete. | |
EventHandler:: |
public | function | Determine weather object has been changed by editing configuration and not which isn't stored in permanent storage. | |
EventHandler:: |
public | function | Determine wheather entity is matching event conditions. | |
EventHandler:: |
protected | function | Log messages to Drupal watchdog. | |
EventHandler:: |
protected | function | Log error result from services client operation. | |
EventHandler:: |
public | function | Retrieve instance of object initialized with object cache. | |
EventHandler:: |
public | function | Remove existing plugin from configuration. This does is not saved to DB until save() method is called. | |
EventHandler:: |
public | function | Remove tag from event. | |
EventHandler:: |
public | function | Save current event configuration to database. | |
EventHandler:: |
public | function | Set new connection to remote site. | |
EventHandler:: |
public | function | Set entity for current event. | |
EventHandler:: |
public | function | Store current object state to object cache. | |
EventHandler:: |
public | function | Update plugin configuration. This does is not saved to DB until save() method is called. | |
EventHandler:: |
public | function | Return TRUE if this entity shouldn't be send automatically to all connections. | |
EventHandler:: |
public | function |
Constructor. Overrides ServicesClientPlugin:: |
|
ServicesClientPlugin:: |
protected | property | Plugin specific configuration | |
ServicesClientPlugin:: |
protected | property | Event definition | |
ServicesClientPlugin:: |
public | function |
Validate configuration form. Overrides ServicesClientConfigurableInterface:: |
1 |
ServicesClientPlugin:: |
public | function |
Retrieve current plugin configuration. Overrides ServicesClientConfigurableInterface:: |
|
ServicesClientPlugin:: |
public | function |
Set configuration of plugin. Overrides ServicesClientConfigurableInterface:: |