setApiKey($api_key); } } /** * @param $key * @return $this */ public function setApiKey($key) { $parts = str_getcsv($key, '-'); if (count($parts) == 2) { $this->data_center = $parts[1]; } $this->api_key = $parts[0]; return $this; } /** * @param $dc * @return $this */ public function setDataCenter($dc) { $this->data_center = $dc; return $this; } /** * @param $version * @return $this */ public function setVersion($version) { $this->version = $version; return $this; } /** * @param bool $return_profile * @param bool $throw_error * @return array|bool|mixed|null|object * @throws Exception */ public function ping($return_profile = false, $throw_error = false) { try { $profile = $this->get('/'); return $return_profile ? $profile : true; } catch (MailChimp_WooCommerce_Error $e) { if ($throw_error) { throw $e; } return false; } } /** * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getProfile() { return $this->get('/'); } /** * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getAuthorizedApps() { return $this->get('authorized-apps'); } /** * @param $id * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getAuthorizedAppDetails($id) { return $this->get("authorized-apps/$id"); } /** * @param $client_id * @param $client_secret * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function linkAuthorizedApp($client_id, $client_secret) { return $this->post('authorized-apps', array('client_id' => $client_id, 'client_secret' => $client_secret)); } /** * @param $list_id * @param $email * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function member($list_id, $email) { $hash = md5(strtolower(trim($email))); return $this->get("lists/$list_id/members/$hash", array()); } /** * @param $list_id * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function members($list_id) { return $this->get("lists/$list_id/members"); } /** * @param $list_id * @param $email * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function deleteMember($list_id, $email) { $hash = md5(strtolower(trim($email))); return (bool) $this->delete("lists/$list_id/members/$hash", array()); } /** * @param $list_id * @param $email * @param bool $subscribed * @param array $merge_fields * @param array $list_interests * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function subscribe($list_id, $email, $subscribed = true, $merge_fields = array(), $list_interests = array(), $language = null, $gdpr_fields = null) { if (is_string($subscribed)) { $status = $subscribed; } else { if ($subscribed === true) { $status = 'subscribed'; } elseif ($subscribed === false) { $status = 'pending'; } else { $status = 'transactional'; } } $data = array( 'email_type' => 'html', 'email_address' => $email, 'status' => $status, 'merge_fields' => $merge_fields, 'interests' => $list_interests, 'language' => $language, 'marketing_permissions' => $gdpr_fields, ); if (empty($data['merge_fields'])) { unset($data['merge_fields']); } if (empty($data['interests'])) { unset($data['interests']); } if (empty($data['language'])) { unset($data['language']); } if (empty($data['marketing_permissions'])) { unset($data['marketing_permissions']); } mailchimp_debug('api.subscribe', "Subscribing {$email}", $data); return $this->post("lists/$list_id/members?skip_merge_validation=true", $data); } /** * @param $list_id * @param $email * @param bool $subscribed * @param array $merge_fields * @param array $list_interests * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error */ public function update($list_id, $email, $subscribed = true, $merge_fields = array(), $list_interests = array(), $language = null, $gdpr_fields = null) { $hash = md5(strtolower(trim($email))); if ($subscribed === true) { $status = 'subscribed'; } elseif ($subscribed === false) { $status = 'unsubscribed'; } elseif ($subscribed === null) { $status = 'cleaned'; } else { $status = $subscribed; } $data = array( 'email_address' => $email, 'status' => $status, 'merge_fields' => $merge_fields, 'interests' => $list_interests, 'language' => $language, 'marketing_permissions' => $gdpr_fields, ); if (empty($data['merge_fields'])) { unset($data['merge_fields']); } if (empty($data['interests'])) { unset($data['interests']); } if (empty($data['language'])) { unset($data['language']); } if (empty($data['marketing_permissions'])) { unset($data['marketing_permissions']); } mailchimp_debug('api.update_member', "Updating {$email}", $data); return $this->patch("lists/$list_id/members/$hash?skip_merge_validation=true", $data); } /** * @param $list_id * @return mixed * @throws \Throwable */ public function getSubscribedCount($list_id) { if (empty($list_id)) { return 0; } return $this->get("lists/{$list_id}/members?status=subscribed&count=1")['total_items']; } /** * @param $list_id * @return mixed * @throws \Throwable */ public function getUnsubscribedCount($list_id) { if (empty($list_id)) { return 0; } return $this->get("lists/{$list_id}/members?status=unsubscribed&count=1")['total_items']; } /** * @param $list_id * @return mixed * @throws \Throwable */ public function getTransactionalCount($list_id) { if (empty($list_id)) { return 0; } return $this->get("lists/{$list_id}/members?status=transactional&count=1")['total_items']; } /** * @param $list_id * @param $email * @param bool $fail_silently * @param MailChimp_WooCommerce_Order $order * @return array|bool|mixed|object|null * @throws MailChimp_WooCommerce_Error|\Exception */ public function updateMemberTags($list_id, $email, $fail_silently = false, $order = null) { $hash = md5(strtolower(trim($email))); $tags = mailchimp_get_user_tags_to_update($email, $order); if (empty($tags)) return false; $data = array( 'tags' => $tags ); mailchimp_debug('api.update_member_tags', "Updating {$email}", $data); try { return $this->post("lists/$list_id/members/$hash/tags", $data); } catch (\Exception $e) { if (!$fail_silently) throw $e; } return false; } /** * @param $list_id * @param $email * @param bool $subscribed * @param array $merge_fields * @param array $list_interests * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function updateOrCreate($list_id, $email, $subscribed = true, $merge_fields = array(), $list_interests = array(), $language = null) { $hash = md5(strtolower(trim($email))); if ($subscribed === true) { $status = 'subscribed'; $status_if_new = 'subscribed'; } elseif ($subscribed === false) { $status = 'unsubscribed'; $status_if_new = 'pending'; } elseif ($subscribed === null) { $status = 'cleaned'; $status_if_new = 'subscribed'; } else { $status = $subscribed; $status_if_new = 'pending'; } $data = array( 'email_address' => $email, 'status' => $status, 'status_if_new' => $status_if_new, 'merge_fields' => $merge_fields, 'interests' => $list_interests, 'language' => $language ); if (empty($data['merge_fields'])) { unset($data['merge_fields']); } if (empty($data['interests'])) { unset($data['interests']); } if (empty($data['language'])) { unset($data['language']); } mailchimp_debug('api.update_or_create', "Update Or Create {$email}", $data); return $this->put("lists/$list_id/members/$hash", $data); } /** * @param MailChimp_WooCommerce_CreateListSubmission $submission * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function createList(MailChimp_WooCommerce_CreateListSubmission $submission) { return $this->post('lists', $submission->getSubmission()); } /** * @param string $list_id * @param MailChimp_WooCommerce_CreateListSubmission $submission * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function updateList($list_id, MailChimp_WooCommerce_CreateListSubmission $submission) { return $this->patch("lists/{$list_id}", $submission->getSubmission()); } /** * @param bool $as_list * @param int $count * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getLists($as_list = false, $count = 100) { $result = $this->get('lists', array('count' => $count)); if (!is_array($result)) { throw new MailChimp_WooCommerce_RateLimitError('getting lists api failure, retry again.'); } if ($as_list) { $lists = array(); if ($result) { $result = (object)$result; if (isset($result->lists) && is_array($result->lists)) { foreach ($result->lists as $list) { $list = (object)$list; $lists[$list->id] = $list->name; } } } return $lists; } return $result; } /** * @param $id * @return bool */ public function hasList($id) { try { return (bool) $this->getList($id); } catch (\Exception $e) { return false; } } /** * @param $id * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getList($id) { $result = $this->get('lists/' . $id); if (!is_array($result)) { throw new MailChimp_WooCommerce_RateLimitError('getting list api failure, retry again.'); } return $result; } /** * @param $id * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function deleteList($id) { return (bool) $this->delete('lists/'.$id); } /** * @return array|mixed * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getListsWithMergeFields() { $lists = $this->getLists(true); foreach ($lists as $id => $name) { $lists[$id] = $this->mergeFields($id, 100); } return $lists; } /** * @param $list_id * @param int $count * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function mergeFields($list_id, $count = 10) { $result = $this->get("lists/$list_id/merge-fields", array('count' => $count,)); if (!is_array($result)) { throw new MailChimp_WooCommerce_RateLimitError('getting merge field api failure, retry again.'); } return $result; } /** * @param $list_id * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getInterestGroups($list_id) { if (empty($list_id)) { return array(); } $result = $this->get("lists/$list_id/interest-categories"); return $result; } /** * @param $list_id * @param $group_id * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getInterestGroupOptions($list_id, $group_id) { if (empty($list_id) || empty($group_id)) { return array(); } $result = $this->get("lists/$list_id/interest-categories/$group_id/interests"); return $result; } /** * @param $store_id * @param int $page * @param int $count * @param DateTime|null $since * @param null $campaign_id * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function orders($store_id, $page = 1, $count = 10, \DateTime $since = null, $campaign_id = null) { $result = $this->get('ecommerce/stores/'.$store_id.'/orders', array( 'start' => $page, 'count' => $count, 'offset' => ($page * $count), 'since' => ($since ? $since->format('Y-m-d H:i:s') : null), 'cid' => $campaign_id, )); return $result; } /** * @param $store_id * @return int|mixed * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getOrderCount($store_id) { $data = $this->get("ecommerce/stores/{$store_id}/orders?count=1"); if (!is_array($data)) { return 0; } return $data['total_items']; } /** * @param $store_id * @param bool $throw * @return bool|MailChimp_WooCommerce_Store * @throws MailChimp_WooCommerce_Error */ public function getStore($store_id, $throw = false) { try { $data = $this->get("ecommerce/stores/$store_id"); if (!is_array($data)) { throw new MailChimp_WooCommerce_RateLimitError('getting store api failure, retry again.'); } if (!isset($data['id']) || !isset($data['name'])) { return false; } $store = new MailChimp_WooCommerce_Store(); return $store->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if ($throw) throw $e; return false; } catch (\Exception $e) { if ($throw) throw $e; return false; } } /** * @param $campaign_id * @param bool $throw_if_invalid * @return array|bool|mixed|object|null * @throws Exception */ public function getCampaign($campaign_id, $throw_if_invalid = true) { // don't let an empty campaign ID do anything if (empty($campaign_id)) return false; // if we found the campaign ID already and it's been stored in the cache, return it from the cache instead. if (($data = get_site_transient('mailchimp-woocommerce-has-campaign-id-'.$campaign_id)) && !empty($data)) { return $data; } if (get_site_transient('mailchimp-woocommerce-no-campaign-id-'.$campaign_id)) { return false; } try { $data = $this->get("campaigns/$campaign_id"); delete_site_transient('mailchimp-woocommerce-no-campaign-id-'.$campaign_id); set_site_transient('mailchimp-woocommerce-has-campaign-id-'.$campaign_id, $data, 60 * 30); return $data; } catch (\Exception $e) { mailchimp_debug('campaign_get.error', 'No campaign with provided ID: '. $campaign_id. ' :: '. $e->getMessage(). ' :: in '.$e->getFile().' :: on '.$e->getLine()); set_site_transient('mailchimp-woocommerce-no-campaign-id-'.$campaign_id, true, 60 * 30); if (!$throw_if_invalid) { return false; } throw $e; } } /** * @param $store_id * @return array|bool */ public function checkConnectedSite($store_id) { try { return $this->get("connected-sites/{$store_id}"); } catch (MailChimp_WooCommerce_Error $e) { return false; } catch (\Exception $e) { return false; } } /** * @param $store_id * @return array|bool|mixed|null|object */ public function connectSite($store_id) { try { return $this->post("connected-sites/{$store_id}/actions/verify-script-installation", array()); } catch (MailChimp_WooCommerce_Error $e) { return false; } catch (\Exception $e) { return false; } } /** * @return array|bool */ public function stores() { try { $data = $this->get("ecommerce/stores", array('count' => 1000)); if (!isset($data['stores']) || empty($data['stores']) || !is_array($data['stores'])) { return array(); } $response = array(); foreach ($data['stores'] as $store_data) { $store = new MailChimp_WooCommerce_Store(); $response[] = $store->fromArray($store_data); } return $response; } catch (MailChimp_WooCommerce_Error $e) { return false; } catch (\Exception $e) { return false; } } /** * @param $store_id * @param $is_syncing * @return array|bool|mixed|null|object */ public function flagStoreSync($store_id, $is_syncing) { try { // pull the store to make sure we have one. if (!($store = $this->getStore($store_id))) { return false; } // flag it as ^^^ is_syncing ^^^ $store->flagSyncing($is_syncing); // patch the store data return $this->patch("ecommerce/stores/{$store_id}", $store->toArray()); } catch (\Exception $e) { mailchimp_log('flag.store_sync', $e->getMessage(). ' :: in '.$e->getFile().' :: on '.$e->getLine()); } return false; } /** * @param MailChimp_WooCommerce_Store $store * @param bool $silent * @return bool|MailChimp_WooCommerce_Store * @throws Exception */ public function addStore(MailChimp_WooCommerce_Store $store, $silent = true) { try { $this->validateStoreSubmission($store); $data = $this->post("ecommerce/stores", $store->toArray()); $store = new MailChimp_WooCommerce_Store(); return $store->fromArray($data); } catch (\Exception $e) { if (!$silent) throw $e; return false; } } /** * @param MailChimp_WooCommerce_Store $store * @param bool $silent * @return bool|MailChimp_WooCommerce_Store * @throws Exception */ public function updateStore(MailChimp_WooCommerce_Store $store, $silent = true) { try { $this->validateStoreSubmission($store); $data = $this->patch("ecommerce/stores/{$store->getId()}", $store->toArray()); $store = new MailChimp_WooCommerce_Store(); return $store->fromArray($data); } catch (\Exception $e) { if (!$silent) throw $e; return false; } } /** * @param $store_id * @return bool */ public function deleteStore($store_id) { try { return (bool) $this->delete("ecommerce/stores/$store_id"); } catch (MailChimp_WooCommerce_Error $e) { mailchimp_error("delete_store {$store_id}", $e->getMessage()); return false; } catch (\Exception $e) { mailchimp_error("delete_store {$store_id}", $e->getMessage()); return false; } } /** * @param $store_id * @param $customer_id * @param boolean $throw * @return bool|MailChimp_WooCommerce_Customer * @throws Exception */ public function getCustomer($store_id, $customer_id, $throw = false) { try { $data = $this->get("ecommerce/stores/$store_id/customers/$customer_id"); if (!is_array($data)) { throw new MailChimp_WooCommerce_RateLimitError('getting customer api failure, retry again.'); } $customer = new MailChimp_WooCommerce_Customer(); return $customer->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if ($throw) throw $e; return false; } } /** * @param MailChimp_WooCommerce_Customer $customer * @return bool|MailChimp_WooCommerce_Customer * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function addCustomer(MailChimp_WooCommerce_Customer $customer) { if (!($this->validateStoreSubmission($customer))) { return false; } $data = $this->post("ecommerce/stores", $customer->toArray()); if (!is_array($data)) { throw new MailChimp_WooCommerce_RateLimitError('adding customer api failure, retry again.'); } $customer = new MailChimp_WooCommerce_Customer(); return $customer->fromArray($data); } /** * @param $store_id * @param int $page * @param int $count * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function carts($store_id, $page = 1, $count = 10) { $result = $this->get('ecommerce/stores/'.$store_id.'/carts', array( 'start' => $page, 'count' => $count, 'offset' => ($page * $count), )); return $result; } /** * @param $store_id * @param MailChimp_WooCommerce_Cart $cart * @param bool $silent * @return bool|MailChimp_WooCommerce_Cart * @throws Exception * @throws MailChimp_WooCommerce_Error */ public function addCart($store_id, MailChimp_WooCommerce_Cart $cart, $silent = true) { try { $email = $cart->getCustomer()->getEmailAddress(); if (mailchimp_email_is_privacy_protected($email) || mailchimp_email_is_amazon($email)) { return false; } mailchimp_debug('api.addCart', "Adding Cart :: {$email}", $data = $cart->toArray()); $data = $this->post("ecommerce/stores/$store_id/carts", $data); $cart = new MailChimp_WooCommerce_Cart(); return $cart->setStoreID($store_id)->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if (!$silent) throw $e; mailchimp_log('api.addCart', $e->getMessage()); return false; } catch (\Exception $e) { if (!$silent) throw $e; return false; } } /** * @param $store_id * @param MailChimp_WooCommerce_Cart $cart * @param bool $silent * @return bool|MailChimp_WooCommerce_Cart * @throws Exception * @throws MailChimp_WooCommerce_Error */ public function updateCart($store_id, MailChimp_WooCommerce_Cart $cart, $silent = true) { try { $email = $cart->getCustomer()->getEmailAddress(); if (mailchimp_email_is_privacy_protected($email) || mailchimp_email_is_amazon($email)) { return false; } mailchimp_debug('api.updateCart', "Updating Cart :: {$email}", $data = $cart->toArrayForUpdate()); $data = $this->patch("ecommerce/stores/$store_id/carts/{$cart->getId()}", $data); $cart = new MailChimp_WooCommerce_Cart(); return $cart->setStoreID($store_id)->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if (!$silent) throw $e; mailchimp_log('api.updateCart', $e->getMessage()); return false; } catch (\Exception $e) { if (!$silent) throw $e; return false; } } /** * @param $store_id * @param $id * @return bool|MailChimp_WooCommerce_Cart */ public function getCart($store_id, $id) { try { $data = $this->get("ecommerce/stores/$store_id/carts/$id"); $cart = new MailChimp_WooCommerce_Cart(); return $cart->setStoreID($store_id)->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { return false; } catch (\Exception $e) { return false; } } /** * @param $store_id * @param $id * @return bool */ public function deleteCartByID($store_id, $id) { try { return (bool) $this->delete("ecommerce/stores/$store_id/carts/$id"); } catch (MailChimp_WooCommerce_Error $e) { return false; } catch (\Exception $e) { return false; } } /** * @param $store_id * @param MailChimp_WooCommerce_Customer $customer * @param bool $silent * @return bool|MailChimp_WooCommerce_Customer * @throws Exception * @throws MailChimp_WooCommerce_Error */ public function updateCustomer($store_id, MailChimp_WooCommerce_Customer $customer, $silent = true) { try { if (!$this->validateStoreSubmission($customer)) { return false; } $data = $this->patch("ecommerce/stores/$store_id/customers/{$customer->getId()}", $customer->toArray()); $customer = new MailChimp_WooCommerce_Customer(); return $customer->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if (!$silent) throw $e; return false; } } /** * @param $store_id * @param $customer_id * @return bool * @throws Exception */ public function deleteCustomer($store_id, $customer_id) { try { return (bool) $this->delete("ecommerce/stores/$store_id/customers/$customer_id"); } catch (MailChimp_WooCommerce_Error $e) { return false; } } /** * @param $store_id * @param MailChimp_WooCommerce_Order $order * @param bool $silent * @return bool|MailChimp_WooCommerce_Order * @throws Exception */ public function addStoreOrder($store_id, MailChimp_WooCommerce_Order $order, $silent = true) { try { if (!$this->validateStoreSubmission($order)) { return false; } // submit the first one $data = $this->post("ecommerce/stores/$store_id/orders", $order->toArray()); $email_address = $order->getCustomer()->getEmailAddress(); // if the order is in pending status, we need to submit the order again with a paid status. if ($order->shouldConfirmAndPay() && $order->getFinancialStatus() !== 'paid') { $order->setFinancialStatus('paid'); $data = $this->patch("ecommerce/stores/{$store_id}/orders/{$order->getId()}", $order->toArray()); } // update the member tags but fail silently just in case. $this->updateMemberTags(mailchimp_get_list_id(), $email_address, true, $order); update_option('mailchimp-woocommerce-resource-last-updated', time()); $order = new MailChimp_WooCommerce_Order(); return $order->fromArray($data); } catch (\Exception $e) { if (!$silent) throw $e; mailchimp_log('api.add_order.error', $e->getMessage(), array('submission' => $order->toArray())); return false; } } /** * @param $store_id * @param MailChimp_WooCommerce_Order $order * @param bool $silent * @return bool|MailChimp_WooCommerce_Order * @throws Exception */ public function updateStoreOrder($store_id, MailChimp_WooCommerce_Order $order, $silent = true) { try { if (!$this->validateStoreSubmission($order)) { return false; } $order_id = $order->getId(); $data = $this->patch("ecommerce/stores/{$store_id}/orders/{$order_id}", $order->toArray()); //update user tags $email_address = $order->getCustomer()->getEmailAddress(); // if products list differs, we should remove the old products and add new ones $data_lines = $data['lines']; $order_lines = $order->getLinesIds(); foreach ($data_lines as $line) { if (!in_array($line['id'], $order_lines)) { $this->deleteStoreOrderLine($store_id, $order_id, $line['id']); } } // if the order is in pending status, we need to submit the order again with a paid status. if ($order->shouldConfirmAndPay() && $order->getFinancialStatus() !== 'paid') { $order->setFinancialStatus('paid'); $data = $this->patch("ecommerce/stores/{$store_id}/orders/{$order_id}", $order->toArray()); } // update the member tags but fail silently just in case. $this->updateMemberTags(mailchimp_get_list_id(), $email_address, true, $order); $order = new MailChimp_WooCommerce_Order(); return $order->fromArray($data); } catch (\Exception $e) { if (!$silent) throw $e; mailchimp_log('api.update_order.error', $e->getMessage(), array('submission' => $order->toArray())); return false; } } /** * @param $store_id * @param $order_id * @param boolean $throw * @return bool|MailChimp_WooCommerce_Order * @throws Exception */ public function getStoreOrder($store_id, $order_id, $throw = false) { try { $data = $this->get("ecommerce/stores/$store_id/orders/$order_id"); if (!is_array($data)) { throw new MailChimp_WooCommerce_RateLimitError('getting order api failure, retry again.'); } $order = new MailChimp_WooCommerce_Order(); return $order->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if ($throw) throw $e; return false; } } /** * @param $store_id * @param $order_id * @return bool * @throws Exception */ public function deleteStoreOrder($store_id, $order_id) { try { return (bool) $this->delete("ecommerce/stores/$store_id/orders/$order_id"); } catch (MailChimp_WooCommerce_Error $e) { return false; } } /** * @param $store_id * @param $order_id * @param $line_id * @return bool * @throws Exception */ public function deleteStoreOrderLine($store_id, $order_id, $line_id) { try { return (bool) $this->delete("ecommerce/stores/{$store_id}/orders/{$order_id}/lines/{$line_id}"); } catch (MailChimp_WooCommerce_Error $e) { return false; } } /** * @param $store_id * @param $product_id * @param boolean $throw * @return bool|MailChimp_WooCommerce_Product * @throws Exception */ public function getStoreProduct($store_id, $product_id, $throw = false) { try { $data = $this->get("ecommerce/stores/$store_id/products/$product_id"); if (!is_array($data)) { throw new MailChimp_WooCommerce_RateLimitError('getting product api failure, retry again.'); } $product = new MailChimp_WooCommerce_Product(); return $product->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if ($throw) throw $e; return false; } } /** * @param $store_id * @param int $page * @param int $count * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function products($store_id, $page = 1, $count = 10) { $result = $this->get('ecommerce/stores/'.$store_id.'/products', array( 'start' => $page, 'count' => $count, 'offset' => ($page * $count), )); return $result; } /** * @param $store_id * @param MailChimp_WooCommerce_Product $product * @param bool $silent * @return bool|MailChimp_WooCommerce_Product * @throws Exception */ public function addStoreProduct($store_id, MailChimp_WooCommerce_Product $product, $silent = true) { try { if (!$this->validateStoreSubmission($product)) { return false; } $data = $this->post("ecommerce/stores/$store_id/products", $product->toArray()); update_option('mailchimp-woocommerce-resource-last-updated', time()); $product = new MailChimp_WooCommerce_Product(); return $product->fromArray($data); } catch (\Exception $e) { if (!$silent) throw $e; mailchimp_log('api.add_product.error', $e->getMessage(), array('submission' => $product->toArray())); return false; } } /** * @param $store_id * @param MailChimp_WooCommerce_Product $product * @param bool $silent * @return bool|MailChimp_WooCommerce_Product * @throws Exception */ public function updateStoreProduct($store_id, MailChimp_WooCommerce_Product $product, $silent = true) { try { if (!$this->validateStoreSubmission($product)) { return false; } $data = $this->patch("ecommerce/stores/$store_id/products/{$product->getId()}", $product->toArray()); update_option('mailchimp-woocommerce-resource-last-updated', time()); $product = new MailChimp_WooCommerce_Product(); return $product->fromArray($data); } catch (\Exception $e) { if (!$silent) throw $e; mailchimp_log('api.update_product.error', $e->getMessage(), array('submission' => $product->toArray())); return false; } } /** * @param MailChimp_WooCommerce_Order $order * @return array */ public function handleProductsMissingFromAPI(MailChimp_WooCommerce_Order $order) { $missing_products = array(); foreach ($order->items() as $order_item) { /** @var \MailChimp_WooCommerce_LineItem $order_item */ // get the line item name from the order detail just in case we need that title for the product. $job = new MailChimp_WooCommerce_Single_Product($order_item->getProductId(), $order_item->getFallbackTitle()); if ($missing_products[$order_item->getId()] = $job->createModeOnly()->fromOrderItem($order_item)->handle()) { mailchimp_debug("missing_products.fallback", "Product {$order_item->getId()} had to be re-pushed into Mailchimp"); } } return $missing_products; } /** * @return MailChimp_WooCommerce_Product */ public function createEmptyLineItemProductPlaceholder() { $product = new MailChimp_WooCommerce_Product(); $product->setId('empty_line_item_placeholder'); $product->setTitle('Empty Line Item Placeholder'); $product->setVendor('deleted'); $variation = new MailChimp_WooCommerce_ProductVariation(); $variation->setId($product->getId()); $variation->setTitle($product->getTitle()); $variation->setInventoryQuantity(0); $variation->setVisibility('hidden'); $variation->setPrice(1); $product->addVariant($variation); if ((bool) mailchimp_get_data('empty_line_item_placeholder', false)) { return $product; } $store_id = mailchimp_get_store_id(); $api = mailchimp_get_api(); try { $response = $api->addStoreProduct($store_id, $product); mailchimp_set_data('empty_line_item_placeholder', true, 'yes'); return $response; } catch (\Exception $e) { return $product; } } /** * @param $store_id * @param $product_id * @return bool * @throws Exception */ public function deleteStoreProduct($store_id, $product_id) { try { return (bool) $this->delete("ecommerce/stores/$store_id/products/$product_id"); } catch (MailChimp_WooCommerce_Error $e) { return false; } } /** * @param $store_id * @param MailChimp_WooCommerce_PromoRule $rule * @param bool $throw * @return bool|MailChimp_WooCommerce_PromoRule * @throws Exception * @throws MailChimp_WooCommerce_Error */ public function addPromoRule($store_id, MailChimp_WooCommerce_PromoRule $rule, $throw = true) { try { if (($response = $this->updatePromoRule($store_id, $rule, false))) { return $response; } $data = $this->post("ecommerce/stores/{$store_id}/promo-rules", $rule->toArray()); return (new MailChimp_WooCommerce_PromoRule)->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if ($throw) throw $e; return false; } } /** * @param $store_id * @param MailChimp_WooCommerce_PromoRule $rule * @param bool $throw * @return bool|MailChimp_WooCommerce_PromoRule * @throws Exception * @throws MailChimp_WooCommerce_Error */ public function updatePromoRule($store_id, MailChimp_WooCommerce_PromoRule $rule, $throw = true) { try { $data = $this->patch("ecommerce/stores/{$store_id}/promo-rules/{$rule->getId()}", $rule->toArray()); return (new MailChimp_WooCommerce_PromoRule)->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if ($throw) throw $e; return false; } } /** * @param $store_id * @param $rule * @return bool * @throws Exception */ public function deletePromoRule($store_id, $rule) { try { $id = $rule instanceof MailChimp_WooCommerce_PromoRule ? $rule->getId() : $rule; //print_r(array('id' => $id, 'store' => $store_id));die(); return (bool) $this->delete("ecommerce/stores/{$store_id}/promo-rules/{$id}"); } catch (MailChimp_WooCommerce_Error $e) { //\Log::error("MC::deletePromoRule :: {$rule->getId()} :: {$e->getMessage()} on {$e->getLine()} in {$e->getFile()}"); return false; } } /** * @param $store_id * @param int $page * @param int $count * @return array * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getPromoRuleIds($store_id, $page = 1, $count = 10) { $result = $this->get("ecommerce/stores/{$store_id}/promo-rules", [ 'start' => $page, 'count' => $count, 'offset' => $page > 1 ? (($page-1) * $count) : 0, 'include' => 'id', ]); $ids = array(); foreach ($result['promo_rules'] as $rule) { $id = (string) $rule['id']; $ids[$id] = $id; } return $ids; } /** * @param $store_id * @param int $page * @param int $count * @param bool $return_original * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getPromoRules($store_id, $page = 1, $count = 10, $return_original = false) { $result = $this->get("ecommerce/stores/{$store_id}/promo-rules", [ 'start' => $page, 'count' => $count, 'offset' => $page > 1 ? (($page-1) * $count) : 0, ]); if ($return_original) { return $result; } $rules = array(); foreach ($result['promo_rules'] as $rule_data) { $rule = new MailChimp_WooCommerce_PromoRule(); $rule->fromArray($rule_data); $rules[] = $rule; } return $rules; } /** * @param $store_id * @param $rule_id * @param int $page * @param int $count * @param bool $return_original * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ public function getPromoCodesForRule($store_id, $rule_id, $page = 1, $count = 10, $return_original = false) { $result = $this->get("ecommerce/stores/{$store_id}/promo-rules/{$rule_id}/promo_codes", [ 'start' => $page, 'count' => $count, 'offset' => $page > 1 ? (($page-1) * $count) : 0, ]); if ($return_original) { return $result; } $rules = array(); foreach ($result as $rule_data) { $rule = new MailChimp_WooCommerce_PromoCode(); $rule->fromArray($rule_data); $rules[] = $rule; } return $rules; } /** * @param $store_id * @param $rule_id * @param $code_id * @return bool|MailChimp_WooCommerce_PromoCode * @throws Exception */ public function getPromoCodeForRule($store_id, $rule_id, $code_id) { try { $data = $this->get("ecommerce/stores/{$store_id}/promo-rules/{$rule_id}/promo-codes/{$code_id}"); return (new MailChimp_WooCommerce_PromoCode)->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { return false; } } /** * @param $store_id * @param MailChimp_WooCommerce_PromoRule $rule * @param MailChimp_WooCommerce_PromoCode $code * @param bool $throw * @return bool|MailChimp_WooCommerce_PromoCode * @throws Exception * @throws MailChimp_WooCommerce_Error */ public function addPromoCodeForRule($store_id, MailChimp_WooCommerce_PromoRule $rule, MailChimp_WooCommerce_PromoCode $code, $throw = true) { try { if (($result = $this->updatePromoCodeForRule($store_id, $rule, $code, false))) { return $result; } $data = $this->post("ecommerce/stores/{$store_id}/promo-rules/{$rule->getId()}/promo-codes", $code->toArray()); return (new MailChimp_WooCommerce_PromoCode)->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if ($throw) throw $e; return false; } } /** * @param $store_id * @param MailChimp_WooCommerce_PromoRule $rule * @param MailChimp_WooCommerce_PromoCode $code * @param bool $throw * @return bool|MailChimp_WooCommerce_PromoCode * @throws Exception * @throws MailChimp_WooCommerce_Error */ public function updatePromoCodeForRule($store_id, MailChimp_WooCommerce_PromoRule $rule, MailChimp_WooCommerce_PromoCode $code, $throw = true) { try { $data = $this->patch("ecommerce/stores/{$store_id}/promo-rules/{$rule->getId()}/promo-codes/{$code->getId()}", $code->toArray()); return (new MailChimp_WooCommerce_PromoCode)->fromArray($data); } catch (MailChimp_WooCommerce_Error $e) { if ($throw) throw $e; return false; } } /** * @param $store_id * @param $rule_id * @param $code_id * @return bool */ public function deletePromoCodeForRule($store_id, $rule_id, $code_id) { try { return (bool) $this->delete("ecommerce/stores/{$store_id}/promo-rules/{$rule_id}/promo-codes/{$code_id}"); } catch (MailChimp_WooCommerce_Error $e) { return false; } catch (\Exception $e) { return false; } } /** * @param $target * @return bool */ protected function validateStoreSubmission($target) { if ($target instanceof MailChimp_WooCommerce_Order) { return $this->validateStoreOrder($target); } else if ($target instanceof MailChimp_WooCommerce_Customer) { return $this->validateStoreCustomer($target); } return true; } /** * @param MailChimp_WooCommerce_Order $order * @return bool */ protected function validateStoreOrder(MailChimp_WooCommerce_Order $order) { if (!$this->validateStoreCustomer($order->getCustomer())) { return false; } return true; } /** * @param MailChimp_WooCommerce_Customer $customer * @return bool */ protected function validateStoreCustomer(MailChimp_WooCommerce_Customer $customer) { $email = $customer->getEmailAddress(); if (!is_email($email) || mailchimp_email_is_amazon($email) || mailchimp_email_is_privacy_protected($email)) { return false; } return true; } /** * @param string $list_id * @param int $minutes * @return false|mixed */ public function getCachedGDPRFields($list_id, $minutes = 5) { $transient = "mailchimp-woocommerce-gdpr-fields.{$list_id}"; $GDPRfields = get_site_transient($transient); // only return the values if it's a false - or an array if (is_array($GDPRfields)) return $GDPRfields; try { $GDPRfields = $this->getGDPRFields($list_id); set_site_transient($transient, $GDPRfields, 60 * $minutes); } catch (\Exception $e) { $GDPRfields = array(); } return $GDPRfields; } /** * @param * @return */ public function getGDPRFields($list_id) { $one_member = $this->get("lists/$list_id/members?fields=members.marketing_permissions&count=1"); $fields = false; if (is_array($one_member) && isset($one_member['members']) && isset($one_member['members'][0]) && isset($one_member['members'][0]['marketing_permissions'])) { $fields = $one_member['members'][0]['marketing_permissions']; } return $fields; } /** * @param $url * @param null $params * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ protected function delete($url, $params = null) { $curl = curl_init(); $options = $this->applyCurlOptions('DELETE', $url, $params); curl_setopt_array($curl, $options); return $this->processCurlResponse($curl); } /** * @param $url * @param null $params * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ protected function get($url, $params = null) { $curl = curl_init(); $options = $this->applyCurlOptions('GET', $url, $params); curl_setopt_array($curl, $options); return $this->processCurlResponse($curl); } /** * @param $url * @param $body * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error */ protected function patch($url, $body) { // process the patch request the normal way $curl = curl_init(); $json = json_encode($body); $options = $this->applyCurlOptions('PATCH', $url, array(), array( 'Expect:', 'Content-Length: '.strlen($json), )); $options[CURLOPT_POSTFIELDS] = $json; curl_setopt_array($curl, $options); return $this->processCurlResponse($curl); } /** * @param $url * @param $body * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ protected function post($url, $body) { $curl = curl_init(); $json = json_encode($body); $options = $this->applyCurlOptions('POST', $url, array(), array( 'Expect:', 'Content-Length: '.strlen($json), )); $options[CURLOPT_POSTFIELDS] = $json; curl_setopt_array($curl, $options); return $this->processCurlResponse($curl); } /** * @param $url * @param $body * @return array|mixed|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ protected function put($url, $body) { $curl = curl_init(); $json = json_encode($body); $options = $this->applyCurlOptions('PUT', $url, array(), array( 'Expect:', 'Content-Length: '.strlen($json), )); $options[CURLOPT_POSTFIELDS] = $json; curl_setopt_array($curl, $options); return $this->processCurlResponse($curl); } /** * @param string $extra * @param null|array $params * @return string */ protected function url($extra = '', $params = null) { $url = "https://{$this->data_center}.api.mailchimp.com/{$this->version}/"; if (!empty($extra)) { $url .= $extra; } if (!empty($params)) { $url .= '?'.(is_array($params) ? http_build_query($params) : $params); } return $url; } /** * @param $method * @param $url * @param array $params * @param array $headers * @return array */ protected function applyCurlOptions($method, $url, $params = array(), $headers = array()) { $env = mailchimp_environment_variables(); $curl_options = array( CURLOPT_USERPWD => "mailchimp:{$this->api_key}", CURLOPT_CUSTOMREQUEST => strtoupper($method), CURLOPT_URL => $this->url($url, $params), CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLINFO_HEADER_OUT => true, CURLOPT_HTTPHEADER => array_merge(array( 'content-type: application/json', 'accept: application/json', "user-agent: MailChimp for WooCommerce/{$env->version}; PHP/{$env->php_version}; WordPress/{$env->wp_version}; Woo/{$env->wc_version};", ), $headers) ); // if we have a dedicated IP address, and have set a configuration for it, we'll use it here. if (defined('MAILCHIMP_USE_OUTBOUND_IP')) { $curl_options[CURLOPT_INTERFACE] = MAILCHIMP_USE_OUTBOUND_IP; } // if we need to define a specific http version being used for curl requests, we can override this here. if (defined('MAILCHIMP_USE_HTTP_VERSION')) { $curl_options[CURLOPT_HTTP_VERSION] = MAILCHIMP_USE_HTTP_VERSION; } return $curl_options; } /** * @param $curl * @return array|mixed|bool|null|object * @throws Exception * @throws MailChimp_WooCommerce_Error * @throws MailChimp_WooCommerce_ServerError */ protected function processCurlResponse($curl) { $response = curl_exec($curl); $err = curl_error($curl); $info = curl_getinfo($curl); curl_close($curl); if ($err) { throw new MailChimp_WooCommerce_Error('CURL error :: '.$err, '500'); } $data = json_decode($response, true); $http_code = !empty($info) && isset($info['http_code']) ? $info['http_code'] : -1; $called_url = !empty($info) && isset($info['url']) ? $info['url'] : 'none'; // let's block these from doing anything below because the API seems to be having trouble. if ($http_code <= 99) { throw new MailChimp_WooCommerce_RateLimitError('API is failing - try again.'); } // possibily a successful DELETE operation if ($http_code == 204) { return true; } if ($http_code >= 200 && $http_code <= 400) { if (is_array($data)) { try { $this->checkForErrors($data); } catch (\Exception $e) { throw $e; } } return $data; } if ($http_code >= 400 && $http_code <= 500) { if ($http_code == 403) { throw new MailChimp_WooCommerce_RateLimitError(); } throw new MailChimp_WooCommerce_Error($data['title'] .' :: '.$data['detail'], $data['status']); } if ($http_code >= 500) { throw new MailChimp_WooCommerce_ServerError($data['detail'], $data['status']); } if (!is_array($data)) { mailchimp_error("api.debug", 'fallback when data is empty from API', array('url' => $called_url, 'response' => $response)); throw new MailChimp_WooCommerce_ServerError('API response could not be decoded.'); } return null; } /** * @param array $data * @return bool * @throws MailChimp_WooCommerce_Error */ protected function checkForErrors(array $data) { // if we have an array of error data push it into a message if (isset($data['errors'])) { $message = ''; foreach ($data['errors'] as $error) { $message .= '
'.$error['field'].': '.$error['message'].'
'; } throw new MailChimp_WooCommerce_Error($message, $data['status']); } // make sure the response is correct from the data in the response array if (isset($data['status']) && $data['status'] >= 400) { if (isset($data['http_code']) && $data['http_code'] == 403) { throw new MailChimp_WooCommerce_RateLimitError(); } throw new MailChimp_WooCommerce_Error($data['detail'], $data['status']); } return false; } }