Jan Zavrl
Drupal Camp Zagreb, May 2017
@jnzavrl | jzavrl | janzavrl.me
@ndp_studio | ndp-studio.com
Building an API service on Drupal 8, Zagreb, May 2017
Building an API service on Drupal 8, Zagreb, May 2017
Building an API service on Drupal 8, Zagreb, May 2017
Building an API service on Drupal 8, Zagreb, May 2017
Building an API service on Drupal 8, Zagreb, May 2017
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Provides a base class for all Salesforce resource classes.
*/
abstract class SalesforceBaseResource extends ResourceBase {
...
/**
* The Salesforce SOAP contact creation method.
*
* @var string
*/
const ACCOUNT_CONTACT_METHOD = 'addAccountContact';
...
/**
* Returns a new ResourceResponse object containing data.
*
* @param array $data
* Array of information needed to respond with.
*
* @return \Drupal\rest\ResourceResponse
* The response.
*/
public function respond(array $data) {
// Prepare a new ResourceResponse with the data.
$response = new ResourceResponse($data);
return $this->disableCache($response);
}
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Returns a new ModifiedResourceResponse object containing data.
*
* @param array $data
* Array of information needed to respond with.
*
* @return \Drupal\rest\ModifiedResourceResponse
* The response.
*/
public function patchRespond(array $data) {
// Prepare a new ModifiedResourceResponse with the data.
return new ModifiedResourceResponse($data);
}
Building an API service on Drupal 8, Zagreb, May 2017
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Provides a resource to get view modes by entity and bundle.
*
* @RestResource(
* id = "salesforce_get_order",
* label = @Translation("Salesforce get Order"),
* uri_paths = {
* "canonical" = "/v1/salesforce/orders/{id}/{property}"
* }
* )
*/
class SalesforceGetOrder extends SalesforceBaseResource {
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Responds to GET requests for retrieving order information.
*
* @param string $property
* The property of the object to retrieve. Will be passed from the URL
* and is optional.
* @param string $id
* The id of the object to retrieve. Will be passed from the URL.
*
* @return \Drupal\rest\ResourceResponse
* A new ResourceResponse instance.
*/
public function get($property, $id) {
// Get the order array ready for response.
$response = $this->salesforceHelper->getOrder($id, $property);
return $this->respond($response);
}
Building an API service on Drupal 8, Zagreb, May 2017
namespace Drupal\apiservice_salesforce\Plugin\rest\resource;
/**
* Provides a resource to get view modes by entity and bundle.
*
* @RestResource(
* id = "salesforce_create_order",
* label = @Translation("Salesforce create Order"),
* uri_paths = {
* "canonical" = "/v1/salesforce/orders/create",
* "https://www.drupal.org/link-relations/create" = "/v1/salesforce/orders/create"
* }
* )
*/
class SalesforceCreateOrder extends SalesforceBaseResource {
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Responds to POST requests for creating orders.
*
* @param array $data
* The request body with fields to insert.
*
* @return \Drupal\rest\ResourceResponse
* A new ResourceResponse instance.
*/
public function post(array $data = []) {
// Create a new order based on the given array.
$response = $this->salesforceHelper->createOrder($data);
return $this->respond($response);
}
Building an API service on Drupal 8, Zagreb, May 2017
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Class SalesforceSoapForm.
*
* @package Drupal\apiservice_salesforce\Form
*/
class SalesforceSoapForm extends ConfigFormBase {
...
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['username'] = [
'#type' => 'textfield',
'#title' => $this->t('Salesforce SOAP username'),
'#maxlength' => 64,
'#size' => 64,
'#default_value' => $this->config->get('username'),
'#description' => $this->t('Enter the username of your Salesforce account.'),
];
...
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
$this->config->set('username', $form_state->getValue('username'));
...
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Defines the Moodle client entity.
*
* @ConfigEntityType(
* id = "moodle_client",
* label = @Translation("Moodle client"),
* handlers = {
* "list_builder" = "Drupal\apiservice_moodle\MoodleClientListBuilder",
* "form" = {
* "add" = "Drupal\apiservice_moodle\Form\MoodleClientForm",
* "edit" = "Drupal\apiservice_moodle\Form\MoodleClientForm",
* "delete" = "Drupal\apiservice_moodle\Form\MoodleClientDeleteForm"
* },
* "route_provider" = {
* "html" = "Drupal\apiservice_moodle\MoodleClientHtmlRouteProvider",
* },
* },
* config_prefix = "moodle_client",
* admin_permission = "administer site configuration",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid",
* },
* links = {
* "canonical" = "/admin/config/services/moodle/moodle_client/{moodle_client}",
* "add-form" = "/admin/config/services/moodle/moodle_client/add",
* "edit-form" = "/admin/config/services/moodle/moodle_client/{moodle_client}/edit",
* "delete-form" = "/admin/config/services/moodle/moodle_client/{moodle_client}/delete",
* "collection" = "/admin/config/services/moodle/moodle_client"
* }
* )
*/
class MoodleClient extends ConfigEntityBase implements MoodleClientInterface {
Building an API service on Drupal 8, Zagreb, May 2017
/**
* {@inheritdoc}
*/
public function getSoapClient() {
return $this->getMoodleClientPluginManager()->createInstance($this->plugin_id, [
'token' => $this->getToken(),
'endpoint' => $this->getEndpoint(),
'instance' => $this->id(),
'email_notification_status' => $this->getEmailNotificationStatus(),
'basic_auth' => $this->getBasicAuth()
]);
}
Building an API service on Drupal 8, Zagreb, May 2017
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Salesforce mapper service.
*
* @package Drupal\apiservice_salesforce
*/
class SalesforceMapper {
/**
* Main method for retrieving mappings.
*
* The method retrieves mapping information based on the type provided,
* the Salesforce object name and also standardizes the type itself.
*
* @param string $type
* The type of the object we are looking for.
*
* @return array
* Array containing the standardizes type string and the mappings array.
*/
public function getMappings($type) {
$mapping_type = '';
$mapping_object = '';
$mapping_reference = '';
switch ($type) {
case 'account':
case 'Account':
$mapping_type = 'account';
$mapping_object = 'Account';
$mappings = $this->accountMapping();
break;
...
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Contact mapping from this API to the object retrieved from Salesforce.
*
* @return array
* The array containing the mappings.
*/
private function contactMapping() {
return [
'id' => 'X18_Digit_Contact_ID__c',
'account_id' => 'AccountId',
'principal_building' => 'Contact_Principle_Address_Building__c',
'principal_street' => 'Contact_Principle_Address_Street__c',
'principal_area' => 'Contact_Principle_Address_Area__c',
'principal_city' => 'Contact_Principle_Address_City__c',
'principal_state' => 'Contact_Principle_Address_State_Province__c',
'principal_postal_code' => 'Contact_Principle_Address_ZIP_Postal__c',
'principal_country' => 'Contact_Principle_Address_Country__c',
'email_opt_out' => 'HasOptedOutOfEmail',
'website_user_id' => 'WebId__c',
'website_user_ref' => 'Website_User_Ref__c',
'salutation' => 'Salutation',
'first_name' => 'FirstName',
'last_name' => 'LastName',
'title' => 'Title',
'email' => 'Email',
'phone' => 'MobilePhone',
'subscription' => $this->subscriptionMapping(),
'external_credentials' => $this->externalCredentialsMapping(),
];
}
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Maps given data to the ones defined in the mappings.
*
* @param array $mappings
* The mappings structure array.
* @param array $data
* The data that needs mapping.
*
* @return array
* The newly mapped array of data.
*/
private function mapData(array $mappings, array $data) {
$mapped_data = [];
// Loop over the given data and map it properly against the mappings.
foreach ($data as $key => $value) {
if ($mappings['mappings'][$key]) {
$mapped_data[$mappings['mappings'][$key]] = $value;
}
}
return $mapped_data;
}
Building an API service on Drupal 8, Zagreb, May 2017
/**
* Retrieves a referenced object based on the parent object.
*
* @param \Drupal\salesforce\SObject $parent
* The Salesforce object of the parent.
* @param string $child
* The API identifier for the referenced object.
*
* @return array|mixed
* Prepared data of the new referenced object,
* or a message if it couldn't be retrieved.
*/
private function getReferencedObject(SObject $parent, $child) {
// Get mapping for this reference object.
$reference_mapping = $this->salesforceMapper->getMappings($child);
// Prepare the condition fields for the query.
$mapping = array_flip($reference_mapping['mappings']);
$mapping = implode(',', $mapping);
$conditions = [
'conditions' => [
$reference_mapping['reference'] => $parent->id()->__toString(),
],
];
// Run the query.
$result = $this->runQuery($child, $mapping, $conditions);
return $result;
}
Building an API service on Drupal 8, Zagreb, May 2017
Building an API service on Drupal 8, Zagreb, May 2017
@jnzavrl | jzavrl | janzavrl.me
@ndp_studio | ndp-studio.com
Building an API service on Drupal 8, Zagreb, May 2017