Last active
January 8, 2019 15:14
-
-
Save nikathone/a771b707d447200e9c6f0b7389042444 to your computer and use it in GitHub Desktop.
Report drupal commerce order to administrate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\administrate_esr; | |
use Drupal\address\AddressInterface; | |
use Drupal\commerce_order\Entity\OrderInterface; | |
use Drupal\Core\Config\ConfigFactoryInterface; | |
use Drupal\Core\Entity\EntityTypeManagerInterface; | |
use Drupal\Core\Logger\LoggerChannelFactoryInterface; | |
use Drupal\Driver\Exception\Exception; | |
use GuzzleHttp\Client; | |
use GuzzleHttp\Exception\ClientException; | |
use GuzzleHttp\Exception\ConnectException; | |
use GuzzleHttp\Exception\ServerException; | |
/** | |
* The report service. | |
*/ | |
class ReportOrderToAdministrate { | |
/** | |
* The guzzle http client service. | |
* | |
* @var \GuzzleHttp\Client | |
*/ | |
protected $httpClient; | |
/** | |
* The administrate api configurations. | |
* | |
* @var \Drupal\Core\Config\ImmutableConfig | |
*/ | |
protected $apiConfig; | |
/** | |
* The entity type manager. | |
* | |
* @var \Drupal\Core\Entity\EntityTypeManagerInterface | |
*/ | |
protected $entityTypeManager; | |
/** | |
* The administrate esr module logger channel. | |
* | |
* @var \Drupal\Core\Logger\LoggerChannelInterface | |
*/ | |
protected $logger; | |
/** | |
* The variable to hold a loaded contact if any. | |
* | |
* @var \Object | |
*/ | |
protected $contact; | |
/** | |
* Constructs Report object. | |
* | |
* @param \GuzzleHttp\Client $http_client | |
* The http guzzle client. | |
* @param \Drupal\Core\Config\ConfigFactoryInterface $config | |
* The config factory. | |
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager | |
* The entity type manager. | |
* @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger | |
* The logger. | |
*/ | |
public function __construct(Client $http_client, ConfigFactoryInterface $config, EntityTypeManagerInterface $entity_type_manager, LoggerChannelFactoryInterface $logger) { | |
$this->httpClient = $http_client; | |
$this->apiConfig = $config->get('administrate_api.config'); | |
$this->entityTypeManager = $entity_type_manager; | |
$this->logger = $logger->get('administrate_esr'); | |
} | |
/** | |
* Send a drupal commerce order to administrate. | |
* | |
* @param \Drupal\commerce_order\Entity\OrderInterface $order | |
* The commerce order. | |
* | |
* @return bool|void | |
* The feedback. | |
* | |
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException | |
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException | |
* @throws \Drupal\Core\Entity\EntityStorageException | |
*/ | |
public function order(OrderInterface $order) { | |
// It's an order to report in administrate. | |
$administrate_order = $order->hasField('administrate_id'); | |
// If an order is already associated with an administrate id we skip it. | |
$administrate_id = $order->get('administrate_id')->remote_id; | |
if (!$administrate_order || ($administrate_id > 0)) { | |
return; | |
} | |
$order_email = $order->getEmail(); | |
$contact_id = $this->getContactId($order_email, TRUE); | |
if (is_null($contact_id) || $contact_id === FALSE) { | |
/** @var \Drupal\address\AddressInterface $address */ | |
$address = $order->getBillingProfile()->address->first(); | |
$account_id = $this->getAccountId($address->getOrganization(), $order_email); | |
if (is_null($account_id) || $account_id === FALSE) { | |
$account_id = $this->addAccount($address, $order_email); | |
} | |
$contact_id = $this->addContact($address, $order_email, [], $account_id); | |
} | |
else { | |
$account_id = $this->contact->account_id; | |
} | |
$students = []; | |
foreach ($order->getItems() as $order_item) { | |
if (!$order_item->hasField('administrate_learner_details')) { | |
continue; | |
} | |
/** @var \Drupal\commerce_product\Entity\ProductVariationInterface $purchased_entity */ | |
$event_pricing = $order_item->getPurchasedEntity(); | |
$event = $event_pricing->getProduct(); | |
// Getting learner details from order_items. | |
$learner_details = $order_item->get('administrate_learner_details'); | |
foreach ($learner_details as $learner_detail) { | |
/** @var \Drupal\administrate_commerce\Entity\LearnerInterface $learner */ | |
$learner = $learner_detail->entity; | |
$learner_email = $learner->getEmail(); | |
$student_id = $this->getContactId($learner_email); | |
if (is_null($student_id) || $student_id === FALSE) { | |
$name = [ | |
'given' => $learner->getName()->given, | |
'family' => $learner->getName()->family, | |
]; | |
$student_id = $this->addContact( | |
$learner->getAddress(), | |
$learner_email, | |
$name, | |
$account_id, | |
$learner->getName()->title, | |
$learner->getPhone() | |
); | |
} | |
$students[] = [ | |
'event_id' => $event->get('administrate_id')->remote_id, | |
'price' => floatval($order_item->getUnitPrice()->getNumber()), | |
'contact_id' => $student_id, | |
]; | |
} | |
} | |
// For payment transaction code use one payment method from the order. | |
/** @var \Drupal\commerce_payment\PaymentStorageInterface $commerce_payment_storage */ | |
$commerce_payment_storage = $this->entityTypeManager->getStorage('commerce_payment'); | |
$transaction_code = $order->getOrderNumber(); | |
foreach ($commerce_payment_storage->loadMultipleByOrder($order) as $commerce_payment) { | |
$state = $commerce_payment->getState()->value; | |
if ($state == 'completed') { | |
$transaction_code = $commerce_payment->getPaymentGateway()->id(); | |
$transaction_code .= '--' . $commerce_payment->getRemoteId(); | |
break; | |
} | |
} | |
$administrate_order = [ | |
'contact_id' => $contact_id, | |
'currency_id' => $order->getTotalPrice()->getCurrencyCode(), | |
'source_type_id' => 16, | |
'external_id' => $order->id(), | |
'items' => $students, | |
'payment' => [ | |
'amount' => floatval($order->getTotalPrice()->getNumber()), | |
'type' => 'Card', | |
'currency' => $order->getTotalPrice()->getCurrencyCode(), | |
'transaction_code' => $transaction_code, | |
], | |
]; | |
if (!($data = $this->postBody('/orders', $administrate_order))) { | |
return FALSE; | |
} | |
$order->set('administrate_id', ['remote_id' => $data->order_id]); | |
// Log this on the order. | |
/** @var \Drupal\commerce_log\LogStorageInterface $log_storage */ | |
$log_storage = $this->entityTypeManager->getStorage('commerce_log'); | |
$params = ['administrate_id' => $data->order_id]; | |
$log = $log_storage->generate($order, 'order_administrate_reported', $params); | |
$log->save(); | |
} | |
/** | |
* Gets an administrate contact id. | |
* | |
* @param string $email | |
* The email. | |
* @param bool $primary | |
* Whether contact is primary. | |
* | |
* @return bool|int | |
* The contact id or false. | |
*/ | |
private function getContactId($email, $primary = FALSE) { | |
if (!($data = $this->getQuery('/crm/contacts', ['email__eq' => $email]))) { | |
return FALSE; | |
} | |
if ($primary) { | |
$this->contact = $data[0]; | |
} | |
return $data[0]->id; | |
} | |
/** | |
* Adding an administrate contact. | |
* | |
* @param \Drupal\address\AddressInterface $address | |
* The address. | |
* @param string $email | |
* The email. | |
* @param array $name | |
* The name components. | |
* @param int $account_id | |
* The account id. | |
* @param string $salutation | |
* The salutation. | |
* @param string $telephone | |
* The telephone. | |
* | |
* @return bool|int | |
* The account id or false. | |
*/ | |
private function addContact(AddressInterface $address, $email, array $name, $account_id, $salutation = '', $telephone = '') { | |
if (!$name) { | |
$name = [ | |
'given' => $address->getGivenName(), | |
'family' => $address->getFamilyName() | |
]; | |
} | |
$user = [ | |
'first_name' => $name['given'], | |
'last_name' => $name['family'], | |
'account_id' => $account_id, | |
'address_unit' => $address->getAddressLine1(), | |
'address_town' => $address->getLocality(), | |
'address_postcode' => $address->getPostalCode(), | |
'address_region' => $address->getAdministrativeArea(), | |
'address_country_id' => $address->getCountryCode(), | |
'organisation' => $address->getOrganization(), | |
'email' => $email | |
]; | |
if (!empty($telephone)) { | |
$user['tel'] = $telephone; | |
} | |
if (!empty($salutation)) { | |
$user['salutation'] = $salutation; | |
} | |
if (!($data = $this->postBody('/crm/contacts', $user))) { | |
return FALSE; | |
} | |
return $data->id; | |
} | |
/** | |
* Gets an administrate account id. | |
* | |
* @param string $name | |
* The account name. | |
* @param string $email | |
* The account email. | |
* | |
* @return bool|int | |
* The account id or false. | |
*/ | |
private function getAccountId($name, $email) { | |
if (!($data = $this->getQuery('/crm/accounts', ['name__eq' => $name, 'email__eq' => $email]))) { | |
return FALSE; | |
} | |
return $data[0]->id; | |
} | |
/** | |
* Adding an administrate account. | |
* | |
* @param \Drupal\address\AddressInterface $address | |
* The address. | |
* @param string $email | |
* The email. | |
* | |
* @return bool|int | |
* The account id or false. | |
*/ | |
private function addAccount(AddressInterface $address, $email) { | |
$account = [ | |
'name' => $address->getOrganization(), | |
'email' => $email, | |
'address_unit' => $address->getAddressLine1(), | |
'address_town' => $address->getLocality(), | |
'address_postcode' => $address->getPostalCode(), | |
'address_region' => $address->getAdministrativeArea(), | |
'address_country' => $address->getCountryCode(), | |
'company_id' => 1, | |
]; | |
if (!($data = $this->postBody('/crm/accounts', $account))) { | |
return FALSE; | |
} | |
return $data->id; | |
} | |
/** | |
* Gets guzzle request with query. | |
* | |
* @param string $endpoint | |
* The request endpoint. | |
* @param string $query | |
* The query. | |
* | |
* @return bool|mixed | |
* Request status or contents. | |
*/ | |
private function getQuery($endpoint, $query) { | |
return $this->get($endpoint, ['query' => $query]); | |
} | |
/** | |
* Get Guzzle request. | |
* | |
* @param string $endpoint | |
* The request endpoint. | |
* @param array $params | |
* The request parameters. | |
* | |
* @return bool|mixed | |
* Request status or contents. | |
*/ | |
private function get($endpoint, array $params = []) { | |
if (!isset($params['auth'])) { | |
$params['auth'] = $this->getAuth(); | |
} | |
return $this->sendRequest('get', $endpoint, $params); | |
} | |
/** | |
* Post request body. | |
* | |
* @param string $endpoint | |
* The request endpoint. | |
* @param mixed $body | |
* The request body. | |
* | |
* @return bool|mixed | |
* Request status or contents. | |
*/ | |
private function postBody($endpoint, $body) { | |
return $this->post($endpoint, ['body' => $body]); | |
} | |
/** | |
* Make a Guzzle POST request. | |
* | |
* @param string $endpoint | |
* The request endpoint. | |
* @param array $params | |
* The request parameters. | |
* | |
* @return bool|mixed | |
* Request status or contents. | |
*/ | |
private function post($endpoint, array $params = []) { | |
if (isset($params['body'])) { | |
$params['body'] = json_encode($params['body']); | |
} | |
if (!isset($params['auth'])) { | |
$params['auth'] = $this->getAuth(); | |
} | |
if (!isset($params['headers']) || !isset($params['headers']['Content-Type'])) { | |
$params['headers']['Content-Type'] = 'application/json'; | |
} | |
return $this->sendRequest('post', $endpoint, $params); | |
} | |
/** | |
* Gets Authentication credentials. | |
* | |
* @return array | |
* The credentials. | |
*/ | |
private function getAuth() { | |
$user = $this->apiConfig->get('username'); | |
$pass = $this->apiConfig->get('password'); | |
return [$user, $pass]; | |
} | |
/** | |
* Gets Administrate base URL. | |
* | |
* @return string | |
* The base URL. | |
*/ | |
private function getBaseUrl() { | |
$hostname = $this->apiConfig->get('hostname'); | |
if (substr($hostname, -1) == '/') { | |
$url = $hostname . 'api/v2'; | |
} | |
else { | |
$url = $hostname . '/api/v2'; | |
} | |
return $url; | |
} | |
/** | |
* Sends the guzzle request. | |
* | |
* @param string $method | |
* The guzzle request method. | |
* @param string $endpoint | |
* The request endpoint. | |
* @param array $params | |
* The request parameters. | |
* | |
* @return bool|mixed | |
* Request status or contents. | |
*/ | |
private function sendRequest($method, $endpoint, array $params) { | |
$error_code = 0; | |
$error_message = 'unknown'; | |
try { | |
$url = $this->getBaseUrl() . $endpoint; | |
$response = $method == 'post' ? $this->httpClient->post($url, $params) : $this->httpClient->get($url, $params); | |
if ($response->getStatusCode() == 200) { | |
return json_decode((string) $response->getBody()); | |
} | |
else { | |
$resp = $response; | |
} | |
} | |
catch (\Exception $e) { | |
$error_code = $e->getCode(); | |
$error_message = $e->getMessage(); | |
$resp = NULL; | |
} | |
catch (ServerException $e) { | |
$resp = $e->getResponse(); | |
} | |
catch (ClientException $e) { | |
$resp = $e->getResponse(); | |
} | |
catch (ConnectException $e) { | |
$resp = $e->getResponse(); | |
} | |
if ($resp) { | |
$this->logger->notice('STATUS CODE FROM ADMINISTRATE ' . $resp->getStatusCode() . ' ' . $resp->getBody()->getContents()); | |
} | |
else { | |
$message = t('Exception Error code: @code <br/>Exception Error message @message', [ | |
'@code' => $error_code, | |
'@message' => $error_message, | |
])->render(); | |
$this->logger->notice($message); | |
} | |
return FALSE; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment