Added login request

This commit is contained in:
Nedim Uka
2018-06-20 18:03:43 +02:00
parent 4e52521fae
commit 593b445a21
4716 changed files with 1218265 additions and 57 deletions

View File

@@ -0,0 +1,337 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:22 PM
*/
class MailChimp_WooCommerce_Address
{
protected $type;
protected $name;
protected $address1;
protected $address2;
protected $city;
protected $province;
protected $province_code;
protected $postal_code;
protected $country;
protected $country_code;
protected $longitude;
protected $latitude;
protected $phone;
protected $company;
/**
* @return array
*/
public function getValidation()
{
return array(
'address1' => 'string',
'address2' => 'string',
'city' => 'string',
'province' => 'string',
'province_code' => 'string|digits:2',
'postal_code' => 'string',
'country' => 'string',
'country_code' => 'string|digits:2',
'latitude' => 'numeric',
'longitude' => 'numeric',
);
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
* @return MailChimp_WooCommerce_Address
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return mixed
*/
public function getAddress1()
{
return $this->address1;
}
/**
* @param mixed $address1
* @return MailChimp_WooCommerce_Address
*/
public function setAddress1($address1)
{
$this->address1 = $address1;
return $this;
}
/**
* @return mixed
*/
public function getAddress2()
{
return $this->address2;
}
/**
* @param mixed $address2
* @return MailChimp_WooCommerce_Address
*/
public function setAddress2($address2)
{
$this->address2 = $address2;
return $this;
}
/**
* @return mixed
*/
public function getCity()
{
return $this->city;
}
/**
* @param mixed $city
* @return MailChimp_WooCommerce_Address
*/
public function setCity($city)
{
$this->city = $city;
return $this;
}
/**
* @return mixed
*/
public function getProvince()
{
return $this->province;
}
/**
* @param mixed $province
* @return MailChimp_WooCommerce_Address
*/
public function setProvince($province)
{
$this->province = $province;
return $this;
}
/**
* @return mixed
*/
public function getProvinceCode()
{
return $this->province_code;
}
/**
* @param mixed $province_code
* @return MailChimp_WooCommerce_Address
*/
public function setProvinceCode($province_code)
{
$this->province_code = $province_code;
return $this;
}
/**
* @return mixed
*/
public function getPostalCode()
{
return $this->postal_code;
}
/**
* @param mixed $postal_code
* @return MailChimp_WooCommerce_Address
*/
public function setPostalCode($postal_code)
{
$this->postal_code = $postal_code;
return $this;
}
/**
* @return mixed
*/
public function getCountry()
{
return $this->country;
}
/**
* @param mixed $country
* @return MailChimp_WooCommerce_Address
*/
public function setCountry($country)
{
$this->country = $country;
return $this;
}
/**
* @return mixed
*/
public function getCountryCode()
{
return $this->country_code;
}
/**
* @param mixed $country_code
* @return MailChimp_WooCommerce_Address
*/
public function setCountryCode($country_code)
{
$this->country_code = $country_code;
return $this;
}
/**
* @return mixed
*/
public function getLongitude()
{
return $this->longitude;
}
/**
* @param mixed $longitude
* @return MailChimp_WooCommerce_Address
*/
public function setLongitude($longitude)
{
$this->longitude = $longitude;
return $this;
}
/**
* @return mixed
*/
public function getLatitude()
{
return $this->latitude;
}
/**
* @param mixed $latitude
* @return MailChimp_WooCommerce_Address
*/
public function setLatitude($latitude)
{
$this->latitude = $latitude;
return $this;
}
/**
* @return mixed
*/
public function getPhone()
{
return $this->phone;
}
/**
* @param mixed $phone
* @return MailChimp_WooCommerce_Address
*/
public function setPhone($phone)
{
$this->phone = $phone;
return $this;
}
/**
* @return mixed
*/
public function getCompany()
{
return $this->company;
}
/**
* @param mixed $company
* @return MailChimp_WooCommerce_Address
*/
public function setCompany($company)
{
$this->company = $company;
return $this;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'name' => (string) $this->name,
'address1' => (string) $this->address1,
'address2' => (string) $this->address2,
'city' => (string) $this->city,
'province' => (string) $this->province,
'province_code' => (string) $this->province_code,
'postal_code' => (string) $this->postal_code,
'country' => (string) $this->country,
'country_code' => (string) $this->country_code,
'longitude' => ($this->longitude ? (int) $this->longitude : null),
'latitude' => ($this->latitude ? (int) $this->latitude : null),
'phone' => (string) $this->phone,
'company' => (string) $this->company,
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Address
*/
public function fromArray(array $data)
{
$singles = array(
'name', 'address1', 'address2', 'city',
'province', 'province_code', 'postal_code',
'country', 'country_code', 'longitude',
'phone', 'company',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,277 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/15/16
* Time: 1:26 PM
*/
class MailChimp_WooCommerce_Cart
{
protected $store_id;
protected $id;
protected $customer;
protected $campaign_id;
protected $checkout_url;
protected $currency_code;
protected $order_total;
protected $tax_total;
protected $lines = array();
/**
* @param $unique_id
* @return $this
*/
public function setId($unique_id)
{
$this->id = $unique_id;
return $this;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param $store_id
* @return $this
*/
public function setStoreID($store_id)
{
$this->store_id = $store_id;
return $this;
}
/**
* @return mixed
*/
public function getStoreID()
{
if (empty($this->store_id)) {
$this->store_id = mailchimp_get_store_id();
}
return $this->store_id;
}
/**
* @param MailChimp_WooCommerce_Customer $customer
* @return $this
*/
public function setCustomer(MailChimp_WooCommerce_Customer $customer)
{
$this->customer = $customer;
return $this;
}
/**
* @return MailChimp_WooCommerce_Customer
*/
public function getCustomer()
{
if (empty($this->customer)) {
$this->customer = new MailChimp_WooCommerce_Customer();
}
return $this->customer;
}
/**
* @param $id
* @return $this
*/
public function setCampaignID($id)
{
$this->campaign_id = $id;
return $this;
}
/**
* @return mixed
*/
public function getCampaignID()
{
return $this->campaign_id;
}
/**
* @param $url
* @return $this
*/
public function setCheckoutUrl($url)
{
$this->checkout_url = $url;
return $this;
}
/**
* @return string
*/
public function getCheckoutURL()
{
if (empty($this->checkout_url)) {
$this->checkout_url = wc_get_checkout_url();
}
return $this->checkout_url;
}
/**
* @param $code
* @return $this
*/
public function setCurrencyCode($code)
{
$this->currency_code = $code;
return $this;
}
/**
* @return string
*/
public function getCurrencyCode()
{
if (empty($this->currency_code)) {
$options = get_option('mailchimp-woocommerce', array());
$this->currency_code = isset($options['store_currency_code']) ? $options['store_currency_code'] : 'USD';
}
return $this->currency_code;
}
/**
* @param $total
* @return $this
*/
public function setOrderTotal($total)
{
$this->order_total = $total;
return $this;
}
/**
* @return float
*/
public function getOrderTotal()
{
return $this->order_total;
}
/**
* @param $total
* @return $this
*/
public function setTaxTotal($total)
{
$this->tax_total = $total;
return $this;
}
/**
* @return float
*/
public function getTaxTotal()
{
return $this->tax_total;
}
/**
* @param MailChimp_WooCommerce_LineItem $item
* @return $this
*/
public function addItem(MailChimp_WooCommerce_LineItem $item)
{
$this->lines[] = $item;
return $this;
}
/**
* @return array
*/
public function items()
{
return $this->lines;
}
/**
* @return mixed
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'customer' => $this->getCustomer()->toArray(),
'campaign_id' => (string) $this->getCampaignID(),
'checkout_url' => (string) $this->getCheckoutURL(),
'currency_code' => (string) $this->getCurrencyCode(),
'order_total' => floatval($this->getOrderTotal()),
'tax_total' => $this->getTaxTotal() > 0 ? floatval($this->getTaxTotal()) : null,
'lines' => array_map(function($item) {
return $item->toArray();
}, $this->items()),
));
}
/**
* @return array
*/
public function toArrayForUpdate()
{
return mailchimp_array_remove_empty(array(
'campaign_id' => (string) $this->getCampaignID(),
'checkout_url' => (string) $this->getCheckoutURL(),
'currency_code' => (string) $this->getCurrencyCode(),
'order_total' => $this->getOrderTotal(),
'tax_total' => ($this->getTaxTotal() > 0 ? $this->getTaxTotal() : null),
'lines' => array_map(function($item) {
return $item->toArray();
}, $this->items()),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Cart
*/
public function fromArray(array $data)
{
$singles = array(
'store_id', 'id', 'campaign_id', 'checkout_url',
'currency_code', 'order_total', 'tax_total',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('customer', $data) && is_array($data['customer'])) {
$customer = new MailChimp_WooCommerce_Customer();
$this->customer = $customer->fromArray($data['customer']);
}
if (array_key_exists('lines', $data) && is_array($data['lines'])) {
foreach ($data['lines'] as $line_item) {
$item = new MailChimp_WooCommerce_LineItem();
$this->lines[] = $item->fromArray($line_item);
}
}
return $this;
}
}

View File

@@ -0,0 +1,258 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:16 PM
*/
class MailChimp_WooCommerce_Customer
{
protected $id = null;
protected $email_address = null;
protected $opt_in_status = null;
protected $company = null;
protected $first_name = null;
protected $last_name = null;
protected $orders_count = null;
protected $total_spent = null;
protected $address;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required',
'email_address' => 'required|email',
'opt_in_status' => 'required|boolean',
'company' => 'string',
'first_name' => 'string',
'last_name' => 'string',
'orders_count' => 'integer',
'total_spent' => 'integer',
);
}
/**
* @return null
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_Customer
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return null
*/
public function getEmailAddress()
{
return $this->email_address;
}
/**
* @param null $email_address
* @return MailChimp_WooCommerce_Customer
*/
public function setEmailAddress($email_address)
{
$this->email_address = $email_address;
return $this;
}
/**
* @return null
*/
public function getOptInStatus()
{
return $this->opt_in_status;
}
/**
* @param null $opt_in_status
* @return MailChimp_WooCommerce_Customer
*/
public function setOptInStatus($opt_in_status)
{
$this->opt_in_status = $opt_in_status;
return $this;
}
/**
* @return null
*/
public function getCompany()
{
return $this->company;
}
/**
* @param null $company
* @return MailChimp_WooCommerce_Customer
*/
public function setCompany($company)
{
$this->company = $company;
return $this;
}
/**
* @return null
*/
public function getFirstName()
{
return $this->first_name;
}
/**
* @param null $first_name
* @return MailChimp_WooCommerce_Customer
*/
public function setFirstName($first_name)
{
$this->first_name = $first_name;
return $this;
}
/**
* @return null
*/
public function getLastName()
{
return $this->last_name;
}
/**
* @param null $last_name
* @return MailChimp_WooCommerce_Customer
*/
public function setLastName($last_name)
{
$this->last_name = $last_name;
return $this;
}
/**
* @return null
*/
public function getOrdersCount()
{
return $this->orders_count;
}
/**
* @param null $orders_count
* @return MailChimp_WooCommerce_Customer
*/
public function setOrdersCount($orders_count)
{
$this->orders_count = $orders_count;
return $this;
}
/**
* @return null
*/
public function getTotalSpent()
{
return $this->total_spent;
}
/**
* @param null $total_spent
* @return MailChimp_WooCommerce_Customer
*/
public function setTotalSpent($total_spent)
{
$this->total_spent = $total_spent;
return $this;
}
/**
* @return MailChimp_WooCommerce_Address
*/
public function getAddress()
{
if (empty($this->address)) {
$this->address = new MailChimp_WooCommerce_Address();
}
return $this->address;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return MailChimp_WooCommerce_Customer
*/
public function setAddress(MailChimp_WooCommerce_Address $address)
{
$this->address = $address;
return $this;
}
/**
* @return array
*/
public function toArray()
{
$address = $this->getAddress()->toArray();
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'email_address' => (string) $this->getEmailAddress(),
'opt_in_status' => $this->getOptInStatus(),
'company' => (string) $this->getCompany(),
'first_name' => (string) $this->getFirstName(),
'last_name' => (string) $this->getLastName(),
'orders_count' => (int) $this->getOrdersCount(),
'total_spent' => floatval(number_format($this->getTotalSpent(), 2)),
'address' => (empty($address) ? null : $address),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Customer
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'email_address', 'opt_in_status', 'company',
'first_name', 'last_name', 'orders_count', 'total_spent',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('address', $data) && is_array($data['address'])) {
$address = new MailChimp_WooCommerce_Address();
$this->address = $address->fromArray($data['address']);
}
return $this;
}
}

View File

@@ -0,0 +1,180 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:16 PM
*/
class MailChimp_WooCommerce_LineItem
{
protected $id;
protected $product_id;
protected $product_variant_id;
protected $quantity;
protected $price;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'product_id' => 'required|string',
'product_variant_id' => 'required|string',
'quantity' => 'required|integer',
'price' => 'required|numeric',
);
}
/**
* @param $id
* @param $product_id
* @param $variant_id
* @param $quantity
* @param $price
* @return MailChimp_WooCommerce_LineItem
*/
public static function make($id, $product_id, $variant_id, $quantity, $price)
{
$item = new MailChimp_WooCommerce_LineItem();
$item->id = $id;
$item->product_id = $product_id;
$item->product_variant_id = $variant_id;
$item->quantity = $quantity;
$item->price = $price;
return $item;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
* @return MailChimp_WooCommerce_LineItem
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return mixed
*/
public function getProductId()
{
return $this->product_id;
}
/**
* @param mixed $product_id
* @return MailChimp_WooCommerce_LineItem
*/
public function setProductId($product_id)
{
$this->product_id = $product_id;
return $this;
}
/**
* @return mixed
*/
public function getProductVariantId()
{
return $this->product_variant_id;
}
/**
* @param mixed $product_variant_id
* @return MailChimp_WooCommerce_LineItem
*/
public function setProductVariantId($product_variant_id)
{
$this->product_variant_id = $product_variant_id;
return $this;
}
/**
* @return mixed
*/
public function getQuantity()
{
return $this->quantity;
}
/**
* @param mixed $quantity
* @return MailChimp_WooCommerce_LineItem
*/
public function setQuantity($quantity)
{
$this->quantity = $quantity;
return $this;
}
/**
* @return mixed
*/
public function getPrice()
{
return $this->price;
}
/**
* @param mixed $price
* @return MailChimp_WooCommerce_LineItem
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->id,
'product_id' => (string) $this->product_id,
'product_variant_id' => (string) $this->product_variant_id,
'quantity' => (int) $this->quantity,
'price' => (string) $this->price,
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_LineItem
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'product_id', 'product_variant_id', 'quantity', 'price',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,547 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:16 PM
*/
class MailChimp_WooCommerce_Order
{
protected $id = null;
protected $landing_site = null;
protected $customer = null;
protected $campaign_id = null;
protected $financial_status = null;
protected $fulfillment_status = null;
protected $currency_code = null;
protected $order_total = null;
protected $tax_total = null;
protected $discount_total = null;
protected $shipping_total = null;
protected $updated_at_foreign = null;
protected $processed_at_foreign = null;
protected $cancelled_at_foreign = null;
protected $order_url = null;
protected $shipping_address = null;
protected $billing_address = null;
protected $lines = array();
protected $confirm_and_paid = false;
protected $promos = array();
protected $is_amazon_order = false;
/**
* @param $bool
* @return $this
*/
public function flagAsAmazonOrder($bool)
{
$this->is_amazon_order = (bool) $bool;
return $this;
}
/**
* @return bool
*/
public function isFlaggedAsAmazonOrder()
{
return (bool) $this->is_amazon_order;
}
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'landing_site' => 'required|string',
'customer' => 'required',
'campaign_id' => 'string',
'financial_status' => 'string',
'fulfillment_status' => 'string',
'currency_code' => 'required|currency_code',
'order_total' => 'required|numeric',
'tax_total' => 'numeric',
'discount_total' => 'numeric',
'processed_at_foreign' => 'date',
'updated_at_foreign' => 'date',
'cancelled_at_foreign' => 'date',
'order_url' => 'string',
'lines' => 'required|array',
);
}
/**
* @param $id
* @return MailChimp_WooCommerce_Order
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return null|string
*/
public function getId()
{
return $this->id;
}
/**
* @param $landing_site
* @return $this
*/
public function setLandingSite($landing_site)
{
$this->landing_site = $landing_site;
return $this;
}
/**
* @return null|string
*/
public function getLandingSite()
{
return $this->landing_site;
}
/**
* @param MailChimp_WooCommerce_Customer $customer
* @return MailChimp_WooCommerce_Order
*/
public function setCustomer(MailChimp_WooCommerce_Customer $customer)
{
$this->customer = $customer;
return $this;
}
/**
* @return null|MailChimp_WooCommerce_Customer
*/
public function getCustomer()
{
if (empty($this->customer)) {
$this->customer = new MailChimp_WooCommerce_Customer();
}
return $this->customer;
}
/**
* @param MailChimp_WooCommerce_LineItem $item
* @return $this
*/
public function addItem(MailChimp_WooCommerce_LineItem $item)
{
$this->lines[] = $item;
return $this;
}
/**
* @param $code
* @param $amount
* @param bool $is_percentage
* @return $this
*/
public function addDiscount($code, $amount, $is_percentage = false)
{
$this->promos[] = array(
'code' => $code,
'amount_discounted' => $amount,
'type' => $is_percentage ? 'percent' : 'fixed'
);
return $this;
}
/**
* @return array
*/
public function discounts()
{
return $this->promos;
}
/**
* @return array
*/
public function items()
{
return $this->lines;
}
/**
* @return null
*/
public function getCampaignId()
{
return $this->campaign_id;
}
/**
* @param null $campaign_id
* @return MailChimp_WooCommerce_Order
*/
public function setCampaignId($campaign_id)
{
$this->campaign_id = $campaign_id;
return $this;
}
/**
* @return null
*/
public function getFinancialStatus()
{
return $this->financial_status;
}
/**
* @param null $financial_status
* @return MailChimp_WooCommerce_Order
*/
public function setFinancialStatus($financial_status)
{
$this->financial_status = $financial_status;
return $this;
}
/**
* @return null
*/
public function getFulfillmentStatus()
{
return $this->fulfillment_status;
}
/**
* @param null $fulfillment_status
* @return MailChimp_WooCommerce_Order
*/
public function setFulfillmentStatus($fulfillment_status)
{
$this->fulfillment_status = $fulfillment_status;
return $this;
}
/**
* @return null
*/
public function getCurrencyCode()
{
return $this->currency_code;
}
/**
* @param null $currency_code
* @return MailChimp_WooCommerce_Order
*/
public function setCurrencyCode($currency_code)
{
$this->currency_code = $currency_code;
return $this;
}
/**
* @return mixed
*/
public function getOrderTotal()
{
return $this->order_total;
}
/**
* @param mixed $order_total
* @return MailChimp_WooCommerce_Order
*/
public function setOrderTotal($order_total)
{
$this->order_total = $order_total;
return $this;
}
/**
* @param $url
* @return $this
*/
public function setOrderURL($url)
{
if (($url = wp_http_validate_url($url))) {
$this->order_url = $url;
}
return $this;
}
/**
* @return string
*/
public function getOrderURL()
{
return $this->order_url;
}
/**
* @return mixed
*/
public function getTaxTotal()
{
return $this->tax_total;
}
/**
* @param mixed $tax_total
* @return MailChimp_WooCommerce_Order
*/
public function setTaxTotal($tax_total)
{
$this->tax_total = $tax_total;
return $this;
}
/**
* @return mixed
*/
public function getShippingTotal()
{
return $this->shipping_total;
}
/**
* @param mixed $shipping_total
* @return MailChimp_WooCommerce_Order
*/
public function setShippingTotal($shipping_total)
{
$this->shipping_total = $shipping_total;
return $this;
}
/**
* @return mixed
*/
public function getDiscountTotal()
{
return $this->discount_total;
}
/**
* @param mixed $discount_total
* @return MailChimp_WooCommerce_Order
*/
public function setDiscountTotal($discount_total)
{
$this->discount_total = $discount_total;
return $this;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setProcessedAt(\DateTime $time)
{
$this->processed_at_foreign = $time->format('Y-m-d H:i:s');
return $this;
}
/**
* @return null
*/
public function getProcessedAt()
{
return $this->processed_at_foreign;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setCancelledAt(\DateTime $time)
{
$this->cancelled_at_foreign = $time->format('Y-m-d H:i:s');
return $this;
}
/**
* @return null
*/
public function getCancelledAt()
{
return $this->cancelled_at_foreign;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setUpdatedAt(\DateTime $time)
{
$this->updated_at_foreign = $time->format('Y-m-d H:i:s');
return $this;
}
/**
* @return null
*/
public function getUpdatedAt()
{
return $this->updated_at_foreign;
}
/**
* @param $bool
* @param $bool
* @return $this
*/
public function confirmAndPay($bool)
{
$this->confirm_and_paid = (bool) $bool;
return $this;
}
/**
* @return bool
*/
public function shouldConfirmAndPay()
{
return $this->confirm_and_paid;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return $this
*/
public function setShippingAddress(MailChimp_WooCommerce_Address $address)
{
$this->shipping_address = $address;
return $this;
}
/**
* @return MailChimp_WooCommerce_Address
*/
public function getShippingAddress()
{
if (empty($this->shipping_address)) {
$this->shipping_address = new MailChimp_WooCommerce_Address();
}
return $this->shipping_address;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return $this
*/
public function setBillingAddress(MailChimp_WooCommerce_Address $address)
{
$this->billing_address = $address;
return $this;
}
/**
* @return MailChimp_WooCommerce_Address
*/
public function getBillingAddress()
{
if (empty($this->billing_address)) {
$this->billing_address = new MailChimp_WooCommerce_Address();
}
return $this->billing_address;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'landing_site' => (string) $this->getLandingSite(),
'customer' => $this->getCustomer()->toArray(),
'campaign_id' => (string) $this->getCampaignId(),
'financial_status' => (string) $this->getFinancialStatus(),
'fulfillment_status' => (string) $this->getFulfillmentStatus(),
'currency_code' => (string) $this->getCurrencyCode(),
'order_total' => floatval($this->getOrderTotal()),
'order_url' => (string) $this->getOrderURL(),
'tax_total' => floatval($this->getTaxTotal()),
'discount_total' => floatval($this->getDiscountTotal()),
'shipping_total' => floatval($this->getShippingTotal()),
'processed_at_foreign' => (string) $this->getProcessedAt(),
'cancelled_at_foreign' => (string) $this->getCancelledAt(),
'updated_at_foreign' => (string) $this->getUpdatedAt(),
'shipping_address' => $this->getShippingAddress()->toArray(),
'billing_address' => $this->getBillingAddress()->toArray(),
'promos' => !empty($this->promos) ? $this->promos : null,
'lines' => array_map(function ($item) {
/** @var MailChimp_WooCommerce_LineItem $item */
return $item->toArray();
}, $this->items()),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Order
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'landing_site', 'campaign_id', 'financial_status', 'fulfillment_status',
'currency_code', 'order_total', 'order_url', 'tax_total', 'discount_total', 'processed_at_foreign',
'cancelled_at_foreign', 'updated_at_foreign'
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('shipping_address', $data) && is_array($data['shipping_address'])) {
$shipping = new MailChimp_WooCommerce_Address();
$this->shipping_address = $shipping->fromArray($data['shipping_address']);
}
if (array_key_exists('billing_address', $data) && is_array($data['billing_address'])) {
$billing = new MailChimp_WooCommerce_Address();
$this->billing_address = $billing->fromArray($data['billing_address']);
}
if (array_key_exists('promos', $data)) {
$this->promos = $data['promos'];
}
if (array_key_exists('lines', $data) && is_array($data['lines'])) {
$this->lines = array();
foreach ($data['lines'] as $line_item) {
$item = new MailChimp_WooCommerce_LineItem();
$this->lines[] = $item->fromArray($line_item);
}
}
return $this;
}
}

View File

@@ -0,0 +1,250 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:17 PM
*/
class MailChimp_WooCommerce_ProductVariation
{
protected $id = null;
protected $title = null;
protected $url = null;
protected $sku = null;
protected $price = null;
protected $inventory_quantity = null;
protected $image_url = null;
protected $backorders = null;
protected $visibility = null;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'title' => 'required|string',
'url' => 'url',
'sku' => 'string',
'price' => 'numeric',
'inventory_quantity' => 'integer',
'image_url' => 'url',
'backorders' => 'string',
'visibility' => 'string',
);
}
/**
* @return null
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return null
*/
public function getTitle()
{
return $this->title;
}
/**
* @param null $title
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* @return null
*/
public function getUrl()
{
return $this->url;
}
/**
* @param null $url
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* @return null
*/
public function getSku()
{
return $this->sku;
}
/**
* @param null $sku
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setSku($sku)
{
$this->sku = $sku;
return $this;
}
/**
* @return null
*/
public function getPrice()
{
return $this->price;
}
/**
* @param null $price
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* @return null
*/
public function getInventoryQuantity()
{
return $this->inventory_quantity;
}
/**
* @param null $inventory_quantity
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setInventoryQuantity($inventory_quantity)
{
$this->inventory_quantity = $inventory_quantity;
return $this;
}
/**
* @return null
*/
public function getImageUrl()
{
return !empty($this->image_url) ? $this->image_url : null;
}
/**
* @param null $image_url
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setImageUrl($image_url)
{
$this->image_url = $image_url;
return $this;
}
/**
* @return null
*/
public function getBackorders()
{
return $this->backorders;
}
/**
* @param null $backorders
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setBackorders($backorders)
{
$this->backorders = $backorders;
return $this;
}
/**
* @return null
*/
public function getVisibility()
{
return $this->visibility;
}
/**
* @param null $visibility
* @return MailChimp_WooCommerce_ProductVariation
*/
public function setVisibility($visibility)
{
$this->visibility = $visibility;
return $this;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'title' => $this->getTitle(),
'url' => (string) $this->getUrl(),
'sku' => (string) $this->getSku(),
'price' => $this->getPrice(),
'inventory_quantity' => (int) $this->getInventoryQuantity(),
'image_url' => (string) $this->getImageUrl(),
'backorders' => $this->getBackorders() ? 'true' : 'false',
'visibility' => (string) $this->getVisibility(),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_ProductVariation
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'title', 'url', 'sku',
'price', 'inventory_quantity', 'image_url', 'backorders',
'visibility',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,282 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 2:17 PM
*/
class MailChimp_WooCommerce_Product
{
protected $id;
protected $title;
protected $handle = null;
protected $url = null;
protected $description = null;
protected $type = null;
protected $vendor = null;
protected $image_url = null;
protected $variants = array();
protected $published_at_foreign = null;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'title' => 'required|string',
'handle' => 'string',
'url' => 'url',
'description' => 'string',
'type' => 'string',
'vendor' => 'string',
'image_url' => 'url',
'variants' => 'required|array',
'published_at_foreign' => 'date',
);
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
* @return MailChimp_WooCommerce_Product
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return mixed
*/
public function getTitle()
{
return $this->title;
}
/**
* @param mixed $title
* @return MailChimp_WooCommerce_Product
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* @return null
*/
public function getHandle()
{
return $this->handle;
}
/**
* @param null $handle
* @return MailChimp_WooCommerce_Product
*/
public function setHandle($handle)
{
$this->handle = $handle;
return $this;
}
/**
* @return null
*/
public function getUrl()
{
return $this->url;
}
/**
* @param null $url
* @return MailChimp_WooCommerce_Product
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* @return null
*/
public function getDescription()
{
return $this->description;
}
/**
* @param null $description
* @return MailChimp_WooCommerce_Product
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @return null
*/
public function getType()
{
return $this->type;
}
/**
* @param null $type
* @return MailChimp_WooCommerce_Product
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return null
*/
public function getVendor()
{
return $this->vendor;
}
/**
* @param null $vendor
* @return MailChimp_WooCommerce_Product
*/
public function setVendor($vendor)
{
$this->vendor = $vendor;
return $this;
}
/**
* @return null
*/
public function getImageUrl()
{
return $this->image_url;
}
/**
* @param null $image_url
* @return MailChimp_WooCommerce_Product
*/
public function setImageUrl($image_url)
{
$this->image_url = $image_url;
return $this;
}
/**
* @return array
*/
public function getVariations()
{
return $this->variants;
}
/**
* @param MailChimp_WooCommerce_ProductVariation $variation
* @return MailChimp_WooCommerce_Product
*/
public function addVariant(MailChimp_WooCommerce_ProductVariation $variation)
{
$this->variants[] = $variation;
return $this;
}
/**
* @return string
*/
public function getPublishedAtForeign()
{
return $this->published_at_foreign;
}
/**
* @param \DateTime $time
* @return MailChimp_WooCommerce_Product
*/
public function setPublishedAtForeign(\DateTime $time)
{
$this->published_at_foreign = $time->format('Y-m-d H:i:s');
return $this;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => (string) $this->getId(),
'title' => $this->getTitle(),
'handle' => (string) $this->getHandle(),
'url' => (string) $this->getUrl(),
'description' => (string) $this->getDescription(),
'type' => (string) $this->getType(),
'vendor' => (string) $this->getVendor(),
'image_url' => (string) $this->getImageUrl(),
'variants' => array_map(function ($item) {
return $item->toArray();
}, $this->getVariations()),
'published_at_foreign' => (string) $this->getPublishedAtForeign(),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Product
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'title', 'handle', 'url',
'description', 'type', 'vendor', 'image_url',
'published_at_foreign',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('variants', $data) && is_array($data['variants'])) {
$this->variants = array();
foreach ($data['variants'] as $variant) {
$variation = new MailChimp_WooCommerce_ProductVariation();
$this->variants[] = $variation->fromArray($variant);
}
}
return $this;
}
}

View File

@@ -0,0 +1,230 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 6/13/17
* Time: 1:19 PM
*/
class MailChimp_WooCommerce_PromoCode
{
/**
* @var string
* @title Promo Rule Foreign ID
* @description A unique identifier for the promo code
*/
protected $id;
/**
* @var string
* @title Code
* @required
* @description The discount code
*/
protected $code;
/**
* @var string
* @title Promo Redemption Url
* @required
* @description The url that should be used in the promotion campaign. Eg. A url that applies promo code directly at checkout or a url that points to sale page. Use store url if promotion url is not available.
*/
protected $redemption_url;
/**
* @var string
* @title Description
* @default null
* @description Number of times promo code has been used.
*/
protected $usage_count;
/**
* @var boolean
* @title Enabled
* @default true
* @description Whether the promo code is currently enabled. ***
*/
protected $enabled;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $created_at_foreign;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $updated_at_foreign;
/**
* @var MailChimp_WooCommerce_PromoRule|null
*/
protected $promo_rule;
/**
* @return array
*/
public function getValidation()
{
return [
'id' => 'required',
'code' => 'required',
'redemption_url' => 'required',
'usage_count' => 'integer',
'created_at_foreign' => 'date',
'updated_at_foreign' => 'date',
];
}
/**
* @param MailChimp_WooCommerce_PromoRule $promo
* @return MailChimp_WooCommerce_PromoCode
*/
public function attachPromoRule(MailChimp_WooCommerce_PromoRule $promo)
{
$this->promo_rule = $promo;
return $this;
}
/**
* @return MailChimp_WooCommerce_PromoRule|null
*/
public function getAttachedPromoRule()
{
return $this->promo_rule;
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_PromoCode
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return string
*/
public function getCode()
{
return $this->code;
}
/**
* @param string $code
* @return MailChimp_WooCommerce_PromoCode
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* @return string
*/
public function getRedemptionURL()
{
return $this->redemption_url;
}
/**
* @param string $url
* @return MailChimp_WooCommerce_PromoCode
*/
public function setRedemptionURL($url)
{
$this->redemption_url = $url;
return $this;
}
public function getUsageCount()
{
return $this->usage_count;
}
/**
* @param $count
* @return MailChimp_WooCommerce_PromoCode
*/
public function setUsageCount($count)
{
$this->usage_count = $count;
return $this;
}
/**
* @param $enabled
* @return MailChimp_WooCommerce_PromoCode
*/
public function setEnabled($enabled)
{
$this->enabled = (bool) $enabled;
return $this;
}
/**
* @return bool
*/
public function isEnabled()
{
return (bool) $this->enabled;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty([
'id' => (string) $this->getId(),
'code' => (string) $this->getCode(),
'redemption_url' => (string) $this->getRedemptionURL(),
'usage_count' => $this->getUsageCount(),
'enabled' => $this->isEnabled(),
]);
}
/**
* @param array $data
* @return MailChimp_WooCommerce_PromoCode
*/
public function fromArray(array $data)
{
$singles = [
'id', 'code', 'usage_count', 'enabled',
'redemption_url', 'created_at_foreign', 'updated_at_foreign',
];
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,405 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 6/13/17
* Time: 1:19 PM
*/
class MailChimp_WooCommerce_PromoRule
{
/**
* @var string
* @title Promo Rule Foreign ID
* @default = null
* @description
* A unique identifier for the promo rule. If Ecomm platform does not support promo rule,
* use promo code id as promo rule id.
* Restricted to UTF-8 characters with max length 50
*/
protected $id;
/**
* @var string
* @title Title
* @default null
* @description The title that will show up in promotion campaign. Restricted to UTF-8 characters with max length 100
*/
protected $title;
/**
* @var string
* @title Description
* @default null
* @description The description of a promotion
*/
protected $description;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $starts_at;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $ends_at;
/**
* @var float
* @title Amount
* @required
* @description The amount of discount; Positive dollar or percentage amount.
*/
protected $amount;
/**
* @var string
* @title Type
* @required
* @description One of fixed , percentage
*/
protected $type;
/**
* @var string
* @title Target
* @required
* @description One of per_item, total, shipping
*/
protected $target;
/**
* @var boolean
* @title Enabled
* @default true
* @description Whether the promo rule is currently enabled
*/
protected $enabled = true;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $created_at_foreign;
/**
* @var \DateTime
* @title Start Time
* @default null
* @description The date and time when the promotion starts in ISO 8601 format
*/
protected $updated_at_foreign;
/**
* @return array
*/
public function getValidation()
{
return [
'id' => 'required',
'amount' => 'required|number',
'type' => 'required',
'target' => 'required',
'enabled' => 'boolean',
'starts_at' => 'date',
'ends_at' => 'date',
'created_at_foreign' => 'date',
'updated_at_foreign' => 'date',
];
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_PromoRule
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $name
* @return MailChimp_WooCommerce_PromoRule
*/
public function setTitle($name)
{
$this->title = $name;
return $this;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* @param string $description
* @return MailChimp_WooCommerce_PromoRule
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @param \DateTime $date
* @return $this
*/
public function setStartsAt(\DateTime $date)
{
$this->starts_at = (string) $date;
return $this;
}
/**
* @return \DateTime
*/
public function getStartsAt()
{
return $this->starts_at;
}
/**
* @param \DateTime $date
* @return $this
*/
public function setEndsAt(\DateTime $date)
{
$this->ends_at = (string) $date;
return $this;
}
/**
* @return \DateTime
*/
public function getEndsAt()
{
return $this->ends_at;
}
/**
* @param $enabled
* @return $this
*/
public function setEnabled($enabled)
{
$this->enabled = (bool) $enabled;
return $this;
}
/**
* @return bool
*/
public function isEnabled()
{
return (bool) $this->enabled;
}
/**
* @return string
*/
public function getAmount()
{
return $this->amount;
}
/**
* @param int $amount
* @return MailChimp_WooCommerce_PromoRule
*/
public function setAmount($amount)
{
$this->amount = $amount;
return $this;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @return string
*/
public function getTarget()
{
return $this->target;
}
/**
* @return $this
*/
public function setTypeFixed()
{
$this->type = 'fixed';
return $this;
}
/**
* @return $this
*/
public function setTypePercentage()
{
$this->type = 'percentage';
return $this;
}
/**
* @return $this
*/
public function setTargetTypePerItem()
{
$this->target = 'per_item';
return $this;
}
/**
* @return $this
*/
public function setTargetTypeShipping()
{
$this->target = 'shipping';
return $this;
}
/**
* @return $this
*/
public function setTargetTypeTotal()
{
$this->target = 'total';
return $this;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setUpdatedAt(\DateTime $time)
{
$this->updated_at_foreign = (string) $time;
return $this;
}
/**
* @return null
*/
public function getUpdatedAt()
{
return $this->updated_at_foreign;
}
/**
* @param \DateTime $time
* @return $this
*/
public function setCreatedAt(\DateTime $time)
{
$this->created_at_foreign = (string) $time;
return $this;
}
/**
* @return null
*/
public function getCreatedAt()
{
return $this->created_at_foreign;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty([
'id' => (string) $this->getId(),
'title' => (string) $this->getTitle(),
'description' => (string) $this->getDescription(),
'starts_at' => (string) $this->getStartsAt(),
'ends_at' => (string) $this->getEndsAt(),
'amount' => floatval($this->getAmount()),
'type' => (string) $this->getType(),
'target' => (string) $this->getTarget(),
'enabled' => (bool) $this->isEnabled(),
'created_at_foreign' => (string) $this->getCreatedAt(),
'updated_at_foreign' => (string) $this->getUpdatedAt(),
]);
}
/**
* @param array $data
* @return MailChimp_WooCommerce_PromoRule
*/
public function fromArray(array $data)
{
$singles = [
'id',
'title',
'description',
'starts_at',
'ends_at',
'amount',
'type',
'target',
'enabled',
'created_at_foreign',
'updated_at_foreign'
];
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
return $this;
}
}

View File

@@ -0,0 +1,390 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 3/8/16
* Time: 3:13 PM
*/
class MailChimp_WooCommerce_Store
{
protected $id = null;
protected $is_syncing = false;
protected $list_id = null;
protected $name = null;
protected $domain = null;
protected $email_address = null;
protected $currency_code = null;
protected $money_format = null;
protected $primary_locale = null;
protected $timezone = null;
protected $phone = null;
protected $address = null;
protected $platform = null;
protected $connected_site = null;
/**
* @return array
*/
public function getValidation()
{
return array(
'id' => 'required|string',
'list_id' => 'required|string',
'name' => 'required|string',
'domain' => 'string',
'email_address' => 'email',
'currency_code' => 'required|currency_code',
'primary_locale' => 'locale_basic',
'timezone' => 'timezone',
'phone' => 'string',
);
}
/**
* @return null
*/
public function getId()
{
return $this->id;
}
/**
* @param null $id
* @return MailChimp_WooCommerce_Store
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @param $bool
* @return $this
*/
public function flagSyncing($bool)
{
$this->is_syncing = $bool;
return $this;
}
/**
* @return bool
*/
public function isSyncing()
{
return $this->is_syncing;
}
/**
* @return null
*/
public function getListId()
{
return $this->list_id;
}
/**
* @param null $list_id
* @return MailChimp_WooCommerce_Store
*/
public function setListId($list_id)
{
$this->list_id = $list_id;
return $this;
}
/**
* @return null
*/
public function getName()
{
return $this->name;
}
/**
* @param null $name
* @return MailChimp_WooCommerce_Store;
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return null
*/
public function getDomain()
{
return $this->domain;
}
/**
* @param null $domain
* @return MailChimp_WooCommerce_Store;
*/
public function setDomain($domain)
{
$this->domain = $domain;
return $this;
}
/**
* @return null
*/
public function getEmailAddress()
{
return $this->email_address;
}
/**
* @param null $email_address
* @return MailChimp_WooCommerce_Store;
*/
public function setEmailAddress($email_address)
{
$this->email_address = $email_address;
return $this;
}
/**
* @return null
*/
public function getCurrencyCode()
{
return $this->currency_code;
}
/**
* @param null $currency_code
* @return MailChimp_WooCommerce_Store;
*/
public function setCurrencyCode($currency_code)
{
$this->currency_code = $currency_code;
return $this;
}
/**
* @return null
*/
public function getMoneyFormat()
{
return $this->money_format;
}
/**
* @param null $money_format
* @return MailChimp_WooCommerce_Store;
*/
public function setMoneyFormat($money_format)
{
$this->money_format = $money_format;
return $this;
}
/**
* @return null
*/
public function getPrimaryLocale()
{
return $this->primary_locale;
}
/**
* @param null $primary_locale
* @return MailChimp_WooCommerce_Store;
*/
public function setPrimaryLocale($primary_locale)
{
$this->primary_locale = $primary_locale;
return $this;
}
/**
* @return null
*/
public function getTimezone()
{
return $this->timezone;
}
/**
* @param null $timezone
* @return MailChimp_WooCommerce_Store;
*/
public function setTimezone($timezone)
{
$this->timezone = $timezone;
return $this;
}
/**
* @return null
*/
public function getPhone()
{
return $this->phone;
}
/**
* @param null $phone
* @return MailChimp_WooCommerce_Store;
*/
public function setPhone($phone)
{
$this->phone = $phone;
return $this;
}
/**
* @param $platform
* @return $this
*/
public function setPlatform($platform)
{
$this->platform = $platform;
return $this;
}
/**
* @return string
*/
public function getPlatform()
{
return $this->platform;
}
/**
* @return MailChimp_WooCommerce_Address
*/
public function getAddress()
{
if (empty($this->address)) {
$this->address = new MailChimp_WooCommerce_Address();
}
return $this->address;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return Store;
*/
public function setAddress(MailChimp_WooCommerce_Address $address)
{
$this->address = $address;
return $this;
}
/**
* @return null|string
*/
public function getConnectedSiteForeignID()
{
return $this->getConnectedSiteParam('site_foreign_id');
}
/**
* @return null|string
*/
public function getConnectedSiteScriptUrl()
{
if (($script = $this->getConnectedSiteParam('site_script'))) {
return $script['url'];
}
return false;
}
/**
* @return null|string
*/
public function getConnectedSiteScriptFragment()
{
if (($script = $this->getConnectedSiteParam('site_script'))) {
return $script['fragment'];
}
return false;
}
/**
* @param $key
* @param null $default
* @return null
*/
public function getConnectedSiteParam($key, $default = null)
{
if (empty($this->connected_site)) {
return $default;
}
return array_key_exists($key, $this->connected_site) ? $this->connected_site[$key] : null;
}
/**
* @return array
*/
public function toArray()
{
return mailchimp_array_remove_empty(array(
'id' => $this->getId(),
'is_syncing' => $this->isSyncing(),
'platform' => $this->getPlatform(),
'list_id' => $this->getListId(),
'name' => $this->getName(),
'domain' => $this->getDomain(),
'email_address' => $this->getEmailAddress(),
'currency_code' => $this->getCurrencyCode(),
'money_format' => $this->getMoneyFormat(),
'primary_locale' => $this->getPrimaryLocale(),
'timezone' => $this->getTimezone(),
'phone' => $this->getPhone(),
'address' => $this->getAddress()->toArray(),
));
}
/**
* @param array $data
* @return MailChimp_WooCommerce_Store
*/
public function fromArray(array $data)
{
$singles = array(
'id', 'list_id', 'name', 'domain', 'is_syncing',
'email_address', 'currency_code', 'money_format',
'primary_locale', 'timezone', 'phone', 'platform',
);
foreach ($singles as $key) {
if (array_key_exists($key, $data)) {
$this->$key = $data[$key];
}
}
if (array_key_exists('address', $data)) {
$address = new MailChimp_WooCommerce_Address();
$this->address = $address->fromArray($data['address']);
}
if (array_key_exists('connected_site', $data)) {
$this->connected_site = $data['connected_site'];
}
return $this;
}
}

View File

@@ -0,0 +1,101 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/13/16
* Time: 2:32 PM
*/
class MailChimp_WooCommerce_Api
{
protected static $filterable_actions = array(
'paginate-resource',
);
/**
* @param int $default_page
* @param int $default_per
* @return array
*/
public static function filter($default_page = null, $default_per = null)
{
if (isset($_GET['mailchimp-woocommerce']) && isset($_GET['mailchimp-woocommerce']['action'])) {
if (in_array($_GET['mailchimp-woocommerce']['action'], static::$filterable_actions)) {
if (empty($default_page)) {
$page = isset($_GET['page']) ? (int) $_GET['page'] : null;
}
if (empty($default_per)) {
$per = isset($_GET['per']) ? (int) $_GET['per'] : null;
}
}
}
if (empty($page)) $page = 1;
if (empty($per)) $per = 5;
return array($page, $per);
}
/**
* @param null $page
* @param null $per
* @return object|stdClass
*/
public function paginateProducts($page = null, $per = null)
{
return $this->paginate('products', $page, $per);
}
/**
* @param null $page
* @param null $per
* @return object|stdClass
*/
public function paginateOrders($page = null, $per = null)
{
return $this->paginate('orders', $page, $per);
}
/**
* @param $resource
* @param int $page
* @param int $per
* @return object|stdClass
*/
public function paginate($resource, $page = 1, $per = 5)
{
if (($sync = $this->engine($resource))) {
return $sync->compile($page, $per);
}
return (object) array(
'endpoint' => $resource,
'page' => $page,
'count' => 0,
'stuffed' => false,
'items' => array(),
);
}
/**
* @param $resource
* @return bool|MailChimp_WooCommerce_Transform_Orders|MailChimp_WooCommerce_Transform_Products|MailChimp_WooCommerce_Transform_Coupons
*/
public function engine($resource)
{
switch ($resource) {
case 'products' :
return new MailChimp_WooCommerce_Transform_Products();
break;
case 'orders' :
return new MailChimp_WooCommerce_Transform_Orders();
break;
case 'coupons':
return new MailChimp_WooCommerce_Transform_Coupons();
default:
return false;
}
}
}

View File

@@ -0,0 +1,162 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/8/16
* Time: 4:16 PM
*/
class MailChimp_WooCommerce_CreateListSubmission
{
/**
* @var array
*/
protected $props = array();
/**
* @param $name
* @return $this
*/
public function setName($name)
{
$this->props['name'] = $name;
return $this;
}
/**
* @param $bool
* @return $this
*/
public function setUseArchiveBar($bool)
{
$this->props['use_archive_bar'] = (bool) $bool;
return $this;
}
/**
* @param $reminder
* @return $this
*/
public function setPermissionReminder($reminder)
{
$this->props['permission_reminder'] = $reminder;
return $this;
}
/**
* @param $email
* @return $this
*/
public function setNotifyOnSubscribe($email)
{
$this->props['notify_on_subscribe'] = $email;
return $this;
}
/**
* @param string $email
* @return $this
*/
public function setNotifyOnUnSubscribe($email)
{
$this->props['notify_on_unsubscribe'] = $email;
return $this;
}
/**
* @param $bool
* @return $this
*/
public function setEmailTypeOption($bool)
{
$this->props['email_type_option'] = (bool) $bool;
return $this;
}
/**
* @param bool $public
* @return $this
*/
public function setVisibility($public = true)
{
$this->props['visibility'] = $public ? 'pub' : 'prv';
return $this;
}
/**
* @param $name
* @param $email
* @param $subject
* @param string $language
* @return $this
*/
public function setCampaignDefaults($name, $email, $subject, $language = 'en')
{
$this->props['campaign_defaults'] = array(
'from_name' => $name,
'from_email' => $email,
'subject' => $subject,
'language' => $language,
);
return $this;
}
/**
* @param MailChimp_WooCommerce_Address $address
* @return $this
*/
public function setContact(MailChimp_WooCommerce_Address $address)
{
$data = array();
if (($company = $address->getCompany()) && !empty($company)) {
$data['company'] = $company;
}
if (($street = $address->getAddress1()) && !empty($address)) {
$data['address1'] = $street;
}
if (($city = $address->getCity()) && !empty($city)) {
$data['city'] = $city;
}
if (($state = $address->getProvince()) && !empty($state)) {
$data['state'] = $state;
}
if (($zip = $address->getPostalCode()) && !empty($zip)) {
$data['zip'] = $zip;
}
if (($country = $address->getCountry()) && !empty($country)) {
$data['country'] = $country;
}
if (($phone = $address->getPhone()) && !empty($phone)) {
$data['phone'] = $phone;
}
$this->props['contact'] = $data;
return $this;
}
/**
* @return array
*/
public function getSubmission()
{
return $this->props;
}
}

View File

@@ -0,0 +1,136 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 10/06/17
* Time: 8:29 AM
*/
class MailChimp_WooCommerce_Transform_Coupons
{
/**
* @param int $page
* @param int $limit
* @return \stdClass
*/
public function compile($page = 1, $limit = 5)
{
$response = (object) array(
'endpoint' => 'coupons',
'page' => $page ? $page : 1,
'limit' => (int) $limit,
'count' => 0,
'stuffed' => false,
'items' => array(),
);
if ((($coupons = $this->getCouponPosts($page, $limit)) && !empty($coupons))) {
foreach ($coupons as $post) {
$response->items[] = $this->transform($post->ID);
$response->count++;
}
}
$response->stuffed = ($response->count > 0 && (int) $response->count === (int) $limit) ? true : false;
return $response;
}
/**
* @param int $post_id
* @return MailChimp_WooCommerce_PromoCode
*/
public function transform($post_id)
{
$resource = new WC_Coupon($post_id);
$valid = true;
if (($exp = $resource->get_date_expires()) && current_time('timestamp', true) > $exp->getTimestamp()) {
$valid = false;
}
$rule = new MailChimp_WooCommerce_PromoRule();
$rule->setId($resource->get_id());
$rule->setTitle($resource->get_code());
$rule->setDescription($resource->get_description());
$rule->setEnabled($valid);
$rule->setAmount($resource->get_amount('edit'));
if (!$rule->getDescription()) {
$rule->setDescription($resource->get_code());
}
switch ($resource->get_discount_type()) {
case 'fixed_product':
$rule->setTypeFixed();
$rule->setTargetTypePerItem();
break;
case 'fixed_cart':
$rule->setTypeFixed();
$rule->setTargetTypeTotal();
break;
case 'percent':
$rule->setTypePercentage();
$rule->setTargetTypeTotal();
$rule->setAmount(($resource->get_amount('edit')/100));
break;
}
if (($exp = $resource->get_date_expires())) {
$rule->setEndsAt($exp);
}
$code = new MailChimp_WooCommerce_PromoCode();
$code->setId($resource->get_id());
$code->setCode($resource->get_code());
$code->setEnabled($valid);
$code->setRedemptionURL(get_home_url());
$code->setUsageCount($resource->get_usage_count());
// attach the rule for use.
$code->attachPromoRule($rule);
return $code;
}
/**
* @param int $page
* @param int $posts
* @return array|bool
*/
public function getCouponPosts($page = 1, $posts = 5)
{
$coupons = get_posts(array(
'post_type' => array_merge(array_keys(wc_get_product_types()), array('shop_coupon')),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'ID',
'order' => 'ASC',
));
if (empty($coupons)) {
sleep(2);
$coupons = get_posts(array(
'post_type' => array_merge(array_keys(wc_get_product_types()), array('shop_coupon')),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'ID',
'order' => 'ASC',
));
if (empty($coupons)) {
return false;
}
}
return $coupons;
}
}

View File

@@ -0,0 +1,381 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/13/16
* Time: 8:29 AM
*/
class MailChimp_WooCommerce_Transform_Orders
{
public $campaign_id = null;
/**
* @param int $page
* @param int $limit
* @return \stdClass
*/
public function compile($page = 1, $limit = 5)
{
$response = (object) array(
'endpoint' => 'orders',
'page' => $page ? $page : 1,
'limit' => (int) $limit,
'count' => 0,
'valid' => 0,
'drafts' => 0,
'stuffed' => false,
'items' => array(),
);
if ((($orders = $this->getOrderPosts($page, $limit)) && !empty($orders))) {
foreach ($orders as $post) {
$response->count++;
if ($post->post_status === 'auto-draft') {
$response->drafts++;
continue;
}
$order = $this->transform($post);
if (!$order->isFlaggedAsAmazonOrder()) {
$response->valid++;
$response->items[] = $order;
}
}
}
$response->stuffed = ($response->count > 0 && (int) $response->count === (int) $limit) ? true : false;
return $response;
}
/**
* @param WP_Post $post
* @return MailChimp_WooCommerce_Order
*/
public function transform(WP_Post $post)
{
$woo = new WC_Order($post);
$order = new MailChimp_WooCommerce_Order();
// just skip these altogether because we can't submit any amazon orders anyway.
if (mailchimp_string_contains($woo->get_billing_email(), '@marketplace.amazon.com')) {
return $order->flagAsAmazonOrder(true);
}
$order->setId($woo->get_order_number());
// if we have a campaign id let's set it now.
if (!empty($this->campaign_id)) {
$order->setCampaignId($this->campaign_id);
}
$order->setProcessedAt($woo->get_date_created()->setTimezone(new \DateTimeZone('UTC')));
$order->setCurrencyCode($woo->get_currency());
// grab the current statuses - this will end up being custom at some point.
$statuses = $this->getOrderStatuses();
// grab the order status
$status = $woo->get_status();
// map the fulfillment and financial statuses based on the map above.
$fulfillment_status = array_key_exists($status, $statuses) ? $statuses[$status]->fulfillment : null;
$financial_status = array_key_exists($status, $statuses) ? $statuses[$status]->financial : $status;
// set the fulfillment_status
$order->setFulfillmentStatus($fulfillment_status);
// set the financial status
$order->setFinancialStatus($financial_status);
// if the status is processing, we need to send this one first, then send a 'paid' status right after.
if ($status === 'processing') {
$order->confirmAndPay(true);
}
// only set this if the order is cancelled.
if ($status === 'cancelled') {
$order->setCancelledAt($woo->get_date_modified()->setTimezone(new \DateTimeZone('UTC')));
}
// set the total
$order->setOrderTotal($woo->get_total());
// set the order URL
$order->setOrderURL($woo->get_view_order_url());
// if we have any tax
$order->setTaxTotal($woo->get_total_tax());
// if we have shipping.
$order->setShippingTotal($woo->get_shipping_total());
// set the order discount
$order->setDiscountTotal($woo->get_total_discount());
// set the customer
$order->setCustomer($this->buildCustomerFromOrder($woo));
// apply the addresses to the order
$order->setShippingAddress($this->transformShippingAddress($woo));
$order->setBillingAddress($this->transformBillingAddress($woo));
// loop through all the order items
foreach ($woo->get_items() as $key => $order_detail) {
/** @var WC_Order_Item_Product $order_detail */
// add it into the order item container.
$item = $this->transformLineItem($key, $order_detail);
// if we don't have a product post with this id, we need to add a deleted product to the MC side
if (!($product = $order_detail->get_product()) || 'trash' === $product->get_status()) {
$pid = $order_detail->get_product_id();
// check if it exists, otherwise create a new one.
if (($deleted_product = MailChimp_WooCommerce_Transform_Products::deleted($pid))) {
// swap out the old item id and product variant id with the deleted version.
$item->setProductId("deleted_{$pid}");
$item->setProductVariantId("deleted_{$pid}");
// add the item and continue on the loop.
$order->addItem($item);
continue;
}
mailchimp_log('order.items.error', "Order #{$woo->get_id()} :: Product {$pid} does not exist!");
continue;
}
$order->addItem($item);
}
//if (($refund = $woo->get_total_refunded()) && $refund > 0){
// this is where we would be altering the submission to tell us about the refund.
//}
return $order;
}
/**
* @param WC_Order $order
* @return MailChimp_WooCommerce_Customer
*/
public function buildCustomerFromOrder(WC_Order $order)
{
$customer = new MailChimp_WooCommerce_Customer();
$customer->setId(md5(trim(strtolower($order->get_billing_email()))));
$customer->setCompany($order->get_billing_company());
$customer->setEmailAddress(trim($order->get_billing_email()));
$customer->setFirstName($order->get_billing_first_name());
$customer->setLastName($order->get_billing_last_name());
$customer->setAddress($this->transformBillingAddress($order));
if (!($stats = $this->getCustomerOrderTotals($order->get_user_id()))) {
$stats = (object) array('count' => 0, 'total' => 0);
}
$customer->setOrdersCount($stats->count);
$customer->setTotalSpent($stats->total);
// we are saving the post meta for subscribers on each order... so if they have subscribed on checkout
$subscriber_meta = get_post_meta($order->get_id(), 'mailchimp_woocommerce_is_subscribed', true);
$subscribed_on_order = $subscriber_meta === '' ? false : (bool) $subscriber_meta;
$customer->setOptInStatus($subscribed_on_order);
// if they didn't subscribe on the order, we need to check to make sure they're not already a subscriber
// if they are, we just need to make sure that we don't unsubscribe them just because they unchecked this box.
if (!$subscribed_on_order) {
try {
$subscriber = mailchimp_get_api()->member(mailchimp_get_list_id(), $customer->getEmailAddress());
$status = !in_array($subscriber['status'], array('unsubscribed', 'transactional'));
$customer->setOptInStatus($status);
} catch (\Exception $e) {}
}
return $customer;
}
/**
* @param $key
* @param WC_Order_Item_Product $order_detail
* @return MailChimp_WooCommerce_LineItem
*/
protected function transformLineItem($key, $order_detail)
{
// fire up a new MC line item
$item = new MailChimp_WooCommerce_LineItem();
$item->setId($key);
$item->setPrice($order_detail->get_total());
$item->setProductId($order_detail->get_product_id());
$variation_id = $order_detail->get_variation_id();
if (empty($variation_id)) $variation_id = $order_detail->get_product_id();
$item->setProductVariantId($variation_id);
$item->setQuantity($order_detail->get_quantity());
if ($item->getQuantity() > 1) {
$current_price = $item->getPrice();
$price = ($current_price/$item->getQuantity());
$item->setPrice($price);
}
return $item;
}
/**
* @param WC_Order $order
* @return MailChimp_WooCommerce_Address
*/
public function transformBillingAddress(WC_Order $order)
{
// use the info from the order to compile an address.
$address = new MailChimp_WooCommerce_Address();
$address->setAddress1($order->get_billing_address_1());
$address->setAddress2($order->get_billing_address_2());
$address->setCity($order->get_billing_city());
$address->setProvince($order->get_billing_state());
$address->setPostalCode($order->get_billing_postcode());
$address->setCountry($order->get_billing_country());
$address->setPhone($order->get_billing_phone());
$bfn = $order->get_billing_first_name();
$bln = $order->get_billing_last_name();
// if we have billing names set it here
if (!empty($bfn) && !empty($bln)) {
$address->setName("{$bfn} {$bln}");
}
return $address;
}
/**
* @param WC_Order $order
* @return MailChimp_WooCommerce_Address
*/
public function transformShippingAddress(WC_Order $order)
{
$address = new MailChimp_WooCommerce_Address();
$address->setAddress1($order->get_shipping_address_1());
$address->setAddress2($order->get_shipping_address_2());
$address->setCity($order->get_shipping_city());
$address->setProvince($order->get_shipping_state());
$address->setPostalCode($order->get_shipping_postcode());
$address->setCountry($order->get_shipping_country());
// shipping does not have a phone number, so maybe use this?
$address->setPhone($order->get_billing_phone());
$sfn = $order->get_shipping_first_name();
$sln = $order->get_shipping_last_name();
// if we have billing names set it here
if (!empty($sfn) && !empty($sln)) {
$address->setName("{$sfn} {$sln}");
}
return $address;
}
/**
* @param int $page
* @param int $posts
* @return array|bool
*/
public function getOrderPosts($page = 1, $posts = 5)
{
$params = array(
'post_type' => wc_get_order_types(),
'post_status' => array_keys(wc_get_order_statuses()),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'id',
'order' => 'ASC',
);
$orders = get_posts($params);
if (empty($orders)) {
sleep(2);
$orders = get_posts($params);
}
return empty($orders) ? false : $orders;
}
/**
* returns an object with a 'total' and a 'count'.
*
* @param $user_id
* @return object
*/
public function getCustomerOrderTotals($user_id)
{
$customer = new WC_Customer($user_id);
$customer->get_order_count();
$customer->get_total_spent();
return (object) array(
'count' => $customer->get_order_count(),
'total' => $customer->get_total_spent()
);
}
/**
* "Pending payment" in the UI fires the order confirmation email MailChimp
* "Completed” in the UI fires the MailChimp Order Invoice
* "Cancelled" does what we think it does
*
* @return array
*/
public function getOrderStatuses()
{
return array(
// Order received (unpaid)
'pending' => (object) array(
'financial' => 'pending',
'fulfillment' => null
),
// Payment received and stock has been reduced the order is awaiting fulfillment.
// All product orders require processing, except those for digital downloads
'processing' => (object) array(
'financial' => 'pending',
'fulfillment' => null
),
// Awaiting payment stock is reduced, but you need to confirm payment
'on-hold' => (object) array(
'financial' => 'on-hold',
'fulfillment' => null
),
// Order fulfilled and complete requires no further action
'completed' => (object) array(
'financial' => 'fulfilled',
'fulfillment' => 'fulfilled'
),
// Cancelled by an admin or the customer no further action required
'cancelled' => (object) array(
'financial' => 'cancelled',
'fulfillment' => null
),
// Refunded by an admin no further action required
'refunded' => (object) array(
'financial' => 'refunded',
'fulfillment' => null
),
// Payment failed or was declined (unpaid). Note that this status may not show immediately and
// instead show as Pending until verified (i.e., PayPal)
'failed' => (object) array(
'financial' => 'failed',
'fulfillment' => null
),
);
}
}

View File

@@ -0,0 +1,536 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@mailchimp.com
* Date: 7/13/16
* Time: 8:29 AM
*/
class MailChimp_WooCommerce_Transform_Orders
{
public $campaign_id = null;
protected $use_user_address = false;
/**
* @param int $page
* @param int $limit
* @return \stdClass
*/
public function compile($page = 1, $limit = 5)
{
$response = (object) array(
'endpoint' => 'orders',
'page' => $page ? $page : 1,
'limit' => (int) $limit,
'count' => 0,
'valid' => 0,
'drafts' => 0,
'stuffed' => false,
'items' => array(),
);
if ((($orders = $this->getOrderPosts($page, $limit)) && !empty($orders))) {
foreach ($orders as $post) {
$response->count++;
if ($post->post_status === 'auto-draft') {
$response->drafts++;
continue;
}
$order = $this->transform($post);
if (!$order->isFlaggedAsAmazonOrder()) {
$response->valid++;
$response->items[] = $order;
}
}
}
$response->stuffed = ($response->count > 0 && (int) $response->count === (int) $limit) ? true : false;
return $response;
}
/**
* @param WC_Order $woo
* @return array
*/
protected function dates(WC_Order $woo)
{
if (method_exists($woo, 'get_date_modified')) {
$created_at = $woo->get_date_modified();
$updated_at = $woo->get_date_modified();
} elseif (property_exists($woo, 'order_date') && property_exists($woo, 'modified_date')) {
$created_at = $woo->order_date ? new \DateTime($woo->order_date) : null;
$updated_at = $woo->modified_date ? new \DateTime($woo->modified_date) : null;
} else {
$created_at = $updated_at = new \DateTime();
}
return array($created_at, $updated_at);
}
/**
* @param WP_Post $post
* @return MailChimp_WooCommerce_Order
*/
public function transform(WP_Post $post)
{
$woo = new WC_Order($post);
$order = new MailChimp_WooCommerce_Order();
$order->setId($woo->get_order_number());
// just skip these altogether because we can't submit any amazon orders anyway.
if (mailchimp_string_contains($woo->billing_email, '@marketplace.amazon.com')) {
return $order->flagAsAmazonOrder(true);
}
// if we have a campaign id let's set it now.
if (!empty($this->campaign_id)) {
$order->setCampaignId($this->campaign_id);
}
$order->setProcessedAt($woo->get_date_created()->setTimezone(new \DateTimeZone('UTC')));
$order->setCurrencyCode($woo->get_currency());
// grab the current statuses - this will end up being custom at some point.
$statuses = $this->getOrderStatuses();
// grab the order status
$status = $woo->get_status();
// map the fulfillment and financial statuses based on the map above.
$fulfillment_status = array_key_exists($status, $statuses) ? $statuses[$status]->fulfillment : null;
$financial_status = array_key_exists($status, $statuses) ? $statuses[$status]->financial : $status;
// set the fulfillment_status
$order->setFulfillmentStatus($fulfillment_status);
// set the financial status
$order->setFinancialStatus($financial_status);
// if the status is processing, we need to send this one first, then send a 'paid' status right after.
if ($status === 'processing') {
$order->confirmAndPay(true);
}
// only set this if the order is cancelled.
if ($status === 'cancelled') {
$order->setCancelledAt($woo->get_date_modified()->setTimezone(new \DateTimeZone('UTC')));
}
// set the total
$order->setOrderTotal($woo->get_total());
// set the order URL
$order->setOrderURL($woo->get_view_order_url());
// if we have any tax
$order->setTaxTotal($woo->get_total_tax());
// if we have shipping.
$order->setShippingTotal($woo->get_total_shipping());
// set the order discount
$order->setDiscountTotal($woo->get_total_discount());
// set the customer
$order->setCustomer($this->buildCustomerFromOrder($woo));
// apply the addresses to the order
$addresses = $this->getOrderAddresses($woo);
$order->setShippingAddress($addresses->shipping);
$order->setBillingAddress($addresses->billing);
// loop through all the order items
foreach ($woo->get_items() as $key => $order_detail) {
// add it into the order item container.
$item = $this->buildLineItem($key, $order_detail);
// if we don't have a product post with this id, we need to add a deleted product to the MC side
if (!($product_post = get_post($item->getProductId()))) {
// check if it exists, otherwise create a new one.
if (($deleted_product = MailChimp_WooCommerce_Transform_Products::deleted($item->getProductId()))) {
$deleted_product_id = "deleted_{$item->getProductId()}";
// swap out the old item id and product variant id with the deleted version.
$item->setProductId($deleted_product_id);
$item->setProductVariantId($deleted_product_id);
// add the item and continue on the loop.
$order->addItem($item);
continue;
}
mailchimp_log('order.items.error', "Order #{$woo->get_order_number()} :: Product {$item->getProductId()} does not exist!");
continue;
}
$order->addItem($item);
}
// apply the coupon discounts
if (function_exists('wc_get_coupon_id_by_code') && ($used_coupons = $woo->get_used_coupons()) && is_array($used_coupons)) {
foreach ($used_coupons as $coupon_code) {
if (($coupon_id = wc_get_coupon_id_by_code($coupon_code))) {
$coupon = new WC_Coupon($coupon_id);
$is_percentage = $coupon->get_discount_type() === 'percent';
$order->addDiscount($coupon_code, $coupon->get_amount('edit'), $is_percentage);
}
}
}
//if (($refund = $woo->get_total_refunded()) && $refund > 0){
// this is where we would be altering the submission to tell us about the refund.
//}
return $order;
}
/**
* @param WC_Order $order
* @return MailChimp_WooCommerce_Customer
*/
public function buildCustomerFromOrder(WC_Order $order)
{
$customer = new MailChimp_WooCommerce_Customer();
$customer->setId(md5(trim(strtolower($order->billing_email))));
$customer->setCompany($order->billing_company);
$customer->setEmailAddress(trim($order->billing_email));
$customer->setFirstName($order->billing_first_name);
$customer->setLastName($order->billing_last_name);
$customer->setOrdersCount(1);
$customer->setTotalSpent($order->get_total());
// we are saving the post meta for subscribers on each order... so if they have subscribed on checkout
$subscriber_meta = get_post_meta($order->get_id(), 'mailchimp_woocommerce_is_subscribed', true);
$subscribed_on_order = $subscriber_meta === '' ? false : (bool) $subscriber_meta;
$customer->setOptInStatus($subscribed_on_order);
// if they didn't subscribe on the order, we need to check to make sure they're not already a subscriber
// if they are, we just need to make sure that we don't unsubscribe them just because they unchecked this box.
if (!$subscribed_on_order) {
try {
$subscriber = mailchimp_get_api()->member(mailchimp_get_list_id(), $customer->getEmailAddress());
$status = !in_array($subscriber['status'], array('unsubscribed', 'transactional'));
$customer->setOptInStatus($status);
} catch (\Exception $e) {}
}
// use the info from the order to compile an address.
$address = new MailChimp_WooCommerce_Address();
$address->setAddress1($order->billing_address_1);
$address->setAddress2($order->billing_address_2);
$address->setCity($order->billing_city);
$address->setProvince($order->billing_state);
$address->setPostalCode($order->billing_postcode);
$address->setCountry($order->billing_country);
$address->setPhone($order->billing_phone);
// if we have billing names set it here
if (!empty($order->billing_first_name) && !empty($order->billing_last_name)) {
$address->setName($order->billing_first_name.' '.$order->billing_last_name);
}
$customer->setAddress($address);
if (($user = get_userdata($order->customer_user))) {
/**
* IF we wanted to use the user data instead we would do it here.
* but we discussed using the billing address instead.
*/
if ($this->use_user_address) {
$customer->setId($user->ID);
$customer->setEmailAddress($user->user_email);
$customer->setFirstName($user->first_name);
$customer->setLastName($user->last_name);
if (($address = $this->getUserAddress($user->ID))) {
if (count($address->toArray()) > 3) {
$customer->setAddress($address);
}
}
}
if (!($stats = $this->getCustomerOrderTotals($order->customer_user))) {
$stats = (object) array('count' => 0, 'total' => 0);
}
$customer->setOrdersCount($stats->count);
$customer->setTotalSpent($stats->total);
}
return $customer;
}
/**
* @param $key
* @param $order_detail
* @return MailChimp_WooCommerce_LineItem
*/
protected function buildLineItem($key, $order_detail)
{
// fire up a new MC line item
$item = new MailChimp_WooCommerce_LineItem();
$item->setId($key);
if (isset($order_detail['item_meta']) && is_array($order_detail['item_meta'])) {
foreach ($order_detail['item_meta'] as $meta_key => $meta_data_array) {
if (!isset($meta_data_array[0])) {
continue;
}
switch ($meta_key) {
case '_line_subtotal':
$item->setPrice($meta_data_array[0]);
break;
case '_product_id':
$item->setProductId($meta_data_array[0]);
break;
case '_variation_id':
$item->setProductVariantId($meta_data_array[0]);
break;
case '_qty':
$item->setQuantity($meta_data_array[0]);
break;
}
}
if ($item->getProductVariantId() <= 0) {
$item->setProductVariantId($item->getProductId());
}
} elseif (isset($order_detail['item_meta_array']) && is_array($order_detail['item_meta_array'])) {
/// Some users have the newer version of the item meta.
foreach ($order_detail['item_meta_array'] as $meta_id => $object) {
if (!isset($object->key)) {
continue;
}
switch ($object->key) {
case '_line_subtotal':
$item->setPrice($object->value);
break;
case '_product_id':
$item->setProductId($object->value);
break;
case '_variation_id':
$item->setProductVariantId($object->value);
break;
case '_qty':
$item->setQuantity($object->value);
break;
}
}
if ($item->getProductVariantId() <= 0) {
$item->setProductVariantId($item->getProductId());
}
}
if ($item->getQuantity() > 1) {
$current_price = $item->getPrice();
$price = ($current_price/$item->getQuantity());
$item->setPrice($price);
}
return $item;
}
/**
* @param int $page
* @param int $posts
* @return array|bool
*/
public function getOrderPosts($page = 1, $posts = 5)
{
$params = array(
'post_type' => 'shop_order',
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'id',
'order' => 'ASC',
);
$orders = get_posts($params);
if (empty($orders)) {
sleep(2);
$orders = get_posts($params);
}
return empty($orders) ? false : $orders;
}
/**
* returns an object with a 'total' and a 'count'.
*
* @param $user_id
* @return object
*/
public function getCustomerOrderTotals($user_id)
{
$stats = (object) array('count' => 0, 'total' => 0);
if (!empty($user_id)) {
$orders = get_posts(apply_filters('woocommerce_my_account_my_orders_query', array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_order',
'post_status' => 'publish'
)));
foreach ($orders as $order) {
$woo = new WC_Order($order);
$stats->total += $woo->get_total();
$stats->count++;
}
return $stats;
}
return false;
}
/**
* @param WC_Order $order
* @return object
*/
public function getOrderAddresses(WC_Order $order)
{
// use the info from the order to compile an address.
$billing = new MailChimp_WooCommerce_Address();
$billing->setAddress1($order->billing_address_1);
$billing->setAddress2($order->billing_address_2);
$billing->setCity($order->billing_city);
$billing->setProvince($order->billing_state);
$billing->setPostalCode($order->billing_postcode);
$billing->setCountry($order->billing_country);
$billing->setPhone($order->billing_phone);
// if we have billing names go ahead and apply them
if (!empty($order->billing_first_name) && !empty($order->billing_last_name)) {
$billing->setName($order->billing_first_name.' '.$order->billing_last_name);
}
$shipping = new MailChimp_WooCommerce_Address();
$shipping->setAddress1($order->shipping_address_1);
$shipping->setAddress2($order->shipping_address_2);
$shipping->setCity($order->shipping_city);
$shipping->setProvince($order->shipping_state);
$shipping->setPostalCode($order->shipping_postcode);
$shipping->setCountry($order->shipping_country);
if (isset($order->shipping_phone)) {
$shipping->setPhone($order->shipping_phone);
}
// if we have shipping names go ahead and apply them
if (!empty($order->shipping_first_name) && !empty($order->shipping_last_name)) {
$shipping->setName($order->shipping_first_name.' '.$order->shipping_last_name);
}
return (object) array('billing' => $billing, 'shipping' => $shipping);
}
/**
* @param $user_id
* @param string $type
* @return MailChimp_WooCommerce_Address
*/
public function getUserAddress($user_id, $type = 'billing')
{
$address = new MailChimp_WooCommerce_Address();
// pull all the meta for this user.
$meta = get_user_meta($user_id);
// loop through all the possible address properties, and if we have on on the user, set the property
// because it's more up to date.
$address_props = array(
$type.'_address_1' => 'setAddress1',
$type.'_address_2' => 'setAddress2',
$type.'_city' => 'setCity',
$type.'_state' => 'setProvince',
$type.'_postcode' => 'setPostalCode',
$type.'_country' => 'setCountry',
$type.'_phone' => 'setPhone',
);
// loop through all the address properties and set the values if we have one.
foreach ($address_props as $address_key => $address_call) {
if (isset($meta[$address_key]) && !empty($meta[$address_key]) && isset($meta[$address_key][0])) {
$address->$address_call($meta[$address_key][0]);
}
}
return $address;
}
/**
* @return array
*/
public function getOrderStatuses()
{
return array(
// Order received (unpaid)
'pending' => (object) array(
'financial' => 'pending',
'fulfillment' => null
),
// Payment received and stock has been reduced the order is awaiting fulfillment.
// All product orders require processing, except those for digital downloads
'processing' => (object) array(
'financial' => 'pending',
'fulfillment' => null
),
// Awaiting payment stock is reduced, but you need to confirm payment
'on-hold' => (object) array(
'financial' => 'on-hold',
'fulfillment' => null
),
// Order fulfilled and complete requires no further action
'completed' => (object) array(
'financial' => 'fulfilled',
'fulfillment' => 'fulfilled'
),
// Cancelled by an admin or the customer no further action required
'cancelled' => (object) array(
'financial' => 'cancelled',
'fulfillment' => null
),
// Refunded by an admin no further action required
'refunded' => (object) array(
'financial' => 'refunded',
'fulfillment' => null
),
// Payment failed or was declined (unpaid). Note that this status may not show immediately and
// instead show as Pending until verified (i.e., PayPal)
'failed' => (object) array(
'financial' => 'failed',
'fulfillment' => null
),
);
}
}

View File

@@ -0,0 +1,283 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/13/16
* Time: 8:29 AM
*/
class MailChimp_WooCommerce_Transform_Products
{
/**
* @param int $page
* @param int $limit
* @return \stdClass
*/
public function compile($page = 1, $limit = 5)
{
$response = (object) array(
'endpoint' => 'products',
'page' => $page ? $page : 1,
'limit' => (int) $limit,
'count' => 0,
'stuffed' => false,
'items' => array(),
);
if ((($products = $this->getProductPosts($page, $limit)) && !empty($products))) {
foreach ($products as $post) {
$response->items[] = $this->transform($post);
$response->count++;
}
}
$response->stuffed = ($response->count > 0 && (int) $response->count === (int) $limit) ? true : false;
return $response;
}
/**
* @param WP_Post $post
* @return MailChimp_WooCommerce_Product
*/
public function transform(WP_Post $post)
{
if (!($woo = wc_get_product($post))) {
return $this->wooProductNotLoadedCorrectly($post);
}
$variant_posts = $this->getProductVariantPosts($post->ID);
$variants = $variant_posts ? array_merge(array($woo), $variant_posts) : array($woo);
$is_variant = count($variants) > 1;
$product = new MailChimp_WooCommerce_Product();
$product->setId($woo->get_id());
$product->setHandle($post->post_name);
$product->setImageUrl($this->getProductImage($post));
$product->setDescription($post->post_content);
$product->setPublishedAtForeign(mailchimp_date_utc($post->post_date));
$product->setTitle($woo->get_title());
$product->setUrl($woo->get_permalink());
foreach ($variants as $variant) {
$product_variant = $this->variant($is_variant, $variant, $woo->get_title());
$product_variant_title = $product_variant->getTitle();
if (empty($product_variant_title)) {
$product_variant->setTitle($woo->get_title());
}
$product_variant_image = $product_variant->getImageUrl();
if (empty($product_variant_image)) {
$product_variant->setImageUrl($product->getImageUrl());
}
$product->addVariant($product_variant);
}
return $product;
}
/**
* @param $is_variant
* @param WP_Post $post
* @param string $fallback_title
* @return MailChimp_WooCommerce_ProductVariation
*/
public function variant($is_variant, $post, $fallback_title = null)
{
if ($post instanceof WC_Product || $post instanceof WC_Product_Variation) {
$woo = $post;
} else {
if (isset($post->post_type) && $post->post_type === 'product_variation') {
$woo = new WC_Product_Variation($post->ID);
} else {
$woo = wc_get_product($post);
}
}
$variant = new MailChimp_WooCommerce_ProductVariation();
$variant->setId($woo->get_id());
$variant->setUrl($woo->get_permalink());
$variant->setImageUrl($this->getProductImage($post));
$variant->setPrice($woo->get_price());
$variant->setSku($woo->get_sku());
$variant->setBackorders($woo->backorders_allowed());
// only set these properties if the product is currently visible or purchasable.
if ($woo->is_purchasable() && $woo->is_visible()) {
if ($woo->is_in_stock()) {
$variant->setInventoryQuantity(($woo->managing_stock() ? $woo->get_stock_quantity() : 1000000));
} else {
$variant->setInventoryQuantity(0);
}
} else {
$variant->setInventoryQuantity(0);
}
if ($woo instanceof WC_Product_Variation) {
$variation_title = $woo->get_title();
if (empty($variation_title)) $variation_title = $fallback_title;
$title = array($variation_title);
foreach ($woo->get_variation_attributes() as $attribute => $value) {
if (is_string($value)) {
$name = ucfirst(str_replace(array('attribute_pa_', 'attribute_'), '', $attribute));
$title[] = "$name = $value";
}
}
$variant->setTitle(implode(' :: ', $title));
$variant->setVisibility(($woo->variation_is_visible() ? 'visible' : ''));
} else {
$variant->setVisibility(($woo->is_visible() ? 'visible' : ''));
$variant->setTitle($woo->get_title());
}
return $variant;
}
/**
* @param int $page
* @param int $posts
* @return array|bool
*/
public function getProductPosts($page = 1, $posts = 5)
{
$products = get_posts(array(
'post_type' => array_merge(array_keys(wc_get_product_types()), array('product')),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'ID',
'order' => 'ASC',
));
if (empty($products)) {
sleep(2);
$products = get_posts(array(
'post_type' => array_merge(array_keys(wc_get_product_types()), array('product')),
'posts_per_page' => $posts,
'paged' => $page,
'orderby' => 'ID',
'order' => 'ASC',
));
if (empty($products)) {
return false;
}
}
return $products;
}
/**
* @param $id
* @return array|bool
*/
public function getProductVariantPosts($id)
{
$variants = get_posts(array(
'numberposts' => 99999,
'order' => 'ASC',
'orderby' => 'ID',
'post_type' => 'product_variation',
'post_parent' => $id,
));
if (empty($variants)) {
return false;
}
return $variants;
}
/**
* @param $post_id
* @return false|string
*/
public function getProductImage($post_id)
{
$meta = get_post_meta($post_id);
$key = '_thumbnail_id';
$image_key = $this->getProductImageKey();
if ($meta && is_array($meta) && array_key_exists($key, $meta) && isset($meta[$key][0])) {
$img = wp_get_attachment_image($meta[$key][0], $image_key);
if (!empty($img)) return $img;
}
return get_the_post_thumbnail_url($post_id, $image_key);
}
/**
* @return null|string
*/
public function getProductImageKey()
{
return mailchimp_get_option('mailchimp_product_image_key', 'medium');
}
/**
* @param $id
* @return bool|MailChimp_WooCommerce_Product
* @throws Exception
*/
public static function deleted($id)
{
$store_id = mailchimp_get_store_id();
$api = mailchimp_get_api();
if (!($product = $api->getStoreProduct($store_id, "deleted_{$id}"))) {
$product = new MailChimp_WooCommerce_Product();
$product->setId("deleted_{$id}");
$product->setTitle("deleted_{$id}");
$variant = new MailChimp_WooCommerce_ProductVariation();
$variant->setId("deleted_{$id}");
$variant->setTitle("deleted_{$id}");
$product->addVariant($variant);
return $api->addStoreProduct($store_id, $product);
}
return $product;
}
/**
* @param \WP_Post $post
* @return MailChimp_WooCommerce_Product
*/
protected function wooProductNotLoadedCorrectly($post)
{
$product = new MailChimp_WooCommerce_Product();
$product->setId($post->ID);
$product->setHandle($post->post_name);
$product->setDescription($post->post_content);
$product->setImageUrl($this->getProductImage($post));
$variant = $this->variant(false, $post, $post->post_name);
if (!$variant->getImageUrl()) {
$variant->setImageUrl($product->getImageUrl());
}
$product->addVariant($variant);
return $product;
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Created by PhpStorm.
*
* User: kingpin
* Email: ryan@vextras.com
* Date: 6/18/15
* Time: 11:13 AM
*/
class MailChimp_WooCommerce_Error extends \Exception
{
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Created by PhpStorm.
*
* User: kingpin
* Email: ryan@vextras.com
* Date: 6/18/15
* Time: 11:13 AM
*/
class MailChimp_WooCommerce_ServerError extends MailChimp_WooCommerce_Error
{
}

View File

@@ -0,0 +1,135 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/12/16
* Time: 1:38 PM
*/
class MailChimp_WooCommerce_CurrencyCodes
{
/**
* @return array
*/
public static function all()
{
return array(
'AFA' => array('Afghan Afghani', '971'),
'AWG' => array('Aruban Florin', '533'),
'AUD' => array('Australian Dollars', '036'),
'ARS' => array('Argentine Pes', '032'),
'AZN' => array('Azerbaijanian Manat', '944'),
'BSD' => array('Bahamian Dollar', '044'),
'BDT' => array('Bangladeshi Taka', '050'),
'BBD' => array('Barbados Dollar', '052'),
'BYN' => array('Belarussian Rouble', '974'),
'BOB' => array('Bolivian Boliviano', '068'),
'BRL' => array('Brazilian Real', '986'),
'GBP' => array('British Pounds Sterling', '826'),
'BGN' => array('Bulgarian Lev', '975'),
'KHR' => array('Cambodia Riel', '116'),
'CAD' => array('Canadian Dollars', '124'),
'KYD' => array('Cayman Islands Dollar', '136'),
'CLP' => array('Chilean Peso', '152'),
'CNY' => array('Chinese Renminbi Yuan', '156'),
'COP' => array('Colombian Peso', '170'),
'CRC' => array('Costa Rican Colon', '188'),
'HRK' => array('Croatia Kuna', '191'),
'CPY' => array('Cypriot Pounds', '196'),
'CZK' => array('Czech Koruna', '203'),
'DKK' => array('Danish Krone', '208'),
'DOP' => array('Dominican Republic Peso', '214'),
'XCD' => array('East Caribbean Dollar', '951'),
'EGP' => array('Egyptian Pound', '818'),
'ERN' => array('Eritrean Nakfa', '232'),
'EEK' => array('Estonia Kroon', '233'),
'EUR' => array('Euro', '978'),
'GEL' => array('Georgian Lari', '981'),
'GHC' => array('Ghana Cedi', '288'),
'GIP' => array('Gibraltar Pound', '292'),
'GTQ' => array('Guatemala Quetzal', '320'),
'HNL' => array('Honduras Lempira', '340'),
'HKD' => array('Hong Kong Dollars', '344'),
'HUF' => array('Hungary Forint', '348'),
'ISK' => array('Icelandic Krona', '352'),
'INR' => array('Indian Rupee', '356'),
'IDR' => array('Indonesia Rupiah', '360'),
'ILS' => array('Israel Shekel', '376'),
'JMD' => array('Jamaican Dollar', '388'),
'JPY' => array('Japanese yen', '392'),
'KZT' => array('Kazakhstan Tenge', '368'),
'KES' => array('Kenyan Shilling', '404'),
'KWD' => array('Kuwaiti Dinar', '414'),
'LVL' => array('Latvia Lat', '428'),
'LBP' => array('Lebanese Pound', '422'),
'LTL' => array('Lithuania Litas', '440'),
'MDL' => array('Moldovan Leu', '498'),
'MOP' => array('Macau Pataca', '446'),
'MKD' => array('Macedonian Denar', '807'),
'MGA' => array('Malagascy Ariary', '969'),
'MYR' => array('Malaysian Ringgit', '458'),
'MTL' => array('Maltese Lira', '470'),
'BAM' => array('Marka', '977'),
'MUR' => array('Mauritius Rupee', '480'),
'MXN' => array('Mexican Pesos', '484'),
'MZM' => array('Mozambique Metical', '508'),
'NPR' => array('Nepalese Rupee', '524'),
'ANG' => array('Netherlands Antilles Guilder', '532'),
'TWD' => array('New Taiwanese Dollars', '901'),
'NZD' => array('New Zealand Dollars', '554'),
'NIO' => array('Nicaragua Cordoba', '558'),
'NGN' => array('Nigeria Naira', '566'),
'KPW' => array('North Korean Won', '408'),
'NOK' => array('Norwegian Krone', '578'),
'OMR' => array('Omani Riyal', '512'),
'PKR' => array('Pakistani Rupee', '586'),
'PYG' => array('Paraguay Guarani', '600'),
'PEN' => array('Peru New Sol', '604'),
'PHP' => array('Philippine Pesos', '608'),
'PLN' => array('Polish Zloty', '985'),
'QAR' => array('Qatari Riyal', '634'),
'RON' => array('Romanian New Leu', '946'),
'RUB' => array('Russian Federation Ruble', '643'),
'SAR' => array('Saudi Riyal', '682'),
'CSD' => array('Serbian Dinar', '891'),
'SCR' => array('Seychelles Rupee', '690'),
'SGD' => array('Singapore Dollars', '702'),
'SKK' => array('Slovak Koruna', '703'),
'SIT' => array('Slovenia Tolar', '705'),
'ZAR' => array('South African Rand', '710'),
'KRW' => array('South Korean Won', '410'),
'LKR' => array('Sri Lankan Rupee', '144'),
'SRD' => array('Surinam Dollar', '968'),
'SEK' => array('Swedish Krona', '752'),
'CHF' => array('Swiss Francs', '756'),
'TZS' => array('Tanzanian Shilling', '834'),
'THB' => array('Thai Baht', '764'),
'TTD' => array('Trinidad and Tobago Dollar', '780'),
'TRY' => array('Turkish New Lira', '949'),
'AED' => array('UAE Dirham', '784'),
'USD' => array('US Dollars', '840'),
'UGX' => array('Ugandian Shilling', '800'),
'UAH' => array('Ukraine Hryvna', '980'),
'UYU' => array('Uruguayan Peso', '858'),
'UZS' => array('Uzbekistani Som', '860'),
'VEB' => array('Venezuela Bolivar', '862'),
'VND' => array('Vietnam Dong', '704'),
'AMK' => array('Zambian Kwacha', '894'),
'ZWD' => array('Zimbabwe Dollar', '716'),
);
}
/**
* @return array
*/
public static function lists()
{
$response = array();
foreach (static::all() as $key => $data) {
$response[$key] = $data[0];
}
return $response;
}
}

View File

@@ -0,0 +1,469 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/12/16
* Time: 2:07 PM
*/
class MailChimp_Api_Locales
{
/**
* @return array
*/
public static function all()
{
return array(
"af_NA"=> "Afrikaans (Namibia)",
"af_ZA"=> "Afrikaans (South Africa)",
"af"=> "Afrikaans",
"ak_GH"=> "Akan (Ghana)",
"ak"=> "Akan",
"sq_AL"=> "Albanian (Albania)",
"sq"=> "Albanian",
"am_ET"=> "Amharic (Ethiopia)",
"am"=> "Amharic",
"ar_DZ"=> "Arabic (Algeria)",
"ar_BH"=> "Arabic (Bahrain)",
"ar_EG"=> "Arabic (Egypt)",
"ar_IQ"=> "Arabic (Iraq)",
"ar_JO"=> "Arabic (Jordan)",
"ar_KW"=> "Arabic (Kuwait)",
"ar_LB"=> "Arabic (Lebanon)",
"ar_LY"=> "Arabic (Libya)",
"ar_MA"=> "Arabic (Morocco)",
"ar_OM"=> "Arabic (Oman)",
"ar_QA"=> "Arabic (Qatar)",
"ar_SA"=> "Arabic (Saudi Arabia)",
"ar_SD"=> "Arabic (Sudan)",
"ar_SY"=> "Arabic (Syria)",
"ar_TN"=> "Arabic (Tunisia)",
"ar_AE"=> "Arabic (United Arab Emirates)",
"ar_YE"=> "Arabic (Yemen)",
"ar"=> "Arabic",
"hy_AM"=> "Armenian (Armenia)",
"hy"=> "Armenian",
"as_IN"=> "Assamese (India)",
"as"=> "Assamese",
"asa_TZ"=> "Asu (Tanzania)",
"asa"=> "Asu",
"az_Cyrl"=> "Azerbaijani (Cyrillic)",
"az_Cyrl_AZ"=> "Azerbaijani (Cyrillic, Azerbaijan)",
"az_Latn"=> "Azerbaijani (Latin)",
"az_Latn_AZ"=> "Azerbaijani (Latin, Azerbaijan)",
"az"=> "Azerbaijani",
"bm_ML"=> "Bambara (Mali)",
"bm"=> "Bambara",
"eu_ES"=> "Basque (Spain)",
"eu"=> "Basque",
"be_BY"=> "Belarusian (Belarus)",
"be"=> "Belarusian",
"bem_ZM"=> "Bemba (Zambia)",
"bem"=> "Bemba",
"bez_TZ"=> "Bena (Tanzania)",
"bez"=> "Bena",
"bn_BD"=> "Bengali (Bangladesh)",
"bn_IN"=> "Bengali (India)",
"bn"=> "Bengali",
"bs_BA"=> "Bosnian (Bosnia and Herzegovina)",
"bs"=> "Bosnian",
"bg_BG"=> "Bulgarian (Bulgaria)",
"bg"=> "Bulgarian",
"my_MM"=> "Burmese (Myanmar [Burma])",
"my"=> "Burmese",
"ca_ES"=> "Catalan (Spain)",
"ca"=> "Catalan",
"tzm_Latn"=> "Central Morocco Tamazight (Latin)",
"tzm_Latn_MA"=> "Central Morocco Tamazight (Latin, Morocco)",
"tzm"=> "Central Morocco Tamazight",
"chr_US"=> "Cherokee (United States)",
"chr"=> "Cherokee",
"cgg_UG"=> "Chiga (Uganda)",
"cgg"=> "Chiga",
"zh_Hans"=> "Chinese (Simplified Han)",
"zh_Hans_CN"=> "Chinese (Simplified Han, China)",
"zh_Hans_HK"=> "Chinese (Simplified Han, Hong Kong SAR China)",
"zh_Hans_MO"=> "Chinese (Simplified Han, Macau SAR China)",
"zh_Hans_SG"=> "Chinese (Simplified Han, Singapore)",
"zh_Hant"=> "Chinese (Traditional Han)",
"zh_Hant_HK"=> "Chinese (Traditional Han, Hong Kong SAR China)",
"zh_Hant_MO"=> "Chinese (Traditional Han, Macau SAR China)",
"zh_Hant_TW"=> "Chinese (Traditional Han, Taiwan)",
"zh"=> "Chinese",
"kw_GB"=> "Cornish (United Kingdom)",
"kw"=> "Cornish",
"hr_HR"=> "Croatian (Croatia)",
"hr"=> "Croatian",
"cs_CZ"=> "Czech (Czech Republic)",
"cs"=> "Czech",
"da_DK"=> "Danish (Denmark)",
"da"=> "Danish",
"nl_BE"=> "Dutch (Belgium)",
"nl_NL"=> "Dutch (Netherlands)",
"nl"=> "Dutch",
"ebu_KE"=> "Embu (Kenya)",
"ebu"=> "Embu",
"en_AS"=> "English (American Samoa)",
"en_AU"=> "English (Australia)",
"en_BE"=> "English (Belgium)",
"en_BZ"=> "English (Belize)",
"en_BW"=> "English (Botswana)",
"en_CA"=> "English (Canada)",
"en_GU"=> "English (Guam)",
"en_HK"=> "English (Hong Kong SAR China)",
"en_IN"=> "English (India)",
"en_IE"=> "English (Ireland)",
"en_JM"=> "English (Jamaica)",
"en_MT"=> "English (Malta)",
"en_MH"=> "English (Marshall Islands)",
"en_MU"=> "English (Mauritius)",
"en_NA"=> "English (Namibia)",
"en_NZ"=> "English (New Zealand)",
"en_MP"=> "English (Northern Mariana Islands)",
"en_PK"=> "English (Pakistan)",
"en_PH"=> "English (Philippines)",
"en_SG"=> "English (Singapore)",
"en_ZA"=> "English (South Africa)",
"en_TT"=> "English (Trinidad and Tobago)",
"en_UM"=> "English (U.S. Minor Outlying Islands)",
"en_VI"=> "English (U.S. Virgin Islands)",
"en_GB"=> "English (United Kingdom)",
"en_US"=> "English (United States)",
"en_ZW"=> "English (Zimbabwe)",
"en"=> "English",
"eo"=> "Esperanto",
"et_EE"=> "Estonian (Estonia)",
"et"=> "Estonian",
"ee_GH"=> "Ewe (Ghana)",
"ee_TG"=> "Ewe (Togo)",
"ee"=> "Ewe",
"fo_FO"=> "Faroese (Faroe Islands)",
"fo"=> "Faroese",
"fil_PH"=> "Filipino (Philippines)",
"fil"=> "Filipino",
"fi_FI"=> "Finnish (Finland)",
"fi"=> "Finnish",
"fr_BE"=> "French (Belgium)",
"fr_BJ"=> "French (Benin)",
"fr_BF"=> "French (Burkina Faso)",
"fr_BI"=> "French (Burundi)",
"fr_CM"=> "French (Cameroon)",
"fr_CA"=> "French (Canada)",
"fr_CF"=> "French (Central African Republic)",
"fr_TD"=> "French (Chad)",
"fr_KM"=> "French (Comoros)",
"fr_CG"=> "French (Congo - Brazzaville)",
"fr_CD"=> "French (Congo - Kinshasa)",
"fr_CI"=> "French (Côte dIvoire)",
"fr_DJ"=> "French (Djibouti)",
"fr_GQ"=> "French (Equatorial Guinea)",
"fr_FR"=> "French (France)",
"fr_GA"=> "French (Gabon)",
"fr_GP"=> "French (Guadeloupe)",
"fr_GN"=> "French (Guinea)",
"fr_LU"=> "French (Luxembourg)",
"fr_MG"=> "French (Madagascar)",
"fr_ML"=> "French (Mali)",
"fr_MQ"=> "French (Martinique)",
"fr_MC"=> "French (Monaco)",
"fr_NE"=> "French (Niger)",
"fr_RW"=> "French (Rwanda)",
"fr_RE"=> "French (Réunion)",
"fr_BL"=> "French (Saint Barthélemy)",
"fr_MF"=> "French (Saint Martin)",
"fr_SN"=> "French (Senegal)",
"fr_CH"=> "French (Switzerland)",
"fr_TG"=> "French (Togo)",
"fr"=> "French",
"ff_SN"=> "Fulah (Senegal)",
"ff"=> "Fulah",
"gl_ES"=> "Galician (Spain)",
"gl"=> "Galician",
"lg_UG"=> "Ganda (Uganda)",
"lg"=> "Ganda",
"ka_GE"=> "Georgian (Georgia)",
"ka"=> "Georgian",
"de_AT"=> "German (Austria)",
"de_BE"=> "German (Belgium)",
"de_DE"=> "German (Germany)",
"de_LI"=> "German (Liechtenstein)",
"de_LU"=> "German (Luxembourg)",
"de_CH"=> "German (Switzerland)",
"de"=> "German",
"el_CY"=> "Greek (Cyprus)",
"el_GR"=> "Greek (Greece)",
"el"=> "Greek",
"gu_IN"=> "Gujarati (India)",
"gu"=> "Gujarati",
"guz_KE"=> "Gusii (Kenya)",
"guz"=> "Gusii",
"ha_Latn"=> "Hausa (Latin)",
"ha_Latn_GH"=> "Hausa (Latin, Ghana)",
"ha_Latn_NE"=> "Hausa (Latin, Niger)",
"ha_Latn_NG"=> "Hausa (Latin, Nigeria)",
"ha"=> "Hausa",
"haw_US"=> "Hawaiian (United States)",
"haw"=> "Hawaiian",
"he_IL"=> "Hebrew (Israel)",
"he"=> "Hebrew",
"hi_IN"=> "Hindi (India)",
"hi"=> "Hindi",
"hu_HU"=> "Hungarian (Hungary)",
"hu"=> "Hungarian",
"is_IS"=> "Icelandic (Iceland)",
"is"=> "Icelandic",
"ig_NG"=> "Igbo (Nigeria)",
"ig"=> "Igbo",
"id_ID"=> "Indonesian (Indonesia)",
"id"=> "Indonesian",
"ga_IE"=> "Irish (Ireland)",
"ga"=> "Irish",
"it_IT"=> "Italian (Italy)",
"it_CH"=> "Italian (Switzerland)",
"it"=> "Italian",
"ja_JP"=> "Japanese (Japan)",
"ja"=> "Japanese",
"kea_CV"=> "Kabuverdianu (Cape Verde)",
"kea"=> "Kabuverdianu",
"kab_DZ"=> "Kabyle (Algeria)",
"kab"=> "Kabyle",
"kl_GL"=> "Kalaallisut (Greenland)",
"kl"=> "Kalaallisut",
"kln_KE"=> "Kalenjin (Kenya)",
"kln"=> "Kalenjin",
"kam_KE"=> "Kamba (Kenya)",
"kam"=> "Kamba",
"kn_IN"=> "Kannada (India)",
"kn"=> "Kannada",
"kk_Cyrl"=> "Kazakh (Cyrillic)",
"kk_Cyrl_KZ"=> "Kazakh (Cyrillic, Kazakhstan)",
"kk"=> "Kazakh",
"km_KH"=> "Khmer (Cambodia)",
"km"=> "Khmer",
"ki_KE"=> "Kikuyu (Kenya)",
"ki"=> "Kikuyu",
"rw_RW"=> "Kinyarwanda (Rwanda)",
"rw"=> "Kinyarwanda",
"kok_IN"=> "Konkani (India)",
"kok"=> "Konkani",
"ko_KR"=> "Korean (South Korea)",
"ko"=> "Korean",
"khq_ML"=> "Koyra Chiini (Mali)",
"khq"=> "Koyra Chiini",
"ses_ML"=> "Koyraboro Senni (Mali)",
"ses"=> "Koyraboro Senni",
"lag_TZ"=> "Langi (Tanzania)",
"lag"=> "Langi",
"lv_LV"=> "Latvian (Latvia)",
"lv"=> "Latvian",
"lt_LT"=> "Lithuanian (Lithuania)",
"lt"=> "Lithuanian",
"luo_KE"=> "Luo (Kenya)",
"luo"=> "Luo",
"luy_KE"=> "Luyia (Kenya)",
"luy"=> "Luyia",
"mk_MK"=> "Macedonian (Macedonia)",
"mk"=> "Macedonian",
"jmc_TZ"=> "Machame (Tanzania)",
"jmc"=> "Machame",
"kde_TZ"=> "Makonde (Tanzania)",
"kde"=> "Makonde",
"mg_MG"=> "Malagasy (Madagascar)",
"mg"=> "Malagasy",
"ms_BN"=> "Malay (Brunei)",
"ms_MY"=> "Malay (Malaysia)",
"ms"=> "Malay",
"ml_IN"=> "Malayalam (India)",
"ml"=> "Malayalam",
"mt_MT"=> "Maltese (Malta)",
"mt"=> "Maltese",
"gv_GB"=> "Manx (United Kingdom)",
"gv"=> "Manx",
"mr_IN"=> "Marathi (India)",
"mr"=> "Marathi",
"mas_KE"=> "Masai (Kenya)",
"mas_TZ"=> "Masai (Tanzania)",
"mas"=> "Masai",
"mer_KE"=> "Meru (Kenya)",
"mer"=> "Meru",
"mfe_MU"=> "Morisyen (Mauritius)",
"mfe"=> "Morisyen",
"naq_NA"=> "Nama (Namibia)",
"naq"=> "Nama",
"ne_IN"=> "Nepali (India)",
"ne_NP"=> "Nepali (Nepal)",
"ne"=> "Nepali",
"nd_ZW"=> "North Ndebele (Zimbabwe)",
"nd"=> "North Ndebele",
"nb_NO"=> "Norwegian Bokmål (Norway)",
"nb"=> "Norwegian Bokmål",
"nn_NO"=> "Norwegian Nynorsk (Norway)",
"nn"=> "Norwegian Nynorsk",
"nyn_UG"=> "Nyankole (Uganda)",
"nyn"=> "Nyankole",
"or_IN"=> "Oriya (India)",
"or"=> "Oriya",
"om_ET"=> "Oromo (Ethiopia)",
"om_KE"=> "Oromo (Kenya)",
"om"=> "Oromo",
"ps_AF"=> "Pashto (Afghanistan)",
"ps"=> "Pashto",
"fa_AF"=> "Persian (Afghanistan)",
"fa_IR"=> "Persian (Iran)",
"fa"=> "Persian",
"pl_PL"=> "Polish (Poland)",
"pl"=> "Polish",
"pt_BR"=> "Portuguese (Brazil)",
"pt_GW"=> "Portuguese (Guinea-Bissau)",
"pt_MZ"=> "Portuguese (Mozambique)",
"pt_PT"=> "Portuguese (Portugal)",
"pt"=> "Portuguese",
"pa_Arab"=> "Punjabi (Arabic)",
"pa_Arab_PK"=> "Punjabi (Arabic, Pakistan)",
"pa_Guru"=> "Punjabi (Gurmukhi)",
"pa_Guru_IN"=> "Punjabi (Gurmukhi, India)",
"pa"=> "Punjabi",
"ro_MD"=> "Romanian (Moldova)",
"ro_RO"=> "Romanian (Romania)",
"ro"=> "Romanian",
"rm_CH"=> "Romansh (Switzerland)",
"rm"=> "Romansh",
"rof_TZ"=> "Rombo (Tanzania)",
"rof"=> "Rombo",
"ru_MD"=> "Russian (Moldova)",
"ru_RU"=> "Russian (Russia)",
"ru_UA"=> "Russian (Ukraine)",
"ru"=> "Russian",
"rwk_TZ"=> "Rwa (Tanzania)",
"rwk"=> "Rwa",
"saq_KE"=> "Samburu (Kenya)",
"saq"=> "Samburu",
"sg_CF"=> "Sango (Central African Republic)",
"sg"=> "Sango",
"seh_MZ"=> "Sena (Mozambique)",
"seh"=> "Sena",
"sr_Cyrl"=> "Serbian (Cyrillic)",
"sr_Cyrl_BA"=> "Serbian (Cyrillic, Bosnia and Herzegovina)",
"sr_Cyrl_ME"=> "Serbian (Cyrillic, Montenegro)",
"sr_Cyrl_RS"=> "Serbian (Cyrillic, Serbia)",
"sr_Latn"=> "Serbian (Latin)",
"sr_Latn_BA"=> "Serbian (Latin, Bosnia and Herzegovina)",
"sr_Latn_ME"=> "Serbian (Latin, Montenegro)",
"sr_Latn_RS"=> "Serbian (Latin, Serbia)",
"sr"=> "Serbian",
"sn_ZW"=> "Shona (Zimbabwe)",
"sn"=> "Shona",
"ii_CN"=> "Sichuan Yi (China)",
"ii"=> "Sichuan Yi",
"si_LK"=> "Sinhala (Sri Lanka)",
"si"=> "Sinhala",
"sk_SK"=> "Slovak (Slovakia)",
"sk"=> "Slovak",
"sl_SI"=> "Slovenian (Slovenia)",
"sl"=> "Slovenian",
"xog_UG"=> "Soga (Uganda)",
"xog"=> "Soga",
"so_DJ"=> "Somali (Djibouti)",
"so_ET"=> "Somali (Ethiopia)",
"so_KE"=> "Somali (Kenya)",
"so_SO"=> "Somali (Somalia)",
"so"=> "Somali",
"es_AR"=> "Spanish (Argentina)",
"es_BO"=> "Spanish (Bolivia)",
"es_CL"=> "Spanish (Chile)",
"es_CO"=> "Spanish (Colombia)",
"es_CR"=> "Spanish (Costa Rica)",
"es_DO"=> "Spanish (Dominican Republic)",
"es_EC"=> "Spanish (Ecuador)",
"es_SV"=> "Spanish (El Salvador)",
"es_GQ"=> "Spanish (Equatorial Guinea)",
"es_GT"=> "Spanish (Guatemala)",
"es_HN"=> "Spanish (Honduras)",
"es_419"=> "Spanish (Latin America)",
"es_MX"=> "Spanish (Mexico)",
"es_NI"=> "Spanish (Nicaragua)",
"es_PA"=> "Spanish (Panama)",
"es_PY"=> "Spanish (Paraguay)",
"es_PE"=> "Spanish (Peru)",
"es_PR"=> "Spanish (Puerto Rico)",
"es_ES"=> "Spanish (Spain)",
"es_US"=> "Spanish (United States)",
"es_UY"=> "Spanish (Uruguay)",
"es_VE"=> "Spanish (Venezuela)",
"es"=> "Spanish",
"sw_KE"=> "Swahili (Kenya)",
"sw_TZ"=> "Swahili (Tanzania)",
"sw"=> "Swahili",
"sv_FI"=> "Swedish (Finland)",
"sv_SE"=> "Swedish (Sweden)",
"sv"=> "Swedish",
"gsw_CH"=> "Swiss German (Switzerland)",
"gsw"=> "Swiss German",
"shi_Latn"=> "Tachelhit (Latin)",
"shi_Latn_MA"=> "Tachelhit (Latin, Morocco)",
"shi_Tfng"=> "Tachelhit (Tifinagh)",
"shi_Tfng_MA"=> "Tachelhit (Tifinagh, Morocco)",
"shi"=> "Tachelhit",
"dav_KE"=> "Taita (Kenya)",
"dav"=> "Taita",
"ta_IN"=> "Tamil (India)",
"ta_LK"=> "Tamil (Sri Lanka)",
"ta"=> "Tamil",
"te_IN"=> "Telugu (India)",
"te"=> "Telugu",
"teo_KE"=> "Teso (Kenya)",
"teo_UG"=> "Teso (Uganda)",
"teo"=> "Teso",
"th_TH"=> "Thai (Thailand)",
"th"=> "Thai",
"bo_CN"=> "Tibetan (China)",
"bo_IN"=> "Tibetan (India)",
"bo"=> "Tibetan",
"ti_ER"=> "Tigrinya (Eritrea)",
"ti_ET"=> "Tigrinya (Ethiopia)",
"ti"=> "Tigrinya",
"to_TO"=> "Tonga (Tonga)",
"to"=> "Tonga",
"tr_TR"=> "Turkish (Turkey)",
"tr"=> "Turkish",
"uk_UA"=> "Ukrainian (Ukraine)",
"uk"=> "Ukrainian",
"ur_IN"=> "Urdu (India)",
"ur_PK"=> "Urdu (Pakistan)",
"ur"=> "Urdu",
"uz_Arab"=> "Uzbek (Arabic)",
"uz_Arab_AF"=> "Uzbek (Arabic, Afghanistan)",
"uz_Cyrl"=> "Uzbek (Cyrillic)",
"uz_Cyrl_UZ"=> "Uzbek (Cyrillic, Uzbekistan)",
"uz_Latn"=> "Uzbek (Latin)",
"uz_Latn_UZ"=> "Uzbek (Latin, Uzbekistan)",
"uz"=> "Uzbek",
"vi_VN"=> "Vietnamese (Vietnam)",
"vi"=> "Vietnamese",
"vun_TZ"=> "Vunjo (Tanzania)",
"vun"=> "Vunjo",
"cy_GB"=> "Welsh (United Kingdom)",
"cy"=> "Welsh",
"yo_NG"=> "Yoruba (Nigeria)",
"yo"=> "Yoruba",
"zu_ZA"=> "Zulu (South Africa)",
"zu"=> "Zulu"
);
}
/**
* @return array
*/
public static function simple()
{
$response = array();
foreach (static::all() as $key => $value) {
if (!strpos($key, '_') > 0) {
$response[$key] = $value;
}
}
return $response;
}
}

View File

@@ -0,0 +1,100 @@
<?php
/**
* Fired during plugin activation.
*
* This class defines all code necessary to run during the plugin's activation.
*
* @since 1.0.1
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_Activator {
/**
* Short Description. (use period)
*
* Long Description.
*
* @since 1.0.0
*/
public static function activate() {
// create the queue tables because we need them for the sync jobs.
static::create_queue_tables();
// update the settings so we have them for use.
$saved_options = get_option('mailchimp-woocommerce', false);
// if we haven't saved options previously, we will need to create the site id and update base options
if (empty($saved_options)) {
mailchimp_clean_database();
update_option('mailchimp-woocommerce', array());
// only do this if the option has never been set before.
if (!is_multisite()) {
add_option('mailchimp_woocommerce_plugin_do_activation_redirect', true);
}
}
// if we haven't saved the store id yet.
$saved_store_id = get_option('mailchimp-woocommerce-store_id', false);
if (empty($saved_store_id)) {
// add a store id flag which will be a random hash
update_option('mailchimp-woocommerce-store_id', uniqid(), 'yes');
}
if (class_exists('MailChimp_WooCommerce_MailChimpApi')) {
// try this now for existing stores on an update.
mailchimp_update_connected_site_script();
}
}
/**
* Create the queue tables in the DB so we can use it for syncing.
*/
public static function create_queue_tables()
{
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
global $wpdb;
$wpdb->hide_errors();
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}queue (
id bigint(20) NOT NULL AUTO_INCREMENT,
job text NOT NULL,
attempts tinyint(1) NOT NULL DEFAULT 0,
locked tinyint(1) NOT NULL DEFAULT 0,
locked_at datetime DEFAULT NULL,
available_at datetime NOT NULL,
created_at datetime NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta( $sql );
$sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}failed_jobs (
id bigint(20) NOT NULL AUTO_INCREMENT,
job text NOT NULL,
failed_at datetime NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta( $sql );
$sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}mailchimp_carts (
id VARCHAR (255) NOT NULL,
email VARCHAR (100) NOT NULL,
user_id INT (11) DEFAULT NULL,
cart text NOT NULL,
created_at datetime NOT NULL
) $charset_collate;";
dbDelta( $sql );
// set the mailchimp woocommerce version at the time of install
update_site_option('mailchimp_woocommerce_version', mailchimp_environment_variables()->version);
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Fired during plugin deactivation
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
*/
/**
* Fired during plugin deactivation.
*
* This class defines all code necessary to run during the plugin's deactivation.
*
* @since 1.0.1
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_Deactivator {
/**
* Short Description. (use period)
*
* Long Description.
*
* @since 1.0.0
*/
public static function deactivate() {
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Define the internationalization functionality
*
* Loads and defines the internationalization files for this plugin
* so that it is ready for translation.
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
*/
/**
* Define the internationalization functionality.
*
* Loads and defines the internationalization files for this plugin
* so that it is ready for translation.
*
* @since 1.0.1
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_i18n {
/**
* Load the plugin text domain for translation.
*
* @since 1.0.0
*/
public function load_plugin_textdomain() {
load_plugin_textdomain(
'mailchimp-woocommerce',
false,
dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/'
);
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* Register all actions and filters for the plugin
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
*/
/**
* Register all actions and filters for the plugin.
*
* Maintain a list of all hooks that are registered throughout
* the plugin, and register them with the WordPress API. Call the
* run function to execute the list of actions and filters.
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce_Loader {
/**
* The array of actions registered with WordPress.
*
* @since 1.0.0
* @access protected
* @var array $actions The actions registered with WordPress to fire when the plugin loads.
*/
protected $actions;
/**
* The array of filters registered with WordPress.
*
* @since 1.0.0
* @access protected
* @var array $filters The filters registered with WordPress to fire when the plugin loads.
*/
protected $filters;
/**
* Initialize the collections used to maintain the actions and filters.
*
* @since 1.0.0
*/
public function __construct() {
$this->actions = array();
$this->filters = array();
}
/**
* Add a new action to the collection to be registered with WordPress.
*
* @since 1.0.0
* @param string $hook The name of the WordPress action that is being registered.
* @param object $component A reference to the instance of the object on which the action is defined.
* @param string $callback The name of the function definition on the $component.
* @param int $priority Optional. he priority at which the function should be fired. Default is 10.
* @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1.
*/
public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
$this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args );
}
/**
* Add a new filter to the collection to be registered with WordPress.
*
* @since 1.0.0
* @param string $hook The name of the WordPress filter that is being registered.
* @param object $component A reference to the instance of the object on which the filter is defined.
* @param string $callback The name of the function definition on the $component.
* @param int $priority Optional. he priority at which the function should be fired. Default is 10.
* @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1
*/
public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
$this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args );
}
/**
* A utility function that is used to register the actions and hooks into a single
* collection.
*
* @since 1.0.0
* @access private
* @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
* @param string $hook The name of the WordPress filter that is being registered.
* @param object $component A reference to the instance of the object on which the filter is defined.
* @param string $callback The name of the function definition on the $component.
* @param int $priority The priority at which the function should be fired.
* @param int $accepted_args The number of arguments that should be passed to the $callback.
* @return array The collection of actions and filters registered with WordPress.
*/
private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) {
$hooks[] = array(
'hook' => $hook,
'component' => $component,
'callback' => $callback,
'priority' => $priority,
'accepted_args' => $accepted_args
);
return $hooks;
}
/**
* Register the filters and actions with WordPress.
*
* @since 1.0.0
*/
public function run() {
foreach ( $this->filters as $hook ) {
add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}
foreach ( $this->actions as $hook ) {
add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}
}
}

View File

@@ -0,0 +1,110 @@
<?php
/**
* Created by MailChimp.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 2/22/16
* Time: 9:09 AM
*/
class MailChimp_Newsletter extends MailChimp_WooCommerce_Options
{
/**
* @param WC_Checkout $checkout
*/
public function applyNewsletterField($checkout)
{
if (!is_admin()) {
// if the user has chosen to hide the checkbox, don't do anything.
if (($default_setting = $this->getOption('mailchimp_checkbox_defaults', 'check')) === 'hide') {
return;
}
// allow the user to specify the text in the newsletter label.
$label = $this->getOption('newsletter_label', 'Subscribe to our newsletter');
// if the user chose 'check' or nothing at all, we default to true.
$default_checked = $default_setting === 'check';
$status = $default_checked;
// if the user is logged in, we will pull the 'is_subscribed' property out of the meta for the value.
// otherwise we use the default settings.
if (is_user_logged_in()) {
$status = get_user_meta(get_current_user_id(), 'mailchimp_woocommerce_is_subscribed', true);
/// if the user is logged in - and is already subscribed - just ignore this checkbox.
if ((bool) $status) {
return;
}
if ($status === '' || $status === null) {
$status = $default_checked;
}
}
// echo out the checkbox.
$checkbox = '<p class="form-row form-row-wide create-account">';
$checkbox .= '<label for="mailchimp_woocommerce_newsletter" class="woocommerce-form__label woocommerce-form__label-for-checkbox checkbox">';
$checkbox .= '<input class="woocommerce-form__input woocommerce-form__input-checkbox input-checkbox" id="mailchimp_woocommerce_newsletter" type="checkbox" ';
$checkbox .= 'name="mailchimp_woocommerce_newsletter" value="1"'.($status ? ' checked="checked"' : '').'> ';
$checkbox .= '<span>' . $label . '</span>';
$checkbox .= '</label>';
$checkbox .= '</p>';
$checkbox .= '<div class="clear"></div>';
echo $checkbox;
}
}
/**
* @param $order_id
* @param $posted
*/
public function processNewsletterField($order_id, $posted)
{
$this->handleStatus($order_id);
}
/**
* @param WC_Order $order
*/
public function processPayPalNewsletterField($order)
{
$this->handleStatus($order->get_id());
}
/**
* @param $sanitized_user_login
* @param $user_email
* @param $reg_errors
*/
public function processRegistrationForm($sanitized_user_login, $user_email, $reg_errors)
{
if (defined('WOOCOMMERCE_CHECKOUT')) {
return; // Ship checkout
}
$this->handleStatus();
}
/**
* @param null $order_id
* @return bool|int
*/
protected function handleStatus($order_id = null)
{
$status = isset($_POST['mailchimp_woocommerce_newsletter']) ? (int)$_POST['mailchimp_woocommerce_newsletter'] : 0;
if ($order_id) {
update_post_meta($order_id, 'mailchimp_woocommerce_is_subscribed', $status);
}
if (is_user_logged_in()) {
update_user_meta(get_current_user_id(), 'mailchimp_woocommerce_is_subscribed', $status);
return $status;
}
return false;
}
}

View File

@@ -0,0 +1,311 @@
<?php
/**
* Created by MailChimp.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 2/22/16
* Time: 3:45 PM
*/
abstract class MailChimp_WooCommerce_Options
{
/**
* @var MailChimp_WooCommerce_MailChimpApi
*/
protected $api;
protected $plugin_name = 'mailchimp-woocommerce';
protected $environment = 'production';
protected $version = '1.0.0';
protected $plugin_options = null;
protected $is_admin = false;
/**
* hook calls this so that we know the admin is here.
*/
public function adminReady()
{
$this->is_admin = current_user_can('administrator');
if (get_option('mailchimp_woocommerce_plugin_do_activation_redirect', false)) {
delete_option('mailchimp_woocommerce_plugin_do_activation_redirect');
// don't do the redirect while activating the plugin through the rest API. ( Bartosz from Woo asked for this )
if ((defined( 'REST_REQUEST' ) && REST_REQUEST)) {
return;
}
if (!isset($_GET['activate-multi'])) {
wp_redirect("options-general.php?page=mailchimp-woocommerce");
}
}
}
/**
* @return bool
*/
public function isAdmin()
{
return $this->is_admin;
}
/**
* @param $version
*/
public function setVersion($version)
{
$this->version = $version;
}
/**
* @return string
*/
public function getVersion()
{
return $this->version;
}
/**
* @return string
*/
public function getUniqueStoreID()
{
return mailchimp_get_store_id();
}
/**
* @param $env
* @return $this
*/
public function setEnvironment($env)
{
$this->environment = $env;
return $this;
}
/**
* @return string
*/
public function getEnvironment()
{
return $this->environment;
}
/**
* @param $key
* @param null $default
* @return null
*/
public function getOption($key, $default = null)
{
$options = $this->getOptions();
if (isset($options[$key])) {
return $options[$key];
}
return $default;
}
/**
* @param $key
* @param bool $default
* @return bool
*/
public function hasOption($key, $default = false)
{
return (bool) $this->getOption($key, $default);
}
/**
* @return array
*/
public function resetOptions()
{
return $this->plugin_options = get_option($this->plugin_name);
}
/**
* @return array
*/
public function getOptions()
{
if (empty($this->plugin_options)) {
$this->plugin_options = get_option($this->plugin_name);
}
return is_array($this->plugin_options) ? $this->plugin_options : array();
}
/**
* @param $key
* @param $value
* @return $this
*/
public function setData($key, $value)
{
update_option($this->plugin_name.'-'.$key, $value, 'yes');
return $this;
}
/**
* @param $key
* @param null $default
* @return mixed|void
*/
public function getData($key, $default = null)
{
return get_option($this->plugin_name.'-'.$key, $default);
}
/**
* @param $key
* @return bool
*/
public function removeData($key)
{
return delete_option($this->plugin_name.'-'.$key);
}
/**
* @param $key
* @param null $default
* @return null|mixed
*/
public function getCached($key, $default = null)
{
$cached = $this->getData("cached-$key", false);
if (empty($cached) || !($cached = unserialize($cached))) {
return $default;
}
if (empty($cached['till']) || (time() > $cached['till'])) {
$this->removeData("cached-$key");
return $default;
}
return $cached['value'];
}
/**
* @param $key
* @param $value
* @param $seconds
* @return $this
*/
public function setCached($key, $value, $seconds = 60)
{
$time = time();
$data = array('at' => $time, 'till' => $time + $seconds, 'value' => $value);
$this->setData("cached-$key", serialize($data));
return $this;
}
/**
* @param $key
* @param $callable
* @param int $seconds
* @return mixed|null
*/
public function getCachedWithSetDefault($key, $callable, $seconds = 60)
{
if (!($value = $this->getCached($key, false))) {
$value = call_user_func($callable);
$this->setCached($key, $value, $seconds);
}
return $value;
}
/**
* @return bool
*/
public function isConfigured()
{
return true;
//return $this->getOption('public_key', false) && $this->getOption('secret_key', false);
}
/**
* @return bool
*/
protected function doingAjax()
{
return defined('DOING_AJAX') && DOING_AJAX;
}
/**
* @return MailChimp_WooCommerce_MailChimpApi
*/
public function api()
{
if (empty($this->api)) {
$this->api = new MailChimp_WooCommerce_MailChimpApi($this->getOption('mailchimp_api_key', false));
}
return $this->api;
}
/**
* @param array $data
* @param $key
* @param null $default
* @return null|mixed
*/
public function array_get(array $data, $key, $default = null)
{
if (isset($data[$key])) {
return $data[$key];
}
return $default;
}
/**
* @param bool $products
* @param bool $orders
* @return $this
*/
public function removePointers($products = true, $orders = true)
{
if ($products) {
$this->removeProductPointers();
}
if ($orders) {
$this->removeOrderPointers();
}
$this->removeSyncPointers();
$this->removeMiscPointers();
return $this;
}
public function removeProductPointers()
{
delete_option('mailchimp-woocommerce-sync.products.completed_at');
delete_option('mailchimp-woocommerce-sync.products.current_page');
}
public function removeOrderPointers()
{
delete_option('mailchimp-woocommerce-sync.orders.prevent');
delete_option('mailchimp-woocommerce-sync.orders.completed_at');
delete_option('mailchimp-woocommerce-sync.orders.current_page');
}
public function removeSyncPointers()
{
delete_option('mailchimp-woocommerce-sync.orders.prevent');
delete_option('mailchimp-woocommerce-sync.syncing');
delete_option('mailchimp-woocommerce-sync.started_at');
delete_option('mailchimp-woocommerce-sync.completed_at');
}
public function removeMiscPointers()
{
delete_option('mailchimp-woocommerce-errors.store_info');
delete_option('mailchimp-woocommerce-validation.api.ping');
delete_option('mailchimp-woocommerce-cached-api-lists');
delete_option('mailchimp-woocommerce-cached-api-ping-check');
}
}

View File

@@ -0,0 +1,730 @@
<?php
/**
* Created by MailChimp.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 2/17/16
* Time: 12:03 PM
*/
class MailChimp_Service extends MailChimp_WooCommerce_Options
{
protected static $pushed_orders = array();
protected $user_email = null;
protected $previous_email = null;
protected $force_cart_post = false;
protected $cart_was_submitted = false;
protected $cart = array();
protected $validated_cart_db = false;
/**
* hook fired when we know everything is booted
*/
public function wooIsRunning()
{
// make sure the site option for setting the mailchimp_carts has been saved.
$this->validated_cart_db = get_site_option('mailchimp_woocommerce_db_mailchimp_carts', false);
$this->is_admin = current_user_can('administrator');
}
/**
* @param $r
* @param $url
* @return mixed
*/
public function addHttpRequestArgs( $r, $url ) {
// not sure whether or not we need to implement something like this yet.
//$r['headers']['Authorization'] = 'Basic ' . base64_encode('username:password');
return $r;
}
/**
* @param $key
* @param $default
* @return mixed
*/
protected function cookie($key, $default = null)
{
if ($this->is_admin) {
return $default;
}
return isset($_COOKIE[$key]) ? $_COOKIE[$key] : $default;
}
/**
* @param WC_Order $order
*/
public function onNewPayPalOrder($order)
{
$this->onNewOrder($order->get_id());
}
/**
* This should only fire on a web based order so we can do real campaign tracking here.
*
* @param $order_id
*/
public function onNewOrder($order_id)
{
if (!mailchimp_is_configured()) return;
// register this order is already in process..
static::$pushed_orders[$order_id] = true;
// see if we have a session id and a campaign id, also only do this when this user is not the admin.
$campaign_id = $this->getCampaignTrackingID();
// grab the landing site cookie if we have one here.
$landing_site = $this->getLandingSiteCookie();
// expire the landing site cookie so we can rinse and repeat tracking
$this->expireLandingSiteCookie();
// remove this record from the db.
$this->clearCartData();
// queue up the single order to be processed.
$handler = new MailChimp_WooCommerce_Single_Order($order_id, null, $campaign_id, $landing_site);
wp_queue($handler, 60);
}
/**
* @param $order_id
* @param bool $is_admin
*/
public function handleOrderStatusChanged($order_id, $is_admin = false)
{
if (!mailchimp_is_configured()) return;
// register this order is already in process..
static::$pushed_orders[$order_id] = true;
// queue up the single order to be processed.
$handler = new MailChimp_WooCommerce_Single_Order($order_id, null, null, null);
$handler->is_update = true;
$handler->is_admin_save = $is_admin;
wp_queue($handler, 90);
}
/**
* @param $order_id
*/
public function onPartiallyRefunded($order_id)
{
if (!mailchimp_is_configured()) return;
$handler = new MailChimp_WooCommerce_Single_Order($order_id, null, null, null);
$handler->partially_refunded = true;
wp_queue($handler);
}
/**
* Clear the card data for a user.
*/
public function clearCartData()
{
if ($user_email = $this->getCurrentUserEmail()) {
$this->deleteCart($user_email);
}
}
/**
* @param null $updated
* @return bool|null
*/
public function handleCartUpdated($updated = null)
{
if ($updated === false || $this->is_admin || $this->cart_was_submitted || !mailchimp_is_configured()) {
return !is_null($updated) ? $updated : false;
}
if (empty($this->cart)) {
$this->cart = $this->getCartItems();
}
if (($user_email = $this->getCurrentUserEmail())) {
$previous = $this->getPreviousEmailFromSession();
$uid = md5(trim(strtolower($user_email)));
// delete the previous records.
if (!empty($previous) && $previous !== $user_email) {
if ($this->api()->deleteCartByID($this->getUniqueStoreID(), $previous_email = md5(trim(strtolower($previous))))) {
mailchimp_log('ac.cart_swap', "Deleted cart [$previous] :: ID [$previous_email]");
}
// going to delete the cart because we are switching.
$this->deleteCart($previous_email);
}
if ($this->cart && !empty($this->cart)) {
// track the cart locally so we can repopulate things for cross device compatibility.
$this->trackCart($uid, $user_email);
$this->cart_was_submitted = true;
// grab the cookie data that could play important roles in the submission
$campaign = $this->getCampaignTrackingID();
// fire up the job handler
$handler = new MailChimp_WooCommerce_Cart_Update($uid, $user_email, $campaign, $this->cart);
wp_queue($handler);
}
return !is_null($updated) ? $updated : true;
}
return !is_null($updated) ? $updated : false;
}
/**
* @param $post_id
*/
public function handleNewCoupon($post_id)
{
$this->handleCouponSaved($post_id, new WC_Coupon($post_id));
}
/**
* @param $post_id
* @param null $coupon
*/
public function handleCouponSaved($post_id, $coupon = null)
{
if (!mailchimp_is_configured()) return;
if ($coupon instanceof WC_Coupon) {
wp_queue(new MailChimp_WooCommerce_SingleCoupon($post_id));
}
}
/**
* @param $post_id
*/
public function handleCouponRestored($post_id)
{
$this->handleCouponSaved($post_id, new WC_Coupon($post_id));
}
/**
* Save post metadata when a post is saved.
*
* @param int $post_id The post ID.
* @param WP_Post $post The post object.
* @param bool $update Whether this is an existing post being updated or not.
*/
public function handlePostSaved($post_id, $post, $update)
{
if (!mailchimp_is_configured()) return;
if ($post->post_status !== 'auto-draft') {
if ('product' == $post->post_type) {
wp_queue(new MailChimp_WooCommerce_Single_Product($post_id), 5);
} elseif ('shop_order' == $post->post_type) {
$this->handleOrderStatusChanged($post_id, is_admin());
}
}
}
/**
* @param $post_id
*/
public function handlePostTrashed($post_id)
{
if (!mailchimp_is_configured()) return;
switch (get_post_type($post_id)) {
case 'shop_coupon':
mailchimp_get_api()->deletePromoRule(mailchimp_get_store_id(), $post_id);
mailchimp_log('promo_code.deleted', "deleted promo code {$post_id}");
break;
}
}
/**
* @param $post_id
*/
public function handlePostRestored($post_id)
{
if (!mailchimp_is_configured()) return;
switch(get_post_type($post_id)) {
case 'shop_coupon':
return $this->handleCouponRestored($post_id);
break;
}
}
/**
* @param $user_id
*/
public function handleUserRegistration($user_id)
{
if (!mailchimp_is_configured()) return;
$subscribed = (bool) isset($_POST['mailchimp_woocommerce_newsletter']) ?
$_POST['mailchimp_woocommerce_newsletter'] : false;
// update the user meta with the 'is_subscribed' form element
update_user_meta($user_id, 'mailchimp_woocommerce_is_subscribed', $subscribed);
if ($subscribed) {
wp_queue(new MailChimp_WooCommerce_User_Submit($user_id, $subscribed));
}
}
/**
* @param $user_id
* @param $old_user_data
*/
function handleUserUpdated($user_id, $old_user_data)
{
if (!mailchimp_is_configured()) return;
// only update this person if they were marked as subscribed before
$is_subscribed = get_user_meta($user_id, 'mailchimp_woocommerce_is_subscribed', true);
// if they don't have a meta set for is_subscribed, we will get a blank string, so just ignore this.
if ($is_subscribed === '' || $is_subscribed === null) return;
// only send this update if the user actually has a boolean value.
wp_queue(new MailChimp_WooCommerce_User_Submit($user_id, (bool) $is_subscribed, $old_user_data));
}
/**
* Delete all the options pointing to the pages, and re-start the sync process.
* @param bool $only_products
* @return bool
*/
protected function syncProducts($only_products = false)
{
if (!$this->isAdmin()) return false;
$this->removePointers(true, ($only_products ? false : true));
update_option('mailchimp-woocommerce-sync.orders.prevent', $only_products);
MailChimp_WooCommerce_Process_Products::push();
return true;
}
/**
* Delete all the options pointing to the pages, and re-start the sync process.
* @return bool
*/
protected function syncOrders()
{
if (!$this->isAdmin()) return false;
$this->removePointers(false, true);
// since the products are all good, let's sync up the orders now.
wp_queue(new MailChimp_WooCommerce_Process_Orders());
return true;
}
/**
* @return bool|string
*/
public function getCurrentUserEmail()
{
if (isset($this->user_email) && !empty($this->user_email)) {
return $this->user_email = strtolower($this->user_email);
}
$user = wp_get_current_user();
$email = ($user->ID > 0 && isset($user->user_email)) ? $user->user_email : $this->getEmailFromSession();
return $this->user_email = strtolower($email);
}
/**
* @return bool|array
*/
public function getCartItems()
{
if (!($this->cart = $this->getWooSession('cart', false))) {
$this->cart = function_exists('WC') ? false : WC()->cart->get_cart();
} else {
$cart_session = array();
foreach ( $this->cart as $key => $values ) {
$cart_session[$key] = $values;
unset($cart_session[$key]['data']); // Unset product object
}
return $this->cart = $cart_session;
}
return is_array($this->cart) ? $this->cart : false;
}
/**
* Set the cookie of the mailchimp campaigns if we have one.
*/
public function handleCampaignTracking()
{
// set the landing site cookie if we don't have one.
$this->setLandingSiteCookie();
$cookie_duration = $this->getCookieDuration();
// if we have a query string of the mc_cart_id in the URL, that means we are sending a campaign from MC
if (isset($_GET['mc_cart_id']) && !isset($_GET['removed_item'])) {
// try to pull the cart from the database.
if (($cart = $this->getCart($_GET['mc_cart_id'])) && !empty($cart)) {
// set the current user email
$this->user_email = trim(str_replace(' ','+', $cart->email));
if (($current_email = $this->getEmailFromSession()) && $current_email !== $this->user_email) {
$this->previous_email = $current_email;
@setcookie('mailchimp_user_previous_email',$this->user_email, $cookie_duration, '/' );
}
// cookie the current email
@setcookie('mailchimp_user_email', $this->user_email, $cookie_duration, '/' );
// set the cart data.
$this->setWooSession('cart', unserialize($cart->cart));
}
}
if (isset($_REQUEST['mc_cid'])) {
$this->setCampaignTrackingID($_REQUEST['mc_cid'], $cookie_duration);
}
if (isset($_REQUEST['mc_eid'])) {
@setcookie('mailchimp_email_id', trim($_REQUEST['mc_eid']), $cookie_duration, '/' );
}
}
/**
* @return mixed|null
*/
public function getCampaignTrackingID()
{
$cookie = $this->cookie('mailchimp_campaign_id', false);
if (empty($cookie)) {
$cookie = $this->getWooSession('mailchimp_tracking_id', false);
}
return $cookie;
}
/**
* @param $id
* @param $cookie_duration
* @return $this
*/
public function setCampaignTrackingID($id, $cookie_duration)
{
$cid = trim($id);
@setcookie('mailchimp_campaign_id', $cid, $cookie_duration, '/' );
$this->setWooSession('mailchimp_campaign_id', $cid);
return $this;
}
/**
* @return mixed|null
*/
public function getLandingSiteCookie()
{
$cookie = $this->cookie('mailchimp_landing_site', false);
if (empty($cookie)) {
$cookie = $this->getWooSession('mailchimp_landing_site', false);
}
return $cookie;
}
/**
* @return $this
*/
public function setLandingSiteCookie()
{
if (isset($_GET['expire_landing_site'])) $this->expireLandingSiteCookie();
// if we already have a cookie here, we need to skip it.
if ($this->getLandingSiteCookie() != false) return $this;
$http_referer = $this->getReferer();
if (!empty($http_referer)) {
// grab the current landing url since it's a referral.
$landing_site = home_url() . wp_unslash($_SERVER['REQUEST_URI']);
$compare_refer = str_replace(array('http://', 'https://'), '', $http_referer);
$compare_local = str_replace(array('http://', 'https://'), '', $landing_site);
if (strpos($compare_local, $compare_refer) === 0) return $this;
// set the cookie
@setcookie('mailchimp_landing_site', $landing_site, $this->getCookieDuration(), '/' );
$this->setWooSession('mailchimp_landing_site', $landing_site);
}
return $this;
}
/**
* @return array|bool|string
*/
public function getReferer()
{
if (!empty($_REQUEST['_wp_http_referer'])) {
return wp_unslash($_REQUEST['_wp_http_referer']);
} elseif (!empty($_SERVER['HTTP_REFERER'])) {
return wp_unslash( $_SERVER['HTTP_REFERER']);
}
return false;
}
/**
* @return $this
*/
public function expireLandingSiteCookie()
{
@setcookie('mailchimp_landing_site', false, $this->getCookieDuration(), '/' );
$this->setWooSession('mailchimp_landing_site', false);
return $this;
}
/**
* @return bool
*/
protected function getEmailFromSession()
{
return $this->cookie('mailchimp_user_email', false);
}
/**
* @return bool
*/
protected function getPreviousEmailFromSession()
{
if ($this->previous_email) {
return $this->previous_email = strtolower($this->previous_email);
}
$email = $this->cookie('mailchimp_user_previous_email', false);
return $email ? strtolower($email) : false;
}
/**
* @param $key
* @param null $default
* @return mixed|null
*/
public function getWooSession($key, $default = null)
{
if (!function_exists('WC')) return $default;
if (!($woo = WC()) || empty($woo->session)) {
return $default;
}
return $woo->session->get($key, $default);
}
/**
* @param $key
* @param $value
* @return $this
*/
public function setWooSession($key, $value)
{
if (!function_exists('WC')) return $this;
if (!($woo = WC()) || empty($woo->session)) {
return $this;
}
$woo->session->set($key, $value);
return $this;
}
/**
* @param $key
* @return $this
*/
public function removeWooSession($key)
{
if (!function_exists('WC')) return $this;
if (!($woo = WC()) || empty($woo->session)) {
return $this;
}
$woo->session->__unset($key);
return $this;
}
/**
*
*/
public function get_user_by_hash()
{
if ($this->doingAjax() && isset($_GET['hash'])) {
if (($cart = $this->getCart($_GET['hash']))) {
$this->respondJSON(array('success' => true, 'email' => $cart->email));
}
}
$this->respondJSON(array('success' => false, 'email' => false));
}
/**
*
*/
public function set_user_by_email()
{
if ($this->is_admin) {
$this->respondJSON(array('success' => false));
}
if ($this->doingAjax() && isset($_GET['email'])) {
$cookie_duration = $this->getCookieDuration();
$this->user_email = trim(str_replace(' ','+', $_GET['email']));
if (($current_email = $this->getEmailFromSession()) && $current_email !== $this->user_email) {
$this->previous_email = $current_email;
$this->force_cart_post = true;
@setcookie('mailchimp_user_previous_email',$this->user_email, $cookie_duration, '/' );
}
@setcookie('mailchimp_user_email', $this->user_email, $cookie_duration, '/' );
$this->getCartItems();
$this->handleCartUpdated();
$this->respondJSON(array(
'success' => true,
'email' => $this->user_email,
'previous' => $this->previous_email,
'cart' => $this->cart,
));
}
$this->respondJSON(array('success' => false, 'email' => false));
}
/**
* @param string $time
* @return int
*/
protected function getCookieDuration($time = 'thirty_days')
{
$durations = array(
'one_day' => 86400, 'seven_days' => 604800, 'fourteen_days' => 1209600, 'thirty_days' => 2419200,
);
if (!array_key_exists($time, $durations)) {
$time = 'thirty_days';
}
return time() + $durations[$time];
}
/**
* @param $key
* @param bool $default
* @return bool
*/
protected function get($key, $default = false)
{
if (!isset($_REQUEST['mailchimp-woocommerce']) || !isset($_REQUEST['mailchimp-woocommerce'][$key])) {
return $default;
}
return $_REQUEST['mailchimp-woocommerce'][$key];
}
/**
* @param $uid
* @return array|bool|null|object|void
*/
protected function getCart($uid)
{
if (!$this->validated_cart_db) return false;
global $wpdb;
$table = "{$wpdb->prefix}mailchimp_carts";
$statement = "SELECT * FROM $table WHERE id = %s";
$sql = $wpdb->prepare($statement, $uid);
if (($saved_cart = $wpdb->get_row($sql)) && !empty($saved_cart)) {
return $saved_cart;
}
return false;
}
/**
* @param $uid
* @return true
*/
protected function deleteCart($uid)
{
if (!$this->validated_cart_db) return false;
global $wpdb;
$table = "{$wpdb->prefix}mailchimp_carts";
$sql = $wpdb->prepare("DELETE FROM $table WHERE id = %s", $uid);
$wpdb->query($sql);
return true;
}
/**
* @param $uid
* @param $email
* @return bool
*/
protected function trackCart($uid, $email)
{
if (!$this->validated_cart_db) return false;
global $wpdb;
$table = "{$wpdb->prefix}mailchimp_carts";
$statement = "SELECT * FROM $table WHERE id = %s";
$sql = $wpdb->prepare($statement, $uid);
$user_id = get_current_user_id();
if (($saved_cart = $wpdb->get_row($sql)) && is_object($saved_cart)) {
$statement = "UPDATE {$table} SET `cart` = '%s', `email` = '%s', `user_id` = %s WHERE `id` = '%s'";
$sql = $wpdb->prepare($statement, array(maybe_serialize($this->cart), $email, $user_id, $uid));
$wpdb->query($sql);
} else {
$wpdb->insert("{$wpdb->prefix}mailchimp_carts", array(
'id' => $uid,
'email' => $email,
'user_id' => (int) $user_id,
'cart' => maybe_serialize($this->cart),
'created_at' => gmdate('Y-m-d H:i:s', time()),
));
}
return true;
}
/**
* @param $data
*/
protected function respondJSON($data)
{
header('Content-Type: application/json');
echo json_encode($data);
exit;
}
}

View File

@@ -0,0 +1,443 @@
<?php
/**
* The file that defines the core plugin class
*
* A class definition that includes attributes and functions used across both the
* public-facing side of the site and the admin area.
*
* @link https://mailchimp.com
* @since 1.0.1
*
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
*/
/**
* The core plugin class.
*
* This is used to define internationalization, admin-specific hooks, and
* public-facing site hooks.
*
* Also maintains the unique identifier of this plugin as well as the current
* version of the plugin.
*
* @since 1.0.0
* @package MailChimp_WooCommerce
* @subpackage MailChimp_WooCommerce/includes
* @author Ryan Hungate <ryan@vextras.com>
*/
class MailChimp_WooCommerce {
/**
* The loader that's responsible for maintaining and registering all hooks that power
* the plugin.
*
* @since 1.0.0
* @access protected
* @var MailChimp_WooCommerce_Loader $loader Maintains and registers all hooks for the plugin.
*/
protected $loader;
/**
* The unique identifier of this plugin.
*
* @since 1.0.0
* @access protected
* @var string $plugin_name The string used to uniquely identify this plugin.
*/
protected $plugin_name;
/**
* The current version of the plugin.
*
* @since 1.0.0
* @access protected
* @var string $version The current version of the plugin.
*/
protected $version;
/**
* @var string
*/
protected $environment = 'production';
protected static $logging_config = null;
/**
* @return object
*/
public static function getLoggingConfig()
{
if (is_object(static::$logging_config)) {
return static::$logging_config;
}
$plugin_options = get_option('mailchimp-woocommerce');
$is_options = is_array($plugin_options);
$api_key = $is_options && array_key_exists('mailchimp_api_key', $plugin_options) ?
$plugin_options['mailchimp_api_key'] : false;
$enable_logging = $is_options &&
array_key_exists('mailchimp_debugging', $plugin_options) &&
$plugin_options['mailchimp_debugging'];
$account_id = $is_options && array_key_exists('mailchimp_account_info_id', $plugin_options) ?
$plugin_options['mailchimp_account_info_id'] : false;
$username = $is_options && array_key_exists('mailchimp_account_info_username', $plugin_options) ?
$plugin_options['mailchimp_account_info_username'] : false;
$api_key_parts = str_getcsv($api_key, '-');
$data_center = isset($api_key_parts[1]) ? $api_key_parts[1] : 'us1';
return static::$logging_config = (object) array(
'enable_logging' => (bool) $enable_logging,
'account_id' => $account_id,
'username' => $username,
'endpoint' => 'https://ecommerce.'.$data_center.'.list-manage.com/ecommerce/log',
);
}
/**
* Define the core functionality of the plugin.
*
* Set the plugin name and the plugin version that can be used throughout the plugin.
* Load the dependencies, define the locale, and set the hooks for the admin area and
* the public-facing side of the site.
*
* @param string $environment
* @param string $version
*
* @since 1.0.0
*/
public function __construct($environment = 'production', $version = '1.0.0') {
$this->plugin_name = 'mailchimp-woocommerce';
$this->version = $version;
$this->environment = $environment;
$this->load_dependencies();
$this->set_locale();
$this->define_admin_hooks();
$this->define_public_hooks();
$this->activateMailChimpNewsletter();
$this->activateMailChimpService();
}
/**
* Load the required dependencies for this plugin.
*
* Include the following files that make up the plugin:
*
* - MailChimp_WooCommerce_Loader. Orchestrates the hooks of the plugin.
* - MailChimp_WooCommerce_i18n. Defines internationalization functionality.
* - MailChimp_WooCommerce_Admin. Defines all hooks for the admin area.
* - MailChimp_WooCommerce_Public. Defines all hooks for the public side of the site.
*
* Create an instance of the loader which will be used to register the hooks
* with WordPress.
*
* @since 1.0.0
* @access private
*/
private function load_dependencies() {
global $wp_queue;
if (empty($wp_queue)) {
$wp_queue = new WP_Queue();
}
// fire up the loader
$this->loader = new MailChimp_WooCommerce_Loader();
if (!mailchimp_running_in_console() && mailchimp_is_configured()) {
// fire up the http worker container
new WP_Http_Worker($wp_queue);
}
// if we're not running in the console, and the http_worker is not running
if (mailchimp_should_init_queue()) {
try {
// if we do not have a site transient for the queue listener
if (!get_site_transient('http_worker_queue_listen')) {
// set the site transient to expire in 50 seconds so this will not happen too many times
// but still work for cron scripts on the minute mark.
set_site_transient( 'http_worker_queue_listen', microtime(), 50);
// if we have available jobs, call the http worker manually
if ($wp_queue->available_jobs()) {
mailchimp_call_http_worker_manually();
}
}
} catch (\Exception $e) {}
}
}
/**
* Define the locale for this plugin for internationalization.
*
* Uses the MailChimp_WooCommerce_i18n class in order to set the domain and to register the hook
* with WordPress.
*
* @since 1.0.0
* @access private
*/
private function set_locale() {
$plugin_i18n = new MailChimp_WooCommerce_i18n();
$this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' );
}
/**
* Register all of the hooks related to the admin area functionality
* of the plugin.
*
* @since 1.0.0
* @access private
*/
private function define_admin_hooks() {
$plugin_admin = new MailChimp_WooCommerce_Admin( $this->get_plugin_name(), $this->get_version() );
$this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles');
$this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts');
// Add menu item
$this->loader->add_action('admin_menu', $plugin_admin, 'add_plugin_admin_menu');
// Add Settings link to the plugin
$plugin_basename = plugin_basename( plugin_dir_path( __DIR__ ) . $this->plugin_name . '.php');
$this->loader->add_filter('plugin_action_links_' . $plugin_basename, $plugin_admin, 'add_action_links');
// make sure we're listening for the admin init
$this->loader->add_action('admin_init', $plugin_admin, 'options_update');
// put the menu on the admin top bar.
//$this->loader->add_action('admin_bar_menu', $plugin_admin, 'admin_bar', 100);
$this->loader->add_action('plugins_loaded', $plugin_admin, 'update_db_check');
}
/**
* Register all of the hooks related to the public-facing functionality
* of the plugin.
*
* @since 1.0.0
* @access private
*/
private function define_public_hooks() {
$plugin_public = new MailChimp_WooCommerce_Public( $this->get_plugin_name(), $this->get_version() );
$this->loader->add_action('wp_enqueue_scripts', $plugin_public, 'enqueue_styles');
$this->loader->add_action('wp_enqueue_scripts', $plugin_public, 'enqueue_scripts');
}
/**
* Handle the newsletter actions here.
*/
private function activateMailChimpNewsletter()
{
$service = new MailChimp_Newsletter();
if ($service->isConfigured()) {
$service->setEnvironment($this->environment);
$service->setVersion($this->version);
// adding the ability to render the checkbox on another screen of the checkout page.
$render_on = $service->getOption('mailchimp_checkbox_action', 'woocommerce_after_checkout_billing_form');
$this->loader->add_action($render_on, $service, 'applyNewsletterField', 10);
$this->loader->add_action('woocommerce_ppe_checkout_order_review', $service, 'applyNewsletterField', 10);
$this->loader->add_action('woocommerce_register_form', $service, 'applyNewsletterField', 10);
$this->loader->add_action('woocommerce_checkout_order_processed', $service, 'processNewsletterField', 10, 2);
$this->loader->add_action('woocommerce_ppe_do_payaction', $service, 'processPayPalNewsletterField', 10, 1);
$this->loader->add_action('woocommerce_register_post', $service, 'processRegistrationForm', 10, 3);
}
}
/**
* Handle all the service hooks here.
*/
private function activateMailChimpService()
{
$service = new MailChimp_Service();
if ($service->isConfigured()) {
$service->setEnvironment($this->environment);
$service->setVersion($this->version);
// core hook setup
$this->loader->add_action('admin_init', $service, 'adminReady');
$this->loader->add_action('woocommerce_init', $service, 'wooIsRunning');
// for the data sync we need to configure basic auth.
$this->loader->add_filter('http_request_args', $service, 'addHttpRequestArgs', 10, 2);
// campaign tracking
$this->loader->add_action( 'init', $service, 'handleCampaignTracking' );
// order hooks
$this->loader->add_action('woocommerce_thankyou', $service, 'onNewOrder', 10);
$this->loader->add_action('woocommerce_api_create_order', $service, 'onNewOrder', 10);
$this->loader->add_action('woocommerce_ppe_do_payaction', $service, 'onNewPayPalOrder', 10, 1);
$this->loader->add_action('woocommerce_order_status_changed', $service, 'handleOrderStatusChanged', 10);
// partially refunded
$this->loader->add_action('woocommerce_order_partially_refunded', $service, 'onPartiallyRefunded', 10);
// cart hooks
//$this->loader->add_action('woocommerce_cart_updated', $service, 'handleCartUpdated');
$this->loader->add_filter('woocommerce_update_cart_action_cart_updated', $service, 'handleCartUpdated');
$this->loader->add_action('woocommerce_add_to_cart', $service, 'handleCartUpdated');
$this->loader->add_action('woocommerce_cart_item_removed', $service, 'handleCartUpdated');
// save post hooks
$this->loader->add_action('save_post', $service, 'handlePostSaved', 10, 3);
$this->loader->add_action('wp_trash_post', $service, 'handlePostTrashed', 10);
$this->loader->add_action('untrashed_post', $service, 'handlePostRestored', 10);
//coupons
$this->loader->add_action('woocommerce_new_coupon', $service, 'handleNewCoupon', 10);
$this->loader->add_action('woocommerce_coupon_options_save', $service, 'handleCouponSaved', 10, 2);
$this->loader->add_action('woocommerce_api_create_coupon', $service, 'handleCouponSaved', 9, 2);
$this->loader->add_action('woocommerce_delete_coupon', $service, 'handleCouponTrashed', 10);
$this->loader->add_action('woocommerce_trash_coupon', $service, 'handleCouponTrashed', 10);
$this->loader->add_action('woocommerce_api_delete_coupon', $service, 'handleCouponTrashed', 9);
// handle the user registration hook
$this->loader->add_action('user_register', $service, 'handleUserRegistration');
// handle the user updated profile hook
$this->loader->add_action('profile_update', $service, 'handleUserUpdated', 10, 2);
// when someone deletes a user??
//$this->loader->add_action('delete_user', $service, 'handleUserDeleting');
$this->loader->add_action('wp_ajax_nopriv_mailchimp_get_user_by_hash', $service, 'get_user_by_hash');
$this->loader->add_action('wp_ajax_nopriv_mailchimp_set_user_by_email', $service, 'set_user_by_email');
}
}
/**
* Run the loader to execute all of the hooks with WordPress.
*
* @since 1.0.0
*/
public function run() {
$this->loader->run();
}
/**
* The name of the plugin used to uniquely identify it within the context of
* WordPress and to define internationalization functionality.
*
* @since 1.0.1
* @return string The name of the plugin.
*/
public function get_plugin_name() {
return $this->plugin_name;
}
/**
* The reference to the class that orchestrates the hooks with the plugin.
*
* @since 1.0.1
* @return MailChimp_WooCommerce_Loader Orchestrates the hooks of the plugin.
*/
public function get_loader() {
return $this->loader;
}
/**
* Retrieve the version number of the plugin.
*
* @since 1.0.1
* @return string The version number of the plugin.
*/
public function get_version() {
return $this->version;
}
/**
* This is just in case we ever needed to revert back to the old loading
*/
protected function manual_file_loader()
{
$path = plugin_dir_path(dirname( __FILE__ ));
/** The abstract options class.*/
require_once $path . 'includes/class-mailchimp-woocommerce-options.php';
/** The class responsible for orchestrating the actions and filters of the core plugin.*/
require_once $path . 'includes/class-mailchimp-woocommerce-loader.php';
/** The class responsible for defining internationalization functionality of the plugin. */
require_once $path . 'includes/class-mailchimp-woocommerce-i18n.php';
/** The service class.*/
require_once $path . 'includes/class-mailchimp-woocommerce-service.php';
/** The newsletter class. */
require_once $path . 'includes/class-mailchimp-woocommerce-newsletter.php';
/** The class responsible for defining all actions that occur in the admin area.*/
require_once $path . 'admin/class-mailchimp-woocommerce-admin.php';
/** The class responsible for defining all actions that occur in the public-facing side of the site. */
require_once $path . 'public/class-mailchimp-woocommerce-public.php';
/** Require all the MailChimp Assets for the API */
require_once $path . 'includes/api/class-mailchimp-api.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-api.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-create-list-submission.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-transform-orders-wc3.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-transform-products.php';
require_once $path . 'includes/api/class-mailchimp-woocommerce-transform-coupons.php';
/** Require all the mailchimp api asset classes */
require_once $path . 'includes/api/assets/class-mailchimp-address.php';
require_once $path . 'includes/api/assets/class-mailchimp-cart.php';
require_once $path . 'includes/api/assets/class-mailchimp-customer.php';
require_once $path . 'includes/api/assets/class-mailchimp-line-item.php';
require_once $path . 'includes/api/assets/class-mailchimp-order.php';
require_once $path . 'includes/api/assets/class-mailchimp-product.php';
require_once $path . 'includes/api/assets/class-mailchimp-product-variation.php';
require_once $path . 'includes/api/assets/class-mailchimp-store.php';
require_once $path . 'includes/api/assets/class-mailchimp-promo-code.php';
require_once $path . 'includes/api/assets/class-mailchimp-promo-rule.php';
/** Require all the api error helpers */
require_once $path . 'includes/api/errors/class-mailchimp-error.php';
require_once $path . 'includes/api/errors/class-mailchimp-server-error.php';
/** Require the various helper scripts */
require_once $path . 'includes/api/helpers/class-mailchimp-woocommerce-api-currency-codes.php';
require_once $path . 'includes/api/helpers/class-mailchimp-woocommerce-api-locales.php';
/** Background job sync tools */
// make sure the queue exists first since the other files depend on it.
require_once $path . 'includes/vendor/queue.php';
// the abstract bulk sync class
require_once $path.'includes/processes/class-mailchimp-woocommerce-abstract-sync.php';
// bulk data sync
require_once $path.'includes/processes/class-mailchimp-woocommerce-process-orders.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-process-products.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-process-coupons.php';
// individual item sync
require_once $path.'includes/processes/class-mailchimp-woocommerce-cart-update.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-single-order.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-single-product.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-single-coupon.php';
require_once $path.'includes/processes/class-mailchimp-woocommerce-user-submit.php';
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,395 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/14/16
* Time: 11:54 AM
*/
abstract class MailChimp_WooCommerce_Abstract_Sync extends WP_Job
{
/**
* @var MailChimp_WooCommerce_Api
*/
private $api;
/**
* @var MailChimp_WooCommerce_MailChimpApi
*/
private $mc;
/**
* @var string
*/
private $plugin_name = 'mailchimp-woocommerce';
/**
* @var string
*/
protected $store_id = '';
/**
* @return mixed
*/
abstract public function getResourceType();
/**
* @param $item
* @return mixed
*/
abstract protected function iterate($item);
/**
* @return mixed
*/
abstract protected function complete();
/**
* @return mixed
*/
public function go()
{
return $this->handle();
}
/**
* @return string
*/
public function getStoreID()
{
return mailchimp_get_store_id();
}
/**
* Task
*
* Override this method to perform any actions required on each
* queue item. Return the modified item for further processing
* in the next pass through. Or, return false to remove the
* item from the queue.
*
* @param mixed $item Queue item to iterate over
*
* @return mixed
*/
public function handle()
{
global $wpdb;
if (!mailchimp_is_configured()) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
if (!($this->store_id = $this->getStoreID())) {
mailchimp_debug(get_called_class().'@handle', 'store id not loaded');
$this->delete();
return false;
}
// don't let recursion happen.
if ($this->getResourceType() === 'orders' && $this->getResourceCompleteTime()) {
mailchimp_log('sync.stop', "halting the sync for :: {$this->getResourceType()}");
$this->delete();
return false;
}
$page = $this->getResources();
if (empty($page)) {
mailchimp_debug(get_called_class().'@handle', 'could not find any more '.$this->getResourceType().' records ending on page '.$this->getResourcePagePointer());
// call the completed event to process further
$this->resourceComplete($this->getResourceType());
$this->complete();
$this->delete();
return false;
}
$this->setResourcePagePointer(($page->page + 1), $this->getResourceType());
// if we've got a 0 count, that means we're done.
if ($page->count <= 0) {
mailchimp_debug(get_called_class().'@handle', $this->getResourceType().' :: completing now!');
// reset the resource page back to 1
$this->resourceComplete($this->getResourceType());
// call the completed event to process further
$this->complete();
$this->delete();
return false;
}
// iterate through the items and send each one through the pipeline based on this class.
foreach ($page->items as $resource) {
$this->iterate($resource);
}
$this->delete();
$class_name = get_called_class();
$wpdb->query("DELETE FROM {$wpdb->prefix}queue WHERE job LIKE '%{$class_name}%'");
// this will paginate through all records for the resource type until they return no records.
wp_queue(new static());
mailchimp_debug(get_called_class().'@handle', 'queuing up the next job');
return false;
}
/**
* @return $this
*/
public function flagStartSync()
{
$job = new MailChimp_Service();
$job->removeSyncPointers();
$this->setData('sync.config.resync', false);
$this->setData('sync.orders.current_page', 1);
$this->setData('sync.products.current_page', 1);
$this->setData('sync.syncing', true);
$this->setData('sync.started_at', time());
global $wpdb;
try {
$wpdb->show_errors(false);
$wpdb->query("DELETE FROM {$wpdb->prefix}queue");
$wpdb->show_errors(true);
} catch (\Exception $e) {}
mailchimp_log('sync.started', "Starting Sync :: ".date('D, M j, Y g:i A'));
// flag the store as syncing
mailchimp_get_api()->flagStoreSync(mailchimp_get_store_id(), true);
return $this;
}
/**
* @return $this
*/
public function flagStopSync()
{
// this is the last thing we're doing so it's complete as of now.
$this->setData('sync.syncing', false);
$this->setData('sync.completed_at', time());
// set the current sync pages back to 1 if the user hits resync.
$this->setData('sync.orders.current_page', 1);
$this->setData('sync.products.current_page', 1);
mailchimp_log('sync.completed', "Finished Sync :: ".date('D, M j, Y g:i A'));
// flag the store as sync_finished
mailchimp_get_api()->flagStoreSync(mailchimp_get_store_id(), false);
return $this;
}
/**
* @return bool|object|stdClass
*/
public function getResources()
{
$current_page = $this->getResourcePagePointer($this->getResourceType());
if ($current_page === 'complete') {
if (!$this->getData('sync.config.resync', false)) {
return false;
}
$current_page = 1;
$this->setResourcePagePointer($current_page);
$this->setData('sync.config.resync', false);
}
return $this->api()->paginate($this->getResourceType(), $current_page, 5);
}
/**
* @param null|string $resource
* @return $this
*/
public function resetResourcePagePointer($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
$this->setData('sync.'.$resource.'.current_page', 1);
return $this;
}
/**
* @param null|string $resource
* @return null
*/
public function getResourcePagePointer($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
return $this->getData('sync.'.$resource.'.current_page', 1);
}
/**
* @param $page
* @param null $resource
* @return MailChimp_WooCommerce_Abstract_Sync
*/
public function setResourcePagePointer($page, $resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
return $this->setData('sync.'.$resource.'.current_page', $page);
}
/**
* @param null|string $resource
* @return $this
*/
protected function resourceComplete($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
$this->setData('sync.'.$resource.'.current_page', 'complete');
return $this;
}
/**
* @return null
*/
protected function setResourceCompleteTime($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
return $this->setData('sync.'.$resource.'.completed_at', time());
}
/**
* @param null $resource
* @return bool|DateTime
*/
protected function getResourceCompleteTime($resource = null)
{
if (empty($resource)) $resource = $this->getResourceType();
$time = $this->getData('sync.'.$resource.'.completed_at', false);
if ($time > 0) {
try {
$date = new \DateTime();
$date->setTimestamp($time);
return $date;
} catch (\Exception $e) {
return false;
}
}
return false;
}
/**
* @param $key
* @param null $default
* @return null
*/
public function getOption($key, $default = null)
{
$options = $this->getOptions();
if (isset($options[$key])) {
return $options[$key];
}
return $default;
}
/**
* @param $key
* @param $value
* @return $this
*/
public function setOption($key, $value)
{
$options = $this->getOptions();
$options[$key] = $value;
update_option($this->plugin_name, $options);
return $this;
}
/**
* @param $key
* @param bool $default
* @return bool
*/
public function hasOption($key, $default = false)
{
return (bool) $this->getOption($key, $default);
}
/**
* @return array
*/
public function getOptions()
{
$options = get_option($this->plugin_name);
return is_array($options) ? $options : array();
}
/**
* @param $key
* @param $value
* @return $this
*/
public function setData($key, $value)
{
update_option($this->plugin_name.'-'.$key, $value, 'yes');
return $this;
}
/**
* @param $key
* @param null $default
* @return mixed|void
*/
public function getData($key, $default = null)
{
return get_option($this->plugin_name.'-'.$key, $default);
}
/**
* @param $key
* @return bool
*/
public function removeData($key)
{
return delete_option($this->plugin_name.'-'.$key);
}
/**
* @return MailChimp_WooCommerce_Api
*/
protected function api()
{
if (empty($this->api)) {
$this->api = new MailChimp_WooCommerce_Api();
}
return $this->api;
}
/**
* @return MailChimp_WooCommerce_MailChimpApi
*/
protected function mailchimp()
{
if (empty($this->mc)) {
$this->mc = new MailChimp_WooCommerce_MailChimpApi($this->getOption('mailchimp_api_key'));
}
return $this->mc;
}
}

View File

@@ -0,0 +1,182 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/15/16
* Time: 11:42 AM
*/
class MailChimp_WooCommerce_Cart_Update extends WP_Job
{
public $unique_id;
public $email;
public $previous_email;
public $campaign_id;
public $cart_data;
public $ip_address;
/**
* MailChimp_WooCommerce_Cart_Update constructor.
* @param null $uid
* @param null $email
* @param null $campaign_id
* @param array $cart_data
*/
public function __construct($uid = null, $email = null, $campaign_id = null, array $cart_data = array())
{
if ($uid) {
$this->unique_id = $uid;
}
if ($email) {
$this->email = $email;
}
if (!empty($cart_data)) {
$this->cart_data = json_encode($cart_data);
}
if ($campaign_id) {
$this->campaign_id = $campaign_id;
}
$this->ip_address = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
}
/**
* @return bool
*/
public function handle()
{
if (($result = $this->process())) {
mailchimp_log('ac.success', 'Added', array('api_response' => $result->toArray()));
}
return false;
}
/**
* @return bool|MailChimp_WooCommerce_Cart
*/
public function process()
{
try {
if (!mailchimp_is_configured() || !($api = mailchimp_get_api())) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
$options = get_option('mailchimp-woocommerce', array());
$store_id = mailchimp_get_store_id();
$this->cart_data = json_decode($this->cart_data, true);
// delete it and the add it back.
$api->deleteCartByID($store_id, $this->unique_id);
// if they emptied the cart ignore it.
if (!is_array($this->cart_data) || empty($this->cart_data)) {
return false;
}
$checkout_url = wc_get_checkout_url();
if (mailchimp_string_contains($checkout_url, '?')) {
$checkout_url .= '&mc_cart_id='.$this->unique_id;
} else {
$checkout_url .= '?mc_cart_id='.$this->unique_id;
}
$customer = new MailChimp_WooCommerce_Customer();
$customer->setId($this->unique_id);
$customer->setEmailAddress($this->email);
$customer->setOptInStatus(false);
$cart = new MailChimp_WooCommerce_Cart();
$cart->setId($this->unique_id);
$cart->setCampaignID($this->campaign_id);
$cart->setCheckoutUrl($checkout_url);
$cart->setCurrencyCode(isset($options['store_currency_code']) ? $options['store_currency_code'] : 'USD');
$cart->setCustomer($customer);
$order_total = 0;
$products = array();
foreach ($this->cart_data as $hash => $item) {
try {
$line = $this->transformLineItem($hash, $item);
$cart->addItem($line);
$order_total += ($item['quantity'] * $line->getPrice());
$products[] = $line;
} catch (\Exception $e) {}
}
if (empty($products)) {
return false;
}
$cart->setOrderTotal($order_total);
try {
// if the post is successful we're all good.
$api->addCart($store_id, $cart, false);
mailchimp_log('abandoned_cart.success', "email: {$customer->getEmailAddress()} :: checkout_url: $checkout_url");
} catch (\Exception $e) {
mailchimp_error('abandoned_cart.error', "email: {$customer->getEmailAddress()} :: attempting product update :: {$e->getMessage()}");
// if we have an error it's most likely due to a product not being found.
// let's loop through each item, verify that we have the product or not.
// if not, we will add it.
foreach ($products as $item) {
/** @var MailChimp_WooCommerce_LineItem $item */
$transformer = new MailChimp_WooCommerce_Single_Product($item->getProductID());
if (!$transformer->api()->getStoreProduct($store_id, $item->getProductId())) {
$transformer->handle();
}
}
// if the post is successful we're all good.
$api->addCart($store_id, $cart, false);
mailchimp_log('abandoned_cart.success', "email: {$customer->getEmailAddress()}");
}
} catch (\Exception $e) {
update_option('mailchimp-woocommerce-cart-error', $e->getMessage());
mailchimp_error('abandoned_cart.error', $e);
}
return false;
}
/**
* @param string $hash
* @param $item
* @return MailChimp_WooCommerce_LineItem
*/
protected function transformLineItem($hash, $item)
{
$product = wc_get_product($item['product_id']);
$price = $product ? $product->get_price() : 0;
$line = new MailChimp_WooCommerce_LineItem();
$line->setId($hash);
$line->setProductId($item['product_id']);
if (isset($item['variation_id']) && $item['variation_id'] > 0) {
$line->setProductVariantId($item['variation_id']);
} else {
$line->setProductVariantId($item['product_id']);
}
$line->setQuantity($item['quantity']);
$line->setPrice($price);
return $line;
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 10/06/17
* Time: 10:57 AM
*/
class MailChimp_WooCommerce_Process_Coupons extends MailChimp_WooCommerce_Abstract_Sync
{
/**
* @var string
*/
protected $action = 'mailchimp_woocommerce_process_coupons';
/**
* @return string
*/
public function getResourceType()
{
return 'coupons';
}
/**
* @param WC_Coupon $item
*
* @return mixed
*/
protected function iterate($item)
{
if ($item instanceof MailChimp_WooCommerce_PromoCode) {
mailchimp_debug('promo_code_sync', "#{$item->getId()}", $item->toArray());
try {
$this->mailchimp()->addPromoRule($this->store_id, $item->getAttachedPromoRule(), true);
$response = $this->mailchimp()->addPromoCodeForRule($this->store_id, $item->getAttachedPromoRule(), $item, true);
mailchimp_log('coupon_sync.success', "update promo rule :: #{$item->getCode()}");
return $response;
} catch (MailChimp_WooCommerce_ServerError $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "update promo rule :: {$item->getCode()}"));
return false;
} catch (MailChimp_WooCommerce_Error $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "update promo rule :: {$item->getCode()}"));
return false;
} catch (Exception $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "update promo rule :: {$item->getCode()}"));
return false;
}
}
mailchimp_debug('coupon_sync', 'no coupon found', $item);
return false;
}
/**
* After the resources have been loaded and pushed
*/
protected function complete()
{
mailchimp_log('coupon_sync.completed', 'Done with the coupon sync.');
// add a timestamp for the orders sync completion
$this->setResourceCompleteTime();
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/14/16
* Time: 10:57 AM
*/
class MailChimp_WooCommerce_Process_Orders extends MailChimp_WooCommerce_Abstract_Sync
{
/**
* @var string
*/
protected $action = 'mailchimp_woocommerce_process_orders';
public $items = array();
/**
* @return string
*/
public function getResourceType()
{
return 'orders';
}
/**
* @param MailChimp_WooCommerce_Order $item
*
* @return mixed
*/
protected function iterate($item)
{
if ($item instanceof MailChimp_WooCommerce_Order) {
// since we're syncing the customer for the first time, this is where we need to add the override
// for subscriber status. We don't get the checkbox until this plugin is actually installed and working!
if (!($status = $item->getCustomer()->getOptInStatus())) {
try {
$subscriber = $this->mailchimp()->member(mailchimp_get_list_id(), $item->getCustomer()->getEmailAddress());
$status = !in_array($subscriber['status'], array('unsubscribed', 'transactional'));
} catch (\Exception $e) {
$status = (bool) $this->getOption('mailchimp_auto_subscribe', true);
}
$item->getCustomer()->setOptInStatus($status);
}
mailchimp_debug('order_sync', "#{$item->getId()}", $item->toArray());
$type = $this->mailchimp()->getStoreOrder($this->store_id, $item->getId()) ? 'update' : 'create';
$call = $type === 'create' ? 'addStoreOrder' : 'updateStoreOrder';
try {
// if the order is in failed or cancelled status - and it's brand new, we shouldn't submit it.
if ($call === 'addStoreOrder' && in_array($item->getFinancialStatus(), array('failed', 'cancelled'))) {
return false;
}
// make the call
$response = $this->mailchimp()->$call($this->store_id, $item, false);
if (empty($response)) {
mailchimp_error('order_submit.failure', "$call :: #{$item->getId()} :: email: {$item->getCustomer()->getEmailAddress()} produced a blank response from MailChimp");
return $response;
}
mailchimp_log('order_submit.success', "$call :: #{$item->getId()} :: email: {$item->getCustomer()->getEmailAddress()}");
$this->items[] = array('response' => $response, 'item' => $item);
return $response;
} catch (MailChimp_WooCommerce_ServerError $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "$call :: {$item->getId()}"));
return false;
} catch (MailChimp_WooCommerce_Error $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "$call :: {$item->getId()}"));
return false;
} catch (Exception $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, "$call :: {$item->getId()}"));
return false;
}
}
mailchimp_debug('order_submit', 'no order found', $item);
return false;
}
/**
* After the resources have been loaded and pushed
*/
protected function complete()
{
mailchimp_log('order_submit.completed', 'Done with the order sync.');
// add a timestamp for the orders sync completion
$this->setResourceCompleteTime();
// this is the last thing we're doing so it's complete as of now.
$this->flagStopSync();
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/14/16
* Time: 10:57 AM
*/
class MailChimp_WooCommerce_Process_Products extends MailChimp_WooCommerce_Abstract_Sync
{
/**
* @var string
*/
protected $action = 'mailchimp_woocommerce_process_products';
public static function push()
{
$job = new MailChimp_WooCommerce_Process_Products();
$job->flagStartSync();
wp_queue($job);
}
/**
* @return string
*/
public function getResourceType()
{
return 'products';
}
/**
* @param MailChimp_WooCommerce_Product $item
*
* @return mixed
*/
protected function iterate($item) {
if ($item instanceof MailChimp_WooCommerce_Product) {
mailchimp_debug('product_sync', "#{$item->getId()}", $item->toArray());
// need to run the delete option on this before submitting because the API does not support PATCH yet.
$this->mailchimp()->deleteStoreProduct($this->store_id, $item->getId());
// add the product.
try {
// make the call
$response = $this->mailchimp()->addStoreProduct($this->store_id, $item, false);
mailchimp_log('product_sync.success', "addStoreProduct :: #{$response->getId()}");
return $response;
} catch (MailChimp_WooCommerce_ServerError $e) {
mailchimp_error('product_sync.error', mailchimp_error_trace($e, "addStoreProduct :: {$item->getId()}"));
} catch (MailChimp_WooCommerce_Error $e) {
mailchimp_error('product_sync.error', mailchimp_error_trace($e, "addStoreProduct :: {$item->getId()}"));
} catch (Exception $e) {
mailchimp_error('product_sync.error', mailchimp_error_trace($e, "addStoreProduct :: {$item->getId()}"));
}
}
return false;
}
/**
* Called after all the products have been iterated and processed into MailChimp
*/
protected function complete()
{
mailchimp_log('product_sync.completed', 'Done with the product sync :: queuing up the orders next!');
// add a timestamp for the product sync completion
$this->setResourceCompleteTime();
$prevent_order_sync = get_option('mailchimp-woocommerce-sync.orders.prevent', false);
// only do this if we're not strictly syncing products ( which is the default ).
if (!$prevent_order_sync) {
// since the products are all good, let's sync up the orders now.
wp_queue(new MailChimp_WooCommerce_Process_Orders());
}
// since we skipped the orders feed we can delete this option.
delete_option('mailchimp-woocommerce-sync.orders.prevent');
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 10/6/17
* Time: 11:14 AM
*/
class MailChimp_WooCommerce_SingleCoupon extends WP_Job
{
public $coupon_data;
public $post_id;
/**
* MailChimp_WooCommerce_Coupon_Sync constructor.
* @param $post_id
*/
public function __construct($post_id = null)
{
$this->post_id = $post_id;
}
/**
* @return null
*/
public function handle()
{
try {
if (!mailchimp_is_configured()) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
if (empty($this->post_id)) {
mailchimp_error('promo_code.failure', "could not process coupon {$this->post_id}");
return;
}
$api = mailchimp_get_api();
$store_id = mailchimp_get_store_id();
$transformer = new MailChimp_WooCommerce_Transform_Coupons();
$code = $transformer->transform($this->post_id);
$api->addPromoRule($store_id, $code->getAttachedPromoRule(), true);
$api->addPromoCodeForRule($store_id, $code->getAttachedPromoRule(), $code, true);
mailchimp_log('promo_code.update', "updated promo code {$code->getCode()}");
} catch (\Exception $e) {
$promo_code = isset($code) ? "code {$code->getCode()}" : "id {$this->post_id}";
mailchimp_error('promo_code.error', mailchimp_error_trace($e, "error updating promo {$promo_code}"));
}
}
}

View File

@@ -0,0 +1,238 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/15/16
* Time: 11:42 AM
*/
class MailChimp_WooCommerce_Single_Order extends WP_Job
{
public $order_id;
public $cart_session_id;
public $campaign_id;
public $landing_site;
public $is_update = false;
public $is_admin_save = false;
public $partially_refunded = false;
protected $woo_order_number = false;
/**
* MailChimp_WooCommerce_Single_Order constructor.
* @param null $order_id
* @param null $cart_session_id
* @param null $campaign_id
* @param null $landing_site
*/
public function __construct($order_id = null, $cart_session_id = null, $campaign_id = null, $landing_site = null)
{
if (!empty($order_id)) $this->order_id = $order_id;
if (!empty($cart_session_id)) $this->cart_session_id = $cart_session_id;
if (!empty($campaign_id)) $this->campaign_id = $campaign_id;
if (!empty($landing_site)) $this->landing_site = $landing_site;
}
/**
* @return bool
*/
public function handle()
{
$this->process();
return false;
}
public function process()
{
if (!mailchimp_is_configured() || !($api = mailchimp_get_api())) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
$store_id = mailchimp_get_store_id();
if (!($woo_order_number = $this->getRealOrderNumber())) {
mailchimp_log('order_submit.failure', "There is no real order number to use.");
return false;
}
// skip amazon orders
if ($this->isAmazonOrder()) {
mailchimp_log('validation.amazon', "Order #{$woo_order_number} was placed through Amazon. Skipping!");
return false;
}
$job = new MailChimp_WooCommerce_Transform_Orders();
// set the campaign ID
$job->campaign_id = $this->campaign_id;
$call = ($api_response = $api->getStoreOrder($store_id, $woo_order_number)) ? 'updateStoreOrder' : 'addStoreOrder';
if (!$this->is_admin_save && $call === 'addStoreOrder' && $this->is_update === true) {
return false;
}
// if we already pushed this order into the system, we need to unset it now just in case there
// was another campaign that had been sent and this was only an order update.
if ($call === 'updateStoreOrder') {
$job->campaign_id = null;
$this->campaign_id = null;
$this->landing_site = null;
}
// will either add or update the order
try {
if (!($order_post = get_post($this->order_id))) {
return false;
}
// transform the order
$order = $job->transform($order_post);
// will be the same as the customer id. an md5'd hash of a lowercased email.
$this->cart_session_id = $order->getCustomer()->getId();
// delete the AC cart record.
$deleted_abandoned_cart = !empty($this->cart_session_id) && $api->deleteCartByID($store_id, $this->cart_session_id);
// skip amazon orders
if ($order->isFlaggedAsAmazonOrder()) {
mailchimp_log('validation.amazon', "Order #{$woo_order_number} was placed through Amazon. Skipping!");
return false;
}
// if the order is in failed or cancelled status - and it's brand new, we shouldn't submit it.
if ($call === 'addStoreOrder' && in_array($order->getFinancialStatus(), array('failed', 'cancelled'))) {
return false;
}
mailchimp_debug('order_submit', "#{$woo_order_number}", $order->toArray());
// if we're overriding this we need to set it here.
if ($this->partially_refunded) {
$order->setFinancialStatus('partially_refunded');
}
$log = "$call :: #{$order->getId()} :: email: {$order->getCustomer()->getEmailAddress()}";
// only do this stuff on new orders
if ($call === 'addStoreOrder') {
// apply a campaign id if we have one.
if (!empty($this->campaign_id)) {
$log .= ' :: campaign id ' . $this->campaign_id;
$order->setCampaignId($this->campaign_id);
}
// apply the landing site if we have one.
if (!empty($this->landing_site)) {
$log .= ' :: landing site ' . $this->landing_site;
$order->setLandingSite($this->landing_site);
}
}
// update or create
$api_response = $api->$call($store_id, $order, false);
if (empty($api_response)) {
mailchimp_error('order_submit.failure', "$call :: #{$order->getId()} :: email: {$order->getCustomer()->getEmailAddress()} produced a blank response from MailChimp");
return $api_response;
}
if ($deleted_abandoned_cart) {
$log .= " :: abandoned cart deleted [{$this->cart_session_id}]";
}
mailchimp_log('order_submit.success', $log);
return $api_response;
} catch (\Exception $e) {
$message = strtolower($e->getMessage());
mailchimp_error('order_submit.tracing_error', $e);
if (!isset($order)) {
// transform the order
$order = $job->transform(get_post($this->order_id));
$this->cart_session_id = $order->getCustomer()->getId();
}
// this can happen when a customer changes their email.
if (isset($order) && strpos($message, 'not be changed')) {
try {
mailchimp_log('order_submit.deleting_customer', "#{$order->getId()} :: email: {$order->getCustomer()->getEmailAddress()}");
// delete the customer before adding it again.
$api->deleteCustomer($store_id, $order->getCustomer()->getId());
// update or create
$api_response = $api->$call($store_id, $order, false);
$log = "Deleted Customer :: $call :: #{$order->getId()} :: email: {$order->getCustomer()->getEmailAddress()}";
if (!empty($job->campaign_id)) {
$log .= ' :: campaign id '.$job->campaign_id;
}
mailchimp_log('order_submit.success', $log);
// if we're adding a new order and the session id is here, we need to delete the AC cart record.
if (!empty($this->cart_session_id)) {
$api->deleteCartByID($store_id, $this->cart_session_id);
}
return $api_response;
} catch (\Exception $e) {
mailchimp_error('order_submit.error', mailchimp_error_trace($e, 'deleting-customer-re-add :: #'.$this->order_id));
}
}
}
return false;
}
/**
* @return bool
*/
public function getRealOrderNumber()
{
try {
if (empty($this->order_id) || !($order_post = get_post($this->order_id))) {
return false;
}
$woo = new WC_Order($order_post);
return $this->woo_order_number = $woo->get_order_number();
} catch (\Exception $e) {
$this->woo_order_number = false;
mailchimp_error('order_sync.failure', mailchimp_error_trace($e, "{$this->order_id} could not be loaded"));
return false;
}
}
/**
* @return bool
*/
public function isAmazonOrder()
{
try {
if (empty($this->order_id) || !($order_post = get_post($this->order_id))) {
return false;
}
$woo = new WC_Order($order_post);
// just skip these altogether because we can't submit any amazon orders anyway.
return mailchimp_string_contains($woo->get_billing_email(), '@marketplace.amazon.com');
} catch (\Exception $e) {
return false;
}
}
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 7/15/16
* Time: 11:42 AM
*/
class MailChimp_WooCommerce_Single_Product extends WP_Job
{
public $product_id;
protected $store_id;
protected $api;
protected $service;
/**
* MailChimp_WooCommerce_Single_Order constructor.
* @param null|int $product_id
*/
public function __construct($product_id = null)
{
if (!empty($product_id)) {
$this->product_id = $product_id instanceof WP_Post ? $product_id->ID : $product_id;
}
}
/**
* @return bool
*/
public function handle()
{
$this->process();
return false;
}
/**
* @return bool|MailChimp_WooCommerce_Product
*/
public function process()
{
if (empty($this->product_id)) {
return false;
}
if (!mailchimp_is_configured()) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
if ($this->api()->getStoreProduct($this->store_id, $this->product_id)) {
$this->api()->deleteStoreProduct($this->store_id, $this->product_id);
}
try {
if (!($product_post = get_post($this->product_id))) {
return false;
}
$product = $this->transformer()->transform($product_post);
mailchimp_debug('product_submit.debug', "#{$this->product_id}", $product->toArray());
$this->api()->addStoreProduct($this->store_id, $product, false);
mailchimp_log('product_submit.success', "addStoreProduct :: #{$product->getId()}");
update_option('mailchimp-woocommerce-last_product_updated', $product->getId());
return $product;
} catch (MailChimp_WooCommerce_ServerError $e) {
mailchimp_error('product_submit.error', mailchimp_error_trace($e, "addStoreProduct :: #{$this->product_id}"));
} catch (MailChimp_WooCommerce_Error $e) {
mailchimp_log('product_submit.error', mailchimp_error_trace($e, "addStoreProduct :: #{$this->product_id}"));
} catch (Exception $e) {
mailchimp_log('product_submit.error', mailchimp_error_trace($e, "addStoreProduct :: #{$this->product_id}"));
}
return false;
}
/**
* @return MailChimp_WooCommerce_MailChimpApi
*/
public function api()
{
if (is_null($this->api)) {
$this->store_id = mailchimp_get_store_id();
$options = get_option('mailchimp-woocommerce', array());
if (!empty($this->store_id) && is_array($options) && isset($options['mailchimp_api_key'])) {
return $this->api = new MailChimp_WooCommerce_MailChimpApi($options['mailchimp_api_key']);
}
throw new \RuntimeException('The MailChimp API is not currently configured!');
}
return $this->api;
}
/**
* @return MailChimp_WooCommerce_Transform_Products
*/
public function transformer()
{
if (is_null($this->service)) {
return $this->service = new MailChimp_WooCommerce_Transform_Products();
}
return $this->service;
}
}

View File

@@ -0,0 +1,154 @@
<?php
/**
* Created by Vextras.
*
* Name: Ryan Hungate
* Email: ryan@vextras.com
* Date: 11/14/16
* Time: 9:38 AM
*/
class MailChimp_WooCommerce_User_Submit extends WP_Job
{
public $user_id;
public $subscribed;
public $updated_data;
/**
* MailChimp_WooCommerce_User_Submit constructor.
* @param null $user_id
* @param null $subscribed
* @param WP_User|null $updated_data
*/
public function __construct($user_id = null, $subscribed = null, $updated_data = null)
{
if (!empty($user_id)) {
$this->user_id = $user_id;
}
if (is_bool($subscribed)) {
$this->subscribed = $subscribed;
}
if (!empty($updated_data)) {
$this->updated_data = $updated_data->to_array();
}
}
/**
* @return bool
*/
public function handle()
{
if (!mailchimp_is_configured()) {
mailchimp_debug(get_called_class(), 'mailchimp is not configured properly');
return false;
}
$options = get_option('mailchimp-woocommerce', array());
$store_id = mailchimp_get_store_id();
// load up the user.
$user = new WP_User($this->user_id);
// we need a valid user, a valid store id and options to continue
if ($user->ID <= 0 || empty($store_id) || !is_array($options)) {
// seems as if the database records are not being set by the time this queue job is fired,
// just a precautionary to make sure it's available during
sleep(3);
$options = get_option('mailchimp-woocommerce', array());
$store_id = mailchimp_get_store_id();
// load up the user.
$user = new WP_User($this->user_id);
if ($user->ID <= 0 || empty($store_id) || !is_array($options)) {
mailchimp_log('member.sync', "Invalid Data For Submission :: {$user->user_email}");
return false;
}
}
// if we have a null value, we need to grab the correct user meta for is_subscribed
if (is_null($this->subscribed)) {
$user_subscribed = get_user_meta($this->user_id, 'mailchimp_woocommerce_is_subscribed', true);
if ($user_subscribed === '' || $user_subscribed === null) {
mailchimp_log('member.sync', "Skipping sync for {$user->user_email} because no subscriber status has been set");
return false;
}
$this->subscribed = (bool) $user_subscribed;
}
$api_key = isset($options['mailchimp_api_key']) ? $options['mailchimp_api_key'] : false;
$list_id = isset($options['mailchimp_list']) ? $options['mailchimp_list'] : false;
// we need a valid api key and list id to continue
if (empty($api_key) || empty($list_id)) {
mailchimp_log('member.sync', "Invalid Api Key or ListID :: {$user->user_email}");
return false;
}
// don't let anyone be unsubscribed from the list - that should only happen on email campaigns
// and someone clicking the unsubscribe linkage.
if (!$this->subscribed) {
return false;
}
$api = new MailChimp_WooCommerce_MailChimpApi($api_key);
$merge_vars = array();
$fn = trim($user->first_name);
$ln = trim($user->last_name);
if (!empty($fn)) $merge_vars['FNAME'] = $fn;
if (!empty($ln)) $merge_vars['LNAME'] = $ln;
try {
// see if we have a member.
$api->member($list_id, $user->user_email);
// if we're updating a member and the email is different, we need to delete the old person
if (is_array($this->updated_data) && isset($this->updated_data['user_email'])) {
if ($this->updated_data['user_email'] !== $user->user_email) {
// delete the old
$api->deleteMember($list_id, $this->updated_data['user_email']);
// subscribe the new
$api->subscribe($list_id, $user->user_email, $this->subscribed, $merge_vars);
mailchimp_log('member.sync', 'Subscriber Swap '.$this->updated_data['user_email'].' to '.$user->user_email, $merge_vars);
return false;
}
}
// ok let's update this member
$api->update($list_id, $user->user_email, $this->subscribed, $merge_vars);
mailchimp_log('member.sync', "Updated Member {$user->user_email}", $merge_vars);
} catch (\Exception $e) {
// if we have a 404 not found, we can create the member
if ($e->getCode() == 404) {
try {
$api->subscribe($list_id, $user->user_email, $this->subscribed, $merge_vars);
mailchimp_log('member.sync', "Subscribed Member {$user->user_email}", $merge_vars);
} catch (\Exception $e) {
mailchimp_log('member.sync', $e->getMessage());
}
return false;
}
mailchimp_error('member.sync', mailchimp_error_trace($e, $user->user_email));
}
return false;
}
}

View File

@@ -0,0 +1,103 @@
<?php
/*
Plugin Name: WP Background Processing
Plugin URI: https://github.com/A5hleyRich/wp-background-processing
Description: Asynchronous requests and background processing in WordPress.
Author: Delicious Brains Inc.
Version: 1.0
Author URI: https://deliciousbrains.com/
*/
$queue_folder_path = plugin_dir_path( __FILE__ );
require_once $queue_folder_path . 'queue/classes/wp-job.php';
require_once $queue_folder_path . 'queue/classes/wp-queue.php';
require_once $queue_folder_path . 'queue/classes/worker/wp-worker.php';
require_once $queue_folder_path . 'queue/classes/worker/wp-http-worker.php';
global $wp_queue;
$wp_queue = new WP_Queue();
// Add WP CLI commands
if (defined( 'WP_CLI' ) && WP_CLI) {
try {
/**
* Service push to MailChimp
*
* <type>
* : product_sync order_sync order product
*/
function mailchimp_cli_push_command( $args, $assoc_args ) {
if (is_array($args) && isset($args[0])) {
switch($args[0]) {
case 'product_sync':
wp_queue(new MailChimp_WooCommerce_Process_Products());
WP_CLI::success("queued up the product sync!");
break;
case 'order_sync':
wp_queue(new MailChimp_WooCommerce_Process_Orders());
WP_CLI::success("queued up the order sync!");
break;
case 'order':
if (!isset($args[1])) {
wp_die('You must specify an order id as the 2nd parameter.');
}
wp_queue(new MailChimp_WooCommerce_Single_Order($args[1]));
WP_CLI::success("queued up the order {$args[1]}!");
break;
case 'product':
if (!isset($args[1])) {
wp_die('You must specify a product id as the 2nd parameter.');
}
wp_queue(new MailChimp_WooCommerce_Single_Product($args[1]));
WP_CLI::success("queued up the product {$args[1]}!");
break;
}
}
};
WP_CLI::add_command( 'mailchimp_push', 'mailchimp_cli_push_command');
require_once $queue_folder_path . 'queue/classes/cli/queue-command.php';
WP_CLI::add_command( 'queue', 'Queue_Command' );
} catch (\Exception $e) {}
}
if (!mailchimp_running_in_console() && mailchimp_is_configured()) {
// fire up the http worker container
new WP_Http_Worker($wp_queue);
}
// if we're not running in the console, and the http_worker is not running
if (mailchimp_should_init_queue()) {
try {
// if we do not have a site transient for the queue listener
if (!get_site_transient('http_worker_queue_listen')) {
// set the site transient to expire in 50 seconds so this will not happen too many times
// but still work for cron scripts on the minute mark.
set_site_transient( 'http_worker_queue_listen', microtime(), 50);
// if we have available jobs, call the http worker manually
if ($wp_queue->available_jobs()) {
mailchimp_call_http_worker_manually();
}
}
} catch (\Exception $e) {}
}
if (!function_exists( 'wp_queue')) {
/**
* WP queue.
*
* @param WP_Job $job
* @param int $delay
*/
function wp_queue( WP_Job $job, $delay = 0 ) {
global $wp_queue;
$wp_queue->push( $job, $delay );
do_action( 'wp_queue_job_pushed', $job );
}
}

View File

@@ -0,0 +1,391 @@
<?php
/**
* Manage queue and jobs.
*
* @package wp-cli
*/
class Queue_Command extends WP_CLI_Command {
/**
* Timestamp of when this worker started processing the queue.
*
* @var int
*/
protected $start_time;
protected $pid;
protected $command_called;
/**
* Queue_Command constructor.
*/
public function __construct()
{
$this->pid = getmypid();
register_shutdown_function(array($this, 'on_shutdown'));
}
/**
* make sure we remove the site transient
*/
public function on_shutdown()
{
switch ($this->command_called) {
case 'listen':
$this->deleteQueueTimer();
break;
}
}
/**
* Get the expiration for the single cron job
*
* @throws \WP_CLI\ExitException
*/
public function expired_at()
{
$time = $this->getQueueTimer();
if (empty($time)) {
WP_CLI::error('no timer running');
wp_die();
}
WP_CLI::success("Next iteration will happen no later than ".(string) mailchimp_date_utc($time));
wp_die();
}
/**
* Flush all of the records in the queue.
*/
public function flush()
{
global $wpdb;
$this->command_called = 'flush';
$wpdb->query("DELETE FROM {$wpdb->prefix}queue");
}
/**
* Show all the records in the queue.
*/
public function show()
{
global $wpdb;
$this->command_called = 'show';
print_r($wpdb->get_results("SELECT * FROM {$wpdb->prefix}queue"));
}
/**
* Creates the queue tables.
*
* @subcommand create-tables
*/
public function create_tables( $args, $assoc_args = array() ) {
$this->command_called = 'create_tables';
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
global $wpdb;
$wpdb->hide_errors();
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE {$wpdb->prefix}queue (
id bigint(20) NOT NULL AUTO_INCREMENT,
job text NOT NULL,
attempts tinyint(1) NOT NULL DEFAULT 0,
locked tinyint(1) NOT NULL DEFAULT 0,
locked_at datetime DEFAULT NULL,
available_at datetime NOT NULL,
created_at datetime NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta( $sql );
$sql = "CREATE TABLE {$wpdb->prefix}failed_jobs (
id bigint(20) NOT NULL AUTO_INCREMENT,
job text NOT NULL,
failed_at datetime NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta( $sql );
WP_CLI::success( "Table {$wpdb->prefix}queue created." );
}
/**
* Run the queue listener to process jobs
*
* ## OPTIONS
*
* [--force=<0>]
* : Force the listener to ignore the transient and run
*
* [--daemon=<0>]
* : Running the command as a true process using a manager to keep alive.
* If using WP CRON use --daemon=0
* If using a process manager, do nothing or pass in 1
*
* [--multiple=<0>]
* : Allow multiple processes to run at the same time. ( default is 0 )
*
* [--sleep_processing=<1>]
* : How long to sleep between jobs. ( default is 1 second )
*
* [--sleep_empty=<5>]
* : How long to sleep between jobs when nothing is in the queue. ( default is 5 seconds )
* ---
*
* ## EXAMPLES
*
* wp queue listen --daemon=1
* wp queue listen --daemon=0 --sleep_empty=10
*
* ---
*
* @subcommand listen
* @param $args
* @param array $assoc_args
*/
public function listen( $args, $assoc_args = array() ) {
global $wp_queue;
$this->command_called = 'listen';
$this->start_time = time(); // Set start time of current command
$allow_multiple = (isset($assoc_args['multiple']) ? (bool) $assoc_args['multiple'] : null) === true;
$running_as_daemon = (isset($assoc_args['daemon']) ? (bool) $assoc_args['daemon'] : null) === true;
$force = (isset($assoc_args['force']) ? (bool) $assoc_args['force'] : null) === true;
$sleep_between_jobs = isset($assoc_args['sleep_processing']) ? (int) $assoc_args['sleep_processing'] : 1;
$sleep_when_empty = isset($assoc_args['sleep_empty']) ? (int) $assoc_args['sleep_empty'] : 5;
$expire_time = $this->getQueueTimer();
if (!$force && !$allow_multiple) {
if (!empty($expire_time) && ($expire_time+100) > $this->start_time) {
WP_CLI::log('Currently running in another process');
//mailchimp_debug("queue", $message = "wp queue listen is running in another process or waiting to restart at [{$expire_time}] but clock says [{$this->start_time}].");
wp_die();
}
}
$this->updateQueueTimer();
mailchimp_debug("queue", $message = "[start] queue listen process_id [{$this->pid}] :: max_time [{$this->getServerMaxExecutionTime()}] :: memory limit [{$this->getServerMemoryLimit()}]");
WP_CLI::log($message);
$worker = new WP_Worker( $wp_queue );
$loop_counter = 0;
// if the user specifies that they want to run as a daemon we need to allow that.
while ($running_as_daemon || $this->all_good_under_the_hood()) {
$loop_counter++;
// if we're doing single processing only, set the transient
if (!$allow_multiple) {
if ($loop_counter % 5 === 0) {
$this->updateQueueTimer(time() + 300);
}
}
// allow queue to break out of the forever loop if something is going wrong by adding a transient
if ((bool) get_site_transient('kill_wp_queue_listener')) {
break;
}
// log it in increments of 20 to be lighter on the log file
if ($loop_counter % 20 === 0) {
mailchimp_debug("queue listen", $message = "process id {$this->pid} :: loop #{$loop_counter}");
WP_CLI::log($message);
}
$sleep = $sleep_when_empty;
// if the worker has a job, apply the sleep between job timeout
if ($worker->should_run() && $worker->process_next_job()) {
$sleep = $sleep_between_jobs;
if (($job_name = $worker->get_job_name()) !== 'WP_Worker') {
WP_CLI::success('Processed: ' . $job_name);
}
}
sleep($sleep);
}
if (!$allow_multiple) {
$this->deleteQueueTimer();
}
mailchimp_debug("queue", $message = '[end] queue listen process_id = '.$this->pid);
WP_CLI::log($message);
exit;
}
/**
* Process the next job in the queue.
* @subcommand work
*/
public function work( $args, $assoc_args = array() ) {
global $wp_queue;
$this->command_called = 'work';
$worker = new WP_Worker( $wp_queue );
if ( $worker->should_run() ) {
if ( $worker->process_next_job() ) {
WP_CLI::success( 'Processed: ' . $worker->get_job_name() );
} else {
WP_CLI::warning( 'Failed: ' . $worker->get_job_name() );
}
} else {
WP_CLI::log( 'No jobs to process...' );
}
}
/**
* Show queue status.
*/
public function status( $args, $assoc_args = array() ) {
global $wp_queue;
$this->command_called = 'status';
WP_CLI::log( $wp_queue->available_jobs() . ' jobs in the queue' );
WP_CLI::log( $wp_queue->failed_jobs() . ' failed jobs' );
}
/**
* Push failed jobs back onto the queue.
*
* @subcommand restart-failed
*/
public function restart_failed( $args, $assoc_args = array() ) {
global $wp_queue;
$this->command_called = 'restart_failed';
if ( ! $wp_queue->failed_jobs() ) {
WP_CLI::log( 'No failed jobs to restart...' );
return;
}
$count = $wp_queue->restart_failed_jobs();
WP_CLI::success( $count . ' failed jobs pushed to the queue' );
}
/**
* @return mixed
*/
protected function deleteQueueTimer()
{
global $wpdb;
$key = 'mailchimp_woocommerce_queue_listen';
$sql = $wpdb->prepare("DELETE FROM {$wpdb->options} WHERE option_name = %s", $key);
return $wpdb->query($sql);
}
/**
* @return null
*/
protected function getQueueTimer()
{
global $wpdb;
$key = 'mailchimp_woocommerce_queue_listen';
$row = $wpdb->get_row($wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $key));
return is_object($row) ? (int) unserialize($row->option_value) : null;
}
/**
* @param null $time
* @return mixed
*/
protected function updateQueueTimer($time = null)
{
global $wpdb;
if (empty($this->start_time)) {
$this->start_time = time();
}
$value = $time ?: $this->start_time+600;
$values = array(
'option_value' => serialize($value),
'autoload' => 'no',
);
$key = 'mailchimp_woocommerce_queue_listen';
$updated = $wpdb->update($wpdb->options, $values, array('option_name' => $key));
if ($updated) {
return $updated;
}
$values['option_name'] = $key;
return $wpdb->insert($wpdb->options, $values);
}
/**
* @return bool
*/
protected function all_good_under_the_hood()
{
return !$this->time_exceeded() && !$this->memory_exceeded();
}
/**
* Memory exceeded
*
* Ensures the worker process never exceeds 80%
* of the maximum allowed PHP memory.
*
* @return bool
*/
protected function memory_exceeded() {
return memory_get_usage( true ) >= ($this->get_memory_limit() * 0.8);
}
/**
* Get memory limit
*
* @return int
*/
protected function get_memory_limit() {
return intval($this->getServerMemoryLimit()) * 1024 * 1024;
}
/**
* Time exceeded
*
* Ensures the worker never exceeds a sensible time limit (50s by default).
* A timeout limit of 30s is common on shared hosting.
*
* @return bool
*/
protected function time_exceeded() {
return time() >= $this->start_time + apply_filters( 'cli_worker_default_time_limit', ($this->getServerMaxExecutionTime() - 10));
}
/**
* @return int
*/
protected function getServerMaxExecutionTime()
{
$time_limit = (int) function_exists( 'ini_get' ) ? ini_get( 'max_execution_time' ) : 30;
if (!$time_limit || -1 == $time_limit) {
$time_limit = 1800;
}
return $time_limit;
}
/**
* @return string
*/
protected function getServerMemoryLimit()
{
$memory_limit = function_exists( 'ini_get' ) ? ini_get( 'memory_limit' ) : '128M';
if (!$memory_limit || -1 == $memory_limit) {
$memory_limit = '32000M';
}
return (int) preg_replace_callback('/(\-?\d+)(.?)/', function ($m) {
return $m[1] * pow(1024, strpos('BKMG', $m[2]));
}, strtoupper($memory_limit));
}
}

View File

@@ -0,0 +1,340 @@
<?php
if ( ! class_exists( 'WP_Http_Worker' ) ) {
class WP_Http_Worker extends WP_Worker {
/**
* Has the worker been dispatched in this request?
*
* @var bool
*/
protected $dispatched = false;
/**
* Timestamp of when this worker started processing the queue.
*
* @var int
*/
protected $start_time;
/**
* WP_Http_Worker constructor
*
* @param WP_Queue $queue
*/
public function __construct( $queue ) {
parent::__construct( $queue );
// Cron health check
add_action( 'http_worker_cron', array( $this, 'handle_cron' ) );
add_filter( 'cron_schedules', array( $this, 'schedule_cron' ) );
$this->maybe_schedule_cron();
// Dispatch handlers
add_action( 'wp_ajax_http_worker', array( $this, 'maybe_handle' ) );
add_action( 'wp_ajax_nopriv_http_worker', array( $this, 'maybe_handle' ) );
// Dispatch listener
add_action( 'wp_queue_job_pushed', array( $this, 'maybe_dispatch_worker' ) );
if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'http_worker' && check_ajax_referer( 'http_worker', 'nonce', false)) {
add_action('init', array($this, 'handle'));
}
}
/**
* Maybe handle
*
* Process the queue if no other HTTP worker is running and
* the current worker is within server memory and time limit constraints.
* Automatically dispatch another worker and kill the current process if
* jobs remain in the queue and server limits reached.
*/
public function maybe_handle() {
check_ajax_referer( 'http_worker', 'nonce' );
$this->handle();
}
/**
*
*/
public function handle()
{
if ( $this->is_worker_running() ) {
// Worker already running, die
wp_die();
}
// Lock worker to prevent multiple instances spawning
$this->lock_worker();
$processed_something = false;
// Loop over jobs while within server limits
while ( ! $this->time_exceeded() && ! $this->memory_exceeded() ) {
if ( $this->should_run() ) {
$this->process_next_job();
$processed_something = true;
} else {
break;
}
}
// Unlock worker to allow another instance to be spawned
$this->unlock_worker();
$available_jobs = $this->queue->available_jobs();
if (!$processed_something && $available_jobs) {
mailchimp_debug('queue_tracer', "HTTPWorker@handle", array(
'jobs' => $available_jobs,
'time_exceeded' => $this->time_exceeded(),
'memory_exceeded' => $this->memory_exceeded(),
'memory_limit' => $this->get_memory_limit(),
'memory_usage' => memory_get_usage(true),
'ini_memory' => ini_get('memory_limit'),
'php_version' => phpversion(),
));
wp_die();
}
if ($available_jobs) {
// Job queue not empty, dispatch async worker request
$this->dispatch();
}
wp_die();
}
/**
* Memory exceeded
*
* Ensures the worker process never exceeds 80%
* of the maximum allowed PHP memory.
*
* @return bool
*/
protected function memory_exceeded() {
$memory_limit = $this->get_memory_limit() * 0.8; // 80% of max memory
$current_memory = memory_get_usage( true );
$return = false;
if ( $current_memory >= $memory_limit ) {
$return = true;
}
return apply_filters( 'http_worker_memory_exceeded', $return );
}
/**
* Get memory limit
*
* @return int
*/
protected function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
// Sensible default
$memory_limit = '128M';
}
if ( ! $memory_limit || -1 == $memory_limit ) {
// Unlimited, set to 32GB
$memory_limit = '32000M';
}
return (int) preg_replace_callback('/(\-?\d+)(.?)/', function ($m) {
return $m[1] * pow(1024, strpos('BKMG', $m[2]));
}, strtoupper($memory_limit));
}
/**
* Time exceeded
*
* Ensures the worker never exceeds a sensible time limit (20s by default).
* A timeout limit of 30s is common on shared hosting.
*
* @return bool
*/
protected function time_exceeded() {
$finish = $this->start_time + apply_filters( 'http_worker_default_time_limit', 20 ); // 20 seconds
$return = false;
if ( time() >= $finish ) {
$return = true;
}
return apply_filters( 'http_worker_time_exceeded', $return );
}
/**
* Maybe dispatch worker
*
* Dispatch a worker process if we haven't already in this request
* and no other HTTP workers are running.
*
* @param WP_Job $job
*/
public function maybe_dispatch_worker( $job ) {
if ( $this->is_worker_running() ) {
// HTTP worker already running, return
return;
}
// Dispatch async worker request
$this->dispatch();
}
/**
* Is worker running
*
* Check if another instance of the HTTP worker is running.
*
* @return bool
*/
protected function is_worker_running() {
if ( get_site_transient( 'http_worker_lock' ) ) {
// Process already running
return true;
}
return false;
}
/**
* Lock worker
*
* Lock the HTTP worker to prevent multiple instances running.
*/
protected function lock_worker() {
$this->start_time = time(); // Set start time of current worker
$lock_duration = apply_filters( 'http_worker_lock_time', 60 ); // 60 seconds
set_site_transient( 'http_worker_lock', microtime(), $lock_duration );
}
/**
* Unlock worker
*
* Unlock the HTTP worker to allow other instances to be spawned.
*/
protected function unlock_worker() {
delete_site_transient( 'http_worker_lock' );
}
/**
* Dispatch
*
* Fire off a non-blocking async request if we haven't already
* in this request.
*/
protected function dispatch() {
if ( $this->is_http_worker_disabled() ) {
return;
}
if ( ! $this->dispatched ) {
$this->async_request();
}
$this->dispatched = true;
}
/**
* Is HTTP worker disabled
*
* @return bool
*/
protected function is_http_worker_disabled() {
if ( ! defined( 'DISABLE_WP_HTTP_WORKER' ) || true !== DISABLE_WP_HTTP_WORKER ) {
return false;
}
return true;
}
/**
* Async request
*
* Fire off a non-blocking request to admin-ajax.php.
*
* @return array|WP_Error
*/
protected function async_request() {
$action = 'http_worker';
$query_args = apply_filters( 'http_worker_query_args', array(
'action' => $action,
'nonce' => wp_create_nonce( $action ),
) );
$query_url = apply_filters( 'http_worker_query_url', admin_url( 'admin-ajax.php' ) );
$post_args = apply_filters( 'http_worker_post_args', array(
'timeout' => 0.01,
'blocking' => false,
'cookies' => $_COOKIE,
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
) );
$url = add_query_arg( $query_args, $query_url );
return wp_remote_post( esc_url_raw( $url ), $post_args );
}
/**
* @return bool
*/
public function handle_cron() {
if ($this->is_worker_running()) {
wp_die();
}
if ($this->queue->available_jobs()) {
$this->dispatch();
return true;
}
return false;
}
/**
* Cron schedules
*
* @param $schedules
*
* @return mixed
*/
public function schedule_cron( $schedules ) {
$interval = apply_filters( 'http_worker_cron_interval', 3 );
// Adds every 3 minutes to the existing schedules.
$schedules[ 'http_worker_cron_interval' ] = array(
'interval' => MINUTE_IN_SECONDS * $interval,
'display' => sprintf( __( 'Every %d Minutes' ), $interval ),
);
return $schedules;
}
/**
* Maybe schedule cron
*
* Schedule health check cron if not disabled. Remove schedule if
* disabled and already scheduled.
*/
public function maybe_schedule_cron() {
if ( !$this->is_http_worker_disabled() && ! wp_next_scheduled( 'http_worker_cron' )) {
// Schedule health check
wp_schedule_event( time(), 'http_worker_cron_interval', 'http_worker_cron' );
}
}
}
}

View File

@@ -0,0 +1,96 @@
<?php
if ( ! class_exists( 'WP_Worker' ) ) {
class WP_Worker {
/**
* @var WP_Queue
*/
protected $queue;
/**
* @var WP_Job
*/
protected $payload;
/**
* WP_Worker constructor.
*
* @param WP_Queue $queue
*/
public function __construct( $queue ) {
$this->queue = $queue;
}
/**
* Should run
*
* @return bool
*/
public function should_run() {
if ( $this->queue->available_jobs() ) {
return true;
}
return false;
}
/**
* Process next job.
*
* @return bool
*/
public function process_next_job() {
$job = $this->queue->get_next_job();
if (empty($job)) {
return false;
}
$this->payload = unserialize( $job->job );
$this->queue->lock_job( $job );
$this->payload->set_job( $job );
try {
$this->payload->handle();
if ( $this->payload->is_deleted() ) {
// Job manually deleted, delete from queue
$this->queue->delete( $job );
return true;
}
if ( $this->payload->is_released() ) {
// Job manually released, release back onto queue
$this->queue->release( $job, $this->payload->get_delay() );
}
if ( ! $this->payload->is_deleted_or_released() ) {
// Job completed, delete from queue
$this->queue->delete( $job );
}
} catch ( Exception $e ) {
mailchimp_log('queue.error', "{$e->getMessage()} on {$e->getLine()} in {$e->getFile()}", array('job' => get_class($this->payload)));
$this->queue->release( $job );
return false;
}
if (defined('WP_CLI') && WP_CLI && property_exists($this->payload, 'should_kill_queue_listener') && $this->payload->should_kill_queue_listener === true) {
wp_die('killing queue listener');
}
return true;
}
/**
* Get job name.
*
* @return object
*/
public function get_job_name() {
return get_class( $this->payload );
}
}
}

View File

@@ -0,0 +1,105 @@
<?php
if ( ! class_exists( 'WP_Job' ) ) {
abstract class WP_Job {
public $should_kill_queue_listener = false;
/**
* @var stdClass
*/
private $job;
/**
* @var int
*/
private $delay = 0;
/**
* @var bool
*/
private $deleted = false;
/**
* @var bool
*/
private $released = false;
/**
* Set job
*
* @param $job
*/
public function set_job( $job ) {
$this->job = $job;
}
/**
* Delete the job from the queue
*/
protected function delete() {
$this->deleted = true;
}
/**
* Release a job back onto the queue
*
* @param int $delay
*/
protected function release( $delay = 0 ) {
$this->released = true;
$this->delay = $delay;
}
/**
* Attempts
*
* @return int
*/
protected function attempts() {
return (int) $this->job->attempts;
}
/**
* Is deleted.
*
* @return bool
*/
public function is_deleted() {
return $this->deleted;
}
/**
* Is released.
*
* @return bool
*/
public function is_released() {
return $this->released;
}
/**
* Is deleted for released
*
* @return bool
*/
public function is_deleted_or_released() {
return $this->is_deleted() || $this->is_released();
}
/**
* Get delay.
*
* @return int
*/
public function get_delay() {
return $this->delay;
}
/**
* Handle the job.
*/
abstract public function handle();
}
}

View File

@@ -0,0 +1,226 @@
<?php
if ( ! class_exists( 'WP_Queue' ) ) {
class WP_Queue {
/**
* @var string
*/
public $table;
/**
* @var string
*/
public $failed_table;
/**
* @var int
*/
public $release_time = 60;
/**
* WP_Queue constructor
*/
public function __construct() {
global $wpdb;
$this->table = $wpdb->prefix . 'queue';
$this->failed_table = $wpdb->prefix . 'failed_jobs';
}
/**
* Push a job onto the queue.
*
* @param WP_Job $job
* @param int $delay
*
* @return $this
*/
public function push( WP_Job $job, $delay = 0 ) {
global $wpdb;
$data = array(
'job' => maybe_serialize( $job ),
'available_at' => $this->datetime( $delay ),
'created_at' => $this->datetime(),
);
$id = $wpdb->insert( $this->table, $data );
return $this;
}
/**
* Release.
*
* @param object $job
* @param int $delay
*/
public function release( $job, $delay = 0 ) {
if ( $job->attempts >= 3 ) {
$this->failed( $job );
return;
}
global $wpdb;
$data = array(
'attempts' => $job->attempts + 1,
'locked' => 0,
'locked_at' => null,
'available_at' => $this->datetime( $delay ),
);
$where = array(
'id' => $job->id,
);
$wpdb->update( $this->table, $data, $where );
}
/**
* Failed
*
* @param stdClass $job
*/
protected function failed( $job ) {
global $wpdb;
$wpdb->insert( $this->failed_table, array(
'job' => $job->job,
'failed_at' => $this->datetime(),
) );
$payload = unserialize($job->job);
if (method_exists($payload, 'failed')) {
$payload->failed();
}
$this->delete( $job );
}
/**
* Delete.
*
* @param object $job
*/
public function delete( $job ) {
global $wpdb;
$wpdb->delete($this->table, array('id' => $job->id));
}
/**
* Get MySQL datetime.
*
* @param int $offset Seconds, can pass negative int.
*
* @return string
*/
protected function datetime($offset = 0) {
$timestamp = time() + $offset;
return gmdate( 'Y-m-d H:i:s', $timestamp );
}
/**
* Available jobs.
*/
public function available_jobs() {
global $wpdb;
$now = $this->datetime();
$sql = $wpdb->prepare( "
SELECT COUNT(*) FROM {$this->table}
WHERE available_at <= %s"
, $now );
return $wpdb->get_var( $sql );
}
/**
* Available jobs.
*/
public function failed_jobs() {
global $wpdb;
return $wpdb->get_var( "SELECT COUNT(*) FROM {$this->failed_table}" );
}
/**
* Restart failed jobs.
*/
public function restart_failed_jobs() {
global $wpdb;
$count = 0;
$jobs = $wpdb->get_results( "SELECT * FROM {$this->failed_table}" );
foreach ( $jobs as $job ) {
$this->push( maybe_unserialize( $job->job ) );
$wpdb->delete( $this->failed_table, array(
'id' => $job->id,
) );
$count++;
}
return $count;
}
/**
* Get next job.
*/
public function get_next_job() {
global $wpdb;
$this->maybe_release_locked_jobs();
$now = $this->datetime();
$sql = $wpdb->prepare( "
SELECT * FROM {$this->table}
WHERE locked = 0
AND available_at <= %s"
, $now );
return $wpdb->get_row( $sql );
}
/**
* Maybe release locked jobs.
*/
protected function maybe_release_locked_jobs() {
global $wpdb;
$expired = $this->datetime( - $this->release_time );
$sql = $wpdb->prepare( "
UPDATE {$this->table}
SET attempts = attempts + 1, locked = 0, locked_at = NULL
WHERE locked = 1
AND locked_at <= %s"
, $expired );
$wpdb->query( $sql );
}
/**
* Lock job.
*
* @param object $job
*/
public function lock_job( $job ) {
global $wpdb;
$data = array(
'locked' => 1,
'locked_at' => $this->datetime(),
);
$where = array(
'id' => $job->id,
);
$wpdb->update( $this->table, $data, $where );
}
}
}