/CVENTTool/CventClient.class.php

https://github.com/mariothomas1/soflopmi · PHP · 345 lines · 276 code · 35 blank · 34 comment · 59 complexity · 6708cab437e2d8730263b6f7538ff518 MD5 · raw file

  1. <?php
  2. /*
  3. ** CventClient.class.php
  4. ** Author: github.com/gcanivet
  5. ** Description: A php soap client for the Cvent API.
  6. **
  7. ** To Do:
  8. ** - add additional remote functions support
  9. ** - add logging capabilities
  10. ** - proper docs format
  11. **
  12. ** Notes:
  13. ** - Search - 25,000 IDs limit not handled
  14. ** - CreateContact, UpdateContact, DeleteContact, CreateContactGroup, TransferInvitee, and SendEmail - 200 object limit not handled
  15. ** - GetUpdated - 10,000 IDs limit not handled
  16. ** ... Typicaly a limit of 25,000 ids returned, maximum 256 search filter, but depends on Client accounts
  17. **
  18. */
  19. ini_set('soap.wsdl_cache_enabled', 1);
  20. ini_set('soap.wsdl_cache_ttl', 86400); //default: 86400, in seconds
  21. class CventClient extends SoapClient {
  22. public $client;
  23. public $ServerURL;
  24. public $CventSessionHeader;
  25. public $debug = false;
  26. public $MAX_FILTER_SIZE = 100; # 256 doesn't seem to work.
  27. public $RESULTS_PER_PAGE = 200;
  28. public function CventClient() {
  29. }
  30. public function Login($acct, $username, $password) {
  31. $this->client = new SoapDebugClient("https://api.cvent.com/soap/V200611.ASMX?WSDL", array('trace' => true, 'exceptions' => true));
  32. $cache = true;
  33. $file = 'cvent_api_session.txt';
  34. if($cache && file_exists($file) && time() <= strtotime("+1 hour", $last = filemtime($file))) {
  35. # a valid session is cached, use it
  36. if($this->debug) print 'CventClient::Session already exists.<br/>';
  37. $data = file_get_contents($file);
  38. $arr_response = array();
  39. $arr_response = explode(',', $data);
  40. $this->ServerURL = $arr_response[0];
  41. $this->CventSessionHeader = $arr_response[1];
  42. } else { # sessions expire 1hr after CREATION
  43. if($this->debug) print 'CventClient::Session does not exist. Get new one.<br/>';
  44. $params = array();
  45. $params['AccountNumber'] = $acct;
  46. $params['UserName'] = $username;
  47. $params['Password'] = $password;
  48. //herehere
  49. var_dump('deleteme', $params);
  50. $response = $this->client->Login($params);
  51. if(!$response->LoginResult->LoginSuccess) {
  52. throw new Exception("CventClient:: Login unsuccessful");
  53. }
  54. $arr_response = array();
  55. $arr_response[] = $response->LoginResult->ServerURL;
  56. $arr_response[] = $response->LoginResult->CventSessionHeader;
  57. $data = implode(',', $arr_response);
  58. file_put_contents($file, $data);
  59. $this->ServerURL = $arr_response[0];
  60. $this->CventSessionHeader = $arr_response[1];
  61. }
  62. $this->client->__setLocation($this->ServerURL);
  63. $header_body = array('CventSessionValue' => $this->CventSessionHeader);
  64. $header = new SoapHeader('http://api.cvent.com/2006-11', 'CventSessionHeader', $header_body);
  65. $this->client->__setSoapHeaders($header);
  66. if($this->debug) print 'CventClient:: ServerURL: '.$this->ServerURL.', CventSessionHeader: '.$this->CventSessionHeader.'<br/>';
  67. }
  68. public function DescribeGlobal() {
  69. $response = $this->client->DescribeGlobal();
  70. return $response;
  71. }
  72. public function DescribeCvObject($objectTypes) {
  73. $params->ObjectTypes = $objectTypes;
  74. $response = $this->client->DescribeCvObject($params);
  75. return $response;
  76. }
  77. public function GetEventById($eventId) {
  78. $events = $this->RetrieveEvents($eventId);
  79. if(sizeof($events) != 1) throw new Exception('CventClient::GetEventById: EventId '.$eventId.' not found');
  80. return $events[0];
  81. }
  82. public function GetUpcomingEvents() {
  83. // needs to be tested
  84. $v = date('Y-m-d', strtotime('-14 days')).'T00:00:00'; // '2011-10-31T00:00:00';
  85. $response = $this->SearchByFilter('Event', 'AndSearch', array((object) array('Field' => 'EventStartDate', 'Operator' => 'Greater than', 'Value' => $v)));
  86. if(isset($response->SearchResult->Id)) return $response->SearchResult->Id;
  87. return false;
  88. }
  89. public function GetNumberOfRegistrations($eventId) {
  90. // needs to be tested
  91. $response = $this->SearchByFilter('Registration', 'AndSearch', array((object) array('Field' => 'EventId', 'Operator' => 'Equals', 'Value' => $eventId)));
  92. if(isset($response->SearchResult->Id)) return count($response->SearchResult->Id);
  93. return false;
  94. }
  95. public function GetNumberOfGuests($eventId) {
  96. // needs to be tested
  97. $response = $this->SearchByFilter('Guest', 'AndSearch', array((object) array('Field' => 'EventId', 'Operator' => 'Equals', 'Value' => $eventId)));
  98. if(isset($response->SearchResult->Id)) return count($response->SearchResult->Id);
  99. return false;
  100. }
  101. public function SearchAllDistributionLists() {
  102. $response = $this->SearchByFilter('DistributionList', 'OrSearch', array(
  103. (object) array('Field' => 'DistributionListName', 'Operator' => 'Equals', 'Value' => 'Something'),
  104. (object) array('Field' => 'DistributionListName', 'Operator' => 'Not Equal to', 'Value' => 'Something')));
  105. if(isset($response->SearchResult->Id)) return $response->SearchResult->Id;
  106. return false;
  107. }
  108. public function SearchContactBySourceId($remaxId) {
  109. $response = $this->SearchByFilter('Contact', 'AndSearch', array((object) array('Field' => 'SourceId', 'Operator' => 'Equals', 'Value' => $remaxId)));
  110. if(isset($response->SearchResult->Id)) return $response->SearchResult->Id;
  111. return false;
  112. }
  113. public function SearchContactsByGroupId($groupId) {
  114. $response = $this->SearchByFilter('Contact', 'AndSearch', array((object) array('Field' => 'GroupId', 'Operator' => 'Equals', 'Value' => $groupId)));
  115. if(isset($response->SearchResult->Id)) return $response->SearchResult->Id;
  116. return false;
  117. }
  118. public function SearchContactsByDistributionListId($distId) {
  119. $response = $this->SearchByFilter('Contact', 'AndSearch', array((object) array('Field' => 'DistId', 'Operator' => 'Equals', 'Value' => $distId)));
  120. if(isset($response->SearchResult->Id)) return $response->SearchResult->Id;
  121. return false;
  122. }
  123. public function SearchContactByDistributionListIdAndEmail($distId, $email) {
  124. // name implies email is unique
  125. $response = $this->SearchByFilter('Contact', 'AndSearch', array(
  126. (object) array('Field' => 'DistId', 'Operator' => 'Equals', 'Value' => $distId),
  127. (object) array('Field' => 'EmailAddress', 'Operator' => 'Equals', 'Value' => $email)));
  128. if(isset($response->SearchResult->Id)) return $response->SearchResult->Id;
  129. return false;
  130. }
  131. # Retrieve
  132. public function RetrieveEvents($ids) {
  133. return $this->RetrieveAllPages('Event', $ids);
  134. }
  135. public function RetrieveContacts($ids) {
  136. return $this->RetrieveAllPages('Contact', $ids);
  137. }
  138. public function RetrieveDistributionLists($ids) {
  139. return $this->RetrieveAllPages('DistributionList', $ids);
  140. }
  141. public function RetrieveContactBySourceId($remaxid) {
  142. $result = $this->SearchContactBySourceId($remaxid);
  143. if($result === false) throw new Exception("CventClient::RetrieveContactBySourceId::$remaxid not found, cannot retrieve");
  144. $ids[] = $result->SearchResult->Id;
  145. $result = $this->RetrieveContacts($ids);
  146. return $result;
  147. }
  148. public function RetrieveContactIdsBySourceIds($sourceIds) {
  149. // needs to be tested
  150. // this returns Ids, not Objects, for consistency should be renamed SearchContactsBySourceIds($sourceIds)
  151. $total = count($sourceIds);
  152. $contactIds = array();
  153. for($i = 0; $i < count($sourceIds); $i += $this->MAX_FILTER_SIZE) {
  154. if ($this->debug) print "CventClient::RetrieveContactIdsBySourceIds:: retrieving contactIds from $i to ".($i + $this->MAX_FILTER_SIZE)."<br/>";
  155. $batch = array_slice($sourceIds, $i, $i + $this->MAX_FILTER_SIZE);
  156. $criteria = NULL;
  157. $criteria->ObjectType = 'Contact';
  158. $criteria->CvSearchObject->SearchType = 'OrSearch';
  159. for($j=0; $j < sizeof($batch); $j++) {
  160. $criteria->CvSearchObject->Filter[$j]->Field = 'SourceId';
  161. $criteria->CvSearchObject->Filter[$j]->Operator = 'Equals';
  162. $criteria->CvSearchObject->Filter[$j]->Value = $batch[$j];
  163. }
  164. $tmp = $this->client->Search($criteria);
  165. $tmp = $tmp->SearchResult->Id;
  166. if(is_array($tmp)) {
  167. $contactIds = array_merge($contactIds, $tmp);
  168. } else {
  169. $contactIds = array_merge($contactIds, array($tmp));
  170. }
  171. }
  172. return $contactIds;
  173. }
  174. # Create or Updates
  175. public function AddContactsToDistributionList($distId, $contactIds) {
  176. if(!is_array($contactIds)) $contactIds = array($contactIds); // safety measure, contactId must be CvObject type
  177. $response = $this->client->ManageDistributionListMembers((object) array('DistListId' => $distId, 'Action' => 'Add', 'CvObjects' => $contactIds));
  178. if(isset($response->ManageDistributionListMembersResult->ManageDistributionListResult)) return $response->ManageDistributionListMembersResult->ManageDistributionListResult;
  179. return false;
  180. }
  181. public function AddContactToDistributionListByEmailAddress($distId, $email) {
  182. $response = $this->SearchByFilter('Contact', 'AndSearch', array((object) array('Field' => 'EmailAddress', 'Operator' => 'Equals', 'Value' => $email)));
  183. if(!isset($response->SearchResult->Id)) return false;
  184. $contactId = $response->SearchResult->Id;
  185. return $this->AddContactsToDistributionList($distId, array((object) array('Id' => $contactId, 'MessageId' => '')));
  186. }
  187. public function CreateContactAndAddToDistributionList($contact, $distId) {
  188. // pre: contact is an array with appropriate contact fields
  189. $contacts = array($contact);
  190. $results = $this->CreateUpdateContacts('Create', $contacts);
  191. print "<br/>create contacts<pre>";
  192. print_r($results);
  193. print "</pre><br/>";
  194. if(sizeof($results['passed']) == 1) { // new contact
  195. $contactId = $results['passed'][0]['result']->Id;
  196. print "contactId: ".$contactId;
  197. return $this->AddContactsToDistributionList($distId, array((object) array('Id' => $contactId, 'MessageId' => '')));
  198. } elseif (sizeof($results['failed']) == 1) { // error adding contact
  199. $errcode = $results['failed'][0]['result']->Errors->Error[0]->Code;
  200. if($errcode == 'CV40104' || $errcode == 'CV40103') { // contact already exists | duplicated contact object
  201. $emailaddress = $results['failed'][0]['contact']['EmailAddress'];
  202. print "emailaddress: ".$emailaddress;
  203. return $this->AddContactToDistributionListByEmailAddress($distId, $emailaddress);
  204. }
  205. }
  206. return false;
  207. }
  208. public function CreateUpdateContacts($type, $contacts) {
  209. # type = 'Create' or 'Update'
  210. // this could be improved A LOT
  211. if(!is_array($contacts)) $contacts = array($contacts);
  212. $total = sizeof($contacts);
  213. $pages = ceil($total / $this->RESULTS_PER_PAGE);
  214. $remainder = $total % $this->RESULTS_PER_PAGE;
  215. $passed = array();
  216. $failed = array();
  217. for($i = 0; $i < $pages; $i++) {
  218. $x = $i * $this->RESULTS_PER_PAGE;
  219. $y = $this->RESULTS_PER_PAGE;
  220. if($pages == $i + 1) $y = $remainder;
  221. if ($this->debug) print "CventClient::CreateUpdateContacts::Page $i, creating $y Ids starting at array index $x<br/>";
  222. $batch = array_slice($contacts, $x, $y);
  223. $criteria = NULL;
  224. $tmp = NULL;
  225. $criteria->Contacts = $batch;
  226. # process batch
  227. if($type == 'Create') {
  228. $tmp = $this->client->CreateContact($criteria);
  229. $tmp = @$tmp->CreateContactResult->CreateContactResult;
  230. } elseif ($type == 'Update') {
  231. $tmp = $this->client->UpdateContact($criteria);
  232. $tmp = @$tmp->UpdateContactResult->UpdateContactResult;
  233. } else {
  234. throw new Exception("CventClient::CreateUpdateContacts:: Invalid $type for this method");
  235. }
  236. if(isset($tmp)) {
  237. if(is_array($tmp)) {
  238. $result = $tmp;
  239. } else {
  240. $result = array($tmp);
  241. }
  242. if(sizeof($result) != sizeof($batch)) throw new Exception("CventClient::CreateUpdateContacts:: Size of results mismatch with size of batch");
  243. # organize pass/fails
  244. $pass = array();
  245. $fail = array();
  246. for($j = 0; $j < sizeof($result); $j++) {
  247. if(isset($result[$j]->Errors->Error)) {
  248. $fail[] = array('contact' => $batch[$j], 'result' => $result[$j]);
  249. } else {
  250. $pass[] = array('contact' => $batch[$j], 'result' => $result[$j]);
  251. }
  252. }
  253. $failed = array_merge($failed, $fail);
  254. $passed = array_merge($passed, $pass);
  255. }
  256. }
  257. if(sizeof($passed) + sizeof($failed) != $total) throw new Exception("CventClient::CreateUpdateContacts:: Total pass+fails does not match total contacts.");
  258. return array('passed' => $passed, 'failed' => $failed);
  259. }
  260. # helpers
  261. private function RetrieveAllPages($objecttype, $ids) {
  262. if(!is_array($ids)) $ids = array($ids); // safety measure
  263. $results = array();
  264. for($i=0; $i < count($ids); $i += $this->RESULTS_PER_PAGE) {
  265. if ($this->debug) print "CventClient::RetrievePages:: retrieving $objecttype using Ids from $i to ".($i+$this->RESULTS_PER_PAGE)."<br/>";
  266. $batch = array_slice($ids, $i, $i + $this->RESULTS_PER_PAGE);
  267. $criteria = (object) array('ObjectType' => $objecttype, 'Ids' => $batch);
  268. $tmp = $this->client->Retrieve($criteria);
  269. if(is_array($tmp->RetrieveResult->CvObject)) {
  270. $results = array_merge($results, $tmp->RetrieveResult->CvObject);
  271. } else {
  272. $results = array_merge($results, array($tmp->RetrieveResult->CvObject));
  273. }
  274. }
  275. return $results;
  276. }
  277. public function SearchByFilter($objecttype, $type, $filters) {
  278. $response = $this->client->Search((object) array('ObjectType' => $objecttype, 'CvSearchObject' => (object) array('SearchType' => $type, 'Filter' => $filters)));
  279. return $response;
  280. }
  281. }
  282. class SoapDebugClient extends SoapClient {
  283. public function __doRequest($request, $location, $action, $version, $one_way = 0) {
  284. //if (DEBUG) print htmlspecialchars($request);
  285. flush();
  286. return parent::__doRequest($request, $location, $action, $version);
  287. }
  288. public function webServiceDetails() {
  289. print "<strong>Functions:</strong><pre>";
  290. print_r($this->client->__getFunctions());
  291. print "</pre>";
  292. print "<strong>Types:</strong><pre>";
  293. print_r($this->client->__getTypes());
  294. print "</pre>";
  295. }
  296. public function debug() {
  297. print "<pre>";
  298. print htmlspecialchars($this->client->__getLastRequestHeaders());
  299. print "</pre>";
  300. print "<pre>";
  301. print htmlspecialchars($this->client->__getLastRequest());
  302. print "</pre>";
  303. print "<pre>";
  304. print htmlspecialchars($this->client->__getLastResponseHeaders());
  305. print "</pre>";
  306. print "<pre>";
  307. print htmlspecialchars($this->client->__getLastResponse());
  308. print "</pre>";
  309. }
  310. }