marketo_suite-1.0.x-dev/src/MarketoRestHelper.php
src/MarketoRestHelper.php
<?php
namespace Drupal\e3_marketo;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Url;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
/**
* Provides helper functions to access Marketo Rest API.
*
* @package Drupal\e3_marketo
*/
class MarketoRestHelper {
/**
* Marketo API settings.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected ImmutableConfig $apiSettings;
/**
* Logger channel.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected LoggerChannelInterface $logger;
/**
* CventGdprHandler constructor.
*
* @param \GuzzleHttp\Client $httpClient
* HTTP Client.
* @param \Drupal\Core\State\StateInterface $state
* State Storage.
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* Configuration factory service.
* @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerFactory
* Logger channel factory.
*/
public function __construct(
protected Client $httpClient,
protected StateInterface $state,
ConfigFactoryInterface $configFactory,
LoggerChannelFactoryInterface $loggerFactory
) {
$this->apiSettings = $configFactory->get('e3_marketo.settings');
$this->logger = $loggerFactory->get('e3_marketo');
}
/**
* Get access token either from storage or identity endpoint.
*
* @return string|null
* Either retrieved token, or FALSE if operation failed.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getAccessToken() : ?string {
// Retrieve stored token information, if available.
$token_data = $this->state->get('e3_marketo.token_status');
// Check if token has expired or is close to expiration (1 min).
if ($token_data && ($token_data['expires_in'] - time() > 60)) {
return $token_data['access_token'];
}
else {
// Otherwise attempt to generate a new token.
$token_data = $this->generateAccessToken();
if ($token_data) {
return $token_data['access_token'];
}
}
return NULL;
}
/**
* Generate access token, using provided identity endpoint.
*
* @return array|null
* Retrieved token data, or FALSE if operation failed.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function generateAccessToken() : ?array {
// Retrieve ClientID, secret, build identity endpoint.
$client_id = $this->apiSettings->get('client_id');
$client_secret = $this->apiSettings->get('client_secret');
$identity_endpoint = "{$this->apiSettings->get('identity_endpoint_path')}/oauth/token";
// Attempt to retrieve an access token with given settings.
try {
$response = $this->httpClient->get("{$identity_endpoint}?grant_type=client_credentials&client_id={$client_id}&client_secret={$client_secret}");
$result = json_decode($response->getBody()->getContents());
// If successful, save retrieved token data.
if (!empty($result->access_token) && !empty($result->expires_in)) {
$token_data = [
'access_token' => $result->access_token,
'expires_in' => time() + $result->expires_in,
];
$this->state->set('e3_marketo.token_status', $token_data);
return $token_data;
}
}
catch (RequestException $e) {
$this->logger->error($e->getMessage());
}
return NULL;
}
/**
* Retrieve endpoint path for Leads requests.
*
* @return string|null
* Endpoint path or null if not set in Marketo Settings.
*/
public function getLeadsEndpoint() : ?string {
$endpoint = $this->apiSettings->get('endpoint_path');
if ($endpoint) {
$endpoint = $endpoint . '/v1/leads.json';
}
return $endpoint;
}
/**
* Retrieve lead data for specified fields from Marketo.
*
* @param string $tracking_cookie
* Marketo tracking cookie value.
* @param array $fields
* Array of API field names to get the data from.
*
* @return mixed
* Retrieved Marketo Lead data.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getLeadFields(string $tracking_cookie, array $fields) : mixed {
$access_token = $this->getAccessToken();
$endpoint = $this->getLeadsEndpoint();
if (!$endpoint || !$access_token) {
return FALSE;
}
$arguments = [
'filterType' => 'cookie',
];
// Add fields, value of the cookie and access token to query arguments.
if (!empty($tracking_cookie) && !empty($fields)) {
$arguments['filterValues'] = $tracking_cookie;
$arguments['fields'] = implode(',', $fields);
$arguments['access_token'] = $access_token;
}
try {
$marketo_response = $this->httpClient->request('GET', $endpoint, ['query' => $arguments]);
$data = $marketo_response->getBody()->getContents();
}
catch (\Exception $e) {
$data = '{}';
}
return json_decode($data);
}
/**
* Update or create Leads in Marketo.
*
* @param array $lead_data
* Array of Lead data as expected by Marketo.
*
* @return string|null
* Request result.
*
* @throws \GuzzleHttp\Exception\GuzzleException
*
* @see http://developers.marketo.com/rest-api/endpoint-reference/lead-database-endpoint-reference/#!/Leads/syncLeadUsingPOST
*/
public function syncLeads(array $lead_data) : ?string {
$access_token = $this->getAccessToken();
$endpoint = $this->getLeadsEndpoint();
// No need to proceed if any of these are missing.
if (!$endpoint || !$access_token || !$lead_data) {
return NULL;
}
$arguments = [
'access_token' => $access_token,
];
// Create endpoint URL with access token included.
$endpoint = Url::fromUri($endpoint, ['query' => $arguments]);
// Send post request to sync the lead.
try {
$marketo_response = $this->httpClient->post($endpoint->toString(), [
'body' => json_encode($lead_data),
'headers' => [
'Accept' => "application/json",
'Content-Type' => "application/json",
],
'http_errors' => FALSE,
]);
$data = $marketo_response->getBody()->getContents();
}
catch (\Exception $e) {
$data = '{}';
}
return $data;
}
}
