Skip to content
Snippets Groups Projects
Commit 27ce985d authored by Aaron Bauman's avatar Aaron Bauman
Browse files

Merge branch '8.x-3.x' of bitbucket.org:messageagency/sf into auth_refactor_phase1

parents e9772c3e 21e69b44
No related branches found
No related tags found
No related merge requests found
Showing
with 403 additions and 164 deletions
......@@ -5,7 +5,6 @@ namespace Drupal\salesforce_mapping\Commands;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\salesforce\Commands\SalesforceCommandsBase;
use Drupal\salesforce\Rest\RestClient;
use Drupal\salesforce\SelectQuery;
use Drush\Exceptions\UserAbortException;
......@@ -23,7 +22,7 @@ use Symfony\Component\Console\Output\Output;
* - http://cgit.drupalcode.org/devel/tree/src/Commands/DevelCommands.php
* - http://cgit.drupalcode.org/devel/tree/drush.services.yml
*/
class SalesforceMappingCommands extends SalesforceCommandsBase {
class SalesforceMappingCommands extends SalesforceMappingCommandsBase {
protected $salesforceConfig;
protected $database;
......
<?php
namespace Drupal\salesforce_mapping\Commands;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\salesforce\Rest\RestClient;
use Drush\Drush;
use Drush\Exceptions\UserAbortException;
use Symfony\Component\Console\Input\Input;
use Symfony\Component\Console\Output\Output;
use Drupal\salesforce\Commands\SalesforceCommandsBase;
use Drupal\salesforce\Commands\QueryResult;
use Drupal\salesforce\Commands\QueryResultTableFormatter;
/**
* Shared command base for Salesforce Drush commands.
*/
abstract class SalesforceMappingCommandsBase extends SalesforceCommandsBase {
/**
* Salesforce Mapping storage handler.
*
* @var \Drupal\salesforce_mapping\SalesforceMappingStorage
*/
protected $mappingStorage;
/**
* Mapped Object storage handler.
*
* @var \Drupal\salesforce_mapping\MappedObjectStorage
*/
protected $mappedObjectStorage;
/**
* SalesforceMappingCommandsBase constructor.
*
* @param \Drupal\salesforce\Rest\RestClient $client
* SF client.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $etm
* Entity type manager.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function __construct(RestClient $client, EntityTypeManagerInterface $etm) {
parent::__construct($client, $etm);
$this->mappingStorage = $etm->getStorage('salesforce_mapping');
$this->mappedObjectStorage = $etm->getStorage('salesforce_mapped_object');
}
/**
* Collect a salesforce mapping interactively.
*/
protected function interactMapping(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE, $dir = NULL) {
if ($name = $input->getArgument('name')) {
if (strtoupper($name) == 'ALL') {
$input->setArgument('name', 'ALL');
return;
}
/** @var \Drupal\salesforce_mapping\Entity\SalesforceMapping $mapping */
$mapping = $this->mappingStorage->load($name);
if (!$mapping) {
$this->logger()->error(dt('Mapping %name does not exist.', ['%name' => $name]));
}
elseif ($dir == 'push' && !$mapping->doesPush()) {
$this->logger()->error(dt('Mapping %name does not push.', ['%name' => $name]));
}
elseif ($dir == 'pull' && !$mapping->doesPull()) {
$this->logger()->error(dt('Mapping %name does not push.', ['%name' => $name]));
}
else {
return;
}
}
if ($dir == 'pull') {
$options = $this->mappingStorage->loadPullMappings();
}
elseif ($dir == 'push') {
$options = $this->mappingStorage->loadPushMappings();
}
else {
$options = $this->mappingStorage->loadMultiple();
}
$this->doMappingNameOptions($input, array_keys($options), $message, $allOption);
}
/**
* Collect a salesforce mapping name, and set it to a "name" argument.
*/
protected function interactPushMappings(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE) {
return $this->interactMapping($input, $output, $message, $allOption, 'push');
}
/**
* Collect a salesforce mapping name, and set it to a "name" argument.
*/
protected function interactPullMappings(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE) {
return $this->interactMapping($input, $output, $message, $allOption, 'pull');
}
/**
* Helper method to collect the choice from user, given a set of options.
*/
protected function doMappingNameOptions(Input $input, array $options, $message, $allOption = FALSE) {
$options = array_combine($options, $options);
if ($allOption) {
$options['ALL'] = $allOption;
}
if (!$answer = $this->io()->choice($message, $options)) {
throw new UserAbortException();
}
$input->setArgument('name', $answer);
}
/**
* Given a mapping name (and optional direction), get an array of mappings.
*
* @param string $name
* 'ALL' to load all mappings, or a mapping id.
* @param string $dir
* 'push'|'pull'|NULL to load limit mappings by push or pull types.
*
* @return \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface[]
* The mappings.
*/
protected function getMappingsFromName($name, $dir = NULL) {
$mappings = [];
if ($name == 'ALL') {
if ($dir == 'pull') {
$mappings = $this->mappingStorage->loadPullMappings();
}
elseif ($dir == 'push') {
$mappings = $this->mappingStorage->loadPushMappings();
}
else {
$mappings = $this->mappingStorage->loadMultiple();
}
}
else {
$mapping = $this->mappingStorage->load($name);
if ($dir == 'push' && !$mapping->doesPush()) {
throw new \Exception(dt("Mapping !name does not push.", ['!name' => $name]));
}
elseif ($dir == 'pull' && !$mapping->doesPull()) {
throw new \Exception(dt("Mapping !name does not pull.", ['!name' => $name]));
}
$mappings = [$mapping];
}
$mappings = array_filter($mappings);
if (empty($mappings)) {
if ($dir == 'push') {
throw new \Exception(dt('No push mappings loaded'));
}
if ($dir == 'pull') {
throw new \Exception(dt('No pull mappings loaded'));
}
}
return $mappings;
}
/**
* Given a mapping name, get an array of matching push mappings.
*
* @param string $name
* The mapping name.
*
* @return \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface[]
* The matching mappings.
*
* @throws \Exception
*/
protected function getPushMappingsFromName($name) {
return $this->getMappingsFromName($name, 'push');
}
/**
* Given a mappin gname, get an array of matching pull mappings.
*
* @param string $name
* The mapping name.
*
* @return \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface[]
* The pull mappings.
*
* @throws \Exception
*/
protected function getPullMappingsFromName($name) {
return $this->getMappingsFromName($name, 'pull');
}
/**
* Pass-through helper to add appropriate formatters for a query result.
*
* @param \Drupal\salesforce\Commands\QueryResult $query
* The query result.
*
* @return \Drupal\salesforce\Commands\QueryResult
* The same, unchanged query result.
*/
protected function returnQueryResult(QueryResult $query) {
$formatter = new QueryResultTableFormatter();
$formatterManager = Drush::getContainer()->get('formatterManager');
$formatterManager->addFormatter('table', $formatter);
return $query;
}
}
......@@ -4,7 +4,7 @@ namespace Drupal\salesforce_pull\Commands;
use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\salesforce\Commands\SalesforceCommandsBase;
use Drupal\salesforce_mapping\Commands\SalesforceMappingCommandsBase;
use Drupal\salesforce\Event\SalesforceEvents;
use Drupal\salesforce\Rest\RestClient;
use Drupal\salesforce\SFID;
......@@ -24,7 +24,7 @@ use Symfony\Component\Console\Output\Output;
* - http://cgit.drupalcode.org/devel/tree/src/Commands/DevelCommands.php
* - http://cgit.drupalcode.org/devel/tree/drush.services.yml
*/
class SalesforcePullCommands extends SalesforceCommandsBase {
class SalesforcePullCommands extends SalesforceMappingCommandsBase {
/**
* Pull queue handler service.
......
services:
salesforce_pull.commands:
salesforce_push.commands:
class: \Drupal\salesforce_push\Commands\SalesforcePushCommands
arguments: ['@salesforce.client', '@entity_type.manager', '@queue.salesforce_push', '@database']
tags:
- { name: drush.command }
- { name: drush.command }
......@@ -4,7 +4,7 @@ namespace Drupal\salesforce_push\Commands;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\salesforce\Commands\SalesforceCommandsBase;
use Drupal\salesforce_mapping\Commands\SalesforceMappingCommandsBase;
use Drupal\salesforce\Rest\RestClient;
use Drupal\salesforce_push\PushQueue;
use Symfony\Component\Console\Input\Input;
......@@ -21,7 +21,7 @@ use Symfony\Component\Console\Output\Output;
* - http://cgit.drupalcode.org/devel/tree/src/Commands/DevelCommands.php
* - http://cgit.drupalcode.org/devel/tree/drush.services.yml
*/
class SalesforcePushCommands extends SalesforceCommandsBase {
class SalesforcePushCommands extends SalesforceMappingCommandsBase {
/**
* Database service.
......
name: Salesforce Soap
type: module
description: Exposes a SoapClient service for communicating with the Salesforce SOAP API.
package: Salesforce
core: 8.x
dependencies:
- salesforce:salesforce
services:
salesforce.soap_client:
class: Drupal\salesforce_soap\Soap\SoapClient
arguments: ['@salesforce.client']
<?php
namespace Drupal\salesforce_soap\Soap;
use Drupal\salesforce\Rest\RestClientInterface;
use SforcePartnerClient;
/**
* A client for communicating with the Salesforce SOAP API.
*/
class SoapClient extends SforcePartnerClient implements SoapClientInterface {
/**
* Indicates whether or not a successfull connection was made to the SOAP API.
*
* @var bool
*/
protected $isConnected;
/**
* Salesforce REST API client.
*
* @var \Drupal\salesforce\Rest\RestClientInterface
*/
protected $restApi;
/**
* Path to the WSDL that should be used.
*
* @var string
*/
protected $wsdl;
/**
* Constructor which initializes the consumer.
*
* @param \Drupal\salesforce\Rest\RestClientInterface $rest_api
* The Salesforce REST API client.
* @param string $wsdl
* (Optional) Path to the WSDL that should be used. Defaults to using the
* partner WSDL from the developerforce/force.com-toolkit-for-php package.
*/
public function __construct(RestClientInterface $rest_api, $wsdl = NULL) {
parent::__construct();
$this->restApi = $rest_api;
if ($wsdl) {
$this->wsdl = $wsdl;
}
else {
// Determine location of the developerforce/force.com-toolkit-for-php WSDL
// files.
$reflector = new \ReflectionClass('SforcePartnerClient');
$wsdl_dir = dirname($reflector->getFileName());
// Use the partner WSDL.
$this->wsdl = "$wsdl_dir/partner.wsdl.xml";
}
$this->connect();
}
/**
* {@inheritdoc}
*/
public function connect() {
$this->isConnected = FALSE;
// Use the "isAuthorized" callback to initialize session headers.
if ($this->restApi->isAuthorized()) {
$this->createConnection($this->wsdl);
$token = $this->restApi->getAccessToken();
if (!$token) {
$token = $this->restApi->refreshToken();
}
$this->setSessionHeader($token);
$this->setEndPoint($this->restApi->getApiEndPoint('partner'));
$this->isConnected = TRUE;
}
else {
throw new \Exception('Salesforce needs to be authorized to connect to this website.');
}
}
/**
* {@inheritdoc}
*/
public function isConnected() {
return $this->isConnected;
}
/**
* {@inheritdoc}
*/
public function trySoap($function, array $params = [], $refresh = FALSE) {
if ($refresh) {
$this->restApi->refreshToken();
}
if (!$this->isConnected) {
$this->connect();
}
try {
$results = call_user_func_array([$this, $function], $params);
return $results;
}
catch (SoapFault $e) {
// sf:INVALID_SESSION_ID is thrown on expired login (and other reasons).
// Our only recourse is to try refreshing our auth token. If we get any
// other exception, bubble it up.
if ($e->faultcode != 'sf:INVALID_SESSION_ID') {
throw $e;
}
// If we didn't already try it, refresh the access token and try the call
// again.
if (!$refresh) {
return $this->trySoap($function, $params, TRUE);
}
else {
// Our connection is not working.
$this->isConnected = FALSE;
throw $e;
}
}
}
}
<?php
namespace Drupal\salesforce_soap\Soap;
/**
* A client for communicating with the Salesforce SOAP API.
*/
interface SoapClientInterface {
/**
* Establish a connection to the SOAP API.
*/
public function connect();
/**
* Whether or not this client is connected to the SOAP API.
*/
public function isConnected();
/**
* Salesforce SOAP API resource wrapper.
*
* Ensures the connection is established with the SOAP API prior to making the
* call and automatically attempts a re-auth when the API responds with
* invalid session ID / access token.
*
* @param string $function
* The name of the SOAP API function to attempt.
* @param array $params
* (Optional) An array of parameters to pass through to the function.
* @param bool $refresh
* (Optional) Refresh the access token prior to making the call. Defaults
* to FALSE, in which case a refresh is only attempted if the API responds
* invalid session ID / access token.
*
* @return mixed
* The return value from $function.
*
* @see \SforcePartnerClient
*/
public function trySoap($function, array $params = [], $refresh = FALSE);
}
......@@ -595,7 +595,7 @@ class SalesforceCommands extends SalesforceCommandsBase {
* @return \Drupal\salesforce\Commands\QueryResult
* The query result.
*
* @command salesforcef:query-object
* @command salesforce:query-object
* @aliases sfqo,sf-query-object
*/
public function queryObject($object, array $options = [
......
......@@ -29,20 +29,6 @@ abstract class SalesforceCommandsBase extends DrushCommands {
*/
protected $etm;
/**
* Salesforce Mapping storage handler.
*
* @var \Drupal\salesforce_mapping\SalesforceMappingStorage
*/
protected $mappingStorage;
/**
* Mapped Object storage handler.
*
* @var \Drupal\salesforce_mapping\MappedObjectStorage
*/
protected $mappedObjectStorage;
/**
* SalesforceCommandsBase constructor.
*
......@@ -57,8 +43,6 @@ abstract class SalesforceCommandsBase extends DrushCommands {
public function __construct(RestClient $client, EntityTypeManagerInterface $etm) {
$this->client = $client;
$this->etm = $etm;
$this->mappingStorage = $etm->getStorage('salesforce_mapping');
$this->mappedObjectStorage = $etm->getStorage('salesforce_mapped_object');
}
/**
......@@ -77,142 +61,6 @@ abstract class SalesforceCommandsBase extends DrushCommands {
}
}
/**
* Collect a salesforce mapping interactively.
*/
protected function interactMapping(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE, $dir = NULL) {
if ($name = $input->getArgument('name')) {
if (strtoupper($name) == 'ALL') {
$input->setArgument('name', 'ALL');
return;
}
/** @var \Drupal\salesforce_mapping\Entity\SalesforceMapping $mapping */
$mapping = $this->mappingStorage->load($name);
if (!$mapping) {
$this->logger()->error(dt('Mapping %name does not exist.', ['%name' => $name]));
}
elseif ($dir == 'push' && !$mapping->doesPush()) {
$this->logger()->error(dt('Mapping %name does not push.', ['%name' => $name]));
}
elseif ($dir == 'pull' && !$mapping->doesPull()) {
$this->logger()->error(dt('Mapping %name does not push.', ['%name' => $name]));
}
else {
return;
}
}
if ($dir == 'pull') {
$options = $this->mappingStorage->loadPullMappings();
}
elseif ($dir == 'push') {
$options = $this->mappingStorage->loadPushMappings();
}
else {
$options = $this->mappingStorage->loadMultiple();
}
$this->doMappingNameOptions($input, array_keys($options), $message, $allOption);
}
/**
* Collect a salesforce mapping name, and set it to a "name" argument.
*/
protected function interactPushMappings(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE) {
return $this->interactMapping($input, $output, $message, $allOption, 'push');
}
/**
* Collect a salesforce mapping name, and set it to a "name" argument.
*/
protected function interactPullMappings(Input $input, Output $output, $message = 'Choose a Salesforce mapping', $allOption = FALSE) {
return $this->interactMapping($input, $output, $message, $allOption, 'pull');
}
/**
* Helper method to collect the choice from user, given a set of options.
*/
protected function doMappingNameOptions(Input $input, array $options, $message, $allOption = FALSE) {
$options = array_combine($options, $options);
if ($allOption) {
$options['ALL'] = $allOption;
}
if (!$answer = $this->io()->choice($message, $options)) {
throw new UserAbortException();
}
$input->setArgument('name', $answer);
}
/**
* Given a mapping name (and optional direction), get an array of mappings.
*
* @param string $name
* 'ALL' to load all mappings, or a mapping id.
* @param string $dir
* 'push'|'pull'|NULL to load limit mappings by push or pull types.
*
* @return \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface[]
* The mappings.
*/
protected function getMappingsFromName($name, $dir = NULL) {
$mappings = [];
if ($name == 'ALL') {
if ($dir == 'pull') {
$mappings = $this->mappingStorage->loadPullMappings();
}
elseif ($dir == 'push') {
$mappings = $this->mappingStorage->loadPushMappings();
}
else {
$mappings = $this->mappingStorage->loadMultiple();
}
}
else {
$mapping = $this->mappingStorage->load($name);
if ($dir == 'push' && !$mapping->doesPush()) {
throw new \Exception(dt("Mapping !name does not push.", ['!name' => $name]));
}
elseif ($dir == 'pull' && !$mapping->doesPull()) {
throw new \Exception(dt("Mapping !name does not pull.", ['!name' => $name]));
}
$mappings = [$mapping];
}
$mappings = array_filter($mappings);
if (empty($mappings)) {
throw new \Exception(dt('No push mappings loaded'));
}
return $mappings;
}
/**
* Given a mapping name, get an array of matching push mappings.
*
* @param string $name
* The mapping name.
*
* @return \Drupal\salesforce_mapping\Entity\SalesforceMapping[]
* The matching mappings.
*
* @throws \Exception
*/
protected function getPushMappingsFromName($name) {
return $this->getMappingsFromName($name, 'push');
}
/**
* Given a mappin gname, get an array of matching pull mappings.
*
* @param string $name
* The mapping name.
*
* @return \Drupal\salesforce_mapping\Entity\SalesforceMapping[]
* The pull mappings.
*
* @throws \Exception
*/
protected function getPullMappingsFromName($name) {
return $this->getMappingsFromName($name, 'pull');
}
/**
* Pass-through helper to add appropriate formatters for a query result.
*
......
......@@ -854,10 +854,10 @@ class RestClient implements RestClientInterface {
*/
public function getRecordTypeIdByDeveloperName($name, $devname, $reset = FALSE) {
$record_types = $this->getRecordTypes($name, $reset);
if (empty($record_types[$name][$devname])) {
if (empty($record_types[$devname])) {
throw new \Exception("No record type $devname for $name");
}
return $record_types[$name][$devname]->id();
return $record_types[$devname]->id();
}
/**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment