MauticApi.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. /**
  3. * Mautic API Class
  4. */
  5. class MauticApi
  6. {
  7. /**
  8. * API base URL where Mautic is installed
  9. *
  10. * @var string
  11. */
  12. protected $baseUrl;
  13. /**
  14. * Password associated with Username
  15. *
  16. * @var string
  17. */
  18. private $password;
  19. /**
  20. * Username or email, basically the Login Identifier
  21. *
  22. * @var string
  23. */
  24. private $userName;
  25. /**
  26. * Holds string of HTTP response headers
  27. *
  28. * @var string
  29. */
  30. protected $_httpResponseHeaders;
  31. /**
  32. * Holds array of HTTP response CURL info
  33. *
  34. * @var array
  35. */
  36. protected $_httpResponseInfo;
  37. /**
  38. * Log processes
  39. *
  40. * @param array $config [description]
  41. */
  42. public $logs = array();
  43. /**
  44. * Construct
  45. *
  46. * @param array $config
  47. */
  48. public function __construct(array $config)
  49. {
  50. //error checking
  51. $apiUrl = @$config['apiUrl'];
  52. $api_username = @$config['userName'];
  53. $api_password = @$config['password'];
  54. if (empty($apiUrl)) {
  55. throw new Exception("Required config parameter [installation_url] is not set or empty", 1);
  56. }
  57. if (empty($api_username)) {
  58. throw new Exception("Required config parameter [api_username] is not set or empty", 1);
  59. }
  60. if (empty($api_password)) {
  61. throw new Exception("Required config parameter [api_password] is not set or empty", 1);
  62. }
  63. $this->userName = $api_username;
  64. $this->password = $api_password;
  65. $this->setBaseUrl($apiUrl);
  66. }
  67. protected function isAuthorized()
  68. {
  69. return (!empty($this->userName) && !empty($this->password));
  70. }
  71. /**
  72. * Subscribe a contact
  73. *
  74. * @param array $parameters
  75. *
  76. * @return array|mixed
  77. */
  78. public function subscribe(array $parameters)
  79. {
  80. $response = $this->createContact( $parameters );
  81. // Add contact to a list/segment
  82. if ( isset( $response[ 'contact' ][ 'id' ]) && isset( $parameters['segmentId'] ) ) {
  83. $this->addContactSegment( $parameters['segmentId'], $response[ 'contact' ][ 'id' ] );
  84. }
  85. return $response;
  86. }
  87. /**
  88. * Create a new contact
  89. *
  90. * @param array $parameters
  91. *
  92. * @return array|mixed
  93. */
  94. public function createContact(array $parameters)
  95. {
  96. return $this->makeRequest( 'contacts/new', $parameters, 'POST' );
  97. }
  98. /**
  99. * Add a contact to the campaign
  100. *
  101. * @param int $id Campaign ID
  102. * @param int $contactId Contact ID
  103. *
  104. * @return array|mixed
  105. */
  106. public function addContactCampaign($id, $contactId)
  107. {
  108. return $this->makeRequest( 'campaigns/'.$id.'/contact/'.$contactId.'/add', array(), 'POST' );
  109. }
  110. /**
  111. * Add a contact to the segment
  112. *
  113. * @param int $segmentId Segment ID
  114. * @param int $contactId Contact ID
  115. *
  116. * @return array|mixed
  117. */
  118. public function addContactSegment($segmentId, $contactId)
  119. {
  120. return $this->makeRequest( 'segments/'.$segmentId.'/contact/'.$contactId.'/add', array(), 'POST' );
  121. }
  122. /**
  123. * Get campaigns list
  124. *
  125. * @param array $params
  126. * @return array|mixed
  127. */
  128. public function getCampaigns( array $params )
  129. {
  130. return $this->getList( 'campaigns', $params );
  131. }
  132. /**
  133. * Get segments list
  134. *
  135. * @param array $params
  136. * @return array|mixed
  137. */
  138. public function getSegments( array $params = array() )
  139. {
  140. return $this->getList( 'segments', $params );
  141. }
  142. /**
  143. * Get a list of items
  144. *
  145. * $params:
  146. * @param string $context
  147. * @param string $search
  148. * @param int $start
  149. * @param int $limit
  150. * @param string $orderBy
  151. * @param string $orderByDir
  152. * @param bool $publishedOnly
  153. * @param bool $minimal
  154. *
  155. * @return array|mixed
  156. */
  157. public function getList($context, array $params)
  158. {
  159. $parameters = array(
  160. 'search' => '',
  161. 'start' => 0,
  162. 'limit' => 0,
  163. 'orderBy' => '',
  164. 'orderByDir' => 'ASC',
  165. 'publishedOnly' => false,
  166. 'minimal' => false
  167. );
  168. $parameters = array_filter( array_unique( array_merge( $parameters, $params) ) );
  169. return $this->makeRequest( $context, $parameters );
  170. }
  171. /**
  172. * Set the base URL for API endpoints
  173. *
  174. * @param string $url
  175. *
  176. * @return $this
  177. */
  178. public function setBaseUrl($url)
  179. {
  180. if (substr($url, -1) != '/') {
  181. $url .= '/';
  182. }
  183. if (substr($url,-4,4) != 'api/') {
  184. $url .= 'api/';
  185. }
  186. $this->baseUrl = $url;
  187. return $this;
  188. }
  189. /**
  190. * Returns array of HTTP response headers
  191. *
  192. * @return array
  193. */
  194. public function getResponseHeaders()
  195. {
  196. return $this->parseHeaders($this->_httpResponseHeaders);
  197. }
  198. /**
  199. * Returns array of HTTP response headers
  200. *
  201. * @return array
  202. */
  203. public function getResponseInfo()
  204. {
  205. return $this->_httpResponseInfo;
  206. }
  207. /**
  208. * Log messages
  209. *
  210. * @param string $message [description]
  211. * @return [type] [description]
  212. */
  213. protected function log( $message )
  214. {
  215. $this->logs[] = $message;
  216. }
  217. /**
  218. * @param $url
  219. * @param array $headers
  220. * @param array $parameters
  221. * @param $method
  222. * @param array $settings
  223. *
  224. * @return array
  225. */
  226. protected function prepareRequest($url, array $headers, array $parameters, $method, array $settings)
  227. {
  228. //Set Basic Auth parameters/headers
  229. $headers = array_merge($headers, array($this->buildAuthorizationHeader(), 'Expect:'));
  230. return array($headers, $parameters);
  231. }
  232. /**
  233. * Build header for Basic Authentication
  234. *
  235. * @return string
  236. */
  237. private function buildAuthorizationHeader()
  238. {
  239. /*
  240. |--------------------------------------------------------------------------
  241. | Authorization Header
  242. |--------------------------------------------------------------------------
  243. |
  244. | Authorization is passed in the Header using Basic Authentication.
  245. |
  246. | Basically we take the username and password and seperate it with a
  247. | colon (:) and base 64 encode it:
  248. |
  249. | 'Authorization: Basic username:password'
  250. |
  251. | ==> with base64 encoding of the username and password
  252. |
  253. | 'Authorization: Basic dXNlcjpwYXNzd29yZA=='
  254. |
  255. */
  256. return 'Authorization: Basic ' . base64_encode($this->userName.':'.$this->password);
  257. }
  258. /**
  259. * Send API request
  260. *
  261. * @param string $context The type of context we are requesting from the host
  262. * @param array $values Request params
  263. * @return json|array
  264. */
  265. public function makeRequest($context, array $parameters = array(), $method = 'GET', array $settings = array())
  266. {
  267. $url = $this->baseUrl . $context;
  268. list($url, $parameters) = $this->separateUrlParams($url, $parameters);
  269. //make sure $method is capitalized for congruency
  270. $method = strtoupper($method);
  271. $headers = (isset($settings['headers']) && is_array($settings['headers'])) ? $settings['headers'] : array();
  272. list($headers, $parameters) = $this->prepareRequest($url, $headers, $parameters, $method, $settings);
  273. //Set default CURL options
  274. $options = array(
  275. CURLOPT_RETURNTRANSFER => true,
  276. CURLOPT_SSL_VERIFYPEER => false,
  277. //CURLOPT_SSL_VERIFYHOST => false,
  278. CURLOPT_HEADER => true
  279. );
  280. // CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set
  281. $options[CURLOPT_FOLLOWLOCATION] = (ini_get('open_basedir')) ? false : true;
  282. //Set custom REST method if not GET or POST
  283. if (!in_array($method, array('GET', 'POST'))) {
  284. $options[CURLOPT_CUSTOMREQUEST] = $method;
  285. }
  286. //Set post fields for POST/PUT/PATCH requests
  287. $isPost = false;
  288. if (in_array($method, array('POST', 'PUT', 'PATCH'))) {
  289. $isPost = true;
  290. $parameters = http_build_query($parameters, '', '&');
  291. $options[CURLOPT_POST] = true;
  292. $options[CURLOPT_POSTFIELDS] = $parameters;
  293. $this->log('Posted parameters = '.print_r($parameters, true));
  294. }
  295. $query = $this->getQueryParameters($isPost, $parameters);
  296. $this->log('Query parameters = '.print_r($query, true));
  297. //Create a query string for GET/DELETE requests
  298. if (count($query) > 0) {
  299. $queryGlue = strpos($url, '?') === false ? '?' : '&';
  300. $url = $url.$queryGlue.http_build_query($query);
  301. $this->log('URL updated to '.$url);
  302. }
  303. // Set the URL
  304. $options[CURLOPT_URL] = $url;
  305. $headers[] = 'Accept: application/json';
  306. $options[CURLOPT_HTTPHEADER] = $headers;
  307. //Make CURL request
  308. $curl = curl_init();
  309. curl_setopt_array($curl, $options);
  310. $response = curl_exec($curl);
  311. $responseArray = explode("\r\n\r\n", $response);
  312. $body = array_pop($responseArray);
  313. $this->_httpResponseHeaders = implode("\r\n\r\n", $responseArray);
  314. $this->_httpResponseInfo = curl_getinfo($curl);
  315. curl_close($curl);
  316. // Set response
  317. // $return = new Response(array(
  318. // 'code' => $httpResponseCode,
  319. // 'response' => $response
  320. // ));
  321. $responseGood = false;
  322. //Check to see if the response is JSON
  323. $parsed = json_decode($body, true);
  324. if ($parsed === null) {
  325. if (strpos($body, '=') !== false) {
  326. parse_str($body, $parsed);
  327. $responseGood = true;
  328. }
  329. } else {
  330. $responseGood = true;
  331. }
  332. //Show error when http_code is not appropriate
  333. if (!in_array($this->_httpResponseInfo['http_code'], array(200, 201))) {
  334. if ($responseGood) {
  335. return $parsed;
  336. }
  337. throw new Exception($body);
  338. }
  339. return ($responseGood) ? $parsed : $body;
  340. }
  341. /**
  342. * @param $isPost
  343. * @param $parameters
  344. *
  345. * @return array
  346. */
  347. protected function getQueryParameters($isPost, $parameters)
  348. {
  349. return ($isPost) ? array() : $parameters;
  350. }
  351. /**
  352. * Separates parameters from base URL
  353. *
  354. * @param $url
  355. * @param $params
  356. *
  357. * @return array
  358. */
  359. protected function separateUrlParams($url, $params)
  360. {
  361. $a = parse_url($url);
  362. if (!empty($a['query'])) {
  363. parse_str($a['query'], $qparts);
  364. $cleanParams = array();
  365. foreach ($qparts as $k => $v) {
  366. $cleanParams[$k] = $v ? $v : '';
  367. }
  368. $params = array_merge($params, $cleanParams);
  369. $urlParts = explode('?', $url, 2);
  370. $url = $urlParts[0];
  371. }
  372. return array($url, $params);
  373. }
  374. }