diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..57872d0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/vendor/
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 0000000..522fa4a
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1,2 @@
+# Comment line immediately above ownership line is reserved for related gus information. Please be careful while editing.
+#ECCN:Open Source
diff --git a/README.md b/README.md
index 948a02a..39ff9e9 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,11 @@
Force.com Toolkit for PHP
=========================
+### Notice:
+
+This repo and toolkit are no longer supported. This toolkit is based on HTTP 1.0 and may have vulnerabilities. HTTP/1.0 support *likely* will be deprecated. Additionally, this toolkit is currently using v27.0 of the Salesforce API and that version will be officially deprecated as detailed in the [Salesforce Platform API Versions 21.0 through 30.0 Retirement](https://help.salesforce.com/s/articleView?id=000354473&type=1) knowledge article.
+
+---
The Force.com PHP Toolkit provides an easy-to-use wrapper for the Force.com Web Services SOAP API, presenting SOAP client implementations for both the enterprise and partner WSDLs.
-See the [getting started guide](http://wiki.developerforce.com/index.php/Getting_Started_with_the_Force.com_Toolkit_for_PHP) for sample code to create, retrieve, update and delete records in the Force.com database.
+See the [getting started guide](https://developer.salesforce.com/page/PHP_Toolkit_13.0_Getting_Started) for sample code to create, retrieve, update and delete records in the Force.com database.
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..0dcace9
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,15 @@
+{
+ "name": "developerforce/force.com-toolkit-for-php",
+ "description": "A wrapper for the Force.com Web Services SOAP API",
+ "license": "BSD-3-Clause",
+ "autoload": {
+ "classmap": [
+ "soapclient"
+ ]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ }
+}
diff --git a/license b/license
index 16a6267..5201380 100644
--- a/license
+++ b/license
@@ -1,3 +1,9 @@
+This project is licensed under the 'BSD 3-Clause' license [1], also known as
+the 'Modified BSD' license [2].
+
+[1] http://www.opensource.org/licenses/BSD-3-Clause
+[2] http://www.gnu.org/licenses/license-list.html#ModifiedBSD
+
Copyright (c) 2010, Salesforce.com
All rights reserved.
diff --git a/samples/userAuth.php b/samples/userAuth.php
index f38f219..1f5072e 100644
--- a/samples/userAuth.php
+++ b/samples/userAuth.php
@@ -1,14 +1,14 @@
+?>
\ No newline at end of file
diff --git a/soapclient/SforceBaseClient.php b/soapclient/SforceBaseClient.php
index 16fadca..4a59196 100644
--- a/soapclient/SforceBaseClient.php
+++ b/soapclient/SforceBaseClient.php
@@ -29,7 +29,6 @@
require_once ('ProxySettings.php');
require_once ('SforceHeaderOptions.php');
-
/**
* This file contains one class.
* @package SalesforceSoapClient
@@ -42,7 +41,7 @@ class SforceBaseClient {
protected $sforce;
protected $sessionId;
protected $location;
- protected $version = '20.0';
+ protected $version = '27.0';
protected $namespace;
@@ -61,6 +60,10 @@ class SforceBaseClient {
protected $localeOptions;
protected $packageVersionHeader;
+ protected function getSoapClient($wsdl, $options) {
+ return new SoapClient($wsdl, $options);
+ }
+
public function getNamespace() {
return $this->namespace;
}
@@ -90,22 +93,27 @@ public function printDebugInfo() {
echo 'False';
}
}
-
+
/**
* Connect method to www.salesforce.com
*
* @param string $wsdl Salesforce.com Partner WSDL
+ * @param object $proxy (optional) proxy settings with properties host, port,
+ * login and password
+ * @param array $soap_options (optional) Additional options to send to the
+ * SoapClient constructor. @see
+ * http://php.net/manual/en/soapclient.soapclient.php
*/
- public function createConnection($wsdl, $proxy=null) {
+ public function createConnection($wsdl, $proxy=null, $soap_options=array()) {
$phpversion = substr(phpversion(), 0, strpos(phpversion(), '-'));
- $soapClientArray = array (
+ $soapClientArray = array_merge(array (
'user_agent' => 'salesforce-toolkit-php/'.$this->version,
'encoding' => 'utf-8',
'trace' => 1,
'features' => SOAP_SINGLE_ELEMENT_ARRAYS,
'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP
- );
+ ), $soap_options);
// We don't need to parse out any subversion suffix - e.g. "-01" since
// PHP type conversion will ignore it
@@ -122,7 +130,8 @@ public function createConnection($wsdl, $proxy=null) {
$soapClientArray = array_merge($soapClientArray, $proxySettings);
}
- $this->sforce = new SoapClient($wsdl, $soapClientArray);
+ $this->sforce = $this->getSoapClient($wsdl, $soapClientArray);
+
return $this->sforce;
}
@@ -169,8 +178,8 @@ public function login($username, $password) {
* @return LogoutResult
*/
public function logout() {
- $this->setHeaders("logout");
- $arg = new stdClass;
+ $this->setHeaders("logout");
+ $arg = new stdClass();
return $this->sforce->logout();
}
@@ -180,9 +189,9 @@ public function logout() {
* @return invalidateSessionsResult
*/
public function invalidateSessions() {
- $this->setHeaders("invalidateSessions");
- $arg = new stdClass;
- $this->logout();
+ $this->setHeaders("invalidateSessions");
+ $arg = new stdClass();
+ $this->logout();
return $this->sforce->invalidateSessions();
}
@@ -517,6 +526,7 @@ public function sendSingleEmail($request) {
$email = new SoapVar($r, SOAP_ENC_OBJECT, 'SingleEmailMessage', $this->namespace);
array_push($messages, $email);
}
+ $arg = new stdClass();
$arg->messages = $messages;
return $this->_sendEmail($arg);
} else {
@@ -532,6 +542,7 @@ public function sendMassEmail($request) {
$email = new SoapVar($r, SOAP_ENC_OBJECT, 'MassEmailMessage', $this->namespace);
array_push($messages, $email);
}
+ $arg = new stdClass();
$arg->messages = $messages;
return $this->_sendEmail($arg);
} else {
@@ -554,7 +565,7 @@ protected function _sendEmail($arg) {
*/
public function convertLead($leadConverts) {
$this->setHeaders("convertLead");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->leadConverts = $leadConverts;
return $this->sforce->convertLead($arg);
}
@@ -567,9 +578,20 @@ public function convertLead($leadConverts) {
*/
public function delete($ids) {
$this->setHeaders("delete");
- $arg = new stdClass;
- $arg->ids = $ids;
- return $this->sforce->delete($arg)->result;
+ if(count($ids) > 200) {
+ $result = array();
+ $chunked_ids = array_chunk($ids, 200);
+ foreach($chunked_ids as $cids) {
+ $arg = new stdClass;
+ $arg->ids = $cids;
+ $result = array_merge($result, $this->sforce->delete($arg)->result);
+ }
+ } else {
+ $arg = new stdClass;
+ $arg->ids = $ids;
+ $result = $this->sforce->delete($arg)->result;
+ }
+ return $result;
}
/**
@@ -580,7 +602,7 @@ public function delete($ids) {
*/
public function undelete($ids) {
$this->setHeaders("undelete");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->ids = $ids;
return $this->sforce->undelete($arg)->result;
}
@@ -593,7 +615,7 @@ public function undelete($ids) {
*/
public function emptyRecycleBin($ids) {
$this->setHeaders();
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->ids = $ids;
return $this->sforce->emptyRecycleBin($arg)->result;
}
@@ -609,6 +631,7 @@ public function processSubmitRequest($processRequestArray) {
foreach ($processRequestArray as &$process) {
$process = new SoapVar($process, SOAP_ENC_OBJECT, 'ProcessSubmitRequest', $this->namespace);
}
+ $arg = new stdClass();
$arg->actions = $processRequestArray;
return $this->_process($arg);
} else {
@@ -628,6 +651,7 @@ public function processWorkitemRequest($processRequestArray) {
foreach ($processRequestArray as &$process) {
$process = new SoapVar($process, SOAP_ENC_OBJECT, 'ProcessWorkitemRequest', $this->namespace);
}
+ $arg = new stdClass();
$arg->actions = $processRequestArray;
return $this->_process($arg);
} else {
@@ -656,10 +680,12 @@ public function describeGlobal() {
* @param string Type Object Type
* @return DescribeLayoutResult
*/
- public function describeLayout($type) {
+ public function describeLayout($type, array $recordTypeIds=null) {
$this->setHeaders("describeLayout");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->sObjectType = new SoapVar($type, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
+ if (isset($recordTypeIds) && count($recordTypeIds))
+ $arg->recordTypeIds = $recordTypeIds;
return $this->sforce->describeLayout($arg)->result;
}
@@ -672,7 +698,7 @@ public function describeLayout($type) {
*/
public function describeSObject($type) {
$this->setHeaders("describeSObject");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->sObjectType = new SoapVar($type, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
return $this->sforce->describeSObject($arg)->result;
}
@@ -710,7 +736,7 @@ public function describeTabs() {
*/
public function describeDataCategoryGroups($sObjectType) {
$this->setHeaders('describeDataCategoryGroups');
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->sObjectType = new SoapVar($sObjectType, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
return $this->sforce->describeDataCategoryGroups($arg)->result;
}
@@ -724,7 +750,7 @@ public function describeDataCategoryGroups($sObjectType) {
*/
public function describeDataCategoryGroupStructures(array $pairs, $topCategoriesOnly) {
$this->setHeaders('describeDataCategoryGroupStructures');
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->pairs = $pairs;
$arg->topCategoriesOnly = new SoapVar($topCategoriesOnly, XSD_BOOLEAN, 'boolean', 'http://www.w3.org/2001/XMLSchema');
@@ -742,7 +768,7 @@ public function describeDataCategoryGroupStructures(array $pairs, $topCategories
*/
public function getDeleted($type, $startDate, $endDate) {
$this->setHeaders("getDeleted");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->sObjectType = new SoapVar($type, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
$arg->startDate = $startDate;
$arg->endDate = $endDate;
@@ -760,7 +786,7 @@ public function getDeleted($type, $startDate, $endDate) {
*/
public function getUpdated($type, $startDate, $endDate) {
$this->setHeaders("getUpdated");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->sObjectType = new SoapVar($type, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
$arg->startDate = $startDate;
$arg->endDate = $endDate;
@@ -777,10 +803,12 @@ public function getUpdated($type, $startDate, $endDate) {
*/
public function query($query) {
$this->setHeaders("query");
- $QueryResult = $this->sforce->query(array (
+ $raw = $this->sforce->query(array (
'queryString' => $query
))->result;
- return new QueryResult($QueryResult);
+ $QueryResult = new QueryResult($raw);
+ $QueryResult->setSf($this); // Dependency Injection
+ return $QueryResult;
}
/**
@@ -792,10 +820,12 @@ public function query($query) {
*/
public function queryMore($queryLocator) {
$this->setHeaders("queryMore");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->queryLocator = $queryLocator;
- $QueryResult = $this->sforce->queryMore($arg)->result;
- return new QueryResult($QueryResult);
+ $raw = $this->sforce->queryMore($arg)->result;
+ $QueryResult = new QueryResult($raw);
+ $QueryResult->setSf($this); // Dependency Injection
+ return $QueryResult;
}
/**
@@ -807,10 +837,12 @@ public function queryMore($queryLocator) {
*/
public function queryAll($query, $queryOptions = NULL) {
$this->setHeaders("queryAll");
- $QueryResult = $this->sforce->queryAll(array (
+ $raw = $this->sforce->queryAll(array (
'queryString' => $query
))->result;
- return new QueryResult($QueryResult);
+ $QueryResult = new QueryResult($raw);
+ $QueryResult->setSf($this); // Dependency Injection
+ return $QueryResult;
}
@@ -824,7 +856,7 @@ public function queryAll($query, $queryOptions = NULL) {
*/
public function retrieve($fieldList, $sObjectType, $ids) {
$this->setHeaders("retrieve");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->fieldList = $fieldList;
$arg->sObjectType = new SoapVar($sObjectType, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
$arg->ids = $ids;
@@ -839,7 +871,7 @@ public function retrieve($fieldList, $sObjectType, $ids) {
*/
public function search($searchString) {
$this->setHeaders("search");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->searchString = new SoapVar($searchString, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
return new SforceSearchResult($this->sforce->search($arg)->result);
}
@@ -867,7 +899,7 @@ public function getUserInfo() {
*/
public function setPassword($userId, $password) {
$this->setHeaders("setPassword");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->userId = new SoapVar($userId, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
$arg->password = $password;
return $this->sforce->setPassword($arg);
@@ -881,7 +913,7 @@ public function setPassword($userId, $password) {
*/
public function resetPassword($userId) {
$this->setHeaders("resetPassword");
- $arg = new stdClass;
+ $arg = new stdClass();
$arg->userId = new SoapVar($userId, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
return $this->sforce->resetPassword($arg)->result;
}
@@ -911,16 +943,22 @@ public function __construct($response) {
}
}
-class QueryResult {
+class QueryResult implements Iterator{
public $queryLocator;
public $done;
public $records;
public $size;
+ public $pointer; // Current iterator location
+ private $sf; // SOAP Client
+
public function __construct($response) {
$this->queryLocator = $response->queryLocator;
$this->done = $response->done;
$this->size = $response->size;
+
+ $this->pointer = 0;
+ $this->sf = false;
if($response instanceof QueryResult) {
$this->records = $response->records;
@@ -929,16 +967,40 @@ public function __construct($response) {
if (isset($response->records)) {
if (is_array($response->records)) {
foreach ($response->records as $record) {
- $sobject = new SObject($record);
- array_push($this->records, $sobject);
+ array_push($this->records, $record);
};
} else {
- $sobject = new SObject($response->records);
- array_push($this->records, $sobject);
+ array_push($this->records, $record);
}
}
}
}
+
+ public function setSf(SforceBaseClient $sf) { $this->sf = $sf; } // Dependency Injection
+
+ // Basic Iterator implementation functions
+ public function rewind() { $this->pointer = 0; }
+ public function next() { ++$this->pointer; }
+ public function key() { return $this->pointer; }
+ public function current() { return new SObject($this->records[$this->pointer]); }
+
+ public function valid() {
+ while ($this->pointer >= count($this->records)) {
+ // Pointer is larger than (current) result set; see if we can fetch more
+ if ($this->done === false) {
+ if ($this->sf === false) throw new Exception("Dependency not met!");
+ $response = $this->sf->queryMore($this->queryLocator);
+ $this->records = array_merge($this->records, $response->records); // Append more results
+ $this->done = $response->done;
+ $this->queryLocator = $response->queryLocator;
+ } else {
+ return false; // No more records to fetch
+ }
+ }
+ if (isset($this->records[$this->pointer])) return true;
+
+ throw new Exception("QueryResult has gaps in the record data?");
+ }
}
class SObject {
@@ -952,7 +1014,7 @@ public function __construct($response=NULL) {
}
foreach ($response as $responseKey => $responseValue) {
- if (in_array($responseKey, array('Id', 'type', 'any'))) {
+ if (in_array(strval($responseKey), array('Id', 'type', 'any'))) {
continue;
}
$this->$responseKey = $responseValue;
@@ -1068,6 +1130,9 @@ public function __construct($response=NULL) {
}
}
}
+
+ function __get($name) { return (isset($this->fields->$name))? $this->fields->$name : false; }
+ function __isset($name) { return isset($this->fields->$name); }
/**
* Parse the "any" string from an sObject. First strip out the sf: and then
@@ -1079,7 +1144,7 @@ function convertFields($any) {
$array = $this->xml2array('', 2);
- $xml = new stdClass;
+ $xml = new stdClass();
if (!count($array['Object']))
return $xml;
@@ -1152,9 +1217,9 @@ function xml2array($contents, $get_attributes=1) {
$result = $value;
}
- //Set the attributes too.
- if(isset($attributes) && isset($attributes['xsi:nil'])) {
- $result = $attributes['xsi:nil'];
+ //Check for nil and ignore other attributes.
+ if (isset($attributes) && isset($attributes['xsi:nil']) && !strcasecmp($attributes['xsi:nil'], 'true')) {
+ $result = null;
}
break;
}
diff --git a/soapclient/SforceEmail.php b/soapclient/SforceEmail.php
index 1a7f876..b0b37a4 100644
--- a/soapclient/SforceEmail.php
+++ b/soapclient/SforceEmail.php
@@ -81,6 +81,10 @@ public function setHtmlBody($htmlBody) {
$this->htmlBody = $htmlBody;
}
+ public function setOrgWideEmailAddressId($orgWideEmailAddressId) {
+ $this->orgWideEmailAddressId = $orgWideEmailAddressId;
+ }
+
public function setPlainTextBody($plainTextBody) {
$this->plainTextBody = $plainTextBody;
}
diff --git a/soapclient/SforceEnterpriseClient.php b/soapclient/SforceEnterpriseClient.php
index 8b269ad..b018efc 100644
--- a/soapclient/SforceEnterpriseClient.php
+++ b/soapclient/SforceEnterpriseClient.php
@@ -25,7 +25,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
require_once ('SforceBaseClient.php');
-
/**
* This file contains two classes.
* @package SalesforceSoapClient
@@ -37,11 +36,9 @@
*/
class SforceEnterpriseClient extends SforceBaseClient {
const ENTERPRISE_NAMESPACE = 'urn:enterprise.soap.sforce.com';
-
- function SforceEnterpriseClient() {
+ public function __construct() {
$this->namespace = self::ENTERPRISE_NAMESPACE;
}
-
/**
* Adds one or more new individual objects to your organization's data.
* @param array $sObjects Array of one or more sObjects (up to 200) to create.
@@ -50,14 +47,27 @@ function SforceEnterpriseClient() {
* @return SaveResult
*/
public function create($sObjects, $type) {
- foreach ($sObjects as &$sobject) {
- $sobject = new SoapVar($sobject, SOAP_ENC_OBJECT, $type, $this->namespace);
+ $arg = [];
+ foreach ($sObjects as $sObject) {
+ // FIX for fieldsToNull issue - allow array in fieldsToNull (STEP #1)
+ $xmlStr = '';
+ if(isset($sObject->fieldsToNull) && is_array($sObject->fieldsToNull)) {
+ foreach($sObject->fieldsToNull as $fieldToNull) {
+ $xmlStr .= '' . $fieldToNull . '';
+ }
+ }
+ // ------
+
+ $soapObject = new SoapVar($sObject, SOAP_ENC_OBJECT, $type, $this->namespace);
+ // FIX for fieldsToNull issue - allow array in fieldsToNull (STEP #2)
+ if($xmlStr != '') {
+ $soapObject->enc_value->fieldsToNull = new SoapVar(new SoapVar($xmlStr, XSD_ANYXML), SOAP_ENC_ARRAY);
+ }
+ // ------
+ $arg[] = $soapObject;
}
- $arg = $sObjects;
-
return parent::_create(new SoapParam($arg, "sObjects"));
}
-
/**
* Updates one or more new individual objects to your organization's data.
* @param array sObjects Array of sObjects
@@ -66,9 +76,9 @@ public function create($sObjects, $type) {
* @return UpdateResult
*/
public function update($sObjects, $type, $assignment_header = NULL, $mru_header = NULL) {
-
- foreach ($sObjects as &$sObject) {
-
+ $arg = new stdClass;
+ $arg->sObjects = [];
+ foreach ($sObjects as $sObject) {
// FIX for fieldsToNull issue - allow array in fieldsToNull (STEP #1)
$xmlStr = '';
if(isset($sObject->fieldsToNull) && is_array($sObject->fieldsToNull)) {
@@ -78,18 +88,18 @@ public function update($sObjects, $type, $assignment_header = NULL, $mru_header
}
// ------
- $sObject = new SoapVar($sObject, SOAP_ENC_OBJECT, $type, $this->namespace);
+ $soapObject = new SoapVar($sObject, SOAP_ENC_OBJECT, $type, $this->namespace);
// FIX for fieldsToNull issue - allow array in fieldsToNull (STEP #2)
if($xmlStr != '') {
- $sObject->enc_value->fieldsToNull = new SoapVar(new SoapVar($xmlStr, XSD_ANYXML), SOAP_ENC_ARRAY);
+ $soapObject->enc_value->fieldsToNull = new SoapVar(new SoapVar($xmlStr, XSD_ANYXML), SOAP_ENC_ARRAY);
}
// ------
+ $arg->sObjects[] = $soapObject;
}
- $arg->sObjects = $sObjects;
+
return parent::_update($arg);
}
-
/**
* Creates new objects and updates existing objects; uses a custom field to
* determine the presence of existing objects. In most cases, we recommend
@@ -103,8 +113,9 @@ public function update($sObjects, $type, $assignment_header = NULL, $mru_header
*/
public function upsert($ext_Id, $sObjects, $type = 'Contact') {
$arg = new stdClass;
+ $arg->sObjects = [];
$arg->externalIDFieldName = new SoapVar($ext_Id, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
- foreach ($sObjects as &$sObject) {
+ foreach ($sObjects as $sObject) {
// FIX for fieldsToNull issue - allow array in fieldsToNull (STEP #1)
$xmlStr = '';
if(isset($sObject->fieldsToNull) && is_array($sObject->fieldsToNull)) {
@@ -114,18 +125,17 @@ public function upsert($ext_Id, $sObjects, $type = 'Contact') {
}
// ------
- $sObject = new SoapVar($sObject, SOAP_ENC_OBJECT, $type, $this->namespace);
-
+ $soapObject = new SoapVar($sObject, SOAP_ENC_OBJECT, $type, $this->namespace);
// FIX for fieldsToNull issue - allow array in fieldsToNull (STEP #2)
if($xmlStr != '') {
- $sObject->enc_value->fieldsToNull = new SoapVar(new SoapVar($xmlStr, XSD_ANYXML), SOAP_ENC_ARRAY);
+ $soapObject->enc_value->fieldsToNull = new SoapVar(new SoapVar($xmlStr, XSD_ANYXML), SOAP_ENC_ARRAY);
}
// ------
+ $arg->sObjects[] = $soapObject;
}
- $arg->sObjects = $sObjects;
+
return parent::_upsert($arg);
}
-
/**
* Merge records
*
@@ -135,6 +145,7 @@ public function upsert($ext_Id, $sObjects, $type = 'Contact') {
*/
public function merge($mergeRequest, $type) {
$mergeRequest->masterRecord = new SoapVar($mergeRequest->masterRecord, SOAP_ENC_OBJECT, $type, $this->namespace);
+ $arg = new stdClass;
$arg->request = new SoapVar($mergeRequest, SOAP_ENC_OBJECT, 'MergeRequest', $this->namespace);
return parent::_merge($arg);
}
diff --git a/soapclient/SforceMetaObject.php b/soapclient/SforceMetaObject.php
index a1c3baf..5c045af 100644
--- a/soapclient/SforceMetaObject.php
+++ b/soapclient/SforceMetaObject.php
@@ -79,6 +79,10 @@ public function setPluralLabel($pluralLabel) {
$this->pluralLabel = $pluralLabel;
}
+ public function setSharingModel($sharingModel) {
+ $this->sharingModel = $sharingModel;
+ }
+
public function setStartsWith($startsWith) {
$this->startsWith = $startsWith;
}
diff --git a/soapclient/SforceMetadataClient.php b/soapclient/SforceMetadataClient.php
index 24806f6..7477d72 100644
--- a/soapclient/SforceMetadataClient.php
+++ b/soapclient/SforceMetadataClient.php
@@ -30,7 +30,7 @@ class SforceMetadataClient {
public $sforce;
protected $sessionId;
protected $location;
- protected $version = '20.0';
+ protected $version = '27.0';
protected $namespace = 'http://soap.sforce.com/2006/04/metadata';
@@ -116,15 +116,34 @@ public function setSessionHeader($sessionId) {
$this->_setClientId($header_array);
$this->sforce->__setSoapHeaders($header_array);
}
+
+ private function getObjtype($obj) {
+ $classArray = explode('\\', get_class($obj));
+ $objtype = array_pop($classArray);
+ if (strpos($objtype, 'Sforce', 0) === 0) {
+ $objtype = substr($objtype, 6);
+ }
+ return $objtype;
+ }
public function create($obj) {
- $encodedObj->metadata = new SoapVar($obj, SOAP_ENC_OBJECT, 'CustomObject', $this->namespace);
+ $encodedObj = new stdClass();
+ $encodedObj->metadata = new SoapVar($obj, SOAP_ENC_OBJECT, $this->getObjtype($obj), $this->namespace);
return $this->sforce->create($encodedObj);
}
+ public function update($obj) {
+ $encodedObj = new stdClass();
+ $encodedObj->UpdateMetadata = $obj;
+ $encodedObj->UpdateMetadata->metadata = new SoapVar($obj->metadata, SOAP_ENC_OBJECT, $this->getObjtype($obj->metadata), $this->namespace);
+
+ return $this->sforce->update($encodedObj);
+ }
+
public function delete($obj) {
- $encodedObj->metadata = new SoapVar($obj, SOAP_ENC_OBJECT, 'CustomObject', $this->namespace);
+ $encodedObj = new stdClass();
+ $encodedObj->metadata = new SoapVar($obj, SOAP_ENC_OBJECT, $this->getObjtype($obj), $this->namespace);
return $this->sforce->delete($encodedObj);
}
diff --git a/soapclient/SforcePartnerClient.php b/soapclient/SforcePartnerClient.php
index 5a818ad..38c30e8 100644
--- a/soapclient/SforcePartnerClient.php
+++ b/soapclient/SforcePartnerClient.php
@@ -32,6 +32,40 @@
* This file contains two classes.
* @package SalesforceSoapClient
*/
+/**
+ * SforceSoapClient class.
+ *
+ * @package SalesforceSoapClient
+ */
+ // When parsing partner WSDL, when PHP SOAP sees NewValue and OldValue, since
+ // the element has a xsi:type attribute with value 'string', it drops the
+ // string content into the parsed output and loses the tag name. Removing the
+ // xsi:type forces PHP SOAP to just leave the tags intact
+ class SforceSoapClient extends SoapClient {
+ function __doRequest($request, $location, $action, $version, $one_way=0) {
+ $response = parent::__doRequest($request, $location, $action, $version, $one_way);
+
+ // Quick check to only parse the XML here if we think we need to
+ if (strpos($response, 'loadXML($response);
+
+ $nodeList = $dom->getElementsByTagName('NewValue');
+ foreach ($nodeList as $node) {
+ $node->removeAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'type');
+ }
+ $nodeList = $dom->getElementsByTagName('OldValue');
+ foreach ($nodeList as $node) {
+ $node->removeAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'type');
+ }
+
+ return $dom->saveXML();
+ }
+ }
+
/**
* SforcePartnerClient class.
*
@@ -40,9 +74,14 @@
class SforcePartnerClient extends SforceBaseClient {
const PARTNER_NAMESPACE = 'urn:partner.soap.sforce.com';
- function SforcePartnerClient() {
+ public function __construct() {
$this->namespace = self::PARTNER_NAMESPACE;
}
+
+ protected function getSoapClient($wsdl, $options) {
+ // Workaround an issue in parsing OldValue and NewValue in histories
+ return new SforceSoapClient($wsdl, $options);
+ }
/**
* Adds one or more new individual objects to your organization's data.
@@ -184,4 +223,4 @@ private function _retrieveResult($response) {
return $arr;
}
-}
\ No newline at end of file
+}
diff --git a/soapclient/enterprise.wsdl.xml b/soapclient/enterprise.wsdl.xml
index 423bda2..06b1c74 100644
--- a/soapclient/enterprise.wsdl.xml
+++ b/soapclient/enterprise.wsdl.xml
@@ -1,6 +1,6 @@
@@ -3331,7 +3331,7 @@ Copyright 2006-2010 Salesforce.com, inc. All Rights Reserved
Manage your Salesforce.com metadata
-
+
\ No newline at end of file
diff --git a/soapclient/partner.wsdl.xml b/soapclient/partner.wsdl.xml
index 8d75c97..fa3f984 100644
--- a/soapclient/partner.wsdl.xml
+++ b/soapclient/partner.wsdl.xml
@@ -1,6 +1,6 @@