PageRenderTime 67ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/class.contextio.php

http://github.com/contextio/PHP-ContextIO
PHP | 1549 lines | 1173 code | 104 blank | 272 comment | 373 complexity | 7983c47f091633a1dd502a59f238ea23 MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php
  2. /*
  3. Copyright (C) 2011 DokDok Inc.
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to deal
  6. in the Software without restriction, including without limitation the rights
  7. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in
  11. all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18. THE SOFTWARE.
  19. */
  20. /**
  21. * Context.IO API client library
  22. * @copyright Copyright (C) 2011 DokDok Inc.
  23. * @licence http://opensource.org/licenses/mit-license MIT Licence
  24. */
  25. require_once dirname(__FILE__) . '/class.contextioresponse.php';
  26. require_once dirname(__FILE__) . '/OAuth.php';
  27. /**
  28. * Class to manage Context.IO API access
  29. */
  30. class ContextIO {
  31. protected $responseHeaders;
  32. protected $requestHeaders;
  33. protected $oauthKey;
  34. protected $oauthSecret;
  35. protected $saveHeaders;
  36. protected $ssl;
  37. protected $endPoint;
  38. protected $apiVersion;
  39. protected $lastResponse;
  40. protected $authHeaders;
  41. /**
  42. * Instantiate a new ContextIO object. Your OAuth consumer key and secret can be
  43. * found under the "settings" tab of the developer console (https://console.context.io/#settings)
  44. * @param $key Your Context.IO OAuth consumer key
  45. * @param $secret Your Context.IO OAuth consumer secret
  46. */
  47. function __construct($key, $secret) {
  48. $this->oauthKey = $key;
  49. $this->oauthSecret = $secret;
  50. $this->saveHeaders = false;
  51. $this->ssl = true;
  52. $this->endPoint = 'api.context.io';
  53. $this->apiVersion = '2.0';
  54. $this->lastResponse = null;
  55. $this->authHeaders = true;
  56. }
  57. /**
  58. * Attempts to discover IMAP settings for a given email address
  59. * @link http://context.io/docs/2.0/discovery
  60. * @param mixed $params either a string or assoc array
  61. * with email as its key
  62. * @return ContextIOResponse
  63. */
  64. public function discovery($params) {
  65. if (is_string($params)) {
  66. $params = array('email' => $params);
  67. }
  68. else {
  69. $params = $this->_filterParams($params, array('email'), array('email'));
  70. if ($params === false) {
  71. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  72. }
  73. }
  74. return $this->get(null, 'discovery?source_type=imap&email=' . $params['email']);
  75. }
  76. /**
  77. *
  78. * @link http://context.io/docs/2.0/connecttokens
  79. */
  80. public function listConnectTokens($account=null) {
  81. return $this->get($account, 'connect_tokens');
  82. }
  83. /**
  84. *
  85. * @link http://context.io/docs/2.0/connecttokens
  86. */
  87. public function getConnectToken($account=null,$params) {
  88. if (is_string($params)) {
  89. $params = array('token' => $params);
  90. }
  91. else {
  92. $params = $this->_filterParams($params, array('token'));
  93. if ($params === false) {
  94. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  95. }
  96. }
  97. return $this->get($account, 'connect_tokens/' . $params['token']);
  98. }
  99. /**
  100. *
  101. * @link http://context.io/docs/2.0/connecttokens
  102. */
  103. public function addConnectToken($account=null,$params=array()) {
  104. $params = $this->_filterParams($params, array('service_level','email','callback_url','first_name','last_name'), array('callback_url'));
  105. if ($params === false) {
  106. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  107. }
  108. return $this->post($account, 'connect_tokens', $params);
  109. }
  110. /**
  111. *
  112. * @link http://context.io/docs/2.0/connecttokens
  113. */
  114. public function deleteConnectToken($account=null, $params) {
  115. if (is_string($params)) {
  116. $params = array('token' => $params);
  117. }
  118. else {
  119. $params = $this->_filterParams($params, array('token'), array('token'));
  120. if ($params === false) {
  121. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  122. }
  123. }
  124. return $this->delete($account, 'connect_tokens/' . $params['token']);
  125. }
  126. /**
  127. *
  128. * @link http://context.io/docs/2.0/oauthproviders
  129. */
  130. public function listOAuthProviders() {
  131. return $this->get(null, 'oauth_providers');
  132. }
  133. /**
  134. *
  135. * @link http://context.io/docs/2.0/oauthproviders
  136. */
  137. public function getOAuthProvider($params) {
  138. if (is_string($params)) {
  139. $params = array('provider_consumer_key' => $params);
  140. }
  141. else {
  142. $params = $this->_filterParams($params, array('provider_consumer_key'), array('provider_consumer_key'));
  143. if ($params === false) {
  144. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  145. }
  146. }
  147. return $this->get(null, 'oauth_providers/' . $params['provider_consumer_key']);
  148. }
  149. /**
  150. *
  151. * @link http://context.io/docs/2.0/oauthproviders
  152. */
  153. public function addOAuthProvider($params=array()) {
  154. $params = $this->_filterParams($params, array('type','provider_consumer_key','provider_consumer_secret'), array('type','provider_consumer_key','provider_consumer_secret'));
  155. if ($params === false) {
  156. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  157. }
  158. return $this->post(null, 'oauth_providers', $params);
  159. }
  160. /**
  161. *
  162. * @link http://context.io/docs/2.0/oauthproviders
  163. */
  164. public function deleteOAuthProvider($params) {
  165. if (is_string($params)) {
  166. $params = array('provider_consumer_key' => $params);
  167. }
  168. else {
  169. $params = $this->_filterParams($params, array('provider_consumer_key'), array('provider_consumer_key'));
  170. if ($params === false) {
  171. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  172. }
  173. }
  174. return $this->delete(null, 'oauth_providers/' . $params['provider_consumer_key']);
  175. }
  176. /**
  177. * Returns the 20 contacts with whom the most emails were exchanged.
  178. * @link http://context.io/docs/2.0/accounts/contacts
  179. * @param string $account accountId of the mailbox you want to query
  180. * @return ContextIOResponse
  181. */
  182. public function listContacts($account, $params=null) {
  183. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  184. throw new InvalidArgumentException('account must be string representing accountId');
  185. }
  186. if (is_array($params)) {
  187. $params = $this->_filterParams($params, array('active_after','active_before','limit','offset','search'));
  188. if ($params === false) {
  189. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  190. }
  191. }
  192. return $this->get($account, 'contacts', $params);
  193. }
  194. public function getContact($account, $params=array()) {
  195. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  196. throw new InvalidArgumentException('account must be string representing accountId');
  197. }
  198. if (is_string($params)) {
  199. $params = array('email' => $params);
  200. }
  201. else {
  202. $params = $this->_filterParams($params, array('email'), array('email'));
  203. if ($params === false) {
  204. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  205. }
  206. }
  207. return $this->get($account, 'contacts/' . $params['email']);
  208. }
  209. /**
  210. * @link http://context.io/docs/2.0/accounts/contacts/files
  211. * @return ContextIOResponse
  212. */
  213. public function listContactFiles($account, $params) {
  214. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  215. throw new InvalidArgumentException('account must be string representing accountId');
  216. }
  217. $params = $this->_filterParams($params, array('email','limit','offset','scope','group_by_revisions','include_person_info'), array('email'));
  218. if ($params === false) {
  219. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  220. }
  221. return $this->get($account, 'contacts/' . $params['email'] . '/files', $params);
  222. }
  223. /**
  224. * @link http://context.io/docs/2.0/accounts/contacts/messages
  225. * @return ContextIOResponse
  226. */
  227. public function listContactMessages($account, $params) {
  228. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  229. throw new InvalidArgumentException('account must be string representing accountId');
  230. }
  231. $params = $this->_filterParams($params, array('email','limit','offset','scope','folder','include_person_info'), array('email'));
  232. if ($params === false) {
  233. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  234. }
  235. return $this->get($account, 'contacts/' . $params['email'] . '/messages', $params);
  236. }
  237. /**
  238. * @link http://context.io/docs/2.0/accounts/contacts/threads
  239. * @return ContextIOResponse
  240. */
  241. public function listContactThreads($account, $params) {
  242. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  243. throw new InvalidArgumentException('account must be string representing accountId');
  244. }
  245. $params = $this->_filterParams($params, array('email','limit','offset','scope','folder'), array('email'));
  246. if ($params === false) {
  247. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  248. }
  249. return $this->get($account, 'contacts/' . $params['email'] . '/threads', $params);
  250. }
  251. /**
  252. * @link http://context.io/docs/2.0/accounts/files
  253. * @param string $account accountId of the mailbox you want to query
  254. * @param array[string]mixed $params Query parameters for the API call: indexed_after, limit
  255. * @return ContextIOResponse
  256. */
  257. public function listFiles($account, $params=null) {
  258. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  259. throw new InvalidArgumentException('account must be string representing accountId');
  260. }
  261. if (is_array($params)) {
  262. $params = $this->_filterParams($params, array('indexed_before', 'indexed_after','date_before','date_after','file_name','limit', 'offset', 'email', 'to','from','cc','bcc','group_by_revisions','include_person_info'));
  263. if ($params === false) {
  264. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  265. }
  266. }
  267. return $this->get($account, 'files', $params);
  268. }
  269. public function getFile($account, $params) {
  270. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  271. throw new InvalidArgumentException('account must be string representing accountId');
  272. }
  273. if (is_string($params)) {
  274. $params = array('file_id' =>$params);
  275. }
  276. else {
  277. $params = $this->_filterParams($params, array('file_id'), array('file_id'));
  278. if ($params === false) {
  279. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  280. }
  281. }
  282. return $this->get($account, 'files/' . $params['file_id']);
  283. }
  284. public function getFileURL($account, $params) {
  285. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  286. throw new InvalidArgumentException('account must be string representing accountId');
  287. }
  288. if (is_string($params)) {
  289. $params = array('file_id' =>$params);
  290. }
  291. else {
  292. $params = $this->_filterParams($params, array('file_id'), array('file_id'));
  293. }
  294. return $this->get($account, 'files/' . $params['file_id'] . '/content', array('as_link' => 1), array('text/uri-list'));
  295. }
  296. /**
  297. * Returns the content a given attachment. If you want to save the attachment to
  298. * a file, set $saveAs to the destination file name. If $saveAs is left to null,
  299. * the function will return the file data.
  300. * on the
  301. * @link http://context.io/docs/2.0/accounts/files/content
  302. * @param string $account accountId of the mailbox you want to query
  303. * @param array[string]string $params Query parameters for the API call: 'fileId'
  304. * @param string $saveAs Path to local file where the attachment should be saved to.
  305. * @return mixed
  306. */
  307. public function getFileContent($account, $params, $saveAs=null) {
  308. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  309. throw new InvalidArgumentException('account must be string representing accountId');
  310. }
  311. if (is_string($params)) {
  312. $params = array('file_id' =>$params);
  313. }
  314. else {
  315. $params = $this->_filterParams($params, array('file_id'), array('file_id'));
  316. if ($params === false) {
  317. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  318. }
  319. }
  320. $consumer = new ContextIOExtLib\OAuthConsumer($this->oauthKey, $this->oauthSecret);
  321. $baseUrl = $this->build_url('accounts/' . $account . '/files/' . $params['file_id'] . '/content');
  322. $req = ContextIOExtLib\OAuthRequest::from_consumer_and_token($consumer, null, "GET", $baseUrl);
  323. $sig_method = new ContextIOExtLib\OAuthSignatureMethod_HMAC_SHA1();
  324. $req->sign_request($sig_method, $consumer, null);
  325. //get data using signed url
  326. if ($this->authHeaders) {
  327. $curl = curl_init($baseUrl);
  328. curl_setopt($curl, CURLOPT_HTTPHEADER, array($req->to_header()));
  329. }
  330. else {
  331. $curl = curl_init($req->to_url());
  332. }
  333. if ($this->ssl) {
  334. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  335. }
  336. curl_setopt($curl, CURLOPT_USERAGENT, 'ContextIOLibrary/2.0 (PHP)');
  337. if (! is_null($saveAs)) {
  338. $fp = fopen($saveAs, "w");
  339. curl_setopt($curl, CURLOPT_FILE, $fp);
  340. curl_setopt($curl, CURLOPT_HEADER, 0);
  341. curl_exec($curl);
  342. curl_close($curl);
  343. fclose($fp);
  344. return true;
  345. }
  346. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  347. $result = curl_exec($curl);
  348. if (curl_getinfo($curl, CURLINFO_HTTP_CODE) != 200) {
  349. $response = new ContextIOResponse(
  350. curl_getinfo($curl, CURLINFO_HTTP_CODE),
  351. null,
  352. null,
  353. curl_getinfo($curl, CURLINFO_CONTENT_TYPE),
  354. $result);
  355. $this->lastResponse = $response;
  356. curl_close($curl);
  357. return false;
  358. }
  359. curl_close($curl);
  360. return $result;
  361. }
  362. /**
  363. * Given two files, this will return the list of insertions and deletions made
  364. * from the oldest of the two files to the newest one.
  365. * @link http://context.io/docs/2.0/accounts/files/changes
  366. * @param string $account accountId of the mailbox you want to query
  367. * @param array[string]string $params Query parameters for the API call: 'fileId1', 'fileId2'
  368. * @return ContextIOResponse
  369. */
  370. public function getFileChanges($account, $params) {
  371. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  372. throw new InvalidArgumentException('account must be string representing accountId');
  373. }
  374. $params = $this->_filterParams($params, array('file_id1', 'file_id2', 'generate'), array('file_id1','file_id2'));
  375. if ($params === false) {
  376. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  377. }
  378. $newParams = array(
  379. 'file_id' => $params['file_id2']
  380. );
  381. if (! array_key_exists('generate', $params)) {
  382. $newParams['generate'] = 1;
  383. }
  384. else {
  385. $newParams['generate'] = $params['generate'];
  386. }
  387. return $this->get($account, 'files/' . $params['file_id1'] . '/changes', $newParams);
  388. }
  389. /**
  390. * Returns a list of revisions attached to other emails in the
  391. * mailbox for one or more given files (see fileid parameter below).
  392. * @link http://context.io/docs/2.0/accounts/files/revisions
  393. * @param string $account accountId of the mailbox you want to query
  394. * @param array[string]string $params Query parameters for the API call: 'fileId', 'fileName'
  395. * @return ContextIOResponse
  396. */
  397. public function listFileRevisions($account, $params) {
  398. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  399. throw new InvalidArgumentException('account must be string representing accountId');
  400. }
  401. if (is_string($params)) {
  402. $params = array('file_id' =>$params);
  403. }
  404. else {
  405. $params = $this->_filterParams($params, array('file_id', 'include_person_info'), array('file_id'));
  406. if ($params === false) {
  407. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  408. }
  409. }
  410. return $this->get($account, 'files/' . $params['file_id'] . '/revisions', $params);
  411. }
  412. /**
  413. * Returns a list of files that are related to the given file.
  414. * Currently, relation between files is based on how similar their names are.
  415. * You must specify either the fileId of fileName parameter
  416. * @link http://context.io/docs/2.0/accounts/files/related
  417. * @param string $account accountId of the mailbox you want to query
  418. * @param array[string]string $params Query parameters for the API call: 'fileId', 'fileName'
  419. * @return ContextIOResponse
  420. */
  421. public function listFileRelated($account, $params) {
  422. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  423. throw new InvalidArgumentException('account must be string representing accountId');
  424. }
  425. if (is_string($params)) {
  426. $params = array('file_id' =>$params);
  427. }
  428. else {
  429. $params = $this->_filterParams($params, array('file_id','include_person_info'), array('file_id'));
  430. if ($params === false) {
  431. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  432. }
  433. }
  434. return $this->get($account, 'files/' . $params['file_id'] . '/related', $params);
  435. }
  436. /**
  437. * Returns message information
  438. * @param string $account accountId of the mailbox you want to query
  439. * @param array[string]mixed $params Query parameters for the API call: 'subject', 'limit'
  440. * @return ContextIOResponse
  441. */
  442. public function listMessagesBySourceAndFolder($account, $params=null) {
  443. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  444. throw new InvalidArgumentException('account must be string representing accountId');
  445. }
  446. if (is_array($params)) {
  447. $params = $this->_filterParams($params, array('label','folder','limit','offset','type','include_body','include_headers','include_flags','flag_seen'), array('label','folder'));
  448. if ($params === false) {
  449. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  450. }
  451. }
  452. $source = $params['label'];
  453. $folder = $params['folder'];
  454. unset($params['label']);
  455. unset($params['folder']);
  456. return $this->get($account, "sources/$source/folders/$folder/messages", $params);
  457. }
  458. /**
  459. * Returns message information
  460. * @link http://context.io/docs/2.0/accounts/messages
  461. * @param string $account accountId of the mailbox you want to query
  462. * @param array[string]mixed $params Query parameters for the API call: 'subject', 'limit'
  463. * @return ContextIOResponse
  464. */
  465. public function listMessages($account, $params=null) {
  466. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  467. throw new InvalidArgumentException('account must be string representing accountId');
  468. }
  469. if (is_array($params)) {
  470. $params = $this->_filterParams($params, array('subject', 'date_before', 'date_after', 'indexed_after', 'indexed_before', 'limit', 'offset','email', 'to','from','cc','bcc','email_message_id','type','include_body','include_headers','include_flags','folder','gm_search','include_person_info'));
  471. if ($params === false) {
  472. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  473. }
  474. }
  475. return $this->get($account, 'messages', $params);
  476. }
  477. public function addMessageToFolder($account, $params=array()) {
  478. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  479. throw new InvalidArgumentException('account must be string representing accountId');
  480. }
  481. $params = $this->_filterParams($params, array('dst_label','dst_folder','src_file','message_id','email_message_id','gmail_message_id'), array('dst_label','dst_folder'));
  482. if ($params === false) {
  483. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  484. }
  485. if (array_key_exists('src_file', $params)) {
  486. $params['src_file'] = realpath($params['src_file']);
  487. if (($params['src_file'] === false) || !is_readable($params['src_file'])) {
  488. throw new InvalidArgumentException("invalid source file");
  489. }
  490. $src_file = '@' . $params['src_file'];
  491. unset($params['src_file']);
  492. return $this->post($account, 'messages', $params, array('field' => 'message', 'filename' => $src_file));
  493. }
  494. elseif (array_key_exists('message_id', $params)) {
  495. return $this->post($account, 'messages/' . $params['message_id'], $params);
  496. }
  497. elseif (array_key_exists('email_message_id', $params)) {
  498. return $this->post($account, 'messages/' . urlencode($params['email_message_id']), $params);
  499. }
  500. elseif (array_key_exists('gmail_message_id', $params)) {
  501. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  502. return $this->post($account, 'messages/' . $params['gmail_message_id'], $params);
  503. }
  504. return $this->post($account, 'messages/gm-' . $params['gmail_message_id'], $params);
  505. }
  506. else {
  507. throw new InvalidArgumentException('src_file, message_id, email_message_id or gmail_message_id is a required hash key');
  508. }
  509. }
  510. /**
  511. * Returns document and contact information about a message.
  512. * A message can be identified by the value of its Message-ID header
  513. * @link http://context.io/docs/2.0/accounts/messages#id-get
  514. * @param string $account accountId of the mailbox you want to query
  515. * @param array[string]mixed $params Query parameters for the API call: 'emailMessageId'
  516. * @return ContextIOResponse
  517. */
  518. public function getMessage($account, $params) {
  519. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  520. throw new InvalidArgumentException('account must be string representing accountId');
  521. }
  522. if (is_string($params)) {
  523. return $this->get($account, 'messages/' . urlencode($params));
  524. }
  525. else {
  526. $params = $this->_filterParams($params, array('message_id', 'email_message_id', 'gmail_message_id', 'include_person_info', 'type','include_body','include_headers','include_flags'));
  527. if ($params === false) {
  528. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  529. }
  530. if (array_key_exists('message_id', $params)) {
  531. return $this->get($account, 'messages/' . $params['message_id'], $params);
  532. }
  533. elseif (array_key_exists('email_message_id', $params)) {
  534. return $this->get($account, 'messages/' . urlencode($params['email_message_id']), $params);
  535. }
  536. elseif (array_key_exists('gmail_message_id', $params)) {
  537. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  538. return $this->get($account, 'messages/' . $params['gmail_message_id'], $params);
  539. }
  540. return $this->get($account, 'messages/gm-' . $params['gmail_message_id'], $params);
  541. }
  542. else {
  543. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  544. }
  545. }
  546. }
  547. /**
  548. * Returns the message headers of a message.
  549. * A message can be identified by the value of its Message-ID header
  550. * @link http://context.io/docs/2.0/accounts/messages/headers
  551. * @param string $account accountId of the mailbox you want to query
  552. * @param array[string]mixed $params Query parameters for the API call: 'emailMessageId'
  553. * @return ContextIOResponse
  554. */
  555. public function getMessageHeaders($account, $params) {
  556. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  557. throw new InvalidArgumentException('account must be string representing accountId');
  558. }
  559. if (is_string($params)) {
  560. return $this->get($account, 'messages/' . urlencode($params) . '/headers');
  561. }
  562. else {
  563. $params = $this->_filterParams($params, array('message_id','email_message_id', 'gmail_message_id', 'raw'), array());
  564. if (array_key_exists('message_id', $params)) {
  565. return $this->get($account, 'messages/' . $params['message_id']. '/headers', $params);
  566. }
  567. elseif (array_key_exists('email_message_id', $params)) {
  568. return $this->get($account, 'messages/' . urlencode($params['email_message_id']) . '/headers', $params);
  569. }
  570. elseif (array_key_exists('gmail_message_id', $params)) {
  571. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  572. return $this->get($account, 'messages/' . $params['gmail_message_id'] . '/headers', $params);
  573. }
  574. return $this->get($account, 'messages/gm-' . $params['gmail_message_id'] . '/headers', $params);
  575. }
  576. else {
  577. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  578. }
  579. }
  580. }
  581. /**
  582. * Returns the message source of a message.
  583. * A message can be identified by the value of its Message-ID header
  584. * @link http://context.io/docs/2.0/accounts/messages/source
  585. * @param string $account accountId of the mailbox you want to query
  586. * @param array[string]mixed $params Query parameters for the API call: 'emailMessageId'
  587. * @return ContextIOResponse
  588. */
  589. public function getMessageSource($account, $params, $saveAs=null) {
  590. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  591. throw new InvalidArgumentException('account must be string representing accountId');
  592. }
  593. if (is_string($params)) {
  594. $url = 'messages/' . urlencode($params) . '/source';
  595. }
  596. elseif (array_key_exists('message_id', $params)) {
  597. $url = 'messages/' . $params['message_id']. '/source';
  598. }
  599. elseif (array_key_exists('email_message_id', $params)) {
  600. $url = 'messages/' . urlencode($params['email_message_id']) . '/source';
  601. }
  602. elseif (array_key_exists('gmail_message_id', $params)) {
  603. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  604. $url = 'messages/' . $params['gmail_message_id'] . '/source';
  605. }
  606. else {
  607. $url = 'messages/gm-' . $params['gmail_message_id'] . '/source';
  608. }
  609. }
  610. else {
  611. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  612. }
  613. $consumer = new ContextIOExtLib\OAuthConsumer($this->oauthKey, $this->oauthSecret);
  614. $baseUrl = $this->build_url('accounts/' . $account . '/' . $url);
  615. $req = ContextIOExtLib\OAuthRequest::from_consumer_and_token($consumer, null, "GET", $baseUrl);
  616. $sig_method = new ContextIOExtLib\OAuthSignatureMethod_HMAC_SHA1();
  617. $req->sign_request($sig_method, $consumer, null);
  618. //get data using signed url
  619. if ($this->authHeaders) {
  620. $curl = curl_init($baseUrl);
  621. curl_setopt($curl, CURLOPT_HTTPHEADER, array($req->to_header()));
  622. }
  623. else {
  624. $curl = curl_init($req->to_url());
  625. }
  626. if ($this->ssl) {
  627. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  628. }
  629. curl_setopt($curl, CURLOPT_USERAGENT, 'ContextIOLibrary/2.0 (PHP)');
  630. if (! is_null($saveAs)) {
  631. $fp = fopen($saveAs, "w");
  632. curl_setopt($curl, CURLOPT_FILE, $fp);
  633. curl_setopt($curl, CURLOPT_HEADER, 0);
  634. curl_exec($curl);
  635. curl_close($curl);
  636. fclose($fp);
  637. return true;
  638. }
  639. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  640. $result = curl_exec($curl);
  641. if (curl_getinfo($curl, CURLINFO_HTTP_CODE) != 200) {
  642. $response = new ContextIOResponse(
  643. curl_getinfo($curl, CURLINFO_HTTP_CODE),
  644. null,
  645. null,
  646. curl_getinfo($curl, CURLINFO_CONTENT_TYPE),
  647. $result);
  648. $this->lastResponse = $response;
  649. curl_close($curl);
  650. return false;
  651. }
  652. curl_close($curl);
  653. return $result;
  654. }
  655. /**
  656. * Returns the message flags of a message.
  657. * A message can be identified by the value of its Message-ID header
  658. * @link http://context.io/docs/2.0/accounts/messages/flags
  659. * @param string $account accountId of the mailbox you want to query
  660. * @param array[string]mixed $params Query parameters for the API call: 'emailMessageId'
  661. * @return ContextIOResponse
  662. */
  663. public function getMessageFlags($account, $params) {
  664. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  665. throw new InvalidArgumentException('account must be string representing accountId');
  666. }
  667. if (is_string($params)) {
  668. return $this->get($account, 'messages/' . urlencode($params) . '/flags');
  669. }
  670. elseif (array_key_exists('message_id', $params)) {
  671. return $this->get($account, 'messages/' . $params['message_id']. '/flags');
  672. }
  673. elseif (array_key_exists('email_message_id', $params)) {
  674. return $this->get($account, 'messages/' . urlencode($params['email_message_id']) . '/flags');
  675. }
  676. elseif (array_key_exists('gmail_message_id', $params)) {
  677. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  678. return $this->get($account, 'messages/' . $params['gmail_message_id'] . '/flags');
  679. }
  680. return $this->get($account, 'messages/gm-' . $params['gmail_message_id'] . '/flags');
  681. }
  682. else {
  683. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  684. }
  685. }
  686. /**
  687. * Returns the folders the message is part of.
  688. * A message can be identified by the value of its Message-ID header
  689. * @link http://context.io/docs/2.0/accounts/messages/folders
  690. * @param string $account accountId
  691. * @param array[string]mixed $params Query parameters for the API call: 'emailMessageId'
  692. * @return ContextIOResponse
  693. */
  694. public function getMessageFolders($account, $params) {
  695. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  696. throw new InvalidArgumentException('account must be string representing accountId');
  697. }
  698. if (is_string($params)) {
  699. return $this->get($account, 'messages/' . urlencode($params) . '/folders');
  700. }
  701. elseif (array_key_exists('message_id', $params)) {
  702. return $this->get($account, 'messages/' . $params['message_id']. '/folders');
  703. }
  704. elseif (array_key_exists('email_message_id', $params)) {
  705. return $this->get($account, 'messages/' . urlencode($params['email_message_id']) . '/folders');
  706. }
  707. elseif (array_key_exists('gmail_message_id', $params)) {
  708. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  709. return $this->get($account, 'messages/' . $params['gmail_message_id'] . '/folders');
  710. }
  711. return $this->get($account, 'messages/gm-' . $params['gmail_message_id'] . '/folders');
  712. }
  713. else {
  714. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  715. }
  716. }
  717. /**
  718. * Sets the message folders of a message.
  719. * A message can be identified by the value of its Message-ID header
  720. * @param string $account accountId of the mailbox you want to query
  721. * @param array[string]mixed $params Query parameters for the API call: 'emailMessageId'
  722. * @return ContextIOResponse
  723. */
  724. public function setMessageFolders($account, $params) {
  725. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  726. throw new InvalidArgumentException('account must be string representing accountId');
  727. }
  728. $params = $this->_filterParams($params, array('message_id', 'email_message_id', 'gmail_message_id', 'add','remove','folders'));
  729. if ($params === false) {
  730. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  731. }
  732. if (array_key_exists('folders', $params)) {
  733. if (! is_array($params['folders'])) {
  734. throw new InvalidArgumentException("folders must be array");
  735. }
  736. $folderStr = json_encode($params['folders']);
  737. if (array_key_exists('email_message_id', $params)) {
  738. return $this->put($account, 'messages/' . urlencode($params['email_message_id']) . '/folders', $folderStr);
  739. }
  740. elseif (array_key_exists('message_id', $params)) {
  741. return $this->put($account, 'messages/' . $params['message_id'] . '/folders', $folderStr);
  742. }
  743. elseif (array_key_exists('gmail_message_id', $params)) {
  744. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  745. return $this->put($account, 'messages/' . $params['gmail_message_id'] . '/folders', $folderStr);
  746. }
  747. return $this->put($account, 'messages/gm-' . $params['gmail_message_id'] . '/folders', $folderStr);
  748. }
  749. else {
  750. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  751. }
  752. }
  753. else {
  754. $addRemoveParams = array();
  755. foreach (array('add','remove') as $currentName) {
  756. if (array_key_exists($currentName, $params)) {
  757. $addRemoveParams[$currentName] = $params[$currentName];
  758. }
  759. }
  760. if (count(array_keys($addRemoveParams)) == 0) {
  761. throw new InvalidArgumentException("must specify at least one of add,remove");
  762. }
  763. if (array_key_exists('email_message_id', $params)) {
  764. return $this->post($account, 'messages/' . urlencode($params['email_message_id']) . '/folders', $addRemoveParams);
  765. }
  766. elseif (array_key_exists('message_id', $params)) {
  767. return $this->post($account, 'messages/' . $params['message_id'] . '/folders', $addRemoveParams);
  768. }
  769. elseif (array_key_exists('gmail_message_id', $params)) {
  770. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  771. return $this->post($account, 'messages/' . $params['gmail_message_id'] . '/folders', $addRemoveParams);
  772. }
  773. return $this->post($account, 'messages/gm-' . $params['gmail_message_id'] . '/folders', $addRemoveParams);
  774. }
  775. else {
  776. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  777. }
  778. }
  779. }
  780. /**
  781. * Returns the message flags of a message.
  782. * A message can be identified by the value of its Message-ID header
  783. * @link http://context.io/docs/2.0/accounts/messages/flags
  784. * @param string $account accountId of the mailbox you want to query
  785. * @param array[string]mixed $params Query parameters for the API call: 'emailMessageId'
  786. * @return ContextIOResponse
  787. */
  788. public function setMessageFlags($account, $params) {
  789. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  790. throw new InvalidArgumentException('account must be string representing accountId');
  791. }
  792. $params = $this->_filterParams($params, array('message_id', 'email_message_id', 'gmail_message_id', 'seen','answered','flagged','deleted','draft'));
  793. if ($params === false) {
  794. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  795. }
  796. $flagParams = array();
  797. foreach (array('seen','answered','flagged','deleted','draft') as $currentFlagName) {
  798. if (array_key_exists($currentFlagName, $params)) {
  799. if (! is_bool($params[$currentFlagName])) {
  800. throw new InvalidArgumentException("$currentFlagName must be boolean");
  801. }
  802. $flagParams[$currentFlagName] = ($params[$currentFlagName] === true) ? 1 : 0;
  803. }
  804. }
  805. if (count(array_keys($flagParams)) == 0) {
  806. throw new InvalidArgumentException("must specify at least one of seen,answered,flagged,deleted,draft");
  807. }
  808. if (array_key_exists('email_message_id', $params)) {
  809. return $this->post($account, 'messages/' . urlencode($params['email_message_id']) . '/flags', $flagParams);
  810. }
  811. elseif (array_key_exists('message_id', $params)) {
  812. return $this->post($account, 'messages/' . $params['message_id'] . '/flags', $flagParams);
  813. }
  814. elseif (array_key_exists('gmail_message_id', $params)) {
  815. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  816. return $this->post($account, 'messages/' . $params['gmail_message_id'] . '/flags', $flagParams);
  817. }
  818. return $this->post($account, 'messages/gm-' . $params['gmail_message_id'] . '/flags', $flagParams);
  819. }
  820. else {
  821. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  822. }
  823. }
  824. /**
  825. * Returns the message body (excluding attachments) of a message.
  826. * A message can be identified by the value of its Message-ID header
  827. * or by the combination of the date sent timestamp and email address
  828. * of the sender.
  829. * @link http://context.io/docs/2.0/accounts/messages/body
  830. * @param string $account accountId of the mailbox you want to query
  831. * @param array[string]mixed $params Query parameters for the API call: 'emailMessageId', 'from', 'dateSent','type
  832. * @return ContextIOResponse
  833. */
  834. public function getMessageBody($account, $params) {
  835. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  836. throw new InvalidArgumentException('account must be string representing accountId');
  837. }
  838. if (is_string($params)) {
  839. return $this->get($account, 'messages/' . urlencode($params) . '/body');
  840. }
  841. $params = $this->_filterParams($params, array('message_id', 'email_message_id', 'gmail_message_id', 'type'));
  842. if ($params === false) {
  843. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  844. }
  845. if (array_key_exists('email_message_id', $params)) {
  846. return $this->get($account, 'messages/' . urlencode($params['email_message_id']) . '/body', $params);
  847. }
  848. elseif (array_key_exists('message_id', $params)) {
  849. return $this->get($account, 'messages/' . $params['message_id'] . '/body', $params);
  850. }
  851. elseif (array_key_exists('gmail_message_id', $params)) {
  852. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  853. return $this->get($account, 'messages/' . $params['gmail_message_id'] . '/body', $params);
  854. }
  855. return $this->get($account, 'messages/gm-' . $params['gmail_message_id'] . '/body', $params);
  856. }
  857. else {
  858. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  859. }
  860. }
  861. /**
  862. * Returns message and contact information about a given email thread.
  863. * @link http://context.io/docs/2.0/accounts/messages/thread
  864. * @param string $account accountId of the mailbox you want to query
  865. * @param array[string]string $params Query parameters for the API call: 'email_message_id'
  866. * @return ContextIOResponse
  867. */
  868. public function getMessageThread($account, $params) {
  869. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  870. throw new InvalidArgumentException('account must be string representing accountId');
  871. }
  872. if (is_string($params)) {
  873. return $this->get($account, 'messages/' . urlencode($params) . '/thread');
  874. }
  875. $params = $this->_filterParams($params, array('message_id', 'email_message_id', 'gmail_message_id', 'include_body', 'include_headers', 'include_flags', 'type', 'include_person_info'));
  876. if ($params === false) {
  877. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  878. }
  879. if (array_key_exists('email_message_id', $params)) {
  880. return $this->get($account, 'messages/' . urlencode($params['email_message_id']) . '/thread', $params);
  881. }
  882. elseif (array_key_exists('message_id', $params)) {
  883. return $this->get($account, 'messages/' . $params['message_id'] . '/thread', $params);
  884. }
  885. elseif (array_key_exists('gmail_message_id', $params)) {
  886. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  887. return $this->get($account, 'messages/' . $params['gmail_message_id'] . '/thread', $params);
  888. }
  889. return $this->get($account, 'messages/gm-' . $params['gmail_message_id'] . '/thread', $params);
  890. }
  891. else {
  892. throw new InvalidArgumentException('message_id, email_message_id or gmail_message_id is a required hash key');
  893. }
  894. }
  895. /**
  896. * Returns list of threads
  897. * @link http://context.io/docs/2.0/accounts/threads
  898. * @param string $account accountId of the mailbox you want to query
  899. * @param array[string]string $params Query parameters for the API call: 'gmailthreadid'
  900. * @return ContextIOResponse
  901. */
  902. public function listThreads($account, $params=null) {
  903. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  904. throw new InvalidArgumentException('account must be string representing accountId');
  905. }
  906. if (is_array($params)) {
  907. $params = $this->_filterParams($params, array('subject', 'indexed_after', 'indexed_before', 'active_after', 'active_before', 'started_after', 'started_before', 'limit', 'offset','email', 'to','from','cc','bcc','folder'));
  908. if ($params === false) {
  909. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  910. }
  911. }
  912. return $this->get($account, 'threads', $params);
  913. }
  914. /**
  915. * Returns message and contact information about a given email thread.
  916. * @link http://context.io/docs/2.0/accounts/threads
  917. * @param string $account accountId of the mailbox you want to query
  918. * @param array[string]string $params Query parameters for the API call: 'gmailthreadid'
  919. * @return ContextIOResponse
  920. */
  921. public function getThread($account, $params) {
  922. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  923. throw new InvalidArgumentException('account must be string representing accountId');
  924. }
  925. $params = $this->_filterParams($params, array('message_id', 'gmail_thread_id','gmail_message_id','email_message_id','include_body','include_headers','include_flags','type','include_person_info','limit','offset'));
  926. if ($params === false) {
  927. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  928. }
  929. if (array_key_exists('email_message_id', $params)) {
  930. return $this->get($account, 'messages/' . urlencode($params['email_message_id']) . '/thread', $params);
  931. }
  932. elseif (array_key_exists('message_id', $params)) {
  933. return $this->get($account, 'messages/' . $params['message_id'] . '/thread', $params);
  934. }
  935. elseif (array_key_exists('gmail_message_id', $params)) {
  936. if (substr($params['gmail_message_id'],0,3) == 'gm-') {
  937. return $this->get($account, 'messages/' . $params['gmail_message_id'] . '/thread', $params);
  938. }
  939. return $this->get($account, 'messages/gm-' . $params['gmail_message_id'] . '/thread', $params);
  940. }
  941. elseif (array_key_exists('gmail_thread_id', $params)) {
  942. if (substr($params['gmail_thread_id'],0,3) == 'gm-') {
  943. return $this->get($account, 'threads/' . $params['gmail_thread_id'], $params);
  944. }
  945. return $this->get($account, 'threads/gm-' . $params['gmail_thread_id'], $params);
  946. }
  947. else {
  948. throw new InvalidArgumentException('gmail_thread_id, messageId, email_message_id or gmail_message_id are required hash keys');
  949. }
  950. }
  951. public function addAccount($params) {
  952. $params = $this->_filterParams($params, array('email','first_name','last_name','type','server','username','provider_consumer_key','provider_token','provider_token_secret','service_level','sync_period','password','use_ssl','port','callback_url'), array('email'));
  953. if ($params === false) {
  954. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  955. }
  956. return $this->post(null, 'accounts', $params);
  957. }
  958. public function modifyAccount($account, $params) {
  959. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  960. throw new InvalidArgumentException('account must be string representing accountId');
  961. }
  962. $params = $this->_filterParams($params, array('first_name','last_name'));
  963. if ($params === false) {
  964. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  965. }
  966. return $this->post($account, '', $params);
  967. }
  968. public function getAccount($account) {
  969. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  970. throw new InvalidArgumentException('account must be string representing accountId');
  971. }
  972. return $this->get($account);
  973. }
  974. public function deleteAccount($account) {
  975. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  976. throw new InvalidArgumentException('account must be string representing accountId');
  977. }
  978. return $this->delete($account);
  979. }
  980. public function listAccountEmailAddresses($account) {
  981. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  982. throw new InvalidArgumentException('account must be string representing accountId');
  983. }
  984. return $this->get($account, 'email_addresses');
  985. }
  986. public function addEmailAddressToAccount($account, $params) {
  987. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  988. throw new InvalidArgumentException('account must be string representing accountId');
  989. }
  990. $params = $this->_filterParams($params, array('email_address'), array('email_address'));
  991. if ($params === false) {
  992. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  993. }
  994. return $this->post($account, 'email_addresses', $params);
  995. }
  996. public function deleteEmailAddressFromAccount($account, $params) {
  997. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  998. throw new InvalidArgumentException('account must be string representing accountId');
  999. }
  1000. if (is_string($params)) {
  1001. return $this->delete($account, 'email_addresses/' . $params);
  1002. }
  1003. $params = $this->_filterParams($params, array('email_address'), array('email_address'));
  1004. if ($params === false) {
  1005. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1006. }
  1007. return $this->delete($account, 'email_addresses/' . $params['email_address']);
  1008. }
  1009. public function setPrimaryEmailAddressForAccount($account, $params) {
  1010. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1011. throw new InvalidArgumentException('account must be string representing accountId');
  1012. }
  1013. if (is_string($params)) {
  1014. return $this->post($account, 'email_addresses/' . $params, array('primary' => 1));
  1015. }
  1016. $params = $this->_filterParams($params, array('email_address'), array('email_address'));
  1017. if ($params === false) {
  1018. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1019. }
  1020. return $this->post($account, 'email_addresses/' . $params['email_address'], array('primary' => 1));
  1021. }
  1022. public function listAccounts($params=null) {
  1023. if (is_array($params)) {
  1024. $params = $this->_filterParams($params, array('limit','offset','email','status_ok','status'));
  1025. if ($params === false) {
  1026. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1027. }
  1028. }
  1029. return $this->get(null, 'accounts', $params);
  1030. }
  1031. /**
  1032. * Modify the IMAP server settings of an already indexed account
  1033. * @link http://context.io/docs/2.0/accounts/sources
  1034. * @param array[string]string $params Query parameters for the API call: 'credentials', 'mailboxes'
  1035. * @return ContextIOResponse
  1036. */
  1037. public function modifySource($account, $params) {
  1038. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1039. throw new InvalidArgumentException('account must be string representing accountId');
  1040. }
  1041. $params = $this->_filterParams($params, array('provider_token', 'provider_token_secret', 'password', 'provider_consumer_key', 'label', 'mailboxes', 'sync_all_folders', 'service_level','sync_period'), array('label'));
  1042. if ($params === false) {
  1043. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1044. }
  1045. return $this->post($account, 'sources/' . $params['label'], $params);
  1046. }
  1047. public function resetSourceStatus($account, $params) {
  1048. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1049. throw new InvalidArgumentException('account must be string representing accountId');
  1050. }
  1051. if (is_string($params)) {
  1052. $params = array('label' => $params);
  1053. }
  1054. else {
  1055. $params = $this->_filterParams($params, array('label'), array('label'));
  1056. if ($params === false) {
  1057. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1058. }
  1059. }
  1060. return $this->post($account, 'sources/' . $params['label'], array('status' => 1));
  1061. }
  1062. public function listSources($account, $params=null) {
  1063. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1064. throw new InvalidArgumentException('account must be string representing accountId');
  1065. }
  1066. if (is_array($params)) {
  1067. $params = $this->_filterParams($params, array('status_ok','status'));
  1068. if ($params === false) {
  1069. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1070. }
  1071. }
  1072. return $this->get($account, 'sources', $params);
  1073. }
  1074. public function getSource($account, $params) {
  1075. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1076. throw new InvalidArgumentException('account must be string representing accountId');
  1077. }
  1078. if (is_string($params)) {
  1079. $params = array('label' => $params);
  1080. }
  1081. else {
  1082. $params = $this->_filterParams($params, array('label'), array('label'));
  1083. if ($params === false) {
  1084. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1085. }
  1086. }
  1087. return $this->get($account, 'sources/' . $params['label']);
  1088. }
  1089. /**
  1090. * @link http://context.io/docs/2.0/accounts/sources
  1091. * @param array[string]string $params Query parameters for the API call: 'email', 'server', 'username', 'password', 'oauthconsumername', 'oauthtoken', 'oauthtokensecret', 'usessl', 'port'
  1092. * @return ContextIOResponse
  1093. */
  1094. public function addSource($account, $params) {
  1095. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1096. throw new InvalidArgumentException('account must be string representing accountId');
  1097. }
  1098. $params = $this->_filterParams($params, array('type','email','server','username','provider_consumer_key','provider_token','provider_token_secret','service_level','sync_period','sync_all_folders','password','use_ssl','port','callback_url'), array('server','username'));
  1099. if ($params === false) {
  1100. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1101. }
  1102. if (! array_key_exists('type', $params)) {
  1103. $params['type'] = 'imap';
  1104. }
  1105. return $this->post($account, 'sources/', $params);
  1106. }
  1107. /**
  1108. * Remove the connection to an IMAP account
  1109. * @link http://context.io/docs/2.0/accounts/sources
  1110. * @return ContextIOResponse
  1111. */
  1112. public function deleteSource($account, $params=array()) {
  1113. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1114. throw new InvalidArgumentException('account must be string representing accountId');
  1115. }
  1116. if (is_string($params)) {
  1117. $params = array('label' => $params);
  1118. }
  1119. else {
  1120. $params = $this->_filterParams($params, array('label'), array('label'));
  1121. if ($params === false) {
  1122. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1123. }
  1124. }
  1125. return $this->delete($account, 'sources/' . $params['label']);
  1126. }
  1127. public function syncSource($account, $params=array()) {
  1128. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1129. throw new InvalidArgumentException('account must be string representing accountId');
  1130. }
  1131. $params = $this->_filterParams($params, array('label'));
  1132. if ($params === false) {
  1133. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1134. }
  1135. if ($params == array()) {
  1136. return $this->post($account, 'sync');
  1137. }
  1138. return $this->post($account, 'sources/' . $params['label'] . '/sync');
  1139. }
  1140. public function getSync($account, $params=array()) {
  1141. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1142. throw new InvalidArgumentException('account must be string representing accountId');
  1143. }
  1144. $params = $this->_filterParams($params, array('label'));
  1145. if ($params === false) {
  1146. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1147. }
  1148. if ($params == array()) {
  1149. return $this->get($account, 'sync');
  1150. }
  1151. return $this->get($account, 'sources/' . $params['label'] . '/sync');
  1152. }
  1153. public function addFolderToSource($account, $params=array()) {
  1154. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1155. throw new InvalidArgumentException('account must be string representing accountId');
  1156. }
  1157. $params = $this->_filterParams($params, array('label','folder','delim'), array('label','folder'));
  1158. if ($params === false) {
  1159. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1160. }
  1161. if (array_key_exists('delim', $params)) {
  1162. return $this->put($account, 'sources/' . $params['label'] . '/folders/' . urlencode($params['folder']), array('delim' => $params['delim']));
  1163. }
  1164. return $this->put($account, 'sources/' . $params['label'] . '/folders/' . urlencode($params['folder']));
  1165. }
  1166. public function sendMessage($account, $params=array()) {
  1167. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1168. throw new InvalidArgumentException('account must be string representing accountId');
  1169. }
  1170. $params = $this->_filterParams($params, array('label','rcpt','message','message_id', 'gmail_thread_id'), array('label'));
  1171. if ($params === false) {
  1172. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1173. }
  1174. if (! array_key_exists('message_id', $params) && ! array_key_exists('message', $params) && ! array_key_exists('gmail_thread_id', $params)) {
  1175. throw new InvalidArgumentException('gmail_thread_id, message_id or message is a required hash key');
  1176. }
  1177. return $this->post($account, 'exits/' . $params['label'], $params);
  1178. }
  1179. public function listSourceFolders($account, $params=array()) {
  1180. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1181. throw new InvalidArgumentException('account must be string representing accountId');
  1182. }
  1183. if (is_string($params)) {
  1184. $params = array('label' => $params);
  1185. }
  1186. else {
  1187. $params = $this->_filterParams($params, array('label'), array('label'));
  1188. if ($params === false) {
  1189. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1190. }
  1191. }
  1192. return $this->get($account, 'sources/' . $params['label'] . '/folders');
  1193. }
  1194. public function listWebhooks($account) {
  1195. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1196. throw new InvalidArgumentException('account must be string representing accountId');
  1197. }
  1198. return $this->get($account, 'webhooks');
  1199. }
  1200. public function getWebhook($account, $params) {
  1201. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1202. throw new InvalidArgumentException('account must be string representing accountId');
  1203. }
  1204. if (is_string($params)) {
  1205. $params = array('webhook_id' => $params);
  1206. }
  1207. else {
  1208. $params = $this->_filterParams($params, array('webhook_id'), array('webhook_id'));
  1209. if ($params === false) {
  1210. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1211. }
  1212. }
  1213. return $this->get($account, 'webhooks/' . $params['webhook_id']);
  1214. }
  1215. public function addWebhook($account, $params) {
  1216. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1217. throw new InvalidArgumentException('account must be string representing accountId');
  1218. }
  1219. $params = $this->_filterParams($params, array('filter_to', 'filter_from', 'filter_cc', 'filter_subject', 'filter_thread', 'filter_new_important', 'filter_file_name', 'filter_file_revisions', 'sync_period', 'callback_url', 'failure_notif_url','filter_folder_added','filter_folder_removed'), array('callback_url','failure_notif_url'));
  1220. if ($params === false) {
  1221. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1222. }
  1223. return $this->post($account, 'webhooks/', $params);
  1224. }
  1225. public function deleteWebhook($account, $params) {
  1226. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1227. throw new InvalidArgumentException('account must be string representing accountId');
  1228. }
  1229. if (is_string($params)) {
  1230. $params = array('webhook_id' => $params);
  1231. }
  1232. else {
  1233. $params = $this->_filterParams($params, array('webhook_id'), array('webhook_id'));
  1234. if ($params === false) {
  1235. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1236. }
  1237. }
  1238. return $this->delete($account, 'webhooks/' . $params['webhook_id']);
  1239. }
  1240. public function modifyWebhook($account, $params) {
  1241. if (is_null($account) || ! is_string($account) || (! strpos($account, '@') === false)) {
  1242. throw new InvalidArgumentException('account must be string representing accountId');
  1243. }
  1244. $params = $this->_filterParams($params, array('webhook_id', 'active'), array('webhook_id','active'));
  1245. if ($params === false) {
  1246. throw new InvalidArgumentException("params array contains invalid parameters or misses required parameters");
  1247. }
  1248. return $this->post($account, 'webhooks/' . $params['webhook_id'], $params);
  1249. }
  1250. /**
  1251. * Specify whether or not API calls should be made over a secure connection.
  1252. * HTTPS is used on all calls by default.
  1253. * @param bool $sslOn Set to false to make calls over HTTP, true to use HTTPS
  1254. */
  1255. public function setSSL($sslOn=true) {
  1256. $this->ssl = (is_bool($sslOn)) ? $sslOn : true;
  1257. }
  1258. /**
  1259. * Set the API version. By default, the latest official version will be used
  1260. * for all calls.
  1261. * @param string $apiVersion Context.IO API version to use
  1262. * @return boolean success
  1263. */
  1264. public function setApiVersion($apiVersion) {
  1265. if ($apiVersion != '2.0') {
  1266. return false;
  1267. }
  1268. $this->apiVersion = $apiVersion;
  1269. return true;
  1270. }
  1271. /**
  1272. * Specify whether OAuth parameters should be included as URL query parameters
  1273. * or sent as HTTP Authorization headers. The default is URL query parameters.
  1274. * @param bool $authHeadersOn Set to true to use HTTP Authorization headers, false to use URL query params
  1275. */
  1276. public function useAuthorizationHeaders($authHeadersOn = true) {
  1277. $this->authHeaders = (is_bool($authHeadersOn)) ? $authHeadersOn : true;
  1278. }
  1279. /**
  1280. * Returns the ContextIOResponse object for the last API call.
  1281. * @return ContextIOResponse
  1282. */
  1283. public function getLastResponse() {
  1284. return $this->lastResponse;
  1285. }
  1286. protected function build_baseurl() {
  1287. $url = 'http';
  1288. if ($this->ssl) {
  1289. $url = 'https';
  1290. }
  1291. return "$url://" . $this->endPoint . "/" . $this->apiVersion . '/';
  1292. }
  1293. protected function build_url($action) {
  1294. return $this->build_baseurl() . $action;
  1295. }
  1296. public function saveHeaders($yes=true) {
  1297. $this->saveHeaders = $yes;
  1298. }
  1299. protected function get($account, $action='', $parameters=null, $acceptableContentTypes=null) {
  1300. if (is_array($account)) {
  1301. $tmp_results = array();
  1302. foreach ($account as $accnt) {
  1303. $result = $this->_doCall('GET', $accnt, $action, $parameters, null, $acceptableContentTypes);
  1304. if ($result === false) {
  1305. return false;
  1306. }
  1307. $tmp_results[$accnt] = $result;
  1308. }
  1309. return $tmp_results;
  1310. }
  1311. else {
  1312. return $this->_doCall('GET', $account, $action, $parameters, null, $acceptableContentTypes);
  1313. }
  1314. }
  1315. protected function put($account, $action, $parameters=null) {
  1316. return $this->_doCall('PUT', $account, $action, $parameters);
  1317. }
  1318. protected function post($account, $action='', $parameters=null, $file=null) {
  1319. return $this->_doCall('POST', $account, $action, $parameters, $file);
  1320. }
  1321. protected function delete($account, $action='', $parameters=null) {
  1322. return $this->_doCall('DELETE', $account, $action, $parameters);
  1323. }
  1324. protected function _doCall($httpMethod, $account, $action, $parameters=null, $file=null, $acceptableContentTypes=null) {
  1325. $consumer = new ContextIOExtLib\OAuthConsumer($this->oauthKey, $this->oauthSecret);
  1326. if (! is_null($account)) {
  1327. $action = 'accounts/' . $account . '/' . $action;
  1328. if (substr($action,-1) == '/') {
  1329. $action = substr($action,0,-1);
  1330. }
  1331. }
  1332. $baseUrl = $this->build_url($action);
  1333. $isMultiPartPost = (! is_null($file) && array_key_exists('field', $file) && array_key_exists('filename', $file));
  1334. if ($isMultiPartPost || is_string($parameters)) {
  1335. $this->authHeaders = true;
  1336. }
  1337. $req = ContextIOExtLib\OAuthRequest::from_consumer_and_token($consumer, null, $httpMethod, $baseUrl, ($isMultiPartPost || is_string($parameters)) ? array() : $parameters);
  1338. $sig_method = new ContextIOExtLib\OAuthSignatureMethod_HMAC_SHA1();
  1339. $req->sign_request($sig_method, $consumer, null);
  1340. $httpHeadersToSet = array();
  1341. //get data using signed url
  1342. if ($this->authHeaders) {
  1343. if ($httpMethod != 'POST') {
  1344. $curl = curl_init((is_null($parameters) || is_string($parameters) || (count($parameters) == 0)) ? $baseUrl : $baseUrl. '?' . ContextIOExtLib\OAuthUtil::build_http_query($parameters));
  1345. }
  1346. else {
  1347. $curl = curl_init($baseUrl);
  1348. }
  1349. $httpHeadersToSet[] = $req->to_header();
  1350. }
  1351. else {
  1352. $curl = curl_init($req->to_url());
  1353. }
  1354. if ($this->ssl) {
  1355. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  1356. }
  1357. curl_setopt($curl, CURLOPT_USERAGENT, 'ContextIOLibrary/2.0 (PHP)');
  1358. if ($httpMethod != 'GET') {
  1359. if ($httpMethod == 'POST') {
  1360. curl_setopt($curl, CURLOPT_POST, true);
  1361. if (! is_null($parameters)) {
  1362. if (is_null($file)) {
  1363. curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($parameters));
  1364. }
  1365. else {
  1366. $parameters[$file['field']] = $file['filename'];
  1367. curl_setopt($curl, CURLOPT_POSTFIELDS, $parameters);
  1368. }
  1369. }
  1370. elseif (! is_null($file)) {
  1371. curl_setopt($curl, CURLOPT_POSTFIELDS, array($file['field'] => $file['filename']));
  1372. }
  1373. }
  1374. else {
  1375. curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $httpMethod);
  1376. if (($httpMethod == 'PUT') && is_string($parameters)) {
  1377. $httpHeadersToSet[] = 'Content-Length: ' . strlen($parameters);
  1378. $httpHeadersToSet[] = 'Content-Type: application/json';
  1379. curl_setopt($curl, CURLOPT_POSTFIELDS, $parameters);
  1380. }
  1381. }
  1382. }
  1383. if (count($httpHeadersToSet) > 0) {
  1384. curl_setopt($curl, CURLOPT_HTTPHEADER, $httpHeadersToSet);
  1385. }
  1386. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  1387. if ($this->saveHeaders) {
  1388. $this->responseHeaders = array();
  1389. $this->requestHeaders = array();
  1390. curl_setopt($curl, CURLOPT_HEADERFUNCTION, array($this,'_setHeader'));
  1391. curl_setopt($curl, CURLINFO_HEADER_OUT, 1);
  1392. }
  1393. $result = curl_exec($curl);
  1394. $httpHeadersIn = ($this->saveHeaders) ? $this->responseHeaders : null;
  1395. $httpHeadersOut = ($this->saveHeaders) ? preg_split('/(\\n|\\r){1,2}/', curl_getinfo($curl, CURLINFO_HEADER_OUT)) : null;
  1396. if (is_null($acceptableContentTypes)) {
  1397. $response = new ContextIOResponse(
  1398. curl_getinfo($curl, CURLINFO_HTTP_CODE),
  1399. $httpHeadersOut,
  1400. $httpHeadersIn,
  1401. curl_getinfo($curl, CURLINFO_CONTENT_TYPE),
  1402. $result);
  1403. }
  1404. else {
  1405. $response = new ContextIOResponse(
  1406. curl_getinfo($curl, CURLINFO_HTTP_CODE),
  1407. $httpHeadersOut,
  1408. $httpHeadersIn,
  1409. curl_getinfo($curl, CURLINFO_CONTENT_TYPE),
  1410. $result,
  1411. $acceptableContentTypes);
  1412. }
  1413. curl_close($curl);
  1414. if ($response->hasError()) {
  1415. $this->lastResponse = $response;
  1416. return false;
  1417. }
  1418. return $response;
  1419. }
  1420. public function _setHeader($curl,$headers) {
  1421. $this->responseHeaders[] = trim($headers,"\n\r");
  1422. return strlen($headers);
  1423. }
  1424. protected function _filterParams($givenParams, $validParams, $requiredParams=array()) {
  1425. $filteredParams = array();
  1426. foreach ($givenParams as $name => $value) {
  1427. if (in_array(strtolower($name), $validParams)) {
  1428. $filteredParams[strtolower($name)] = $value;
  1429. }
  1430. else {
  1431. return false;
  1432. }
  1433. }
  1434. foreach ($requiredParams as $name) {
  1435. if (! array_key_exists(strtolower($name), $filteredParams)) {
  1436. return false;
  1437. }
  1438. }
  1439. return $filteredParams;
  1440. }
  1441. }
  1442. ?>