From 363ac2f5e7c6a789c7f836bfa47deb9ef5683d2e Mon Sep 17 00:00:00 2001
From: Kathleen Murtagh <kathleen.murtagh@gmail.com>
Date: Fri, 22 Mar 2013 11:59:11 -0700
Subject: [PATCH 1/4] Avoid errors when SalesforceSoapPartner is not fully
 working

---
 modules/salesforce_soap/salesforce_soap.inc | 58 ++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 2 deletions(-)

diff --git a/modules/salesforce_soap/salesforce_soap.inc b/modules/salesforce_soap/salesforce_soap.inc
index 6a7af33..04183bb 100644
--- a/modules/salesforce_soap/salesforce_soap.inc
+++ b/modules/salesforce_soap/salesforce_soap.inc
@@ -11,6 +11,7 @@
  */
 class SalesforceSoapPartner extends SforcePartnerClient {
   protected $salesforceApi;
+  protected $isConnected;
 
   /**
    * Constructor for SalesforceSoapPartner.
@@ -26,9 +27,62 @@ class SalesforceSoapPartner extends SforcePartnerClient {
     if (empty($wsdl)) {
       $wsdl = libraries_get_path('salesforce') . '/soapclient/partner.wsdl.xml';
     }
+    $this->setConnected(FALSE);
     $this->createConnection($wsdl);
     $this->salesforceApi = $sfapi;
-    $this->setSessionHeader($this->salesforceApi->getAccessToken());
-    $this->setEndPoint($this->salesforceApi->getApiEndPoint('partner'));
+
+    // We have to run a test API call here every time a new instance is
+    // created for a couple of reasons. These reasons are explained below.
+    //
+    //   - The Salesforce instance may very well be authorized, which means
+    //     it has a consumer key, secret and refresh token. However, merely
+    //     checking for authorization does not deal with expired access tokens.
+    //     If we were to pass an expired access token to the SOAP client it
+    //     will cheerfully throw INVALID_SESSION_ID exceptions. This situation
+    //     can arise if a client goes to use the SOAP api before interacting
+    //     with the REST api.
+    //
+    //   - We also need to account for cases where there is no access token.
+    //     This can manifest itself during cron runs where cron is running as
+    //     an anonymous user that has yet to establish a session. In this
+    //     scenario the Salesfroce instance is authorized, but doesn't have an
+    //     access token yet. If you pass an empty access token to
+    //     setSessionHeader the SOAP API will throw a fatal PHP error when it
+    //     attempts to set it's own internal SOAP headers via
+    //     __setSoapHeaders().
+    if ($this->salesforceApi->isAuthorized()) {
+      // Run an API call for the reasons discussed above.
+      $this->salesforceApi->apiCall('');
+      $this->setSessionHeader($this->salesforceApi->getAccessToken());
+      $this->setEndPoint($this->salesforceApi->getApiEndPoint('partner'));
+      $this->setConnected(TRUE);
+    }
+    else {
+      // Alert the caller that the Salesforce instance has not been configured.
+      watchdog('salesforce_soap', 'Attempting to use an instance of
+        the SalesforceSoapPartner class with a non-authorized Salesforce API
+        instance. Please ensure the Salesforce API module has been configured
+        and successfully authorized with a Salesforce org.', NULL, WATCHDOG_ERROR);
+
+      $this->setConnected(FALSE);
+    }
+  }
+
+  /**
+   * Setter for isConnected private variable.
+   *
+   * @param boolean $is_connected
+   *   Boolean to indicate whether the instance made a successful connection
+   *   to the SOAP API.
+   */
+  protected function setConnected($is_connected) {
+    $this->isConnected = $is_connected;
+  }
+
+  /**
+   * Indicates whether or not a successfull connection was made the SOAP API.
+   */
+  public function isConnected() {
+    return $this->isConnected;
   }
 }
-- 
1.7.11.7

