Beeketing_IntegrateApp - Version 1.0.0

Version Notes

Add new apps features:
- Email Automation
- Checkout Boost
- Boost Sales
- Product recommendation
- Happy Email

Download this release

Release Info

Developer Beeketing Inc.
Extension Beeketing_IntegrateApp
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

Files changed (42) hide show
  1. app/code/community/Beeketing/IntegrateApp/Block/AppsData.php +53 -0
  2. app/code/community/Beeketing/IntegrateApp/Helper/Collection.php +93 -0
  3. app/code/community/Beeketing/IntegrateApp/Helper/Core.php +128 -0
  4. app/code/community/Beeketing/IntegrateApp/Helper/Customer.php +113 -0
  5. app/code/community/Beeketing/IntegrateApp/Helper/Data.php +87 -0
  6. app/code/community/Beeketing/IntegrateApp/Helper/Order.php +67 -0
  7. app/code/community/Beeketing/IntegrateApp/Helper/Product.php +299 -0
  8. app/code/community/Beeketing/IntegrateApp/Model/Observer.php +173 -0
  9. app/code/community/Beeketing/IntegrateApp/Model/Observer/Cart.php +109 -0
  10. app/code/community/Beeketing/IntegrateApp/Model/Observer/Collection.php +22 -0
  11. app/code/community/Beeketing/IntegrateApp/Model/Observer/Customer.php +39 -0
  12. app/code/community/Beeketing/IntegrateApp/Model/Observer/Order.php +42 -0
  13. app/code/community/Beeketing/IntegrateApp/Model/Observer/Product.php +107 -0
  14. app/code/community/Beeketing/IntegrateApp/controllers/Api/CartController.php +207 -0
  15. app/code/community/Beeketing/IntegrateApp/controllers/Api/CollectionController.php +269 -0
  16. app/code/community/Beeketing/IntegrateApp/controllers/Api/CustomerController.php +74 -0
  17. app/code/community/Beeketing/IntegrateApp/controllers/Api/OrderController.php +71 -0
  18. app/code/community/Beeketing/IntegrateApp/controllers/Api/ProductController.php +149 -0
  19. app/code/community/Beeketing/IntegrateApp/controllers/Api/ShopController.php +73 -0
  20. app/code/community/Beeketing/IntegrateApp/controllers/System/ConfigController.php +45 -0
  21. app/code/community/Beeketing/IntegrateApp/etc/adminhtml.xml +22 -0
  22. app/code/community/Beeketing/IntegrateApp/etc/config.xml +215 -0
  23. app/code/community/Beeketing/IntegrateApp/etc/system.xml +40 -0
  24. app/etc/modules/Beeketing_IntegrateApp.xml +12 -0
  25. lib/Beeketing/BeeketingMagento.php +58 -0
  26. lib/Beeketing/config.php +2 -0
  27. lib/Beeketing/env +1 -0
  28. lib/BeeketingSDK/Api/BeeketingApi.php +670 -0
  29. lib/BeeketingSDK/Api/BeeketingCart.php +395 -0
  30. lib/BeeketingSDK/Api/BeeketingCollections.php +222 -0
  31. lib/BeeketingSDK/Api/BeeketingCollects.php +124 -0
  32. lib/BeeketingSDK/Api/BeeketingCustomers.php +185 -0
  33. lib/BeeketingSDK/Api/BeeketingOrders.php +207 -0
  34. lib/BeeketingSDK/Api/BeeketingProducts.php +727 -0
  35. lib/BeeketingSDK/Api/BeeketingShop.php +60 -0
  36. lib/BeeketingSDK/Config/BeeketingConfig.php +255 -0
  37. lib/BeeketingSDK/Helper/beeketing-cron-functions.php +400 -0
  38. lib/BeeketingSDK/Helper/beeketing-helper-functions.php +386 -0
  39. lib/BeeketingSDK/Snippet/DefaultSnippet.php +79 -0
  40. lib/BeeketingSDK/Snippet/SnippetManager.php +182 -0
  41. lib/BeeketingSDK/Snippet/Templates/CouponBoxSnippet.html +13 -0
  42. package.xml +23 -0
app/code/community/Beeketing/IntegrateApp/Block/AppsData.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if (isset($hasApiKey) && $hasApiKey) {?>
2
+ <?php if (isset($beeketingAppsData['your_apps']) && count($beeketingAppsData['your_apps']) > 0) {?>
3
+ <h3>Your apps</h3>
4
+
5
+ <ul style="width: 100%;">
6
+ <?php foreach($beeketingAppsData['your_apps'] as $app) {?>
7
+ <li style="margin: 20px; float: left;">
8
+ <div style="width: 310px;">
9
+ <a href="<?php echo $app['info_url'];?>" target="_blank">
10
+ <img src="<?php echo $app['img'];?>" alt="<?php echo $app['name'];?>">
11
+ </a>
12
+ </div>
13
+ </li>
14
+ <?php }?>
15
+ </ul>
16
+
17
+ <div style="clear: both;"></div>
18
+
19
+ <br />
20
+ <?php }?>
21
+
22
+ <?php if (isset($beeketingAppsData['more_apps']) && count($beeketingAppsData['more_apps']) > 0) {?>
23
+ <h3>More apps</h3>
24
+
25
+ <ul style="width: 100%;">
26
+ <?php foreach($beeketingAppsData['more_apps'] as $app) {?>
27
+ <li style="margin: 20px; float: left; text-align: center;">
28
+ <div style="width: 310px;">
29
+ <a href="<?php echo $app['info_url'];?>" target="_blank">
30
+ <img src="<?php echo $app['img'];?>" alt="<?php echo $app['name'];?>">
31
+ </a>
32
+ </div>
33
+
34
+ <div style="margin-top: 10px; width: 310px;">
35
+ <div style="float: left;">
36
+ <button type="button" onClick="window.open('<?php echo $app['install_url'];?>', '_blank');">Install</button>
37
+ </div>
38
+
39
+ <div style="float: right;">
40
+ <button type="button" onClick="window.open('<?php echo $app['info_url'];?>', '_blank');">More info</button>
41
+ </div>
42
+
43
+ <div style="clear: both;"></div>
44
+ </div>
45
+ </li>
46
+ <?php }?>
47
+ </ul>
48
+
49
+ <div style="clear: both;"></div>
50
+
51
+ <br />
52
+ <?php }?>
53
+ <?php }?>
app/code/community/Beeketing/IntegrateApp/Helper/Collection.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 24/12/2015
6
+ * Time: 10:00
7
+ */
8
+ class Beeketing_IntegrateApp_Helper_Collection extends Mage_Core_Helper_Abstract
9
+ {
10
+ /**
11
+ * Get data of collection for Beeketing Api
12
+ * @param Mage_Catalog_Model_Category $collection
13
+ * @return mixed
14
+ */
15
+ public function getFormattedCollection($collection)
16
+ {
17
+ if ($collection instanceof Mage_Catalog_Model_Category) {
18
+ $collectionId = $collection->getId();
19
+ } else {
20
+ $collectionId = $collection;
21
+ }
22
+ // Load collection magento
23
+ // This is function get all attribute of magento
24
+ $collection = Mage::getModel('catalog/category')->load($collectionId);
25
+
26
+ if (!$collection || !$collection->getId()) {
27
+ return false;
28
+ }
29
+
30
+ $data = [
31
+ 'ref_id' => (int)$collection->getId(),
32
+ 'title' => $collection->getName(),
33
+ 'handle' => $collection->getUrlPath(),
34
+ 'collection_type' => 1,
35
+ 'image_url' => $collection->getImageUrl()
36
+ ];
37
+
38
+ return $data;
39
+ }
40
+
41
+ /**
42
+ * Get data of collect for Beeketing Api
43
+ * @param integer $collectionId
44
+ * @param integer $productId
45
+ * @param integer $position
46
+ * @return mixed
47
+ */
48
+ public function getFormattedCollect($collectionId, $productId, $position)
49
+ {
50
+ $data = [
51
+ 'ref_id' => $this->generateCollectRefId($collectionId, $productId),
52
+ 'product_ref_id' => $productId,
53
+ 'collection_ref_id' => $collectionId,
54
+ 'position' => $position
55
+ ];
56
+ return $data;
57
+ }
58
+
59
+ /**
60
+ * Generate collect id by using cantor pairing function
61
+ * @param integer $productId
62
+ * @param integer $collectionId
63
+ * @return float
64
+ */
65
+ public function generateCollectRefId($productId, $collectionId)
66
+ {
67
+ return (($productId + $collectionId) * ($productId + $collectionId + 1)) / 2 + $collectionId;
68
+ }
69
+
70
+ /**
71
+ * Add collection to Beeketing Api
72
+ * @param Mage_Catalog_Model_Category $collection
73
+ * @param string $requestType
74
+ */
75
+ public function saveToBeeketingApi($collection, $requestType = BeeketingSDK_Config_BeeketingConfig::SOURCE_TYPE_WEBHOOK)
76
+ {
77
+ // Load category magento
78
+ if (is_int($collection) || is_string($collection)) {
79
+ $collectionId = $collection;
80
+ } else {
81
+ $collectionId = $collection->getId();
82
+ }
83
+ $collection = Mage::getModel('catalog/category')->load($collectionId);
84
+
85
+ // Get product data
86
+ $collectionData = $this->getFormattedCollection($collection);
87
+
88
+ // Push collection to Beeketing platform
89
+ Mage::helper('beeketing_integrateapp/core')->sendRequest('collections/create_update', $collectionData,
90
+ Zend_Http_Client::POST, ['X-Beeketing-Source' => $requestType]);
91
+
92
+ }
93
+ }
app/code/community/Beeketing/IntegrateApp/Helper/Core.php ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Beeketing_IntegrateApp_Helper_Core extends Mage_Core_Helper_Abstract
4
+ {
5
+ const BEEKETING_CART_TOKEN = 'beeketing-cart-token';
6
+
7
+ /**
8
+ * @var Beeketing_BeeketingMagento $beeketingCore
9
+ */
10
+ protected $beeketingCore;
11
+
12
+ public function getApiKey()
13
+ {
14
+ return Mage::getStoreConfig('bee_options/general/api_key');
15
+ }
16
+
17
+ public function getBeeketingMagentoCore()
18
+ {
19
+ // If already have core, return core.
20
+ if ($this->beeketingCore) {
21
+ return $this->beeketingCore;
22
+ }
23
+
24
+ $apiKey = $this->getApiKey();
25
+
26
+ return $this->beeketingCore = new Beeketing_BeeketingMagento($apiKey);
27
+ }
28
+
29
+ /**
30
+ * Get cart token
31
+ *
32
+ * @return mixed
33
+ */
34
+ public function getCartToken()
35
+ {
36
+ if (!isset($_COOKIE[self::BEEKETING_CART_TOKEN])) {
37
+ $apiKey = $this->getApiKey();
38
+ $cartToken = uniqid($apiKey, true);
39
+ setcookie(self::BEEKETING_CART_TOKEN, $cartToken, time() + 31536000, '/');
40
+ }
41
+
42
+ return $_COOKIE[self::BEEKETING_CART_TOKEN];
43
+ }
44
+
45
+ /**
46
+ * Delete cart token
47
+ */
48
+ public function deleteCartToken()
49
+ {
50
+ Mage::getModel('core/cookie')->delete(self::BEEKETING_CART_TOKEN);
51
+ }
52
+
53
+ /**
54
+ * Set last added item
55
+ *
56
+ * @param $itemDetails
57
+ */
58
+ public function setLastAddedItem($itemDetails)
59
+ {
60
+ $domain = $this->getHttpHost();
61
+ // Add cookie to site
62
+ setcookie('beeketing-last-added-items', json_encode($itemDetails), time() + 3600, '/', $domain, false, false);
63
+ }
64
+
65
+ /**
66
+ * Retrieve HTTP HOST
67
+ *
68
+ * @param bool $trimPort
69
+ * @return string
70
+ */
71
+ public function getHttpHost($trimPort = true)
72
+ {
73
+ if (!isset($_SERVER['HTTP_HOST'])) {
74
+ return false;
75
+ }
76
+ $host = $_SERVER['HTTP_HOST'];
77
+ if ($trimPort) {
78
+ $hostParts = explode(':', $_SERVER['HTTP_HOST']);
79
+ $host = $hostParts[0];
80
+ }
81
+
82
+ if (strpos($host, ',') !== false || strpos($host, ';') !== false) {
83
+ $response = new Zend_Controller_Response_Http();
84
+ $response->setHttpResponseCode(400)->sendHeaders();
85
+ exit();
86
+ }
87
+
88
+ return $host;
89
+ }
90
+
91
+ /**
92
+ * Beeketing Api
93
+ * @param string $path
94
+ * @param mixed $data
95
+ * @param string $method
96
+ * @param mixed $headers
97
+ * @return Zend_Http_Response
98
+ */
99
+ public function sendRequest($path, $data = [], $method = Zend_Http_Client::GET, $headers = [])
100
+ {
101
+ $beeketingMagento = $this->getBeeketingMagentoCore();
102
+
103
+ $beeketingConfig = $beeketingMagento->getBeeketingConfig();
104
+ // Init client and add param
105
+ $client = new Zend_Http_Client();
106
+ $client->setUri($beeketingConfig->getPath() . '/rest-api/v1/' . $path);
107
+ $client->setMethod($method);
108
+ $client->setHeaders('X-Beeketing-Key', $this->getApiKey());
109
+ $client->setHeaders('Content-Type', 'application/json');
110
+
111
+ // Add header for request
112
+ if (is_array($headers) && count($headers)) {
113
+ foreach ($headers as $key => $value) {
114
+ $client->setHeaders($key, $value);
115
+ }
116
+ }
117
+
118
+ // Add data for request
119
+ if (is_array($data) && count($data)) {
120
+ $json = json_encode($data);
121
+ $client->setRawData($json, 'application/json');
122
+ }
123
+
124
+ // Return Zend_Http_Response
125
+ return $client->request();
126
+ }
127
+
128
+ }
app/code/community/Beeketing/IntegrateApp/Helper/Customer.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 24/12/2015
6
+ * Time: 09:20
7
+ */
8
+ class Beeketing_IntegrateApp_Helper_Customer extends Mage_Core_Helper_Abstract
9
+ {
10
+ /**
11
+ * Get data of customer for Beeketing Api
12
+ * @param Mage_Customer_Model_Customer $customer
13
+ * @return mixed
14
+ */
15
+ public function getFormattedCustomer($customer)
16
+ {
17
+ if ($customer instanceof Mage_Customer_Model_Customer) {
18
+ $customerId = $customer->getId();
19
+ } else {
20
+ $customerId = $customer;
21
+ }
22
+ // Load customer magento
23
+ // This is function get all attribute of magento
24
+ $customer = Mage::getModel('customer/customer')->load($customerId);
25
+
26
+ if (!$customer || !$customer->getId()) {
27
+ return false;
28
+ }
29
+
30
+ // Get date update product
31
+ $date = Mage::getModel('core/date');
32
+ $dateCreated = $date->gmtDate(BeeketingSDK_Config_BeeketingConfig::BEEKETING_FORMAT_DATE, $customer->getCreatedAt());
33
+
34
+ // Get billing address
35
+ $billingAddress = $customer->getDefaultBillingAddress();
36
+ if ($billingAddress && $billingAddress->getId()) {
37
+
38
+ $street1 = $billingAddress->getStreet1();
39
+ $street2 = $billingAddress->getStreet2();
40
+ $city = $billingAddress->getCity();
41
+ $region = $billingAddress->getRegion();
42
+ $postcode = $billingAddress->getPostcode();
43
+ $company = $billingAddress->getCompany();
44
+
45
+ // Get country name
46
+ if ($billingAddress->getData('country_id')) {
47
+ $country = Mage::getModel('directory/country')->load($billingAddress->getData('country_id'))->getIso2Code();
48
+ $country = Mage::app()->getLocale()->getCountryTranslation($country);
49
+ } else {
50
+ $country = '';
51
+ }
52
+
53
+ } else {
54
+ $street1 = '';
55
+ $street2 = '';
56
+ $city = '';
57
+ $region = '';
58
+ $postcode = '';
59
+ $country = '';
60
+ $company = '';
61
+ }
62
+
63
+ $data = [
64
+ 'ref_id' => $customer->getId(),
65
+ 'email' => $customer->getEmail(),
66
+ 'first_name' => $customer->getFirstname(),
67
+ 'last_name' => $customer->getLastname(),
68
+ 'signed_up_at' => $dateCreated,
69
+ 'address1' => $street1,
70
+ 'address2' => $street2,
71
+ 'city' => $city,
72
+ 'company' => $company,
73
+ 'province' => $region,
74
+ 'zip' => $postcode,
75
+ 'country' => $country,
76
+ ];
77
+
78
+ // Get order of customer
79
+ $orders = Mage::getModel('sales/order')->getCollection()
80
+ ->addAttributeToSelect('*')
81
+ ->addFieldToFilter('customer_id', $customer->getId());
82
+
83
+ // Get total_spent
84
+ $totalSpent = 0;
85
+ foreach ($orders as $order) {
86
+ if ($order->getStatus() == Mage_Sales_Model_Order::STATE_COMPLETE) {
87
+ $totalSpent += $order->getGrandTotal();
88
+ }
89
+ }
90
+ $data['orders_count'] = count($orders);
91
+ $data['total_spent'] = $totalSpent;
92
+ return $data;
93
+ }
94
+
95
+ /**
96
+ * Add customer to Beeketing Api
97
+ * @param Mage_Customer_Model_Customer $customer
98
+ * @param string $requestType
99
+ */
100
+ public function saveToBeeketingApi($customer, $requestType = BeeketingSDK_Config_BeeketingConfig::SOURCE_TYPE_WEBHOOK)
101
+ {
102
+ // Load customer magento
103
+ $customer = Mage::getModel('customer/customer')->load($customer->getId());
104
+
105
+ // Get customer data
106
+ $customerData = $this->getFormattedCustomer($customer);
107
+
108
+ // Push customer data to Beeketing platform
109
+ Mage::helper('beeketing_integrateapp/core')->sendRequest('customers/create_update', $customerData,
110
+ Zend_Http_Client::POST, ['X-Beeketing-Source' => $requestType]);
111
+
112
+ }
113
+ }
app/code/community/Beeketing/IntegrateApp/Helper/Data.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Beeketing_IntegrateApp_Helper_Data extends Mage_Core_Helper_Data
4
+ {
5
+ public function getCartData()
6
+ {
7
+ $cart = Mage::getModel('checkout/cart')->getQuote();
8
+ $cartItems = array();
9
+ $hasChildProductTypes = [
10
+ Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE,
11
+ Mage_Catalog_Model_Product_Type::TYPE_BUNDLE,
12
+ Mage_Catalog_Model_Product_Type::TYPE_GROUPED
13
+ ];
14
+ foreach($cart->getItemsCollection() as $item) {
15
+ if (in_array($item->getProductType(), $hasChildProductTypes)) {
16
+ continue;
17
+ }
18
+ if ($item->getParentItem()) {
19
+ $parentItem = $item->getParentItem();
20
+ } else {
21
+ $parentItem = null;
22
+ }
23
+ $customOptions = [];
24
+ foreach ($item->getOptions() as $option) {
25
+ if (is_string($option->getValue()) && strpos($option->getValue(), 'BK-Type') !== false &&
26
+ $value = unserialize($option->getValue())) {
27
+ $customOptions = $value;
28
+ }
29
+ }
30
+
31
+ $product = Mage::getModel('catalog/product')->load($item->getProductId());
32
+ $row=array();
33
+ $row['id'] = $item->getId();
34
+ $row['product_id'] = $parentItem ? $parentItem->getProductId() : $item->getProductId();
35
+ $row['variant_id'] = $item->getProductId();
36
+ $row['item_url'] = $product->getProductUrl();
37
+ $row['title'] = htmlspecialchars($product->getName(), ENT_QUOTES);
38
+ $row['image'] = Mage::helper('catalog/image')->init($product, 'image')->resize(250)->__toString();
39
+ $row['sku'] = $item->getSku();
40
+ $row['line_price'] = $item->getOriginalPrice();
41
+ $row['price'] = $item->getPrice();
42
+ $row['quantity']= (int)$item->getQty();
43
+ $row['subtotal']= $item->getSubtotal();
44
+ $row['tax_amount']= $item->getTaxAmount();
45
+ $row['tax_percent']= $item->getTaxPercent();
46
+ $row['discount_amount']= $item->getDiscountAmount();
47
+ $row['row_total']= $item->getRowTotal();
48
+ $row['custom_options'] = $customOptions;
49
+ $cartItems[]=$row;
50
+ }
51
+
52
+ $cartData['item_count'] = Mage::helper('checkout/cart')->getSummaryCount();
53
+ $cartData['sub_total'] = $cart->getSubtotal();
54
+ $cartData['grand_total'] = $cart->getGrandTotal();
55
+ $cartData['cart_url'] = Mage::getUrl('checkout/cart');
56
+ $cartData['checkout_url'] = Mage::helper('checkout/url')->getCheckoutUrl();
57
+ $cartData['shop_url'] = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
58
+ $cartData['items'] = $cartItems;
59
+ $cartData['token'] = Mage::helper('beeketing_integrateapp/core')->getCartToken();
60
+
61
+ return $cartData;
62
+ }
63
+
64
+ public function getCurrencyFormat()
65
+ {
66
+ $formattedPrice = Mage::helper('core')->currency(11.11, true, false);
67
+ $formattedPrice = str_replace('11.11', '{{amount}}', $formattedPrice);
68
+ $formattedPrice = preg_replace('/\d+/u', '', $formattedPrice);
69
+ return $formattedPrice;
70
+ }
71
+
72
+ /**
73
+ * Get data of store for Beeketing Api
74
+ * @param Mage_Core_Model_Store $store
75
+ * @return mixed
76
+ */
77
+ public function getFormattedStore($store)
78
+ {
79
+ $data = [
80
+ 'absolute_path' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB),
81
+ 'currency_format' => $this->getCurrencyFormat(),
82
+ 'currency' => $store->getCurrentCurrencyCode(),
83
+ 'timezone' => Mage::getStoreConfig('general/locale/timezone')
84
+ ];
85
+ return $data;
86
+ }
87
+ }
app/code/community/Beeketing/IntegrateApp/Helper/Order.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 24/12/2015
6
+ * Time: 10:14
7
+ */
8
+ class Beeketing_IntegrateApp_Helper_Order extends Mage_Core_Helper_Abstract
9
+ {
10
+ /**
11
+ * Get data of order for Beeketing Api
12
+ * @param Mage_Sales_Model_Order $order
13
+ * @return mixed
14
+ */
15
+ public function getFormattedOrder($order)
16
+ {
17
+ $data = [
18
+ 'ref_id' => $order->getId(),
19
+ 'contact_ref_id' => $order->getCustomerId(),
20
+ 'currency' => $order->getBaseCurrencyCode(),
21
+ 'email' => $order->getCustomerEmail(),
22
+ 'financial_status' => $order->getStatus(),
23
+ 'line_items' => [],
24
+ 'name' => $order->getCustomerFirstname() . ' ' . $order->getCustomerLastname(),
25
+ 'subtotal_price' => $order->getSubtotal(),
26
+ 'total_tax' => $order->getTaxAmount(),
27
+ 'total_discounts' => $order->getDiscountAmount(),
28
+ 'total_price' => $order->getGrandTotal(),
29
+ 'cart_token' => Mage::helper('beeketing_integrateapp/core')->getCartToken(),
30
+ ];
31
+
32
+ $products = [];
33
+ // Get all item in order
34
+ foreach ($order->getItemsCollection() as $item) {
35
+ $products[] = [
36
+ 'ref_id' => $item->getId(),
37
+ 'price' => $item->getPrice(),
38
+ 'sku' => $item->getSku(),
39
+ 'product_ref_id' => $item->getProductId(),
40
+ 'variant_id' => null,
41
+ 'fulfillable_quantity' => $item->getQtyOrdered(),
42
+ ];
43
+ }
44
+
45
+ $data['line_items'] = $products;
46
+ return $data;
47
+ }
48
+
49
+ /**
50
+ * Add order to Beeketing Api
51
+ * @param Mage_Sales_Model_Order $order
52
+ * @param string $requestType
53
+ */
54
+ public function saveToBeeketingApi($order, $requestType = BeeketingSDK_Config_BeeketingConfig::SOURCE_TYPE_WEBHOOK)
55
+ {
56
+ // Load order magento
57
+ $order = Mage::getModel('sales/order')->load($order->getId());
58
+
59
+ // Get order data
60
+ $orderData = $this->getFormattedOrder($order);
61
+
62
+ // Push collection to Beeketing platform
63
+ Mage::helper('beeketing_integrateapp/core')->sendRequest('orders/create_update', $orderData,
64
+ Zend_Http_Client::POST, ['X-Beeketing-Source' => $requestType]);
65
+
66
+ }
67
+ }
app/code/community/Beeketing/IntegrateApp/Helper/Product.php ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 24/12/2015
6
+ * Time: 11:08
7
+ */
8
+ class Beeketing_IntegrateApp_Helper_Product extends Mage_Core_Helper_Data
9
+ {
10
+ /**
11
+ * Get data of product for Beeketing Api
12
+ * @param Mage_Catalog_Model_Product $product
13
+ * @return array
14
+ */
15
+ public function getFormattedProduct($product)
16
+ {
17
+ if ($product instanceof Mage_Catalog_Model_Product) {
18
+ $productId = $product->getId();
19
+ } else {
20
+ $productId = $product;
21
+ }
22
+ // Load product magento
23
+ $product = Mage::getModel('catalog/product')->load($productId);
24
+
25
+ if (!$product || !$product->getId()) {
26
+ return false;
27
+ }
28
+
29
+ // Get date update product
30
+ $date = Mage::getModel('core/date');
31
+ $updatedAt = $date->gmtDate(BeeketingSDK_Config_BeeketingConfig::BEEKETING_FORMAT_DATE, $product->getUpdatedAt());
32
+ $createdAt = $date->gmtDate(BeeketingSDK_Config_BeeketingConfig::BEEKETING_FORMAT_DATE, $product->getCreatedAt());
33
+
34
+
35
+ // Get tag
36
+ $modelTag = Mage::getModel('tag/tag');
37
+ $tags = $modelTag->getResourceCollection()
38
+ ->addPopularity()
39
+ ->addStatusFilter($modelTag->getApprovedStatus())
40
+ ->addProductFilter($product->getId())
41
+ ->setFlag('relation', true)
42
+ ->setActiveFilter()
43
+ ->load();
44
+
45
+ $tagString = [];
46
+ if (isset($tags) && !empty($tags)) {
47
+ foreach ($tags as $tag) {
48
+ $tagString[] = $tag->getName();
49
+ }
50
+ }
51
+
52
+ $images = [];
53
+ foreach ($product->getMediaGalleryImages() as $image) {
54
+ $images[] = Mage::helper('catalog/image')->init($product, 'image', $image->getFile())->resize(250)->__toString();
55
+ }
56
+
57
+ $featureImage = Mage::helper('catalog/image')->init($product, 'image')->resize(250)->__toString();
58
+
59
+ $data = [
60
+ 'sku' => $product->getData('sku'),
61
+ 'handle' => $product->getUrlPath(),
62
+ 'title' => $product->getName(),
63
+ 'type' => $product->getTypeId(),
64
+ 'ref_id' => (int)$product->getId(),
65
+ 'vendor' => '',
66
+ 'published_at' => $product->getVisibility() != 1 ? $createdAt : null,
67
+ 'updated_at' => $updatedAt,
68
+ 'created_at' => $createdAt,
69
+ 'out_stock' => !$product->getIsSalable(),
70
+ 'image_source_url' => $featureImage,
71
+ 'price' => $product->getPrice(),
72
+ 'price_compare' => ($product->getFinalPrice() < $product->getPrice()) ? $product->getFinalPrice() : null,
73
+ 'tags' => count($tagString) ? implode(',', $tagString) : null,
74
+ 'description' => $product->getDescription(),
75
+ 'images' => $images,
76
+ 'featured_image' => $featureImage,
77
+ 'attributes' => [
78
+ 'store_id' => $product->getStoreIds(),
79
+ 'website_ids' => $product->getWebsiteIds(),
80
+ ],
81
+ 'variants' => $this->getProductVariants($product),
82
+ ];
83
+ return $data;
84
+ }
85
+
86
+ /**
87
+ * Add product to Beeketing Api
88
+ * @param Mage_Catalog_Model_Product $product
89
+ * @return array
90
+ */
91
+ public function getProductVariants($product)
92
+ {
93
+ // Get product type
94
+ $productType = $product->getTypeId();
95
+
96
+ // Variation product
97
+ $variationProduct = [];
98
+
99
+ // Get product variation data by product type
100
+ switch ($productType) {
101
+ // Get all configurable
102
+ case 'configurable' :
103
+ // Get product collection configurable
104
+ $configurableProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null, $product);
105
+ $productAttributeOptions = $product->getTypeInstance(true)->getConfigurableAttributesAsArray($product);
106
+
107
+ foreach ($configurableProducts as $configurableProduct) {
108
+ // Not save this product
109
+ if ($configurableProduct->getId() == $product->getId()) {
110
+ continue;
111
+ }
112
+ $configurableProduct = Mage::getModel('catalog/product')->load($configurableProduct->getId());
113
+ $variationProduct[] = $this->getFormattedVariant($configurableProduct, $product, $productAttributeOptions);
114
+ }
115
+ // Get config attribute
116
+ $productModelConfigurable = Mage::getModel('catalog/product_type_configurable');
117
+ $config = $productModelConfigurable->getConfigurableAttributes($product)->getData();
118
+ $variationProduct['raw_data']['configurable'] = $config;
119
+ break;
120
+ // Get all grouped
121
+ case 'grouped' :
122
+ $groupedProducts = Mage::getModel('catalog/product_type_grouped')->getAssociatedProducts($product);
123
+ foreach ($groupedProducts as $groupedProduct) {
124
+ $variationProduct[] = $this->getFormattedVariant($groupedProduct, $product, $groupedProducts);
125
+ }
126
+ break;
127
+ // Product simple and virtual, downloadable, bundle
128
+ default:
129
+ $variationProduct[] = $this->getFormattedVariant($product);
130
+ break;
131
+
132
+ }
133
+
134
+ $variantWithOptions = [];
135
+
136
+ foreach ($product->getOptions() as $o) {
137
+ $optionType = $o->getType();
138
+
139
+ if ($optionType == 'drop_down') {
140
+ $values = $o->getValues();
141
+
142
+ foreach ($values as $k => $v) {
143
+ foreach ($variationProduct as $variant) {
144
+ $variant['attributes'][] = [
145
+ 'name' => $v->getTitle(),
146
+ 'slug' => $v->getTitle(),
147
+ 'option' => $v->getTitle()
148
+ ];
149
+
150
+ $variant['attributes']['custom_option'][$o->getId()] = $v->getOptionTypeId();
151
+ if ($v->getPriceType() == 'fixed') {
152
+ $variant['price'] = (string) ($variant['price'] + $v->getPrice());
153
+ if ($variant['price_compare']) {
154
+ $variant['price_compare'] = (string) ($variant['price_compare'] + $v->getPrice());
155
+ }
156
+ } else {
157
+ $variant['price'] = (string) ($variant['price'] + $variant['price'] * $v->getPrice() / 100);
158
+ if ($variant['price_compare']) {
159
+ $variant['price_compare'] = (string) ($variant['price_compare'] + $variant['price_compare'] * $v->getPrice() / 100);
160
+ }
161
+ }
162
+
163
+ $variantWithOptions[] = $variant;
164
+ }
165
+ }
166
+ }
167
+ }
168
+
169
+ if (count($variantWithOptions) > 0) {
170
+ return $variantWithOptions;
171
+ }
172
+
173
+ return $variationProduct;
174
+
175
+ }
176
+
177
+ /**
178
+ * Get data of product for Beeketing Api
179
+ * @param Mage_Catalog_Model_Product $product
180
+ * @param Mage_Catalog_Model_Product $parent
181
+ * @param $productAttributeOptions array
182
+ * @return array
183
+ */
184
+ public function getFormattedVariant($product, $parent = null, $productAttributeOptions = [])
185
+ {
186
+ // Get date product
187
+ $date = Mage::getModel('core/date');
188
+ $dateUpdated = $date->gmtDate(BeeketingSDK_Config_BeeketingConfig::BEEKETING_FORMAT_DATE, $product->getUpdatedAt());
189
+ $dateCreated = $date->gmtDate(BeeketingSDK_Config_BeeketingConfig::BEEKETING_FORMAT_DATE, $product->getCreatedAt());
190
+
191
+ // Get stock model of product
192
+ $stock = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product);
193
+
194
+ $data = [
195
+ 'ref_id' => (int)$product->getId(),
196
+ 'title' => $product->getName(),
197
+ 'product_ref_id' => $parent ? (int) $parent->getId(): (int) $product->getId(),
198
+ 'price' => $product->getPrice(),
199
+ 'price_compare' => ($product->getFinalPrice() < $product->getPrice()) ? $product->getFinalPrice() : null,
200
+ 'sku' => $product->getData('sku'),
201
+ 'inventory_management' => null,
202
+ 'inventory_quantity' => $stock->getQty(),
203
+ 'in_stock' => $product->isInStock(),
204
+ 'weight' => $product->getWeight(),
205
+ 'taxable' => $product->getTaxClassId(),
206
+ 'visible' => $product->getIsSalable(),
207
+ 'attributes' => [
208
+ 'store_id' => $product->getStoreIds(),
209
+ 'website_ids' => $product->getWebsiteIds(),
210
+ ],
211
+ 'updated' => $dateUpdated,
212
+ 'created' => $dateCreated,
213
+ ];
214
+
215
+ if ($product->getTypeId() == Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE) {
216
+ $links=Mage::getModel('downloadable/link')
217
+ ->getCollection()
218
+ ->addFieldToFilter('product_id',array('eq'=>$product->getId()));
219
+
220
+ foreach($links as $key => $link){
221
+ $data['attributes'][] = [
222
+ 'name' => $key,
223
+ 'slug' => $key,
224
+ 'option' => $key
225
+ ];
226
+
227
+ $data['attributes']['links'][] = $link->getId();
228
+ }
229
+ } elseif($product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
230
+ // Get all product of bundle
231
+ $bundleProducts = $collection = $product->getTypeInstance(true)
232
+ ->getSelectionsCollection(
233
+ $product->getTypeInstance(true)
234
+ ->getOptionsIds($product), $product);
235
+
236
+ // Get only one option for each child product
237
+ foreach ($bundleProducts as $bundleProduct) {
238
+ $data['attributes']['bundle_option'][$bundleProduct->option_id] = $bundleProduct->selection_id;
239
+ if ($bundleProduct->selection_can_change_qty) {
240
+ $bundleQty = 1;
241
+ } else {
242
+ $bundleQty = (int) $bundleProduct->selection_qty;
243
+ }
244
+
245
+ $data['attributes']['bundle_option_qty'][$bundleProduct->option_id] = $bundleQty;
246
+ }
247
+ } elseif ($parent && $parent->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_GROUPED) {
248
+ $data['attributes']['super_group'][$product->getId()] = 1;
249
+ foreach ($productAttributeOptions as $childProduct) {
250
+ if ($childProduct->getId() == $product->getId()) {
251
+ continue;
252
+ }
253
+ $data['attributes']['super_group'][$childProduct->getId()] = 0;
254
+ }
255
+ }
256
+
257
+ if (count($productAttributeOptions)) {
258
+ // Get config attribute
259
+ $productData = $product->getData();
260
+ foreach ($productAttributeOptions as $index => $productAttribute) {
261
+ if (isset($productData[$productAttribute['attribute_code']])) {
262
+ foreach ($productAttribute['values'] as $attribute) {
263
+ if ($attribute['value_index'] == $productData[$productAttribute['attribute_code']]) {
264
+ $data['option' . ($index + 1)] = $productAttribute['attribute_code'] . ' ' . $attribute['store_label'];
265
+ $data['attributes'][] = [
266
+ 'name' => $productAttribute['attribute_code'],
267
+ 'slug' => $productAttribute['attribute_code'],
268
+ 'option' => $attribute['store_label']
269
+ ];
270
+ $data['attributes']['super_attribute'][$productAttribute['attribute_id']] = $attribute['value_index'];
271
+ }
272
+ }
273
+ }
274
+ }
275
+ }
276
+
277
+ return $data;
278
+ }
279
+
280
+ /**
281
+ * Add product to Beeketing Api
282
+ * @param Mage_Catalog_Model_Product $product
283
+ * @param string $requestType
284
+ */
285
+ public function saveToBeeketingApi($product, $requestType = BeeketingSDK_Config_BeeketingConfig::SOURCE_TYPE_WEBHOOK)
286
+ {
287
+ // Load product magento
288
+ // This is function get all attribute of magento
289
+ $product = Mage::getModel('catalog/product')->load($product->getId());
290
+
291
+ // Get product data
292
+ $productData = $this->getFormattedProduct($product);
293
+
294
+ // Push product data to Beeketing platform
295
+ Mage::helper('beeketing_integrateapp/core')->sendRequest('products/create_update', $productData,
296
+ Zend_Http_Client::POST, ['X-Beeketing-Source' => $requestType]);
297
+
298
+ }
299
+ }
app/code/community/Beeketing/IntegrateApp/Model/Observer.php ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Beeketing_IntegrateApp_Model_Observer
4
+ {
5
+ /**
6
+ * Show notification
7
+ * @return bool
8
+ */
9
+ public function showNotifcation()
10
+ {
11
+ //get the admin session
12
+ Mage::getSingleton('core/session', array('name'=>'adminhtml'));
13
+
14
+ //verify if the user is logged in to the backend
15
+ if(!Mage::getSingleton('admin/session')->isLoggedIn()){
16
+ return false;
17
+ }
18
+
19
+ /**
20
+ * @var Beeketing_BeeketingMagento $coreContainer
21
+ */
22
+ $coreContainer = Mage::helper('beeketing_integrateapp/core')->getBeeketingMagentoCore();
23
+
24
+ /**
25
+ * Get api key
26
+ */
27
+ $apiKey = $coreContainer->getBeeketingConfig()->getApiKey();
28
+
29
+ /**
30
+ * Has api key?
31
+ */
32
+ $hasApiKey = ($apiKey) ? true : false;
33
+
34
+ if (!$hasApiKey) {
35
+ $url = Mage::helper('adminhtml')->getUrl('adminhtml/system_config/edit', array(
36
+ 'section'=>'bee_options'
37
+ ));
38
+
39
+ Mage::getSingleton('core/session')->addNotice(
40
+ 'Beeketing has been activated. Please click <a href="'.$url.'">here</a> to add your Access Key.'
41
+ );
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Add block to beeketing configuration
47
+ * @param Varien_Event_Observer $observer
48
+ */
49
+ public function addBlockHtmlBefore(Varien_Event_Observer $observer)
50
+ {
51
+ /**
52
+ * @var Mage_Adminhtml_Block_System_Config_Edit $block
53
+ */
54
+ $block = $observer->getBlock();
55
+
56
+ if (get_class($block) == 'Mage_Adminhtml_Block_System_Config_Edit') {
57
+ /**
58
+ * Get current section
59
+ */
60
+ $currentSection = Mage::app()->getRequest()->getParam('section');
61
+
62
+ /**
63
+ * @var Beeketing_BeeketingMagento $coreContainer
64
+ */
65
+ $coreContainer = Mage::helper('beeketing_integrateapp/core')->getBeeketingMagentoCore();
66
+
67
+ if ($currentSection == 'bee_options') {
68
+ /**
69
+ * Get apps data
70
+ */
71
+ $beeketingAppsData = $coreContainer->getBeeketingConfig()->getAppsDataByApiKey();
72
+
73
+ /**
74
+ * Get api key
75
+ */
76
+ $apiKey = $coreContainer->getBeeketingConfig()->getApiKey();
77
+
78
+ /**
79
+ * Has api key?
80
+ */
81
+ $hasApiKey = ($apiKey) ? true : false;
82
+
83
+ include(__DIR__ . '/../Block/AppsData.php');
84
+
85
+ $signInUrl = $coreContainer->getBeeketingConfig()->getSignInUrl();
86
+
87
+ echo '<script type="text/javascript">window.setTimeout(function() { document.getElementById("beeketing-get-access-key").setAttribute("href", "'. $signInUrl .'"); }, 500);</script>';
88
+ }
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Add front end scripts.
94
+ * @param Varien_Event_Observer $observer
95
+ */
96
+ public function addFrontendScripts(Varien_Event_Observer $observer)
97
+ {
98
+ /**
99
+ * @var Beeketing_BeeketingMagento $coreContainer
100
+ */
101
+ $coreContainer = Mage::helper('beeketing_integrateapp/core')->getBeeketingMagentoCore();
102
+
103
+ /**
104
+ * @var BeeketingSDK_Snippet_SnippetManager $snippetManager;
105
+ */
106
+ $snippetManager = $coreContainer->getSnippetManager();
107
+
108
+ /** @var Mage_Core_Controller_Front_Action $controller */
109
+ $controller = $observer->getAction();
110
+
111
+ /** @var Mage_Core_Model_Layout $layout */
112
+ $layout = $controller->getLayout();
113
+
114
+ if (!$layout->getBlock('before_body_end')) {
115
+ return;
116
+ }
117
+
118
+ // Add coupon box
119
+ /** @var Mage_Core_Block_Abstract $block */
120
+ $block = $layout->createBlock('core/text');
121
+
122
+ $snippetContent = $snippetManager->getAllSnippetContent();
123
+
124
+ if (Mage::registry('current_product')) {
125
+ $snippetContent .= "<script> var __bkt = {}; __bkt.p = 'product'; __bkt.rid = " . Mage::registry('current_product')->getId() . ";</script>";
126
+ } elseif (Mage::registry('current_category')) {
127
+ $snippetContent .= "<script>var __bkt = {}; __bkt.p = 'collection'; __bkt.rid = " . Mage::registry('current_category')->getId() .";</script>";
128
+ } elseif (Mage::getUrl('') == Mage::getUrl('*/*/*', array('_current'=>true, '_use_rewrite'=>true))) {
129
+ $snippetContent .= "<script>var __bkt = {}; __bkt.p = 'home';</script>";
130
+ } elseif(parse_url(Mage::getUrl('checkout/onepage'))['path'] == parse_url(Mage::helper('core/url')->getCurrentUrl())['path']) {
131
+ $snippetContent .= "<script>var __bkt = {}; __bkt.p = 'checkout';</script>";
132
+ } else {
133
+ $request = Mage::app()->getFrontController()->getRequest();
134
+ $module = $request->getModuleName();
135
+ $controller = $request->getControllerName();
136
+ $action = $request->getActionName();
137
+
138
+ if($module == 'checkout' && $controller == 'cart' && $action == 'index') {
139
+ $snippetContent .= "<script>var __bkt = {}; __bkt.p = 'cart';</script>";
140
+ }
141
+ }
142
+
143
+ $website_id = Mage::app()->getWebsite()->getId();
144
+ $store_id = Mage::app()->getStore()->getStoreId();
145
+ $snippetContent .= "<script>if(typeof __bkt != 'undefined') {__bkt.website_id = ". $website_id . "; __bkt.store_id = " . $store_id . ";}</script>";
146
+
147
+ if(Mage::getSingleton('customer/session')->isLoggedIn()) {
148
+ $customerId = Mage::getSingleton('customer/session')->getCustomerId();
149
+ $snippetContent .= "<script>var BKCustomer = {}; BKCustomer.id = " . $customerId . ";</script>";
150
+ }
151
+
152
+ if ($lastAddedItem = Mage::getSingleton('core/session')->getLastAddedItem()) {
153
+ $snippetContent .= "<script>var bkLastAddedItem = JSON.parse('" . $lastAddedItem . "');</script>";
154
+ Mage::getSingleton('core/session')->unsLastAddedItem();
155
+ } elseif ($lastDeletedItem = Mage::getSingleton('core/session')->getLastDeletedItem()) {
156
+ $snippetContent .= "<script>var bkLastDeletedItem = JSON.parse('" . $lastDeletedItem . "');</script>";
157
+ Mage::getSingleton('core/session')->unsLastDeletedItem();
158
+ }
159
+
160
+ if (Mage::getSingleton('core/session')->getBKOrderSuccess()) {
161
+ $snippetContent .= "<script>var bkOrderSuccess = true;</script>";
162
+ Mage::getSingleton('core/session')->unsBKOrderSuccess();
163
+ }
164
+
165
+
166
+ $cartData = Mage::helper('beeketing_integrateapp')->getCartData();
167
+
168
+ $snippetContent .= "<script>var bkCartData = JSON.parse('" . json_encode($cartData)."');</script>";
169
+
170
+ $block->setText($snippetContent);
171
+ $layout->getBlock('before_body_end')->append($block);
172
+ }
173
+ }
app/code/community/Beeketing/IntegrateApp/Model/Observer/Cart.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 25/12/2015
6
+ * Time: 11:04
7
+ */
8
+ class Beeketing_IntegrateApp_Model_Observer_Cart
9
+ {
10
+
11
+ /**
12
+ * Apply discount after adding item to cart
13
+ * @param Varien_Event_Observer $observer
14
+ */
15
+ public function checkoutCartProductAddAfter($observer)
16
+ {
17
+ $action = Mage::app()->getFrontController()->getAction();
18
+
19
+ /* @var $item Mage_Sales_Model_Quote_Item */
20
+ $quoteItem = $observer->getQuoteItem();
21
+
22
+ if ($quoteItem->getParentItem()) {
23
+ $item = $quoteItem->getParentItem();
24
+ } else {
25
+ $item = $quoteItem;
26
+ }
27
+
28
+ // Make sure we don't have a negative
29
+ $attributes = $action->getRequest()->getParam('attributes');
30
+ if (isset($attributes['bk_option'])) {
31
+ $extraOptions = $attributes['bk_option'];
32
+ $item->setCustomPrice($extraOptions['price']);
33
+ $item->setOriginalCustomPrice($extraOptions['price']);
34
+ $item->getProduct()->setIsSuperMode(true);
35
+ } elseif (is_array($attributes)) {
36
+ foreach ($attributes as $attribute) {
37
+ $attribute = is_string($attribute) ? json_decode($attribute, true) : $attribute;
38
+ if (isset($attribute['bk_option']['productId']) && $attribute['bk_option']['productId'] == $item->getProduct()->getId()) {
39
+ $extraOptions = $attribute['bk_option'];
40
+ $item->setCustomPrice($extraOptions['price']);
41
+ $item->setOriginalCustomPrice($extraOptions['price']);
42
+ $item->getProduct()->setIsSuperMode(true);
43
+ break;
44
+ }
45
+ }
46
+ }
47
+
48
+ if ($action->getFullActionName() == 'sales_order_reorder') {
49
+ $buyInfo = $item->getBuyRequest();
50
+ if ($options = $buyInfo->getExtraOptions()) {
51
+ $additionalOptions = array();
52
+ if ($additionalOption = $item->getOptionByCode('additional_options')) {
53
+ $additionalOptions = (array) unserialize($additionalOption->getValue());
54
+ }
55
+ foreach ($options as $key => $value) {
56
+ $additionalOptions[] = array(
57
+ 'label' => $key,
58
+ 'value' => $value,
59
+ );
60
+ }
61
+ $item->addOption(array(
62
+ 'code' => 'additional_options',
63
+ 'value' => serialize($additionalOptions)
64
+ ));
65
+ }
66
+ }
67
+
68
+ // Track event add to cart
69
+ $productVariation = $quoteItem->getProduct();
70
+ $product = $item->getProduct();
71
+ // Get detail
72
+ $itemDetails = [
73
+ 'id' => $quoteItem->getId(),
74
+ 'product_id' => $product->getId(),
75
+ 'variation_id' => $productVariation->getId(),
76
+ 'sku' => $productVariation->getSku(),
77
+ 'title' => htmlspecialchars($productVariation->getName(), ENT_QUOTES),
78
+ 'price' => $productVariation->getPrice(),
79
+ 'quantity' => $quoteItem->getQty(),
80
+ 'item_url' => $product->getProductUrl(),
81
+ 'image' => Mage::helper('catalog/image')->init($product, 'image')->resize(250)->__toString(),
82
+ ];
83
+ // Add to session
84
+ Mage::getSingleton('core/session')->setLastAddedItem(json_encode($itemDetails));
85
+ }
86
+
87
+ /**
88
+ * Remove from cart
89
+ * @param Varien_Event_Observer $observer
90
+ */
91
+ public function removeFromCart($observer)
92
+ {
93
+ $quoteItem = $observer->getQuoteItem();
94
+ $product = $quoteItem->getProduct();
95
+ $itemDetails = [
96
+ 'id' => $quoteItem->getId(),
97
+ 'product_id' => $product->getId(),
98
+ 'variation_id' => $product->getId(),
99
+ 'sku' => $product->getSku(),
100
+ 'title' => htmlspecialchars($product->getName(), ENT_QUOTES),
101
+ 'price' => $product->getPrice(),
102
+ 'quantity' => $quoteItem->getQty(),
103
+ 'item_url' => $product->getProductUrl(),
104
+ 'image' => Mage::helper('catalog/image')->init($product, 'image')->resize(250)->__toString(),
105
+ ];
106
+ // Add to session
107
+ Mage::getSingleton('core/session')->setLastDeletedItem(json_encode($itemDetails));
108
+ }
109
+ }
app/code/community/Beeketing/IntegrateApp/Model/Observer/Collection.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 25/12/2015
6
+ * Time: 10:17
7
+ */
8
+ class Beeketing_IntegrateApp_Model_Observer_Collection
9
+ {
10
+ /**
11
+ * Update collection to Beeketing after collection change
12
+ * @param Varien_Event_Observer $observer
13
+ */
14
+ public function collectionAfterSave($observer)
15
+ {
16
+ // Get collection form event object
17
+ $collection = $observer->getDataObject();
18
+
19
+ // Update collection data to Beeketing Platform
20
+ Mage::helper('beeketing_integrateapp/collection')->saveToBeeketingApi($collection);
21
+ }
22
+ }
app/code/community/Beeketing/IntegrateApp/Model/Observer/Customer.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 25/12/2015
6
+ * Time: 10:33
7
+ */
8
+ class Beeketing_IntegrateApp_Model_Observer_Customer
9
+ {
10
+ /**
11
+ * Update customer to Beeketing after customer change
12
+ * @param Varien_Event_Observer $observer
13
+ */
14
+ public function customerAfterSave($observer)
15
+ {
16
+ // Get customer form event object
17
+ $customer = $observer->getDataObject();
18
+
19
+ Mage::helper('beeketing_integrateapp/customer')->saveToBeeketingApi($customer);
20
+ }
21
+
22
+ /**
23
+ * Delete customer on Beeketing after delete customer on site
24
+ * @param Varien_Event_Observer $observer
25
+ */
26
+ public function customerDeleteAfter($observer)
27
+ {
28
+ // Get customer form event object
29
+ $customer = $observer->getDataObject();
30
+
31
+ // Run delete on Beeketing
32
+ Mage::helper('beeketing_integrateapp/core')->sendRequest(
33
+ 'customers/' . $customer->getId() . '.json',
34
+ [],
35
+ Zend_Http_Client::DELETE,
36
+ ['X-Beeketing-Source' => BeeketingSDK_Config_BeeketingConfig::SOURCE_TYPE_WEBHOOK]
37
+ );
38
+ }
39
+ }
app/code/community/Beeketing/IntegrateApp/Model/Observer/Order.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 25/12/2015
6
+ * Time: 10:28
7
+ */
8
+ class Beeketing_IntegrateApp_Model_Observer_Order
9
+ {
10
+ /**
11
+ * Update order to Beeketing after order change
12
+ * @param Varien_Event_Observer $observer
13
+ */
14
+ public function orderAfterSave($observer)
15
+ {
16
+ // Get order form event object
17
+ $order = $observer->getDataObject();
18
+
19
+ // Delete cart token
20
+ Mage::helper('beeketing_integrateapp/core')->deleteCartToken();
21
+
22
+ // Add to session
23
+ Mage::getSingleton('core/session')->setBKOrderSuccess(true);
24
+
25
+ Mage::helper('beeketing_integrateapp/order')->saveToBeeketingApi($order);
26
+ }
27
+
28
+ /**
29
+ * Add additional options
30
+ * @param Varien_Event_Observer $observer
31
+ */
32
+ public function salesConvertQuoteItemToOrderItem($observer)
33
+ {
34
+ $quoteItem = $observer->getItem();
35
+ if ($additionalOptions = $quoteItem->getOptionByCode('additional_options')) {
36
+ $orderItem = $observer->getOrderItem();
37
+ $options = $orderItem->getProductOptions();
38
+ $options['additional_options'] = unserialize($additionalOptions->getValue());
39
+ $orderItem->setProductOptions($options);
40
+ }
41
+ }
42
+ }
app/code/community/Beeketing/IntegrateApp/Model/Observer/Product.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 24/12/2015
6
+ * Time: 12:05
7
+ */
8
+ class Beeketing_IntegrateApp_Model_Observer_Product
9
+ {
10
+ /**
11
+ * Update product to Beeketing after product change
12
+ * @param Varien_Event_Observer $observer
13
+ */
14
+ public function productAfterSave($observer)
15
+ {
16
+ // Get product form event object
17
+ $product = $observer->getDataObject();
18
+
19
+ $categoryIds = $product->getCategoryIds();
20
+ foreach($categoryIds as $categoryId) {
21
+ // Update collection data to Beeketing Platform
22
+ Mage::helper('beeketing_integrateapp/collection')->saveToBeeketingApi($categoryId);
23
+ }
24
+ Mage::helper('beeketing_integrateapp/product')->saveToBeeketingApi($product);
25
+ }
26
+
27
+ /**
28
+ * Delete product on Beeketing after delete product on site
29
+ * @param Varien_Event_Observer $observer
30
+ */
31
+ public function productDeleteAfter($observer)
32
+ {
33
+ // Get product form event object
34
+ $product = $observer->getDataObject();
35
+
36
+ // Run delete on Beeketing
37
+ Mage::helper('beeketing_integrateapp/core')->sendRequest(
38
+ 'products/' . $product->getId() . '.json',
39
+ [],
40
+ Zend_Http_Client::DELETE,
41
+ ['X-Beeketing-Source' => BeeketingSDK_Config_BeeketingConfig::SOURCE_TYPE_WEBHOOK]
42
+ );
43
+ }
44
+
45
+ /**
46
+ * Add custom option to product
47
+ * @param Varien_Event_Observer $observer
48
+ */
49
+ public function catalogProductLoadAfter($observer)
50
+ {
51
+ // set the additional options on the product
52
+ $action = Mage::app()->getFrontController()->getAction();
53
+
54
+ $attributes = $action->getRequest()->getParam('attributes');
55
+ $product = $observer->getProduct();
56
+
57
+ if (isset($attributes['bk_option'])) {
58
+ $options = $attributes['bk_option'];
59
+ $this->addAdditionalOption($observer, $options);
60
+ } elseif (is_array($attributes)) {
61
+ foreach ($attributes as $attribute) {
62
+ $attribute = is_string($attribute) ? json_decode($attribute, true) : $attribute;
63
+ if (isset($attribute['bk_option']['productId']) && $attribute['bk_option']['productId'] == $product->getId()) {
64
+ $options = $attribute['bk_option'];
65
+ $this->addAdditionalOption($observer, $options);
66
+ break;
67
+ }
68
+ }
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Add additional option
74
+ *
75
+ * @param $observer
76
+ * @param $options
77
+ */
78
+ protected function addAdditionalOption($observer, $options)
79
+ {
80
+ $product = $observer->getProduct();
81
+
82
+ // add to the additional options array
83
+ $additionalOptions = array();
84
+ if ($additionalOption = $product->getCustomOption('additional_options')) {
85
+ $additionalOptions = (array) unserialize($additionalOption->getValue());
86
+ }
87
+
88
+ $additionalOptions[] = array(
89
+ 'label' => 'BK-Type',
90
+ 'value' => $options['type'],
91
+ );
92
+
93
+ $observer->getProduct()
94
+ ->addCustomOption('additional_options', serialize($additionalOptions));
95
+ }
96
+
97
+ /**
98
+ * Product inventory save after
99
+ * @param Varien_Event_Observer $observer
100
+ */
101
+ public function productInventorySaveAfter(Varien_Event_Observer $observer)
102
+ {
103
+ // Get product form event object
104
+ $product = $observer->getDataObject()->getProduct();
105
+ Mage::helper('beeketing_integrateapp/product')->saveToBeeketingApi($product);
106
+ }
107
+ }
app/code/community/Beeketing/IntegrateApp/controllers/Api/CartController.php ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 23/12/2015
6
+ * Time: 15:29
7
+ */
8
+ class Beeketing_IntegrateApp_Api_CartController extends Mage_Core_Controller_Front_Action
9
+ {
10
+ /**
11
+ * Get cart action
12
+ */
13
+ public function getCartAction()
14
+ {
15
+ $cartData = Mage::helper('beeketing_integrateapp')->getCartData();
16
+ $this->getResponse()->setHeader('Content-type', 'application/json');
17
+ $this->getResponse()->setBody(json_encode([
18
+ 'success' => true,
19
+ 'data' => $cartData,
20
+ ]));
21
+ }
22
+
23
+ /**
24
+ * Add cart action
25
+ */
26
+ public function addCartAction()
27
+ {
28
+ $query = $this->getRequest()->getParams();
29
+ $this->getResponse()->setHeader('Content-type', 'application/json');
30
+ if (!isset($query['product_id'])) {
31
+
32
+ $this->getResponse()->setBody(json_encode([
33
+ 'success' => false,
34
+ 'message' => 'Product id not found',
35
+ ]));
36
+
37
+ return;
38
+ }
39
+
40
+ $cart = Mage::getSingleton('checkout/cart');
41
+
42
+ // Add multiple products to cart
43
+ if (is_array($query['product_id'])) {
44
+ foreach ($query['product_id'] as $key => $productId) {
45
+ if (isset($query['qty'][$key])) {
46
+ $filter = new Zend_Filter_LocalizedToNormalized(
47
+ array('locale' => Mage::app()->getLocale()->getLocaleCode())
48
+ );
49
+ $params['qty'] = $filter->filter($query['qty'][$key]);
50
+ }
51
+
52
+ $params['related_product'] = isset($query['related_product']) ? $query['related_product'][$key] : [];
53
+
54
+ if (isset($query['attributes'][$key])) {
55
+ $attribute = json_decode($query['attributes'][$key], true);
56
+ if (isset($attribute['super_attribute'])) {
57
+ $params['super_attribute'] = $attribute['super_attribute'];
58
+ }
59
+
60
+ if (isset($attribute['custom_option'])) {
61
+ $params['options'] = $attribute['custom_option'];
62
+ }
63
+
64
+ if (isset($attribute['links'])) {
65
+ $params['links'] = $attribute['links'];
66
+ }
67
+
68
+ // Grouped product
69
+ if (isset($attribute['super_group'])) {
70
+ $params['super_group'] = $attribute['super_group'];
71
+ }
72
+
73
+ // Bundle products
74
+ if (isset($attribute['bundle_option'])) {
75
+ $params['bundle_option'] = $attribute['bundle_option'];
76
+ }
77
+ }
78
+
79
+ try {
80
+ $product = $product = Mage::getModel('catalog/product')->load((int) $productId);
81
+ $cart->addProduct($product, $params);
82
+
83
+ } catch (Exception $e) {
84
+ $this->getResponse()->setBody(json_encode([
85
+ 'success' => false,
86
+ 'message' => $e->getMessage(),
87
+ ]));
88
+
89
+ return;
90
+ }
91
+
92
+ }
93
+ } else {
94
+ // Add single product to cart
95
+ if (isset($query['qty'])) {
96
+ $filter = new Zend_Filter_LocalizedToNormalized(
97
+ array('locale' => Mage::app()->getLocale()->getLocaleCode())
98
+ );
99
+ $params['qty'] = $filter->filter($query['qty']);
100
+ }
101
+
102
+ $params['related_product'] = isset($query['related_product']) ? $query['related_product'] : [];
103
+
104
+ // Configurable product
105
+ if (isset($query['super_attribute'])) {
106
+ $params['super_attribute'] = $query['super_attribute'];
107
+ } elseif (isset($query['attributes']['super_attribute'])) {
108
+ $params['super_attribute'] = $query['attributes']['super_attribute'];
109
+ }
110
+
111
+ // Grouped product
112
+ if (isset($query['super_group'])) {
113
+ $params['super_group'] = $query['super_group'];
114
+ } elseif (isset($query['attributes']['super_group'])) {
115
+ $params['super_group'] = $query['attributes']['super_group'];
116
+ }
117
+
118
+ if (isset($query['custom_option'])) {
119
+ $params['options'] = $query['custom_option'];
120
+ } elseif (isset($query['attributes']['custom_option'])) {
121
+ $params['options'] = $query['attributes']['custom_option'];
122
+ }
123
+
124
+ // Downloadable products
125
+ if (isset($query['links'])) {
126
+ $params['links'] = $query['links'];
127
+ } elseif (isset($query['attributes']['links'])) {
128
+ $params['links'] = $query['attributes']['links'];
129
+ }
130
+
131
+ // Bundle products
132
+ if (isset($query['bundle_option'])) {
133
+ $params['bundle_option'] = $query['bundle_option'];
134
+ } elseif (isset($query['attributes']['bundle_option'])) {
135
+ $params['bundle_option'] = $query['attributes']['bundle_option'];
136
+ }
137
+
138
+ $product = $product = Mage::getModel('catalog/product')->load((int) $query['product_id']);
139
+
140
+ if (!$product || !$product->getId()) {
141
+ $this->getResponse()->setBody(json_encode([
142
+ 'success' => false,
143
+ 'data' => 'Product not found',
144
+ ]));
145
+ return;
146
+ }
147
+
148
+ try {
149
+ $cart->addProduct($product, $params);
150
+ } catch (Exception $e) {
151
+ $this->getResponse()->setBody(json_encode([
152
+ 'success' => false,
153
+ 'message' => $e->getMessage(),
154
+ ]));
155
+
156
+ return;
157
+ }
158
+ }
159
+
160
+ try {
161
+ $cart->save();
162
+
163
+ Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
164
+ } catch (Exception $e) {
165
+ $this->getResponse()->setBody(json_encode([
166
+ 'success' => false,
167
+ 'message' => $e->getMessage(),
168
+ ]));
169
+
170
+ return;
171
+ }
172
+
173
+ $cartData = Mage::helper('beeketing_integrateapp')->getCartData();
174
+ $this->getResponse()->setBody(json_encode([
175
+ 'success' => true,
176
+ 'data' => $cartData,
177
+ ]));
178
+ }
179
+
180
+ /**
181
+ * Remove from cart
182
+ */
183
+ public function removeFromCartAction()
184
+ {
185
+ $query = $this->getRequest()->getParams();
186
+ $this->getResponse()->setHeader('Content-type', 'application/json');
187
+ if (!isset($query['id'])) {
188
+
189
+ $this->getResponse()->setBody(json_encode([
190
+ 'success' => false,
191
+ 'message' => 'Item id not found',
192
+ ]));
193
+
194
+ return;
195
+ }
196
+
197
+ $cartHelper = Mage::helper('checkout/cart');
198
+ $cartHelper->getCart()->removeItem($query['id'])->save();
199
+
200
+ $this->getResponse()->setBody(json_encode([
201
+ 'success' => true,
202
+ 'data' => [
203
+
204
+ ],
205
+ ]));
206
+ }
207
+ }
app/code/community/Beeketing/IntegrateApp/controllers/Api/CollectionController.php ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 24/12/2015
6
+ * Time: 10:02
7
+ */
8
+
9
+ /**
10
+ * Api Collection Controller
11
+ *
12
+ * @category Beeketing
13
+ * @package Beeketing_IntegrateApp
14
+ * @author Beeketing
15
+ */
16
+ class Beeketing_IntegrateApp_Api_CollectionController extends Mage_Core_Controller_Front_Action
17
+ {
18
+ /**
19
+ * Get collections action
20
+ */
21
+ public function collectionsAction()
22
+ {
23
+ $query = $this->getRequest()->getParams();
24
+ if (!isset($query['limit'])) {
25
+ $limit = 250;
26
+ } else {
27
+ $limit = $query['limit'];
28
+ }
29
+
30
+ if (!isset($query['page'])) {
31
+ $page = 1;
32
+ } else {
33
+ $page = $query['page'];
34
+ }
35
+
36
+ if (!isset($query['title'])) {
37
+ $searchString = '';
38
+ } else {
39
+ $searchString = $query['title'];
40
+ }
41
+
42
+ $collections = Mage::getModel('catalog/category')
43
+ ->getCollection()
44
+ ->addAttributeToFilter('name', array('like' => '%' . $searchString . '%'))
45
+ ->setPageSize($limit)
46
+ ->setCurPage($page);
47
+
48
+ $collectionsArray = [];
49
+ foreach ($collections as $collection) {
50
+ $collectionsArray[] = Mage::helper('beeketing_integrateapp/collection')->getFormattedCollection($collection);
51
+ }
52
+
53
+ $this->getResponse()->setHeader('Content-type', 'application/json');
54
+ $this->getResponse()->setBody(json_encode([
55
+ 'success' => true,
56
+ 'data' => $collectionsArray,
57
+ ]));
58
+ }
59
+
60
+ /**
61
+ * Get single collection action
62
+ */
63
+ public function collectionAction()
64
+ {
65
+ $query = $this->getRequest()->getParams();
66
+ $this->getResponse()->setHeader('Content-type', 'application/json');
67
+ if (!isset($query['id'])) {
68
+ $this->getResponse()->setBody(json_encode([
69
+ 'success' => false,
70
+ 'message' => 'Collection id not found',
71
+ ]));
72
+
73
+ return;
74
+ }
75
+
76
+ $collection = Mage::helper('beeketing_integrateapp/collection')->getFormattedCollection($query['id']);
77
+
78
+ if (!$collection) {
79
+ $this->getResponse()->setBody(json_encode([
80
+ 'success' => false,
81
+ 'message' => 'Collection not found',
82
+ ]));
83
+
84
+ return;
85
+ }
86
+
87
+ $this->getResponse()->setBody(json_encode([
88
+ 'success' => true,
89
+ 'data' => $collection,
90
+ ]));
91
+ }
92
+
93
+ /**
94
+ * Count collections action
95
+ */
96
+ public function collectionCountAction()
97
+ {
98
+ $query = $this->getRequest()->getParams();
99
+
100
+ if (!isset($query['title'])) {
101
+ $searchString = '';
102
+ } else {
103
+ $searchString = $query['title'];
104
+ }
105
+
106
+ $collectionsCount = Mage::getModel('catalog/category')
107
+ ->getCollection()
108
+ ->addAttributeToFilter('name', array('like' => '%' . $searchString . '%'))
109
+ ->count();
110
+
111
+ $this->getResponse()->setHeader('Content-type', 'application/json');
112
+ $this->getResponse()->setBody(json_encode([
113
+ 'success' => true,
114
+ 'data' => $collectionsCount,
115
+ ]));
116
+ }
117
+
118
+ /**
119
+ * Get collect action
120
+ */
121
+ public function collectsAction()
122
+ {
123
+ $query = $this->getRequest()->getParams();
124
+
125
+ if (!isset($query['limit'])) {
126
+ $limit = 250;
127
+ } else {
128
+ $limit = $query['limit'];
129
+ }
130
+
131
+ if (!isset($query['page'])) {
132
+ $page = 1;
133
+ } else {
134
+ $page = $query['page'];
135
+ }
136
+
137
+ $offset = ($page - 1) * $limit;
138
+
139
+ $this->getResponse()->setHeader('Content-type', 'application/json');
140
+
141
+ $collects = [];
142
+ if (isset($query['collection_id'])) {
143
+ $collection = Mage::getModel('catalog/category')->load((int) $query['collection_id']);
144
+ if (!$collection || !$collection->getId()) {
145
+ $this->getResponse()->setBody(json_encode([
146
+ 'success' => false,
147
+ 'message' => 'Collection not found',
148
+ ]));
149
+
150
+ return;
151
+ }
152
+ $productCollection = $collection->getProductCollection();
153
+ $productPositions = $collection->getProductsPosition();
154
+
155
+
156
+ $productIds = $productCollection->getAllIds($limit, $offset);
157
+
158
+ foreach ($productIds as $productId) {
159
+ $collects[] = Mage::helper('beeketing_integrateapp/collection')->getFormattedCollect(
160
+ $collection->getId(), $productId, $productPositions[$productId]);
161
+ }
162
+ } elseif (isset($query['product_id']) && $page == 1) {
163
+ $product = Mage::getModel('catalog/product')->load((int) $query['product_id']);
164
+
165
+ if (!$product || !$product->getId()) {
166
+ $this->getResponse()->setBody(json_encode([
167
+ 'success' => false,
168
+ 'message' => 'Product not found',
169
+ ]));
170
+
171
+ return;
172
+ }
173
+
174
+ $collectionIds = $product->getCategoryIds();
175
+
176
+ $productId = $product->getId();
177
+
178
+ foreach ($collectionIds as $collectionId) {
179
+ $collects[] = Mage::helper('beeketing_integrateapp/collection')->getFormattedCollect(
180
+ $collectionId, $productId, null);
181
+ }
182
+ } else {
183
+ $categories = Mage::getModel('catalog/category')
184
+ ->getCollection();
185
+
186
+ $collectCount = 0;
187
+
188
+ foreach ($categories as $category) {
189
+ $collectCount += $category->getProductCollection()->count();
190
+ }
191
+
192
+ if ($collectCount == 0) {
193
+ goto response;
194
+ }
195
+
196
+ // TODO count collect
197
+ foreach ($categories as $category) {
198
+ $productPositions = $category->getProductsPosition();
199
+ $productCollection = $category->getProductCollection();
200
+ $newLimit = round($productCollection->count() / $collectCount * $limit);
201
+ $newOffset = ($page-1) * $newLimit;
202
+ $productIds = $productCollection->getAllIds($newLimit, $newOffset);
203
+
204
+ foreach ($productIds as $productId) {
205
+ $collects[] = Mage::helper('beeketing_integrateapp/collection')->getFormattedCollect(
206
+ $category->getId(), $productId, $productPositions[$productId]);
207
+ }
208
+ }
209
+ }
210
+
211
+ response:
212
+
213
+ $this->getResponse()->setBody(json_encode([
214
+ 'success' => true,
215
+ 'data' => $collects,
216
+ ]));
217
+ }
218
+
219
+ /**
220
+ * Collect count
221
+ */
222
+ public function collectCountAction()
223
+ {
224
+ $query = $this->getRequest()->getParams();
225
+ $collectCount = 0;
226
+ $this->getResponse()->setHeader('Content-type', 'application/json');
227
+
228
+ if (isset($query['collection_id'])) {
229
+ $collection = Mage::getModel('catalog/category')->load((int) $query['collection_id']);
230
+ if (!$collection || !$collection->getId()) {
231
+ $this->getResponse()->setBody(json_encode([
232
+ 'success' => false,
233
+ 'message' => 'Collection not found',
234
+ ]));
235
+
236
+ return;
237
+ }
238
+
239
+ $collectCount = $collection->getProductCollection()->count();
240
+ } elseif (isset($query['product_id'])) {
241
+ $product = Mage::getModel('catalog/product')->load((int) $query['product_id']);
242
+
243
+ if (!$product || !$product->getId()) {
244
+ $this->getResponse()->setBody(json_encode([
245
+ 'success' => false,
246
+ 'message' => 'Product not found',
247
+ ]));
248
+
249
+ return;
250
+ }
251
+
252
+ $collectionIds = $product->getCategoryIds();
253
+
254
+ $collectCount = count($collectionIds);
255
+ } else {
256
+ $categories = Mage::getModel('catalog/category')
257
+ ->getCollection();
258
+
259
+ foreach ($categories as $category) {
260
+ $collectCount += $category->getProductCollection()->count();
261
+ }
262
+ }
263
+
264
+ $this->getResponse()->setBody(json_encode([
265
+ 'success' => true,
266
+ 'data' => $collectCount,
267
+ ]));
268
+ }
269
+ }
app/code/community/Beeketing/IntegrateApp/controllers/Api/CustomerController.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 24/12/2015
6
+ * Time: 09:06
7
+ */
8
+
9
+ /**
10
+ * Api Customer Controller
11
+ *
12
+ * @category Beeketing
13
+ * @package Beeketing_IntegrateApp
14
+ * @author Beeketing
15
+ */
16
+ class Beeketing_IntegrateApp_Api_CustomerController extends Mage_Core_Controller_Front_Action
17
+ {
18
+
19
+ public function customersAction()
20
+ {
21
+ $query = $this->getRequest()->getParams();
22
+ if (!isset($query['limit'])) {
23
+ $limit = 250;
24
+ } else {
25
+ $limit = $query['limit'];
26
+ }
27
+
28
+ if (!isset($query['page'])) {
29
+ $page = 1;
30
+ } else {
31
+ $page = $query['page'];
32
+ }
33
+
34
+ if (!isset($query['title'])) {
35
+ $searchString = '';
36
+ } else {
37
+ $searchString = $query['title'];
38
+ }
39
+
40
+ $collections = Mage::getModel('customer/customer')
41
+ ->getCollection()
42
+ /*->addAttributeToFilter('name', array('like' => '%' . $searchString . '%'))*/
43
+ ->setPageSize($limit)
44
+ ->setCurPage($page);
45
+
46
+ $customers = [];
47
+ foreach ($collections as $customer) {
48
+ $customers[] = Mage::helper('beeketing_integrateapp/customer')->getFormattedCustomer($customer);
49
+
50
+ }
51
+
52
+ $this->getResponse()->setHeader('Content-type', 'application/json');
53
+ $this->getResponse()->setBody(json_encode([
54
+ 'success' => true,
55
+ 'data' => $customers,
56
+ ]));
57
+ }
58
+
59
+ /**
60
+ * Count customers action
61
+ */
62
+ public function customerCountAction()
63
+ {
64
+ $collectionsCount = Mage::getModel('customer/customer')
65
+ ->getCollection()
66
+ ->count();
67
+
68
+ $this->getResponse()->setHeader('Content-type', 'application/json');
69
+ $this->getResponse()->setBody(json_encode([
70
+ 'success' => true,
71
+ 'data' => $collectionsCount,
72
+ ]));
73
+ }
74
+ }
app/code/community/Beeketing/IntegrateApp/controllers/Api/OrderController.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 24/12/2015
6
+ * Time: 10:13
7
+ */
8
+
9
+ /**
10
+ * Api Order Controller
11
+ *
12
+ * @category Beeketing
13
+ * @package Beeketing_IntegrateApp
14
+ * @author Beeketing
15
+ */
16
+ class Beeketing_IntegrateApp_Api_OrderController extends Mage_Core_Controller_Front_Action
17
+ {
18
+ public function ordersAction()
19
+ {
20
+ $query = $this->getRequest()->getParams();
21
+ if (!isset($query['limit'])) {
22
+ $limit = 250;
23
+ } else {
24
+ $limit = $query['limit'];
25
+ }
26
+
27
+ if (!isset($query['page'])) {
28
+ $page = 1;
29
+ } else {
30
+ $page = $query['page'];
31
+ }
32
+
33
+ if (!isset($query['title'])) {
34
+ $searchString = '';
35
+ } else {
36
+ $searchString = $query['title'];
37
+ }
38
+ $collections = Mage::getModel('sales/order')
39
+ ->getCollection()
40
+ /*->addAttributeToFilter('name', array('like' => '%' . $searchString . '%'))*/
41
+ ->setPageSize($limit)
42
+ ->setCurPage($page);
43
+
44
+ $orders = [];
45
+ foreach ($collections as $order) {
46
+ $orders[] = Mage::helper('beeketing_integrateapp/order')->getFormattedOrder($order);
47
+ }
48
+
49
+ $this->getResponse()->setHeader('Content-type', 'application/json');
50
+ $this->getResponse()->setBody(json_encode([
51
+ 'success' => true,
52
+ 'data' => $orders,
53
+ ]));
54
+ }
55
+
56
+ /**
57
+ * Count orders action
58
+ */
59
+ public function orderCountAction()
60
+ {
61
+ $collectionsCount = Mage::getModel('sales/order')
62
+ ->getCollection()
63
+ ->count();
64
+
65
+ $this->getResponse()->setHeader('Content-type', 'application/json');
66
+ $this->getResponse()->setBody(json_encode([
67
+ 'success' => true,
68
+ 'data' => $collectionsCount,
69
+ ]));
70
+ }
71
+ }
app/code/community/Beeketing/IntegrateApp/controllers/Api/ProductController.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 22/12/2015
6
+ * Time: 17:58
7
+ */
8
+
9
+ /**
10
+ * Api Product Controller
11
+ *
12
+ * @category Beeketing
13
+ * @package Beeketing_IntegrateApp
14
+ * @author Beeketing
15
+ */
16
+ class Beeketing_IntegrateApp_Api_ProductController extends Mage_Core_Controller_Front_Action
17
+ {
18
+ /**
19
+ * Products action
20
+ */
21
+ public function productsAction()
22
+ {
23
+ $query = $this->getRequest()->getParams();
24
+ if (!isset($query['limit'])) {
25
+ $limit = 250;
26
+ } else {
27
+ $limit = $query['limit'];
28
+ }
29
+
30
+ if (!isset($query['page'])) {
31
+ $page = 1;
32
+ } else {
33
+ $page = $query['page'];
34
+ }
35
+
36
+ if (!isset($query['title'])) {
37
+ $searchString = '';
38
+ } else {
39
+ $searchString = $query['title'];
40
+ }
41
+
42
+ if (!isset($query['visible'])) {
43
+ $visibility = [1,2,3,4];
44
+ } elseif ($query['visible']) {
45
+ $visibility = [2,3,4];
46
+ } else {
47
+ $visibility = [1];
48
+ }
49
+
50
+ $collections = Mage::getModel('catalog/product')->getCollection();
51
+
52
+ $collections->addAttributeToFilter('name', array('like' => '%' . $searchString . '%'));
53
+ if (isset($query['updated_at_min'])) {
54
+ $collections->addAttributeToFilter('updated_at', array('gteq' => $query['updated_at_min']));
55
+ }
56
+ if (isset($query['updated_at_max'])) {
57
+ $collections->addAttributeToFilter('updated_at', array('lteq' => $query['updated_at_max']));
58
+ }
59
+ $collections->addAttributeToFilter('visibility', $visibility);
60
+ $collections->setPageSize($limit);
61
+ $collections->setCurPage($page);
62
+
63
+ $products = [];
64
+ foreach ($collections as $product) {
65
+ $products[] = Mage::helper('beeketing_integrateapp/product')->getFormattedProduct($product);
66
+
67
+ }
68
+
69
+ $this->getResponse()->setHeader('Content-type', 'application/json');
70
+ $this->getResponse()->setBody(json_encode([
71
+ 'success' => true,
72
+ 'data' => $products,
73
+ ]));
74
+ }
75
+
76
+ /**
77
+ * Get single product action
78
+ */
79
+ public function productAction()
80
+ {
81
+ $query = $this->getRequest()->getParams();
82
+ $this->getResponse()->setHeader('Content-type', 'application/json');
83
+ if (!isset($query['id'])) {
84
+ $this->getResponse()->setBody(json_encode([
85
+ 'success' => false,
86
+ 'message' => 'Product id not found',
87
+ ]));
88
+
89
+ return;
90
+ }
91
+
92
+ $product = Mage::helper('beeketing_integrateapp/product')->getFormattedProduct($query['id']);
93
+
94
+ if (!$product) {
95
+ $this->getResponse()->setBody(json_encode([
96
+ 'success' => false,
97
+ 'message' => 'Product not found',
98
+ ]));
99
+
100
+ return;
101
+ }
102
+
103
+ $this->getResponse()->setBody(json_encode([
104
+ 'success' => true,
105
+ 'data' => $product,
106
+ ]));
107
+ }
108
+
109
+ /**
110
+ * Count product action
111
+ */
112
+ public function productCountAction()
113
+ {
114
+ $query = $this->getRequest()->getParams();
115
+
116
+ if (!isset($query['title'])) {
117
+ $searchString = '';
118
+ } else {
119
+ $searchString = $query['title'];
120
+ }
121
+
122
+ if (!isset($query['visible'])) {
123
+ $visibility = [1,2,3,4];
124
+ } elseif ($query['visible']) {
125
+ $visibility = [2,3,4];
126
+ } else {
127
+ $visibility = [1];
128
+ }
129
+
130
+ $collections = Mage::getModel('catalog/product')->getCollection();
131
+
132
+ $collections->addAttributeToFilter('name', array('like' => '%' . $searchString . '%'));
133
+ if (isset($query['updated_at_min'])) {
134
+ $collections->addAttributeToFilter('updated_at', array('gteq' => $query['updated_at_min']));
135
+ }
136
+ if (isset($query['updated_at_max'])) {
137
+ $collections->addAttributeToFilter('updated_at', array('lteq' => $query['updated_at_max']));
138
+ }
139
+ $collections->addAttributeToFilter('visibility', $visibility);
140
+
141
+ $collectionsCount = $collections->count();
142
+
143
+ $this->getResponse()->setHeader('Content-type', 'application/json');
144
+ $this->getResponse()->setBody(json_encode([
145
+ 'success' => true,
146
+ 'data' => $collectionsCount,
147
+ ]));
148
+ }
149
+ }
app/code/community/Beeketing/IntegrateApp/controllers/Api/ShopController.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * User: ducanh
5
+ * Date: 24/12/2015
6
+ * Time: 10:53
7
+ */
8
+ class Beeketing_IntegrateApp_Api_ShopController extends Mage_Core_Controller_Front_Action
9
+ {
10
+ /**
11
+ * Shop action
12
+ */
13
+ public function shopAction()
14
+ {
15
+ // Gets the current store's details
16
+ $store = Mage::app()->getStore();
17
+
18
+ $data = Mage::helper('beeketing_integrateapp')->getFormattedStore($store);
19
+
20
+ $this->getResponse()->setHeader('Content-type', 'application/json');
21
+ $this->getResponse()->setBody(json_encode([
22
+ 'success' => true,
23
+ 'data' => $data,
24
+ ]));
25
+ }
26
+
27
+ /**
28
+ * App shared
29
+ */
30
+ public function appSharedAction()
31
+ {
32
+ $query = $this->getRequest()->getParams();
33
+
34
+ if (!isset($query['offer_id']) || !isset($query['post_id'])) {
35
+ $this->getResponse()->setHeader('Content-type', 'application/json');
36
+ $this->getResponse()->setBody(json_encode([
37
+ 'success' => false,
38
+ 'message' => 'Id not found',
39
+ ]));
40
+
41
+ return;
42
+ }
43
+
44
+ $coreHelper = Mage::helper('beeketing_integrateapp/core');
45
+
46
+ $beeketingMagento = $coreHelper->getBeeketingMagentoCore();
47
+
48
+ $beeketingConfig = $beeketingMagento->getBeeketingConfig();
49
+
50
+ // Init client and add param
51
+ try {
52
+ $client = new Zend_Http_Client();
53
+ $client->setUri($beeketingConfig->getPath() . '/cboost/offers/shared?offer_id=' . $query['offer_id'] . '&post_id=' . $query['post_id']);
54
+ $client->setMethod(Zend_Http_Client::POST);
55
+ $client->setHeaders('X-Beeketing-Key', $coreHelper->getApiKey());
56
+ $client->setHeaders('Content-Type', 'application/json');
57
+ $client->setHeaders('X-Beeketing-Source', 'webhook');
58
+
59
+ $apiResponse = $client->request();
60
+
61
+ } catch (Exception $e) {
62
+ $this->getResponse()->setHeader('Content-type', 'application/json');
63
+ $this->getResponse()->setBody(json_encode([
64
+ 'success' => false,
65
+ 'message' => $e->getMessage(),
66
+ ]));
67
+
68
+ return;
69
+ }
70
+
71
+ $this->getResponse()->setBody($apiResponse->getBody());
72
+ }
73
+ }
app/code/community/Beeketing/IntegrateApp/controllers/System/ConfigController.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once Mage::getModuleDir('controllers', 'Mage_Adminhtml') . DS . 'System' . DS . 'ConfigController.php';
4
+
5
+ class Beeketing_IntegrateApp_System_ConfigController extends Mage_Adminhtml_System_ConfigController
6
+ {
7
+ /**
8
+ * Hooks save bee options
9
+ * @throws Mage_Core_Exception
10
+ */
11
+ public function _saveBeeOptions()
12
+ {
13
+ // Get api key
14
+ $apiKey = $_POST['groups']['general']['fields']['api_key']['value'];
15
+
16
+ /**
17
+ * @var Beeketing_BeeketingMagento $coreContainer
18
+ */
19
+ $coreContainer = Mage::helper('beeketing_integrateapp/core')->getBeeketingMagentoCore();
20
+
21
+ // Check
22
+ $verified = $coreContainer->getBeeketingConfig()->isApiKeyExists($apiKey);
23
+
24
+ if (!$verified) {
25
+ throw new Mage_Core_Exception('Oops! we can\'t connect to Beeketing\'s service with your Access Key, please make sure your access key is corrected.');
26
+ }
27
+
28
+ // Set api key
29
+ $coreContainer->getBeeketingConfig()->setApiKey($apiKey);
30
+
31
+ /* @var $session Mage_Adminhtml_Model_Session */
32
+ $session = Mage::getSingleton('adminhtml/session');
33
+
34
+ // Gets the current store's details
35
+ $store = Mage::app()->getStore();
36
+
37
+ $data = Mage::helper('beeketing_integrateapp')->getFormattedStore($store);
38
+
39
+ // Push shop data to Beeketing platform
40
+ Mage::helper('beeketing_integrateapp/core')->sendRequest('shops', $data,
41
+ Zend_Http_Client::PUT, ['X-Beeketing-Source' => BeeketingSDK_Config_BeeketingConfig::SOURCE_TYPE_WEBHOOK]);
42
+
43
+ $session->addSuccess('Awesome! your access key is saved and verified. Next step, select an app to use on your store below.');
44
+ }
45
+ }
app/code/community/Beeketing/IntegrateApp/etc/adminhtml.xml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <acl>
4
+ <resources>
5
+ <admin>
6
+ <children>
7
+ <system>
8
+ <children>
9
+ <config>
10
+ <children>
11
+ <bee_options>
12
+ <title>Configuration</title> <!-- Used in resources tree -->
13
+ </bee_options>
14
+ </children>
15
+ </config>
16
+ </children>
17
+ </system>
18
+ </children>
19
+ </admin>
20
+ </resources>
21
+ </acl>
22
+ </config>
app/code/community/Beeketing/IntegrateApp/etc/config.xml ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Module configuration
5
+ *
6
+ * @author Magento
7
+ */
8
+ -->
9
+ <config>
10
+ <modules>
11
+ <Beeketing_IntegrateApp>
12
+ <version>1.0.0.0.1</version>
13
+ </Beeketing_IntegrateApp>
14
+ </modules>
15
+ <global>
16
+ <models>
17
+ <beeketing_integrateapp>
18
+ <class>Beeketing_IntegrateApp_Model</class>
19
+ </beeketing_integrateapp>
20
+ </models>
21
+ <helpers>
22
+ <beeketing_integrateapp>
23
+ <class>Beeketing_IntegrateApp_Helper</class>
24
+ </beeketing_integrateapp>
25
+ </helpers>
26
+ <events>
27
+ <!-- Magento after save product -->
28
+ <catalog_product_save_after>
29
+ <observers>
30
+ <Beeketing_IntegrateApp_Model_Observer_Product>
31
+ <type>singleton</type>
32
+ <class>Beeketing_IntegrateApp_Model_Observer_Product</class>
33
+ <method>productAfterSave</method>
34
+ </Beeketing_IntegrateApp_Model_Observer_Product>
35
+ </observers>
36
+ </catalog_product_save_after>
37
+ <!-- Magento after delete product -->
38
+ <catalog_product_delete_after>
39
+ <observers>
40
+ <Beeketing_IntegrateApp_Model_Observer_Product>
41
+ <type>singleton</type>
42
+ <class>Beeketing_IntegrateApp_Model_Observer_Product</class>
43
+ <method>productDeleteAfter</method>
44
+ </Beeketing_IntegrateApp_Model_Observer_Product>
45
+ </observers>
46
+ </catalog_product_delete_after>
47
+
48
+ <!-- Magento after save category -->
49
+ <catalog_category_save_after>
50
+ <observers>
51
+ <Beeketing_IntegrateApp_Model_Observer_Collection>
52
+ <type>singleton</type>
53
+ <class>Beeketing_IntegrateApp_Model_Observer_Collection</class>
54
+ <method>collectionAfterSave</method>
55
+ </Beeketing_IntegrateApp_Model_Observer_Collection>
56
+ </observers>
57
+ </catalog_category_save_after>
58
+ <!-- Magento after save customer -->
59
+ <customer_save_after>
60
+ <observers>
61
+ <Beeketing_IntegrateApp_Model_Observer_Customer>
62
+ <type>singleton</type>
63
+ <class>Beeketing_IntegrateApp_Model_Observer_Customer</class>
64
+ <method>customerAfterSave</method>
65
+ </Beeketing_IntegrateApp_Model_Observer_Customer>
66
+ </observers>
67
+ </customer_save_after>
68
+ <!-- Magento after delete customer -->
69
+ <customer_delete_after>
70
+ <observers>
71
+ <Beeketing_IntegrateApp_Model_Observer_Customer>
72
+ <type>singleton</type>
73
+ <class>Beeketing_IntegrateApp_Model_Observer_Customer</class>
74
+ <method>customerDeleteAfter</method>
75
+ </Beeketing_IntegrateApp_Model_Observer_Customer>
76
+ </observers>
77
+ </customer_delete_after>
78
+ <!-- Magento after save order -->
79
+ <sales_order_save_after>
80
+ <observers>
81
+ <Beeketing_IntegrateApp_Model_Observer_Order>
82
+ <type>singleton</type>
83
+ <class>Beeketing_IntegrateApp_Model_Observer_Order</class>
84
+ <method>orderAfterSave</method>
85
+ </Beeketing_IntegrateApp_Model_Observer_Order>
86
+ </observers>
87
+ </sales_order_save_after>
88
+ </events>
89
+ </global>
90
+ <default>
91
+ <bee_options>
92
+ <general>
93
+ <text_field>Default value</text_field>
94
+ <textarea></textarea>
95
+ <dropdown>key2</dropdown>
96
+ <multiple_dropdown>key1,key2</multiple_dropdown>
97
+ <time>11,30,45</time>
98
+ <active>0</active>
99
+ <boolean>1</boolean>
100
+ <dependant_text_field>Default value</dependant_text_field>
101
+ </general>
102
+ </bee_options>
103
+ </default>
104
+ <admin>
105
+ <routers>
106
+ <adminhtml>
107
+ <args>
108
+ <modules>
109
+ <Beeketing_IntegrateApp before="Mage_Adminhtml">Beeketing_IntegrateApp</Beeketing_IntegrateApp>
110
+ </modules>
111
+ </args>
112
+ </adminhtml>
113
+ </routers>
114
+ </admin>
115
+ <adminhtml>
116
+ <events>
117
+ <adminhtml_block_html_before>
118
+ <observers>
119
+ <Beeketing_IntegrateApp_Model_Observer>
120
+ <type>singleton</type>
121
+ <class>Beeketing_IntegrateApp_Model_Observer</class>
122
+ <method>addBlockHtmlBefore</method>
123
+ </Beeketing_IntegrateApp_Model_Observer>
124
+ </observers>
125
+ </adminhtml_block_html_before>
126
+ <controller_action_layout_load_before>
127
+ <observers>
128
+ <Beeketing_IntegrateApp_Model_Observer>
129
+ <type>singleton</type>
130
+ <class>Beeketing_IntegrateApp_Model_Observer</class>
131
+ <method>showNotifcation</method>
132
+ </Beeketing_IntegrateApp_Model_Observer>
133
+ </observers>
134
+ </controller_action_layout_load_before>
135
+ <cataloginventory_stock_item_save_after>
136
+ <observers>
137
+ <Beeketing_IntegrateApp_Model_Observer_Product>
138
+ <type>singleton</type>
139
+ <class>Beeketing_IntegrateApp_Model_Observer_Product</class>
140
+ <method>productInventorySaveAfter</method>
141
+ </Beeketing_IntegrateApp_Model_Observer_Product>
142
+ </observers>
143
+ </cataloginventory_stock_item_save_after>
144
+ </events>
145
+ <layout>
146
+ <updates>
147
+ <index>
148
+ <file>your-group-name/your-extension-name.xml</file>
149
+ </index>
150
+ </updates>
151
+ </layout>
152
+ </adminhtml>
153
+ <frontend>
154
+ <events>
155
+ <controller_action_layout_generate_blocks_after>
156
+ <observers>
157
+ <Beeketing_IntegrateApp_Model_Observer>
158
+ <type>singleton</type>
159
+ <class>Beeketing_IntegrateApp_Model_Observer</class>
160
+ <method>addFrontendScripts</method>
161
+ </Beeketing_IntegrateApp_Model_Observer>
162
+ </observers>
163
+ </controller_action_layout_generate_blocks_after>
164
+ <!-- Magento after add cart -->
165
+ <checkout_cart_product_add_after>
166
+ <observers>
167
+ <Beeketing_IntegrateApp_Model_Observer_Cart>
168
+ <type>singleton</type>
169
+ <class>Beeketing_IntegrateApp_Model_Observer_Cart</class>
170
+ <method>checkoutCartProductAddAfter</method>
171
+ </Beeketing_IntegrateApp_Model_Observer_Cart>
172
+ </observers>
173
+ </checkout_cart_product_add_after>
174
+ <!-- Magento remove from cart -->
175
+ <sales_quote_remove_item>
176
+ <observers>
177
+ <Beeketing_IntegrateApp_Model_Observer_Cart>
178
+ <type>singleton</type>
179
+ <class>Beeketing_IntegrateApp_Model_Observer_Cart</class>
180
+ <method>removeFromCart</method>
181
+ </Beeketing_IntegrateApp_Model_Observer_Cart>
182
+ </observers>
183
+ </sales_quote_remove_item>
184
+ <!--Add extra option-->
185
+ <sales_convert_quote_item_to_order_item>
186
+ <observers>
187
+ <Beeketing_IntegrateApp_Model_Observer_Order>
188
+ <type>singleton</type>
189
+ <class>Beeketing_IntegrateApp_Model_Observer_Order</class>
190
+ <method>salesConvertQuoteItemToOrderItem</method>
191
+ </Beeketing_IntegrateApp_Model_Observer_Order>
192
+ </observers>
193
+ </sales_convert_quote_item_to_order_item>
194
+ <!--Add custom option to product-->
195
+ <catalog_product_load_after>
196
+ <observers>
197
+ <Beeketing_IntegrateApp_Model_Observer_Product>
198
+ <type>singleton</type>
199
+ <class>Beeketing_IntegrateApp_Model_Observer_Product</class>
200
+ <method>catalogProductLoadAfter</method>
201
+ </Beeketing_IntegrateApp_Model_Observer_Product>
202
+ </observers>
203
+ </catalog_product_load_after>
204
+ </events>
205
+ <routers>
206
+ <beeketing>
207
+ <use>standard</use>
208
+ <args>
209
+ <module>Beeketing_IntegrateApp</module>
210
+ <frontName>beeketing</frontName>
211
+ </args>
212
+ </beeketing>
213
+ </routers>
214
+ </frontend>
215
+ </config>
app/code/community/Beeketing/IntegrateApp/etc/system.xml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <tabs>
4
+ <beeketing_config translate="label" module="beeketing_integrateapp">
5
+ <label>Beeketing</label>
6
+ <sort_order>150</sort_order>
7
+ </beeketing_config>
8
+ </tabs>
9
+ <sections>
10
+ <bee_options translate="label" module="beeketing_integrateapp">
11
+ <label>Configuration</label>
12
+ <tab>beeketing_config</tab>
13
+ <sort_order>10</sort_order>
14
+ <show_in_default>1</show_in_default>
15
+ <show_in_website>1</show_in_website>
16
+ <show_in_store>1</show_in_store>
17
+ <groups>
18
+ <general translate="label comment">
19
+ <label>Access Key</label>
20
+ <sort_order>50</sort_order>
21
+ <show_in_default>1</show_in_default>
22
+ <show_in_website>1</show_in_website>
23
+ <show_in_store>1</show_in_store>
24
+ <comment><![CDATA[Enter your Access Key below to connect your store with Beeketing, you can <a href="javascript:void(0);" id="beeketing-get-access-key" target="_blank">get your access key</a> from your Beeketing's account page.]]></comment>
25
+ <fields>
26
+ <api_key translate="label comment">
27
+ <label>Access Key</label>
28
+ <frontend_type>text</frontend_type>
29
+ <sort_order>10</sort_order>
30
+ <show_in_default>1</show_in_default>
31
+ <show_in_website>1</show_in_website>
32
+ <show_in_store>1</show_in_store>
33
+ </api_key>
34
+ </fields>
35
+ <expanded>1</expanded>
36
+ </general>
37
+ </groups>
38
+ </bee_options>
39
+ </sections>
40
+ </config>
app/etc/modules/Beeketing_IntegrateApp.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Beeketing_IntegrateApp>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Adminhtml />
9
+ </depends>
10
+ </Beeketing_IntegrateApp>
11
+ </modules>
12
+ </config>
lib/Beeketing/BeeketingMagento.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Defined environments
5
+ * List: prod, master, staging, local
6
+ */
7
+ require_once('config.php');
8
+
9
+ $env = file_get_contents(__DIR__.'/env');
10
+ $env = trim($env);
11
+
12
+ define('BEEKETING_ENVIRONMENT', $env);
13
+
14
+ class Beeketing_BeeketingMagento
15
+ {
16
+ /**
17
+ * @var BeeketingSDK_Snippet_SnippetManager $snippetManager
18
+ */
19
+ protected $snippetManager;
20
+
21
+ /**
22
+ * @var BeeketingSDK_Config_BeeketingConfig
23
+ */
24
+ protected $beeketingConfig;
25
+
26
+ /**
27
+ * Set constructor
28
+ * @param $apiKey
29
+ */
30
+ public function __construct($apiKey)
31
+ {
32
+ # Set beeketing config
33
+ $this->beeketingConfig = new BeeketingSDK_Config_BeeketingConfig();
34
+ $this->beeketingConfig->setEnv(BEEKETING_ENVIRONMENT);
35
+ $this->beeketingConfig->setApiKey($apiKey);
36
+ $this->beeketingConfig->setPlatform('magento');
37
+
38
+ $this->snippetManager = new BeeketingSDK_Snippet_SnippetManager();
39
+ $defaultSnippet = new BeeketingSDK_Snippet_DefaultSnippet($this->snippetManager, $this->beeketingConfig);
40
+ $defaultSnippet->start();
41
+ }
42
+
43
+ /**
44
+ * @return BeeketingSDK_Config_BeeketingConfig
45
+ */
46
+ public function getBeeketingConfig()
47
+ {
48
+ return $this->beeketingConfig;
49
+ }
50
+
51
+ /**
52
+ * @return BeeketingSDK_Snippet_SnippetManager
53
+ */
54
+ public function getSnippetManager()
55
+ {
56
+ return $this->snippetManager;
57
+ }
58
+ }
lib/Beeketing/config.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ define('BEEKETING_PATH', 'https://go.beeketing.com');
lib/Beeketing/env ADDED
@@ -0,0 +1 @@
 
1
+ prod
lib/BeeketingSDK/Api/BeeketingApi.php ADDED
@@ -0,0 +1,670 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class BeeketingSDK_Api_BeeketingApi.
5
+ *
6
+ * @class BeeketingSDK_Api_BeeketingApi
7
+ * @version 1.0.0
8
+ * @author Beeketing
9
+ */
10
+ class BeeketingSDK_Api_BeeketingApi
11
+ {
12
+ const CART_TOKEN_LIFE_TIME = 31536000;
13
+
14
+ const METHOD_GET = 'GET';
15
+
16
+ const METHOD_POST = 'POST';
17
+
18
+ const METHOD_DELETE = 'DELETE';
19
+
20
+ const METHOD_PUT = 'PUT';
21
+
22
+ const BEEKETING_SOURCE = 'webhook';
23
+
24
+ /**
25
+ * Beeketing Api Key
26
+ *
27
+ * @since 2.0.0
28
+ * @var string $apiKey
29
+ */
30
+ protected $apiKey;
31
+
32
+ /**
33
+ * Beeketing Api URL
34
+ *
35
+ * @since 2.0.0
36
+ * @var string $appUrl
37
+ */
38
+ protected $apiUrl;
39
+
40
+ /**
41
+ * @since 2.0.0
42
+ * @var $client
43
+ */
44
+ protected $client;
45
+
46
+ /**
47
+ * Constructor
48
+ *
49
+ * @since 2.0.0
50
+ * @param $apiKey
51
+ */
52
+ public function __construct( $apiKey )
53
+ {
54
+ $this->apiUrl = BEEKETING_PATH . '/rest-api/v1/';
55
+ $this->apiKey = $apiKey;
56
+ add_action( 'init', array( $this, 'listenCommand' ) );
57
+
58
+ add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'listenCartActions' ) );
59
+ }
60
+
61
+ /**
62
+ * Set Api Key
63
+ *
64
+ * @since 2.0.0
65
+ * @param $apiKey
66
+ * @return $this
67
+ */
68
+ public function setApiKey( $apiKey )
69
+ {
70
+ $this->apiKey = $apiKey;
71
+
72
+ return $this;
73
+ }
74
+
75
+ /**
76
+ * Get Api Key
77
+ *
78
+ * @since 2.0.0
79
+ * @return string
80
+ */
81
+ public function getApiKey()
82
+ {
83
+ return $this->apiKey;
84
+ }
85
+
86
+ /**
87
+ * Set api url
88
+ *
89
+ * @since 2.0.0
90
+ * @param $url
91
+ * @return $this
92
+ */
93
+ public function setApiUrl( $url )
94
+ {
95
+ $this->apiUrl = $url;
96
+
97
+ return $this;
98
+ }
99
+
100
+ /**
101
+ * Get api url
102
+ *
103
+ * @since 2.0.0
104
+ * @return string
105
+ */
106
+ public function getApiUrl()
107
+ {
108
+ return $this->apiUrl;
109
+ }
110
+
111
+ /**
112
+ * Set http client
113
+ *
114
+ * @since 2.0.0
115
+ * @param $client
116
+ * @return $this
117
+ */
118
+ public function setHttpClient( $client )
119
+ {
120
+ $this->client = $client;
121
+
122
+ return $this;
123
+ }
124
+
125
+ /**
126
+ * Get http client
127
+ *
128
+ * @since 2.0.0
129
+ * @return mixed
130
+ */
131
+ public function getHttpClient()
132
+ {
133
+ return $this->client;
134
+ }
135
+
136
+ /**
137
+ * Listen command
138
+ *
139
+ * @since 2.0.0
140
+ * Listen to requests from Beeketing
141
+ */
142
+ public function listenCommand()
143
+ {
144
+ if ( ! isset( $_GET['bk_send_action'] ) ) {
145
+ return;
146
+ }
147
+
148
+ $command = $_GET['bk_send_action'];
149
+
150
+ if ( ! isset( $_GET['access_token'] ) ) {
151
+ wp_send_json_error( [ 'message' => 'Access token not found' ] );
152
+ die;
153
+ }
154
+
155
+ $access_token = $_GET['access_token'];
156
+
157
+ if ( $access_token != $this->apiKey ) {
158
+ wp_send_json_error( [ 'message' => 'Invalid access token' ] );
159
+ die;
160
+ }
161
+
162
+ error_reporting(0);
163
+
164
+
165
+ switch ( $command ) {
166
+ case 'test-request':
167
+ wp_send_json_success([
168
+ 'apache_request_headers' => function_exists('apache_request_headers'),
169
+ 'getallheaders' => function_exists('getallheaders'),
170
+ 'header' => getallheaders(),
171
+ 'post' => $_POST,
172
+ 'get' => $_GET
173
+ ]);
174
+
175
+ die;
176
+ break;
177
+
178
+ case 'sync-products':
179
+ if ( 1 == get_option( 'beeketing_completed_initial_product_sync', 0 ) ) {
180
+ // Reset complete syncing flag to wake it up
181
+ update_option( 'beeketing_completed_initial_product_sync', 0 );
182
+ update_option( 'beeketing_current_sync_time', time() );
183
+ }
184
+ wp_send_json( [ 'success' => true ] );
185
+ die;
186
+ break;
187
+
188
+ case 'sync-collections':
189
+ if ( 1 == get_option( 'beeketing_completed_initial_collection_sync', 0 ) ) {
190
+ // Reset complete syncing flag to wake it up
191
+ update_option( 'beeketing_completed_initial_collection_sync', 0 );
192
+ update_option( 'beeketing_current_sync_time', time() );
193
+ }
194
+ wp_send_json( [ 'success' => true ] );
195
+ die;
196
+ break;
197
+
198
+ case 'sync-orders':
199
+ if ( 1 == get_option( 'beeketing_completed_initial_order_sync', 0 ) ) {
200
+ // Reset complete syncing flag to wake it up
201
+ update_option( 'beeketing_completed_initial_order_sync', 0 );
202
+ update_option( 'beeketing_current_sync_time', time() );
203
+ }
204
+ wp_send_json( [ 'success' => true ] );
205
+ die;
206
+ break;
207
+
208
+ case 'sync-collects':
209
+ if ( 1 == get_option( 'beeketing_completed_initial_order_sync', 0 ) ) {
210
+ // Reset complete syncing flag to wake it up
211
+ update_option( 'beeketing_completed_initial_order_sync', 0 );
212
+ update_option( 'beeketing_current_sync_time', time() );
213
+ }
214
+ wp_send_json( [ 'success' => true ] );
215
+ die;
216
+ break;
217
+
218
+ case 'sync-customers':
219
+ if ( 1 == get_option( 'beeketing_completed_initial_customer_sync', 0 ) ) {
220
+ // Reset complete syncing flag to wake it up
221
+ update_option( 'beeketing_completed_initial_customer_sync', 0 );
222
+ update_option( 'beeketing_current_sync_time', time() );
223
+ }
224
+ wp_send_json( [ 'success' => true ] );
225
+ die;
226
+ break;
227
+
228
+ case 'create-variation':
229
+ if ( ! isset( $_GET['id'] ) ) {
230
+ wp_send_json_error( [ 'message' => 'Product id not found' ] );
231
+ die;
232
+ }
233
+
234
+ $header = getallheaders();
235
+
236
+ if ( isset( $_POST['bk_data'] ) ) {
237
+ $data = $_POST['bk_data'];
238
+ } elseif ( isset( $header['X-BK-DATA'] ) ) {
239
+ $data = json_decode( $header['X-BK-DATA'], true );
240
+ } else {
241
+ $data = [];
242
+ }
243
+
244
+ $variation_data = BeeketingWooCommerce()->products->create_gift_variation( $_GET['id'], $data );
245
+ if ( isset( $variation_data['success'] ) && $variation_data['success'] ) {
246
+ wp_send_json_success( $variation_data['data'] );
247
+ die;
248
+ }
249
+
250
+ wp_send_json( $variation_data );
251
+
252
+ die;
253
+ break;
254
+
255
+ case 'update-variation':
256
+ if ( ! isset( $_GET['variation_id'] ) ) {
257
+ wp_send_json_error( [ 'message' => 'Variation id not found' ] );
258
+ die;
259
+ }
260
+
261
+ $header = getallheaders();
262
+
263
+ if ( isset( $_POST['bk_data'] ) ) {
264
+ $data = $_POST['bk_data'];
265
+ } elseif ( isset( $header['X-BK-DATA'] ) ) {
266
+ $data = json_decode( $header['X-BK-DATA'], true );
267
+ } else {
268
+ $data = [];
269
+ }
270
+
271
+ $variation_data = BeeketingWooCommerce()->products->update_variation( $_GET['variation_id'], $data );
272
+ if ( isset( $variation_data['success'] ) && $variation_data['success'] ) {
273
+ wp_send_json_success( $variation_data['data'] );
274
+ die;
275
+ }
276
+
277
+ wp_send_json( $variation_data );
278
+
279
+ die;
280
+ break;
281
+
282
+ case 'get-variation':
283
+ if ( ! isset( $_GET['id'] ) ) {
284
+ wp_send_json_error( [ 'message' => 'Variation id not found' ] );
285
+ die;
286
+ }
287
+ $product_variation = $product_variation = get_post( $_GET['id'] );
288
+ if ( $product_variation->post_type != 'product_variation' && $product_variation->post_parent != 0 ) {
289
+ wp_send_json_error( [ 'message' => 'Not a variant' ] );
290
+ die;
291
+ }
292
+
293
+ if ( $product_variation->post_parent == 0 ) {
294
+ $product = wc_get_product( $_GET['id'] );
295
+ $variation_data = BeeketingWooCommerce()->products->get_formatted_variant( $product, $product );
296
+ } else {
297
+ $variation_data = BeeketingWooCommerce()->products->get_variant_data( $product_variation );
298
+ }
299
+ wp_send_json_success( $variation_data );
300
+
301
+ die;
302
+ break;
303
+
304
+ case 'delete-variation':
305
+ if ( ! isset( $_GET['variation_id'] ) ) {
306
+ wp_send_json_error( [ 'message' => 'Variant id not found' ] );
307
+ die;
308
+ }
309
+ $response = BeeketingWooCommerce()->products->beeketing_remove_variation( $_GET['variation_id'] );
310
+ if ( isset( $response['success'] ) && $response['success'] ) {
311
+ wp_send_json( [ 'success' => true ] );
312
+ die;
313
+ }
314
+
315
+ wp_send_json( $response );
316
+
317
+ die;
318
+ break;
319
+
320
+ case 'get-products':
321
+ $params = $_GET;
322
+ $params = $this->cleanUpParams( $params );
323
+ $response = BeeketingWooCommerce()->products->get_products( null, null, $params );
324
+
325
+ wp_send_json_success( $response['products'] );
326
+ die;
327
+ break;
328
+
329
+ case 'get-product':
330
+ if ( ! isset( $_GET['id'] ) ) {
331
+ wp_send_json_error( [ 'message' => 'Id not found' ] );
332
+ die;
333
+ }
334
+ $product = BeeketingWooCommerce()->products->get_formatted_product( (int) $_GET['id'] );
335
+ if (!$product) {
336
+ wp_send_json_error( [ 'Product not found' ] );
337
+ die;
338
+ }
339
+
340
+ wp_send_json_success( $product['product'] );
341
+ die;
342
+ break;
343
+
344
+ case 'get-collections':
345
+ $params = $_GET;
346
+ $params = $this->cleanUpParams($params);
347
+ $response = BeeketingWooCommerce()->collections->get_product_categories( null, $params );
348
+
349
+ wp_send_json_success( $response['product_categories'] );
350
+ die;
351
+ break;
352
+
353
+ case 'update-site-url':
354
+ BeeketingWooCommerce()->shop->update_shop_info_to_beeketing();
355
+ wp_send_json_success();
356
+ die;
357
+ break;
358
+
359
+ case 'share-facebook':
360
+ if ( ! isset( $_GET['offer_id'] ) || ! isset( $_GET['post_id'] ) ) {
361
+ wp_send_json_error( [ 'message' => 'Id not found' ] );
362
+ die;
363
+ }
364
+
365
+ $headers = array( 'Content-Type' => 'application/json', 'X-Beeketing-Key' => $this->apiKey, 'X-Beeketing-Source' => self::BEEKETING_SOURCE );
366
+
367
+ $apiResponse = wp_remote_post( BEEKETING_PATH . '/cboost/offers/shared?offer_id=' . $_GET['offer_id'] . '&post_id=' . $_GET['post_id'], array(
368
+ 'method' => self::METHOD_PUT,
369
+ 'timeout' => 45,
370
+ 'redirection' => 5,
371
+ 'httpversion' => '1.0',
372
+ 'blocking' => true,
373
+ 'headers' => $headers,
374
+ 'body' => json_encode( [] ),
375
+ 'cookies' => array()
376
+ )
377
+ );
378
+
379
+ if ( is_wp_error( $apiResponse ) ) {
380
+ return $apiResponse;
381
+ } else {
382
+ $response['response'] = $apiResponse['response'];
383
+ $response['body'] = $apiResponse['body'];
384
+ echo ( json_decode( $apiResponse['body'], true ) );
385
+ }
386
+ die;
387
+ break;
388
+
389
+ default:
390
+ wp_send_json_error( [ 'message' => 'Action not found' ] );
391
+ die;
392
+ break;
393
+ }
394
+ }
395
+
396
+ /**
397
+ * Remove cart
398
+ *
399
+ * @since 2.0.0
400
+ */
401
+ public function listenCartActions()
402
+ {
403
+ if ( ! isset( $_GET['bk_cart_action'] ) ) {
404
+ return;
405
+ }
406
+
407
+ $command = $_GET['bk_cart_action'];
408
+
409
+ if ( ! isset( $_GET['access_token'] ) ) {
410
+ wp_send_json_error( [ 'message' => 'Access token not found' ] );
411
+ die;
412
+ }
413
+
414
+ $access_token = $_GET['access_token'];
415
+
416
+ if ( $access_token != $this->apiKey ) {
417
+ wp_send_json_error( [ 'message' => 'Invalid access token' ] );
418
+ die;
419
+ }
420
+
421
+ error_reporting(0);
422
+
423
+ switch ( $command ) {
424
+ case 'add':
425
+ if ( ! isset( $_POST['product_id'] ) ) {
426
+ wp_send_json_error( [ 'message' => 'product id not found' ] );
427
+ die;
428
+ }
429
+
430
+ if ( is_array( $_POST['product_id'] ) ) {
431
+ foreach ( $_POST['product_id'] as $key => $product_id ) {
432
+ $data = [
433
+ 'product_id' => (int) $product_id,
434
+ 'variation_id' => isset( $_POST['id'][ $key ] ) ? (int) $_POST['id'][ $key ] : null,
435
+ 'quantity' => isset( $_POST['qty'][ $key ]) ? (int) $_POST['qty'][ $key ] : 1,
436
+ 'attributes' => isset( $_POST['attributes'][ $key ]) ? $_POST['attributes'][ $key ] : []
437
+ ];
438
+
439
+ BeeketingWooCommerce()->cart->beeketing_add_to_cart( $data );
440
+ }
441
+
442
+ $cartData = BeeketingWooCommerce()->cart->get_formatted_cart_data();
443
+ wp_send_json( $cartData );
444
+ die;
445
+ } else {
446
+ $data = [
447
+ 'product_id' => (int) $_POST['product_id'],
448
+ 'variation_id' => isset( $_POST['id'] ) ? (int) $_POST['id'] : null,
449
+ 'quantity' => isset( $_POST['qty'] ) ? (int) $_POST['qty'] : 1,
450
+ 'attributes' => isset( $_POST['attributes'] ) ? $_POST['attributes'] : []
451
+ ];
452
+
453
+ $variation = BeeketingWooCommerce()->cart->beeketing_add_to_cart( $data );
454
+ if ( $variation ) {
455
+ wp_send_json( $variation );
456
+ die;
457
+ }
458
+ }
459
+
460
+ wp_send_json_error();
461
+ die;
462
+ break;
463
+
464
+ case 'remove':
465
+ if ( ! isset( $_GET['cart_item_key'] ) ) {
466
+ wp_send_json_error( [ 'message' => 'Cart item key not found' ] );
467
+ die;
468
+ }
469
+
470
+ $result = BeeketingWooCommerce()->cart->remove_from_cart( $_GET['cart_item_key'] );
471
+ if ( $result ) {
472
+ wp_send_json_success();
473
+ die;
474
+ }
475
+ wp_send_json_error();
476
+ break;
477
+
478
+ default:
479
+ wp_send_json_error( [ 'message' => 'Action not found' ] );
480
+ die;
481
+ break;
482
+ }
483
+
484
+
485
+ if ( ! isset( $_GET['bk_remove_cart'] ) ) {
486
+ return;
487
+ }
488
+
489
+ if ( ! isset( $_GET['access_token'] ) ) {
490
+ wp_send_json_error( [ 'message' => 'Access token not found' ] );
491
+ die;
492
+ }
493
+
494
+ $access_token = $_GET['access_token'];
495
+
496
+ if ( $access_token != $this->apiKey ) {
497
+ wp_send_json_error( [ 'message' => 'Invalid access token' ] );
498
+ die;
499
+ }
500
+
501
+ $result = BeeketingWooCommerce()->cart->remove_from_cart( $_GET['bk_remove_cart'] );
502
+ if ( $result ) {
503
+ wp_send_json_success();
504
+ die;
505
+ }
506
+ wp_send_json_error();
507
+ die;
508
+ }
509
+
510
+ /**
511
+ * Clean up params
512
+ *
513
+ * @param array $params
514
+ * @return array
515
+ */
516
+ public function cleanUpParams( $params = [] )
517
+ {
518
+ if ( isset( $params['bk_send_action'] ) ) {
519
+ unset( $params['bk_send_action'] );
520
+ }
521
+ if ( isset( $params['access_token'] ) ) {
522
+ unset( $params['access_token'] );
523
+ }
524
+
525
+ return $params;
526
+ }
527
+
528
+ /**
529
+ * API Get
530
+ *
531
+ * @since 2.0.0
532
+ * @param $apiMethod
533
+ * @param array $args
534
+ * @return mixed
535
+ */
536
+ public function apiGet( $apiMethod, $args = array() )
537
+ {
538
+ $headers = array( 'Content-Type' => 'application/json', 'X-Beeketing-Key' => $this->apiKey, 'X-Beeketing-Source' => self::BEEKETING_SOURCE );
539
+
540
+ $apiResponse = wp_remote_get( $this->apiUrl . $apiMethod . '.json', array(
541
+ 'timeout' => 5,
542
+ 'redirection' => 5,
543
+ 'httpversion' => '1.0',
544
+ 'blocking' => true,
545
+ 'headers' => $headers,
546
+ 'body' => json_encode( $args ),
547
+ 'cookies' => array()
548
+ )
549
+ );
550
+
551
+ if ( is_wp_error( $apiResponse ) ) {
552
+ return $apiResponse;
553
+ } else {
554
+ $response['response'] = $apiResponse['response'];
555
+ $response['body'] = $apiResponse['body'];
556
+ return $response;
557
+ }
558
+ }
559
+
560
+ /**
561
+ * API Post
562
+ *
563
+ * @since 2.0.0
564
+ * @param $apiMethod
565
+ * @param array $args
566
+ * @return mixed
567
+ */
568
+ public function apiPost( $apiMethod, $args = array() )
569
+ {
570
+ $headers = array( 'Content-Type' => 'application/json', 'X-Beeketing-Key' => $this->apiKey, 'X-Beeketing-Source' => self::BEEKETING_SOURCE );
571
+
572
+ $apiResponse = wp_remote_post( $this->apiUrl . $apiMethod . '.json', array(
573
+ 'method' => self::METHOD_POST,
574
+ 'timeout' => 45,
575
+ 'redirection' => 5,
576
+ 'httpversion' => '1.0',
577
+ 'blocking' => true,
578
+ 'headers' => $headers,
579
+ 'body' => json_encode( $args ),
580
+ 'cookies' => array()
581
+ )
582
+ );
583
+
584
+ if ( is_wp_error( $apiResponse ) ) {
585
+ return $apiResponse;
586
+ } else {
587
+ $response['response'] = $apiResponse['response'];
588
+ $response['body'] = $apiResponse['body'];
589
+ return $response;
590
+ }
591
+ }
592
+
593
+ /**
594
+ * API Put
595
+ *
596
+ * @since 2.0.0
597
+ * @param $apiMethod
598
+ * @param array $args
599
+ * @return mixed
600
+ */
601
+ public function apiPut( $apiMethod, $args = array() )
602
+ {
603
+ $headers = array( 'Content-Type' => 'application/json', 'X-Beeketing-Key' => $this->apiKey, 'X-Beeketing-Source' => self::BEEKETING_SOURCE );
604
+
605
+ $apiResponse = wp_remote_post( $this->apiUrl . $apiMethod . '.json', array(
606
+ 'method' => self::METHOD_PUT,
607
+ 'timeout' => 45,
608
+ 'redirection' => 5,
609
+ 'httpversion' => '1.0',
610
+ 'blocking' => true,
611
+ 'headers' => $headers,
612
+ 'body' => json_encode( $args ),
613
+ 'cookies' => array()
614
+ )
615
+ );
616
+
617
+ if ( is_wp_error( $apiResponse ) ) {
618
+ return $apiResponse;
619
+ } else {
620
+ $response['response'] = $apiResponse['response'];
621
+ $response['body'] = $apiResponse['body'];
622
+ return $response;
623
+ }
624
+ }
625
+
626
+ /**
627
+ * API Delete
628
+ *
629
+ * @since 2.0.0
630
+ * @param $apiMethod
631
+ * @param array $args
632
+ * @return mixed
633
+ */
634
+ public function apiDelete( $apiMethod, $args = array() )
635
+ {
636
+ $headers = array( 'Content-Type' => 'application/json', 'X-Beeketing-Key' => $this->apiKey, 'X-Beeketing-Source' => self::BEEKETING_SOURCE );
637
+
638
+ $apiResponse = wp_remote_post( $this->apiUrl . $apiMethod . '.json', array(
639
+ 'method' => self::METHOD_DELETE,
640
+ 'timeout' => 45,
641
+ 'redirection' => 5,
642
+ 'httpversion' => '1.0',
643
+ 'blocking' => true,
644
+ 'headers' => $headers,
645
+ 'body' => json_encode( $args ),
646
+ 'cookies' => array()
647
+ )
648
+ );
649
+
650
+ if ( is_wp_error( $apiResponse ) ) {
651
+ return $apiResponse;
652
+ } else {
653
+ $response['response'] = $apiResponse['response'];
654
+ $response['body'] = $apiResponse['body'];
655
+ return $response;
656
+ }
657
+ }
658
+
659
+ /**
660
+ * Check and add cart token
661
+ *
662
+ * @since 2.0.0
663
+ */
664
+ public function checkAndAddCartToken()
665
+ {
666
+ if ( ! isset( $_COOKIE['beeketing-cart-token'] ) ) {
667
+ setcookie( 'beeketing-cart-token', uniqid( $this->apiKey, true ), time() + self::CART_TOKEN_LIFE_TIME, '/' );
668
+ }
669
+ }
670
+ }
lib/BeeketingSDK/Api/BeeketingCart.php ADDED
@@ -0,0 +1,395 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ /**
5
+ * Class BeeketingSDK_Api_BeeketingCart.
6
+ *
7
+ * @class BeeketingSDK_Api_BeeketingCart
8
+ * @version 1.0.0
9
+ * @author Beeketing
10
+ */
11
+ class BeeketingSDK_Api_BeeketingCart
12
+ {
13
+ /**
14
+ * Constructor.
15
+ *
16
+ * @since 2.0.0
17
+ */
18
+ public function __construct()
19
+ {
20
+ add_filter( 'add_to_cart_fragments', array( $this, 'header_add_to_cart_fragment' ), 10, 1 );
21
+
22
+ add_action( 'woocommerce_add_to_cart', array( $this, 'listen_add_cart' ), 10, 6 );
23
+
24
+ add_action( 'woocommerce_cart_item_removed', array( $this, 'listen_cart_item_removed' ), 10, 2 );
25
+
26
+ add_action( 'woocommerce_after_cart_item_quantity_update', array( $this, 'listen_cart_item_quantity_update' ), 10, 3 );
27
+ }
28
+
29
+ /**
30
+ * Listen add to cart event
31
+ *
32
+ * @since 2.0.0
33
+ * @param $cart_item_key
34
+ * @param $product_id
35
+ * @param $quantity
36
+ * @param $variation_id
37
+ * @param $variation
38
+ * @param $cart_item_data
39
+ */
40
+ public function listen_add_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data )
41
+ {
42
+ $item_details = [
43
+ 'cart_item_key' => $cart_item_key,
44
+ 'product_id' => $product_id,
45
+ 'quantity' => $quantity,
46
+ 'variation_id' => $variation_id,
47
+ 'cart_item_data' => $cart_item_data,
48
+ ];
49
+ if (!isset($_COOKIE['beeketing-last-added-items'])) {
50
+ setcookie('beeketing-last-added-items', json_encode($item_details), time() + 3600, '/');
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Listen cart item removed
56
+ *
57
+ * @since 2.0.0
58
+ * @param $cart_item_key
59
+ * @param $cart
60
+ */
61
+ public function listen_cart_item_removed( $cart_item_key, $cart )
62
+ {
63
+ if ( ! isset( $cart->removed_cart_contents[ $cart_item_key ] ) ) {
64
+ return;
65
+ }
66
+
67
+ $removed_item = $cart->removed_cart_contents[ $cart_item_key ];
68
+
69
+ $_product = $removed_item['data']->post;
70
+ $price = $removed_item['data']->price;
71
+ unset( $removed_item['data'] );
72
+
73
+ $item_details = array_merge([
74
+ 'product_token' => $cart_item_key,
75
+ 'url' => $_product->guid,
76
+ 'title' => $_product->post_title,
77
+ 'price' => $price,
78
+ ], $removed_item);
79
+
80
+ if ( ! isset( $_COOKIE['beeketing-cart-last-deleted-items'] ) ) {
81
+ setcookie( 'beeketing-cart-last-deleted-items', json_encode($item_details), time() + 3600, '/' );
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Listen cart item quantity update
87
+ *
88
+ * @since 2.0.0
89
+ * @param $cart_item_key
90
+ * @param $quantity
91
+ * @param $old_quantity
92
+ */
93
+ public function listen_cart_item_quantity_update( $cart_item_key, $quantity, $old_quantity )
94
+ {
95
+ if ( $quantity > $old_quantity ) {
96
+ if ( ! isset($_COOKIE['beeketing-last-added-items'] ) ) {
97
+ $item_details = [
98
+ 'cart_item_key' => $cart_item_key,
99
+ 'quantity' => $quantity - $old_quantity,
100
+ ];
101
+ setcookie( 'beeketing-last-added-items', json_encode($item_details), time() + 3600, '/' );
102
+ }
103
+ } else {
104
+ if ( ! isset( $_COOKIE['beeketing-last-removed-items'] ) ) {
105
+ $item_details = [
106
+ 'cart_item_key' => $cart_item_key,
107
+ 'quantity' => $old_quantity - $quantity,
108
+ ];
109
+ setcookie( 'beeketing-last-removed-items', json_encode($item_details), time() + 3600, '/' );
110
+ }
111
+ }
112
+
113
+ }
114
+
115
+ /**
116
+ * Add to cart fragment
117
+ *
118
+ * @since 2.0.0
119
+ * @param $fragments
120
+ * @return mixed
121
+ */
122
+ public function header_add_to_cart_fragment( $fragments )
123
+ {
124
+ $fragments['beeketing_cart_data'] = $this->get_formatted_cart_data();
125
+ return $fragments;
126
+ }
127
+
128
+ /**
129
+ * Get formatted cart data
130
+ *
131
+ * @since 2.0.0
132
+ * @return array
133
+ */
134
+ public function get_formatted_cart_data()
135
+ {
136
+ // Init cart data
137
+ global $woocommerce;
138
+ $cart = $woocommerce->cart;
139
+ $items = $cart->get_cart();
140
+
141
+ $cartData = [];
142
+ $itemCount = 0;
143
+ $totalPrice = 0;
144
+ foreach ( $items as $item => $values ) {
145
+ $_product = $values['data']->post;
146
+ $price = $values['data']->price;
147
+ $itemCount += $values['quantity'];
148
+ $totalPrice += $price * $values['quantity'];
149
+ if ( $values['variation_id'] > 0 ) {
150
+ $variation = get_post( $values['variation_id'] );
151
+ $title = $variation->post_title;
152
+ } else {
153
+ $title = $_product->post_title;
154
+ }
155
+ unset($values['data']);
156
+ $image_data = wp_get_attachment_image_src( get_post_thumbnail_id( $_product->ID ), 'thumbnail' );
157
+ $cartData['items'][$item] = array_merge([
158
+ 'product_token' => $item,
159
+ 'url' => get_permalink( $_product->ID ),
160
+ 'title' => $title,
161
+ 'price' => $price,
162
+ 'image' => isset( $image_data[0] ) ? $image_data[0] : '',
163
+ ], $values);
164
+ }
165
+
166
+ $cartData['item_count'] = $itemCount;
167
+ $cartData['total_price'] = $totalPrice;
168
+ $cartData['cart_url'] = $cart->get_cart_url();
169
+ $cartData['checkout_url'] = $cart->get_checkout_url();
170
+ $cartData['shop_url'] = get_permalink( woocommerce_get_page_id('shop') );
171
+ if ( isset( $_COOKIE['beeketing-cart-token'] ) ) {
172
+ $cartData['token'] = $_COOKIE['beeketing-cart-token'];
173
+ }
174
+
175
+ return $cartData;
176
+ }
177
+
178
+ /**
179
+ * Add to cart
180
+ *
181
+ * @since 2.0.0
182
+ * @param $data
183
+ * @return bool
184
+ */
185
+ public function beeketing_add_to_cart( $data )
186
+ {
187
+ if ( empty( $data['product_id'] ) || ! is_numeric( $data['product_id'] ) ) {
188
+ return false;
189
+ }
190
+
191
+ $product_id = absint( $data['product_id'] );
192
+ $adding_to_cart = wc_get_product( $product_id );
193
+
194
+ if ( ! $adding_to_cart ) {
195
+ return false;
196
+ }
197
+
198
+ if ( is_array( $data['attributes'] ) ) {
199
+ $attributes = $data['attributes'];
200
+ } else {
201
+ $attributes = json_decode( stripslashes( $data['attributes'] ), true );
202
+ }
203
+
204
+ foreach ( $attributes as $attribute ) {
205
+ $data[ 'attribute_' . sanitize_title( $attribute['name'] ) ] = $attribute['option'];
206
+ }
207
+
208
+ $add_to_cart_handler = $adding_to_cart->product_type;
209
+ $data['price'] = $adding_to_cart->get_price();
210
+
211
+ // Variable product handling
212
+ if ( 'variable' === $add_to_cart_handler ) {
213
+ $was_added_to_cart = self::add_to_cart_handler_variable( $product_id, $data );
214
+
215
+ // Grouped Products
216
+ } elseif ( 'grouped' === $add_to_cart_handler ) {
217
+ $was_added_to_cart = self::add_to_cart_handler_grouped( $product_id, $data );
218
+
219
+ // Custom Handler
220
+ } else {
221
+ $was_added_to_cart = self::add_to_cart_handler_simple( $product_id, $data );
222
+ }
223
+
224
+ // If we added the product to the cart we can now optionally do a redirect.
225
+ if ( $was_added_to_cart && wc_notice_count( 'error' ) === 0 ) {
226
+ return $was_added_to_cart;
227
+ }
228
+
229
+ return false;
230
+ }
231
+
232
+ /**
233
+ * Remove item from cart
234
+ *
235
+ * @since 2.0.0
236
+ * @param $cart_item_key
237
+ * @return bool
238
+ */
239
+ public function remove_from_cart( $cart_item_key )
240
+ {
241
+ $cart_item_key = sanitize_text_field( $cart_item_key );
242
+
243
+ if ( $cart_item = WC()->cart->get_cart_item( $cart_item_key ) ) {
244
+ WC()->cart->remove_cart_item( $cart_item_key );
245
+ return true;
246
+ }
247
+
248
+ return false;
249
+ }
250
+
251
+ /**
252
+ * Handle adding simple products to the cart
253
+ *
254
+ * @since 2.0.0
255
+ * @param int $product_id
256
+ * @param $data
257
+ * @return bool success or not
258
+ */
259
+ private static function add_to_cart_handler_simple( $product_id, $data ) {
260
+ $quantity = empty( $data['quantity'] ) ? 1 : wc_stock_amount( $data['quantity'] );
261
+ $variation_id = empty( $data['variation_id'] ) ? '' : absint( $data['variation_id'] );
262
+ $passed_validation = true;
263
+
264
+ if ( $data['variation_id'] ) {
265
+ if ( isset( $data['price'] ) && $data['price'] == 0 ) {
266
+ $attributes = [
267
+ 'type' => 'Free Gift'
268
+ ];
269
+ } else {
270
+ $attributes = [
271
+ 'type' => 'BK Variation'
272
+ ];
273
+ }
274
+
275
+ } else {
276
+ $attributes = [];
277
+ }
278
+
279
+ if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $attributes ) !== false ) {
280
+ wc_add_to_cart_message( $product_id );
281
+ return true;
282
+ }
283
+ return false;
284
+ }
285
+
286
+ /**
287
+ * Handle adding grouped products to the cart
288
+ *
289
+ * @since 2.0.0
290
+ * @param int $product_id
291
+ * @param $data
292
+ * @return bool success or not
293
+ */
294
+ private static function add_to_cart_handler_grouped( $product_id, $data ) {
295
+ $was_added_to_cart = false;
296
+ $added_to_cart = array();
297
+
298
+ if ( ! empty( $data['quantity'] ) && is_array( $data['quantity'] ) ) {
299
+ $quantity_set = false;
300
+
301
+ foreach ( $data['quantity'] as $item => $quantity ) {
302
+ if ( $quantity <= 0 ) {
303
+ continue;
304
+ }
305
+ $quantity_set = true;
306
+
307
+ // Add to cart validation
308
+ $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $item, $quantity );
309
+
310
+ if ( $passed_validation && WC()->cart->add_to_cart( $item, $quantity ) !== false ) {
311
+ $was_added_to_cart = true;
312
+ $added_to_cart[] = $item;
313
+ }
314
+ }
315
+
316
+ if ( ! $was_added_to_cart && ! $quantity_set ) {
317
+ wc_add_notice( __( 'Please choose the quantity of items you wish to add to your cart&hellip;', 'woocommerce' ), 'error' );
318
+ } elseif ( $was_added_to_cart ) {
319
+ wc_add_to_cart_message( $added_to_cart );
320
+ return true;
321
+ }
322
+
323
+ } elseif ( $product_id ) {
324
+ /* Link on product archives */
325
+ wc_add_notice( __( 'Please choose a product to add to your cart&hellip;', 'woocommerce' ), 'error' );
326
+ }
327
+ return false;
328
+ }
329
+
330
+ /**
331
+ * Handle adding variable products to the cart
332
+ *
333
+ * @since 2.0.0
334
+ * @param int $product_id
335
+ * @param $data
336
+ * @return bool success or not
337
+ */
338
+ private static function add_to_cart_handler_variable( $product_id, $data ) {
339
+ $adding_to_cart = wc_get_product( $product_id );
340
+ $variation_id = empty( $data['variation_id'] ) ? '' : absint( $data['variation_id'] );
341
+ $quantity = empty( $data['quantity'] ) ? 1 : wc_stock_amount( $data['quantity'] );
342
+ $missing_attributes = array();
343
+ $variations = array();
344
+ $attributes = $adding_to_cart->get_attributes();
345
+ $variation = wc_get_product( $variation_id );
346
+
347
+ // Verify all attributes
348
+ foreach ( $attributes as $attribute ) {
349
+ if ( ! $attribute['is_variation'] ) {
350
+ continue;
351
+ }
352
+
353
+ $taxonomy = 'attribute_' . sanitize_title( $attribute['name'] );
354
+
355
+ if ( isset( $data[ $taxonomy ] ) ) {
356
+
357
+ // Get value from post data
358
+ if ( $attribute['is_taxonomy'] ) {
359
+ // Don't use wc_clean as it destroys sanitized characters
360
+ $value = sanitize_title( stripslashes( $data[ $taxonomy ] ) );
361
+ } else {
362
+ $value = wc_clean( stripslashes( $data[ $taxonomy ] ) );
363
+ }
364
+
365
+ // Get valid value from variation
366
+ $valid_value = $variation->variation_data[ $taxonomy ];
367
+
368
+ // Allow if valid
369
+ if ( '' === $valid_value || $valid_value === $value ) {
370
+ $variations[ $taxonomy ] = $value;
371
+ continue;
372
+ }
373
+
374
+ } else {
375
+ $missing_attributes[] = wc_attribute_label( $attribute['name'] );
376
+ }
377
+ }
378
+
379
+ if ( $missing_attributes ) {
380
+ return false;
381
+ } elseif ( empty( $variation_id ) ) {
382
+ return false;
383
+ } else {
384
+ // Add to cart validation
385
+ $passed_validation = true;
386
+
387
+ if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations ) !== false ) {
388
+ wc_add_to_cart_message( $product_id );
389
+ return true;
390
+ }
391
+ }
392
+ return false;
393
+ }
394
+
395
+ }
lib/BeeketingSDK/Api/BeeketingCollections.php ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class BeeketingSDK_Api_BeeketingCollections.
5
+ *
6
+ * @class BeeketingSDK_Api_BeeketingCollections
7
+ * @version 1.0.0
8
+ * @author Beeketing
9
+ */
10
+ class BeeketingSDK_Api_BeeketingCollections
11
+ {
12
+ /**
13
+ * Constructor.
14
+ *
15
+ * @since 2.0.0
16
+ */
17
+ public function __construct()
18
+ {
19
+
20
+ // Delete
21
+ add_action( 'delete_term', array( $this, 'delete_product_category_from_beeketing' ), 10, 4 );
22
+
23
+ // Create
24
+ add_action( 'created_term', array( $this, 'add_product_category_to_beeketing' ), 10, 3 );
25
+
26
+ // Edit
27
+ add_action( 'edited_term', array( $this, 'update_product_category_to_beeketing' ), 10, 3 );
28
+
29
+ }
30
+
31
+ /**
32
+ * Processes collection queue.
33
+ *
34
+ * Process the collections that are in the queue.
35
+ *
36
+ * @since 2.0.0
37
+ */
38
+ public function process_queue() {
39
+
40
+ $queue = get_option( '_beeketing_queue', array() );
41
+
42
+ // Process products
43
+ if ( isset( $queue['product_category'] ) && is_array( $queue['product_category'] ) ) {
44
+ foreach ( array_slice( $queue['product_category'], 0, 225, true ) as $key => $collection ) {
45
+
46
+ if ( 'delete' == $collection['action'] ) {
47
+ $response = $this->delete_product_category_from_beeketing( $collection['id'], null, 'product_cat', null );
48
+ } elseif( 'add' == $collection['action'] ) {
49
+ $response = $this->add_product_category_to_beeketing( $collection['id'], null, 'product_cat' );
50
+ } else {
51
+ $response = $this->update_product_category_to_beeketing( $collection['id'], null, 'product_cat' );
52
+ }
53
+
54
+ if ( ! is_wp_error( $response ) && in_array( $response['response']['code'], array( '200', '201', '204', '400', '404' ) ) ) { // Unset from queue when appropiate
55
+ unset( $queue['products'][ $key ] );
56
+ }
57
+
58
+ }
59
+ }
60
+
61
+ update_option( '_beeketing_queue', $queue );
62
+
63
+ }
64
+
65
+ /**
66
+ * Add product category to beeketing
67
+ *
68
+ * @since 2.0.0
69
+ * @param $term_id
70
+ * @param $tt_id
71
+ * @param $taxonomy
72
+ * @return bool
73
+ */
74
+ public function add_product_category_to_beeketing( $term_id, $tt_id, $taxonomy )
75
+ {
76
+ if ( $taxonomy != 'product_cat' ) {
77
+ return false;
78
+ }
79
+
80
+ $product_category = $this->get_formatted_product_category( $term_id );
81
+
82
+ $response = BeeketingWooCommerce()->api->apiPost( 'collections/create_update', $product_category['product_category'] );
83
+
84
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
85
+ $queue = get_option( '_beeketing_queue', array() );
86
+ $queue['product_category'][ $term_id ] = array( 'id' => $term_id, 'action' => 'add' );
87
+ update_option( '_beeketing_queue', $queue );
88
+ } elseif ( in_array( $response['response']['code'], array( '200', '201' ) ) ) {
89
+ update_woocommerce_term_meta( $term_id, '_beeketing_last_update', time() );
90
+ $updated_categories = get_option( '_beeketing_updated_categories', [] );
91
+ $updated_categories[] = $term_id;
92
+ update_option( '_beeketing_updated_categories', $updated_categories );
93
+ }
94
+
95
+ return $response;
96
+ }
97
+
98
+ /**
99
+ * Update product category to beeketing
100
+ *
101
+ * @since 2.0.0
102
+ * @param $term_id
103
+ * @param $tt_id
104
+ * @param $taxonomy
105
+ * @return bool
106
+ */
107
+ public function update_product_category_to_beeketing( $term_id, $tt_id, $taxonomy )
108
+ {
109
+ if ( $taxonomy != 'product_cat' ) {
110
+ return false;
111
+ }
112
+
113
+ $product_category = $this->get_formatted_product_category( $term_id );
114
+
115
+ $response = BeeketingWooCommerce()->api->apiPost('collections/create_update', $product_category['product_category']);
116
+
117
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
118
+ $queue = get_option( '_beeketing_queue', array() );
119
+ $queue['product_category'][ $term_id ] = array( 'id' => $term_id, 'action' => 'update' );
120
+ update_option( '_beeketing_queue', $queue );
121
+ } elseif ( in_array( $response['response']['code'], array( '200', '201' ) ) ) {
122
+ update_woocommerce_term_meta( $term_id, '_beeketing_last_update', time() );
123
+ $updated_categories = get_option( '_beeketing_updated_categories', [] );
124
+ $updated_categories[] = $term_id;
125
+ update_option( '_beeketing_updated_categories', $updated_categories );
126
+ }
127
+
128
+ return $response;
129
+ }
130
+
131
+ /**
132
+ * Delete product category from beeketing
133
+ *
134
+ * @since 2.0.0
135
+ * @param $term
136
+ * @param $tt_id
137
+ * @param $taxonomy
138
+ * @param $deleted_term
139
+ * @return bool
140
+ */
141
+ public function delete_product_category_from_beeketing( $term, $tt_id, $taxonomy, $deleted_term )
142
+ {
143
+ if ($taxonomy != 'product_cat') {
144
+ return false;
145
+ }
146
+
147
+ $response = BeeketingWooCommerce()->api->apiDelete( 'collections/' . $term );
148
+
149
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
150
+ $queue = get_option( '_beeketing_queue', array() );
151
+ $queue['product_category'][ $term ] = array( 'id' => $term, 'action' => 'delete' );
152
+ update_option( '_beeketing_queue', $queue );
153
+ }
154
+
155
+ return $response;
156
+ }
157
+
158
+ /**
159
+ * Get a listing of product categories
160
+ *
161
+ * @since 2.0.0
162
+ * @param string|null $fields fields to limit response to
163
+ * @param array $filter
164
+ * @return array
165
+ */
166
+ public function get_product_categories( $fields = null, $filter = array() )
167
+ {
168
+
169
+ if ( isset( $filter['limit'] ) ) {
170
+ $filter['number'] = $filter['limit'];
171
+ unset( $filter['limit'] );
172
+ }
173
+
174
+ if ( isset( $filter['title'] ) ) {
175
+ $filter['search'] = $filter['title'];
176
+ unset( $filter['title'] );
177
+ }
178
+
179
+ $product_categories = array();
180
+ $terms = get_terms( 'product_cat', array_merge(array( 'hide_empty' => false, 'fields' => 'ids' ), $filter ) );
181
+ foreach ( $terms as $term_id ) {
182
+ $product_categories[] = current( $this->get_formatted_product_category( $term_id, $fields ) );
183
+ }
184
+ return array( 'product_categories' => $product_categories );
185
+ }
186
+
187
+ /**
188
+ * Get the product category for the given ID
189
+ *
190
+ * @since 2.0.0
191
+ * @param string $id product category term ID
192
+ * @param string|null $fields fields to limit response to
193
+ * @return array
194
+ */
195
+ public function get_formatted_product_category( $id, $fields = null )
196
+ {
197
+ $id = absint( $id );
198
+ // Validate ID
199
+ if ( empty( $id ) ) {
200
+ return false;
201
+ }
202
+
203
+ $term = get_term( $id, 'product_cat' );
204
+ if ( is_wp_error( $term ) || is_null( $term ) ) {
205
+ return false;
206
+ }
207
+ $term_id = intval( $term->term_id );
208
+
209
+ // Get category image
210
+ $image = '';
211
+ if ( $image_id = get_woocommerce_term_meta( $term_id, 'thumbnail_id' ) ) {
212
+ $image = wp_get_attachment_url( $image_id );
213
+ }
214
+ $product_category = array(
215
+ 'ref_id' => $term_id,
216
+ 'title' => $term->name,
217
+ 'image_url' => $image ? esc_url( $image ) : '',
218
+ );
219
+ return array( 'product_category' => $product_category );
220
+
221
+ }
222
+ }
lib/BeeketingSDK/Api/BeeketingCollects.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class BeeketingSDK_Api_BeeketingCollects.
5
+ *
6
+ * @class BeeketingSDK_Api_BeeketingCollects
7
+ * @version 1.0.0
8
+ * @author Beeketing
9
+ */
10
+ class BeeketingSDK_Api_BeeketingCollects
11
+ {
12
+ /**
13
+ * Processes collect queue.
14
+ *
15
+ * Process the collects that are in the queue.
16
+ *
17
+ * @since 2.0.0
18
+ */
19
+ public function process_queue()
20
+ {
21
+
22
+ $queue = get_option( '_beeketing_queue', array() );
23
+
24
+ // Process products
25
+ if ( isset( $queue['collect'] ) && is_array( $queue['collect'] ) ) {
26
+ foreach ( array_slice( $queue['collect'], 0, 225, true ) as $key => $collect ) {
27
+
28
+ if ( 'update' == $collect['action'] ) {
29
+ $response = $this->update_collect( $collect['product_id'], $collect['collection_id'] );
30
+ }
31
+
32
+ if ( isset($response) && ! is_wp_error( $response ) && in_array( $response['response']['code'], array( '200', '201', '204', '400', '404' ) ) ) { // Unset from queue when appropiate
33
+ unset( $queue['collect'][$key] );
34
+ }
35
+
36
+ }
37
+ }
38
+
39
+ update_option( '_beeketing_queue', $queue );
40
+
41
+ }
42
+
43
+ /**
44
+ * Sync collect by collection id
45
+ *
46
+ * @since 2.0.0
47
+ * @param $collection_id
48
+ */
49
+ public function sync_collect_by_collection_id( $collection_id )
50
+ {
51
+ $product_offset = 0;
52
+ while (true) {
53
+ $product_ids = beeketing_get_product_ids_in_collection( $collection_id, [
54
+ 'posts_per_page' => 250,
55
+ 'offset' => $product_offset * 250,
56
+ ]);
57
+
58
+ if ( ! $product_ids ) {
59
+ break;
60
+ }
61
+
62
+ foreach ( $product_ids as $product_id ) {
63
+ $this->update_collect( $product_id, $collection_id );
64
+ }
65
+
66
+ $product_offset ++;
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Update collect
72
+ *
73
+ * @since 2.0.0
74
+ * @param $product_id
75
+ * @param $collection_id
76
+ * @return mixed
77
+ */
78
+ public function update_collect( $product_id, $collection_id )
79
+ {
80
+ $collect_data = $this->get_formatted_collect( $product_id, $collection_id );
81
+
82
+ $response = BeeketingWooCommerce()->api->apiPost( 'collects', $collect_data['collect'] );
83
+
84
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
85
+ $queue = get_option( '_beeketing_queue', array( ) );
86
+ $queue['collect'][$collect_data['id']] = array( 'id' => $collect_data['id'], 'action' => 'update' );
87
+ update_option( '_beeketing_queue', $queue );
88
+ }
89
+
90
+ return $response;
91
+ }
92
+
93
+ /**
94
+ * Get formatted collect
95
+ *
96
+ * @since 2.0.0
97
+ * @param $product_id
98
+ * @param $collection_id
99
+ * @return array
100
+ */
101
+ public function get_formatted_collect( $product_id, $collection_id )
102
+ {
103
+ return array(
104
+ 'collect' => array(
105
+ 'ref_id' => $this->generate_collect_id( $product_id, $collection_id ),
106
+ 'product_ref_id' => $product_id,
107
+ 'collection_ref_id' => $collection_id,
108
+ ),
109
+ );
110
+ }
111
+
112
+ /**
113
+ * Generate collect id by using cantor pairing function
114
+ *
115
+ * @since 2.0.0
116
+ * @param $product_id
117
+ * @param $collection_id
118
+ * @return float
119
+ */
120
+ public function generate_collect_id( $product_id, $collection_id )
121
+ {
122
+ return ( ( $product_id + $collection_id ) * ( $product_id + $collection_id + 1 ) ) / 2 + $collection_id;
123
+ }
124
+ }
lib/BeeketingSDK/Api/BeeketingCustomers.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class BeeketingSDK_Api_BeeketingCustomers.
4
+ *
5
+ * @class BeeketingSDK_Api_BeeketingCustomers
6
+ * @version 1.0.0
7
+ * @author Beeketing
8
+ */
9
+
10
+ /**
11
+ * Class BeeketingSDK_Api_BeeketingCustomers.
12
+ *
13
+ * @class BeeketingSDK_Api_BeeketingCustomers
14
+ * @version 1.0.0
15
+ * @author Beeketing
16
+ */
17
+ class BeeketingSDK_Api_BeeketingCustomers
18
+ {
19
+ /**
20
+ * Constructor.
21
+ *
22
+ * @since 2.0.0
23
+ */
24
+ public function __construct()
25
+ {
26
+ // User register
27
+ add_action( 'user_register', array( $this, 'beeketing_add_customer' ), 10, 2 );
28
+ // User Update
29
+ add_action( 'profile_update', array( $this, 'beeketing_update_customer' ), 10, 2 );
30
+ // User Delete
31
+ add_action( 'delete_user', array( $this, 'beeketing_delete_customer' ), 10, 2 );
32
+ }
33
+
34
+ /**
35
+ * Processes customer queue.
36
+ *
37
+ * Process the customers that are in the queue.
38
+ *
39
+ * @since 2.0.0
40
+ */
41
+ public function process_queue() {
42
+
43
+ $queue = get_option( '_beeketing_queue', array() );
44
+
45
+ // Process products
46
+ if ( isset( $queue['customers'] ) && is_array( $queue['customers'] ) ) {
47
+ foreach ( array_slice( $queue['customers'], 0, 225, true ) as $key => $customer ) {
48
+
49
+ if ( 'delete' == $customer['action'] ) {
50
+ $response = $this->beeketing_delete_customer( $customer['id'], null );
51
+ } elseif( 'add' == $customer['action'] ) {
52
+ $response = $this->beeketing_add_customer( $customer['id'], null );
53
+ } else {
54
+ $response = $this->beeketing_update_customer( $customer['id'], null );
55
+ }
56
+
57
+ if ( ! is_wp_error( $response ) && in_array( $response['response']['code'], array( '200', '201', '204', '400', '404' ) ) ) { // Unset from queue when appropiate
58
+ unset( $queue['products'][ $key ] );
59
+ }
60
+
61
+ }
62
+ }
63
+
64
+ update_option( '_beeketing_queue', $queue );
65
+
66
+ }
67
+
68
+ /**
69
+ * Add customer
70
+ *
71
+ * @since 2.0.0
72
+ * @param $user_id
73
+ * @param $old_user_data
74
+ * @return mixed
75
+ */
76
+ public function beeketing_add_customer( $user_id, $old_user_data )
77
+ {
78
+ $user_data = $this->get_customer( $user_id );
79
+ $response = BeeketingWooCommerce()->api->apiPost( 'customers/create_update', $user_data['customer'] );
80
+
81
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
82
+ $queue = get_option( '_beeketing_queue', array() );
83
+ $queue['customers'][$user_id] = array( 'id' => $user_id, 'action' => 'add' );
84
+ update_option( '_beeketing_queue', $queue );
85
+ } elseif ( in_array( $response['response']['code'], array( '200', '201' ) ) ) {
86
+ update_user_meta( $user_id, '_beeketing_last_update', time() );
87
+ }
88
+
89
+ return $response;
90
+ }
91
+
92
+ /**
93
+ * Update customer
94
+ *
95
+ * @since 2.0.0
96
+ * @param $user_id
97
+ * @param $old_user_data
98
+ * @return mixed
99
+ */
100
+ public function beeketing_update_customer( $user_id, $old_user_data )
101
+ {
102
+ $user_data = $this->get_customer( $user_id );
103
+ $response = BeeketingWooCommerce()->api->apiPost( 'customers/create_update', $user_data['customer'] );
104
+
105
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
106
+ $queue = get_option( '_beeketing_queue', array() );
107
+ $queue['customers'][$user_id] = array( 'id' => $user_id, 'action' => 'update' );
108
+ update_option( '_beeketing_queue', $queue );
109
+ } elseif ( in_array( $response['response']['code'], array( '200', '201' ) ) ) {
110
+ update_user_meta( $user_id, '_beeketing_last_update', time() );
111
+ }
112
+
113
+ return $response;
114
+ }
115
+
116
+ /**
117
+ * Delete customer
118
+ *
119
+ * @since 2.0.0
120
+ * @param $user_id
121
+ * @return mixed
122
+ */
123
+ public function beeketing_delete_customer( $user_id, $reassign )
124
+ {
125
+ $response = BeeketingWooCommerce()->api->apiDelete( 'customers/' . $user_id );
126
+
127
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
128
+ $queue = get_option( '_beeketing_queue', array() );
129
+ $queue['customers'][$user_id] = array( 'id' => $user_id, 'action' => 'delete' );
130
+ update_option( '_beeketing_queue', $queue );
131
+ }
132
+
133
+ return $response;
134
+ }
135
+
136
+ /**
137
+ * Get all customers
138
+ *
139
+ * @since 2.0.0
140
+ * @param array $fields
141
+ * @param array $filter
142
+ * @param int $page
143
+ * @return array
144
+ */
145
+ public function get_customers( $fields = null, $filter = array(), $page = 1 ) {
146
+ $query = beeketing_query_customers( $filter );
147
+ $customers = array();
148
+ foreach ( $query->get_results() as $user_id ) {
149
+ $customers[] = $this->get_customer( $user_id, $fields );
150
+ }
151
+
152
+ return array( 'customers' => $customers );
153
+ }
154
+
155
+ /**
156
+ * Get the customer for the given ID
157
+ *
158
+ * @since 2.0.0
159
+ * @param int $id the customer ID
160
+ * @param array $fields
161
+ * @return array
162
+ */
163
+ public function get_customer( $id, $fields = null ) {
164
+ global $wpdb;
165
+
166
+ $customer = new WP_User( $id );
167
+
168
+ $customer_data = [
169
+ 'ref_id' => $customer->ID,
170
+ 'email' => $customer->user_email,
171
+ 'first_name' => $customer->first_name,
172
+ 'last_name' => $customer->last_name,
173
+ 'signed_up_at' => beeketing_format_datetime( $customer->user_registered, true ),
174
+ 'address1' => $customer->billing_address_1,
175
+ 'address2' => $customer->billing_address_2,
176
+ 'city' => $customer->billing_city,
177
+ 'company' => $customer->billing_company,
178
+ 'province' => $customer->billing_state,
179
+ 'zip' => $customer->billing_postcode,
180
+ 'country' => $customer->billing_country,
181
+ ];
182
+ return array( 'customer' => $customer_data );
183
+ }
184
+
185
+ }
lib/BeeketingSDK/Api/BeeketingOrders.php ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class BeeketingSDK_Api_BeeketingOrders.
5
+ *
6
+ * @class BeeketingSDK_Api_BeeketingOrders
7
+ * @version 1.0.0
8
+ * @author Beeketing
9
+ */
10
+ class BeeketingSDK_Api_BeeketingOrders
11
+ {
12
+ /**
13
+ * Constructor.
14
+ *
15
+ * @since 2.0.0
16
+ */
17
+ public function __construct()
18
+ {
19
+ // Save user token on checkout
20
+ add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'order_save_user_token' ), 10, 2 );
21
+
22
+ // Check product stock, if empty update product
23
+ add_action( 'woocommerce_reduce_order_stock', array( $this, 'update_products_in_order' ), 10, 1 );
24
+
25
+ }
26
+
27
+ /**
28
+ * Processes order queue.
29
+ *
30
+ * Process the orders that are in the queue.
31
+ *
32
+ * @since 2.0.0
33
+ */
34
+ public function process_queue() {
35
+
36
+ $queue = get_option( '_beeketing_queue', array() );
37
+
38
+ // Process products
39
+ if ( isset( $queue['orders'] ) && is_array( $queue['orders'] ) ) {
40
+ foreach ( array_slice( $queue['orders'], 0, 225, true ) as $key => $order ) {
41
+
42
+ if ( 'add' == $order['action'] ) {
43
+ $response = $this->add_order_to_beeketing( $order['id'] );
44
+ }
45
+
46
+ if ( isset( $response ) && ! is_wp_error( $response ) && in_array( $response['response']['code'], array( '200', '201', '204', '400', '404' ) ) ) { // Unset from queue when appropiate
47
+ unset( $queue['products'][ $key ] );
48
+ }
49
+
50
+ }
51
+ }
52
+
53
+ update_option( '_beeketing_queue', $queue );
54
+
55
+ }
56
+
57
+
58
+ /**
59
+ * Save user token.
60
+ *
61
+ * Save the user token from the beeketing cookie at checkout.
62
+ * After save it will immediately be deleted. When deleted it will
63
+ * automatically re-generate a new one to track the new purchase flow.
64
+ *
65
+ * @since 2.0.0
66
+ *
67
+ * @param int $order_id ID of the order that is being processed.
68
+ * @param array $posted List of $_POST values.
69
+ */
70
+ public function order_save_user_token( $order_id, $posted )
71
+ {
72
+ if ( isset( $_COOKIE['beeketing-cart-token'] ) ) {
73
+ update_post_meta( $order_id, '_beeketing_cart_token', $_COOKIE['beeketing-cart-token'] );
74
+ // Delete cart token
75
+ setcookie( 'beeketing-cart-token', '', time() - BeeketingSDK_Api_BeeketingApi::CART_TOKEN_LIFE_TIME + 1, '/' );
76
+ }
77
+
78
+ $this->add_order_to_beeketing( $order_id );
79
+ }
80
+
81
+ /**
82
+ * Update order
83
+ *
84
+ * @since 2.0.0
85
+ * @param $order_id
86
+ * @return mixed
87
+ */
88
+ public function add_order_to_beeketing( $order_id )
89
+ {
90
+ $order_data = $this->get_formatted_order( $order_id );
91
+
92
+ $response = BeeketingWooCommerce()->api->apiPost( 'orders/create_update', $order_data['order'] );
93
+
94
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
95
+ $queue = get_option( '_beeketing_queue', array() );
96
+ $queue['orders'][ $order_id ] = array( 'id' => $order_id, 'action' => 'add' );
97
+ update_option( '_beeketing_queue', $queue );
98
+ } elseif ( in_array( $response['response']['code'], array( '200', '201' ) ) ) {
99
+ update_post_meta( $order_id, '_beeketing_last_update', time() );
100
+ }
101
+
102
+ return $response;
103
+ }
104
+
105
+
106
+ /**
107
+ * Update products.
108
+ *
109
+ * Maybe send a update to Beeketing. Check if the product is stock-managed,
110
+ * when it is, a update will be send to Beeketing to make sure the product
111
+ * is up to date.
112
+ *
113
+ * @since 2.0.0
114
+ *
115
+ * @param WC_Order $order Order object.
116
+ */
117
+ public function update_products_in_order( $order )
118
+ {
119
+ foreach ( $order->get_items() as $item ) {
120
+
121
+ if ( $item['product_id'] > 0 ) {
122
+ $_product = $order->get_product_from_item( $item );
123
+
124
+ if ( $_product && $_product->exists() && $_product->managing_stock() ) {
125
+ // Sync this product
126
+ BeeketingWooCommerce()->products->update_product_to_beeketing( $_product->id );
127
+
128
+ }
129
+
130
+ }
131
+
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Get all orders
137
+ *
138
+ * @since 2.0.0
139
+ * @param string $fields
140
+ * @param array $filter
141
+ * @param string $status
142
+ * @param int $page
143
+ * @return array
144
+ */
145
+ public function get_orders( $fields = null, $filter = array(), $status = null, $page = 1 ) {
146
+ if ( ! empty( $status ) ) {
147
+ $filter['status'] = $status;
148
+ }
149
+ $filter['page'] = $page;
150
+ $query = beeketing_query_orders( $filter );
151
+ $orders = array();
152
+ foreach ( $query->posts as $order_id ) {
153
+
154
+ $orders[] = $this->get_formatted_order( $order_id, $fields, $filter );
155
+ }
156
+
157
+ return array( 'orders' => $orders );
158
+ }
159
+
160
+ /**
161
+ * Get the order for the given ID
162
+ *
163
+ * @since 2.0.0
164
+ * @param int $id the order ID
165
+ * @param array $fields
166
+ * @param array $filter
167
+ * @return array
168
+ */
169
+ public function get_formatted_order( $id, $fields = null, $filter = array() )
170
+ {
171
+ // Get the decimal precession
172
+ $dp = ( isset( $filter['dp'] ) ? intval( $filter['dp'] ) : 2 );
173
+ $order = wc_get_order( $id );
174
+ $order_data = [
175
+ 'ref_id' => $order->id,
176
+ 'contact_ref_id' => $order->get_user_id(),
177
+ 'financial_status' => $order->get_status(),
178
+ 'line_items' => [],
179
+ 'cart_token' => get_post_meta( $id, '_beeketing_cart_token', true ),
180
+ 'total_price' => $order->get_total(),
181
+ 'subtotal_price' => $order->get_subtotal()
182
+ ];
183
+
184
+ // add line items
185
+ foreach ( $order->get_items() as $item_id => $item ) {
186
+ $product = $order->get_product_from_item( $item );
187
+ $product_id = null;
188
+ $product_sku = null;
189
+ // Check if the product exists.
190
+ if ( is_object( $product ) ) {
191
+ $product_sku = $product->get_sku();
192
+ }
193
+
194
+
195
+ $order_data['line_items'][] = [
196
+ 'ref_id' => $item_id,
197
+ 'price' => wc_format_decimal( $order->get_item_total( $item, false, false ), $dp ),
198
+ 'sku' => $product_sku,
199
+ 'product_ref_id' => $product->id,
200
+ 'variant_id' => ( isset( $product->variation_id ) ) ? $product->variation_id : null,
201
+ 'fulfillable_quantity' => wc_stock_amount( $item['qty'] ),
202
+ ];
203
+ }
204
+
205
+ return array( 'order' => $order_data );
206
+ }
207
+ }
lib/BeeketingSDK/Api/BeeketingProducts.php ADDED
@@ -0,0 +1,727 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class BeeketingSDK_Api_BeeketingProducts.
4
+ *
5
+ * @class BeeketingSDK_Api_BeeketingProducts
6
+ * @version 1.0.0
7
+ * @author Beeketing
8
+ */
9
+ class BeeketingSDK_Api_BeeketingProducts
10
+ {
11
+ /**
12
+ * Constructor.
13
+ *
14
+ * @since 2.0.0
15
+ */
16
+ public function __construct() {
17
+
18
+ // Create/Update product
19
+ add_action( 'save_post', array( $this, 'add_product_to_beeketing' ), 20 );
20
+
21
+ // Trash product
22
+ add_action( 'trash_product', array( $this, 'delete_product_from_beeketing' ), 10, 2 );
23
+
24
+ // Recover product
25
+ add_action( 'untrashed_post', array( $this, 'beeketing_recover_product' ) );
26
+ }
27
+
28
+ /**
29
+ * Add / Edit variation
30
+ *
31
+ * @since 2.0.0
32
+ * @param $post_id
33
+ * @param $data
34
+ * @return bool
35
+ */
36
+ public function beeketing_add_variation( $post_id, $data )
37
+ {
38
+ return beeketing_save_variations( $post_id, $data );
39
+ }
40
+
41
+ /**
42
+ * Delete variants
43
+ *
44
+ * @param $variation_id
45
+ * @return bool
46
+ */
47
+ public function beeketing_remove_variation( $variation_id )
48
+ {
49
+ $variation = get_post( $variation_id );
50
+
51
+ if ( !$variation ) {
52
+ return [
53
+ 'success' => false,
54
+ 'message' => 'Variant not found',
55
+ ];
56
+ }
57
+
58
+ if ( 'product_variation' == $variation->post_type ) {
59
+ wp_delete_post( $variation_id );
60
+ } else {
61
+ return [
62
+ 'success' => false,
63
+ 'message' => 'Invalid product type',
64
+ ];
65
+ }
66
+
67
+ return [
68
+ 'success' => true,
69
+ ];
70
+ }
71
+
72
+
73
+ /**
74
+ * Create variation product for given item.
75
+ *
76
+ * @since 2.0.0
77
+ * @access public
78
+ *
79
+ * @param integer $product_id Product to create variation of
80
+ *
81
+ * @param $data
82
+ * @return int Product variation id
83
+ */
84
+ public function create_gift_variation( $product_id, $data )
85
+ {
86
+ if ( ! isset( $data[ 'option1' ] ) ) {
87
+ return [
88
+ 'success' => false,
89
+ 'message' => 'Option1 is required',
90
+ ];
91
+ }
92
+
93
+ $product_data = $this->get_formatted_product( $product_id );
94
+ if ( !$product_data ) {
95
+ return [
96
+ 'success' => false,
97
+ 'message' => 'Product not found',
98
+ ];
99
+ }
100
+
101
+ foreach ( $product_data['variants'] as $variant ) {
102
+ if ( $variant['option1'] == $data['option1'] ) {
103
+ return [
104
+ 'success' => false,
105
+ 'message' => 'Variant existed',
106
+ ];
107
+ }
108
+ }
109
+ //if product variation doesn't exist, add one
110
+ $admin = get_users( 'orderby=nicename&role=administrator&number=1' );
111
+ $variation = array(
112
+ 'post_author' => $admin[0]->ID,
113
+ 'post_status' => 'publish',
114
+ 'post_name' => 'product-' . $product_id . '-variation',
115
+ 'post_parent' => $product_id,
116
+ 'post_title' => isset($data['title']) ? $data['title']: '',
117
+ 'post_type' => 'product_variation',
118
+ 'comment_status' => 'closed',
119
+ 'ping_status' => 'closed',
120
+ );
121
+ $post_id = wp_insert_post( $variation );
122
+ if ( isset( $data['price'] ) ) {
123
+ update_post_meta( $post_id, '_price', $data['price'] );
124
+ update_post_meta( $post_id, '_regular_price', $data['price'] );
125
+ }
126
+ if ( isset( $data['option1'] ) ) {
127
+ update_post_meta( $post_id, '_bk_option1', $data['option1'] );
128
+ }
129
+ if ( isset( $data['sku'] ) ) {
130
+ update_post_meta( $post_id, '_sku', $data['sku'] );
131
+ }
132
+ if ( isset( $data['attributes'] ) ) {
133
+ foreach ( $data['attributes'] as $attribute ) {
134
+ update_post_meta( $post_id, 'attribute_' . sanitize_title( $attribute['name'] ), $attribute['option'] );
135
+ }
136
+ }
137
+
138
+ update_post_meta( $post_id, '_beeketing_product_variation', 1 );
139
+
140
+ $product_variation = get_post( $post_id );
141
+
142
+ return [
143
+ 'success' => true,
144
+ 'data' => $this->get_variant_data( $product_variation, $product_id ),
145
+ ];
146
+ }
147
+
148
+ /**
149
+ * Update variation
150
+ *
151
+ * @since 2.0.0
152
+ * @param $variation_id
153
+ * @param $data
154
+ * @return array|bool
155
+ */
156
+ public function update_variation( $variation_id, $data )
157
+ {
158
+ $product_variation = get_post( $variation_id );
159
+
160
+ if ( ! $product_variation ) {
161
+ return [
162
+ 'success' => false,
163
+ 'message' => 'Variation not found',
164
+ ];
165
+ }
166
+
167
+ if ( isset( $data['price'] ) ) {
168
+ update_post_meta( $variation_id, '_price', $data['price'] );
169
+ update_post_meta( $variation_id, '_regular_price', $data['price'] );
170
+ }
171
+ if ( isset( $data['option1'] ) ) {
172
+ update_post_meta( $variation_id, '_bk_option1', $data['option1'] );
173
+ }
174
+ if ( isset( $data['sku'] ) ) {
175
+ update_post_meta( $variation_id, '_sku', $data['sku'] );
176
+ }
177
+ if ( isset( $data['attributes'] ) ) {
178
+ foreach ( $data['attributes'] as $attribute ) {
179
+ update_post_meta( $variation_id, 'attribute_' . sanitize_title( $attribute['name'] ), $attribute['option'] );
180
+ }
181
+ }
182
+
183
+ update_post_meta( $variation_id, '_beeketing_product_variation', 1 );
184
+
185
+ return [
186
+ 'success' => true,
187
+ 'data' => $this->get_variant_data( get_post( $variation_id ) ),
188
+ ];
189
+ }
190
+
191
+ /**
192
+ * Get variantion data
193
+ *
194
+ * @since 2.0.0
195
+ * @param $variation
196
+ * @param $product_id
197
+ * @return array
198
+ */
199
+ public function get_variant_data( $variation, $product_id = null )
200
+ {
201
+ $product_variation = wc_get_product( $variation->ID );
202
+ $variation_array = [
203
+ 'ref_id' => $variation->ID,
204
+ 'image' => beeketing_get_product_images( $product_variation )[0]['src'],
205
+ 'title' => $variation->post_title,
206
+ 'option1' => get_post_meta( $variation->ID, '_bk_option1', true ),
207
+ 'product_ref_id' => $product_id ? $product_id : $product_variation->id,
208
+ 'price' => $product_variation->get_price(),
209
+ 'price_compare' => $product_variation->get_sale_price() ? $product_variation->get_sale_price() : null,
210
+ 'sku' => $product_variation->get_sku(),
211
+ 'inventory_management' => $product_variation->managing_stock() ? 'yes' : 'no',
212
+ 'inventory_quantity' => $product_variation->get_stock_quantity(),
213
+ 'in_stock' => $product_variation->is_in_stock(),
214
+ 'weight' => $product_variation->get_weight() ? $product_variation->get_weight() : null,
215
+ 'taxable' => $product_variation->is_taxable(),
216
+ 'visible' => $product_variation->variation_is_visible(),
217
+ 'attributes' => beeketing_product_get_attributes( $product_variation ),
218
+ 'updated' => beeketing_format_datetime( $variation->post_modified_gmt ),
219
+ 'created' => beeketing_format_datetime( $variation->post_date_gmt ),
220
+ ];
221
+
222
+ return $variation_array;
223
+ }
224
+
225
+ /**
226
+ * Fetch gift items added to the cart.
227
+ *
228
+ * @since 2.0.0
229
+ * @access public
230
+ *
231
+ * @return array<String> Gift items in cart
232
+ */
233
+ public function get_gift_products_in_cart()
234
+ {
235
+ $free_items = array();
236
+ $cart_items = WC()->cart->cart_contents;
237
+ if( empty($cart_items) ) {
238
+ return $free_items;
239
+ }
240
+ foreach( $cart_items as $key => $content ) {
241
+ $is_gift_product = ! empty( $content['variation_id'] ) && (bool) get_post_meta( $content['variation_id'], '_beeketing_gift_product' );
242
+ if( $is_gift_product ) {
243
+ $free_items[] = $content['product_id'];
244
+ }
245
+ }
246
+ return $free_items;
247
+ }
248
+
249
+ /**
250
+ * Add new product to Beeketing
251
+ *
252
+ * @since 2.0.0
253
+ * @param $post_id
254
+ * @param bool $is_syncing
255
+ * @return bool
256
+ */
257
+ public function add_product_to_beeketing( $post_id, $is_syncing = false )
258
+ {
259
+ // Bail if its not a product / if its trashed
260
+ if ( 'product' !== get_post_type( $post_id ) || in_array( get_post_status( $post_id ), ['trash', 'auto-draft'] ) ) {
261
+ return false;
262
+ }
263
+ $product = wc_get_product( $post_id );
264
+
265
+ if ( $product->is_type( 'grouped' ) ) {
266
+ return false;
267
+ }
268
+
269
+ if ( !$is_syncing ) {
270
+
271
+ if ( $product->is_type( 'simple' ) ) {
272
+ $queue = get_option( '_beeketing_queue', array() );
273
+ $queue['products'][ $post_id ] = array( 'id' => $post_id, 'action' => 'add' );
274
+ return true;
275
+ }
276
+ }
277
+
278
+ $args = $this->get_formatted_product( $post_id, $is_syncing );
279
+
280
+ $response = BeeketingWooCommerce()->api->apiPost( 'products/create_update', $args['product'] );
281
+
282
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
283
+ $queue = get_option( '_beeketing_queue', array() );
284
+ $queue['products'][ $post_id ] = array( 'id' => $post_id, 'action' => 'add' );
285
+ update_option( '_beeketing_queue', $queue );
286
+ } elseif (in_array( $response['response']['code'], array( '200', '201' ))) {
287
+ update_post_meta( $post_id, '_beeketing_last_update', time() );
288
+ }
289
+
290
+ return $response;
291
+ }
292
+
293
+ /**
294
+ * Update product.
295
+ *
296
+ * Update a product when its being saved/published. When a download gets
297
+ * updated, the data will be send to Beeketing to keep the data synced.
298
+ *
299
+ * @since 2.0.0
300
+ *
301
+ * @param int $post_id ID of the post currently being saved.
302
+ * @return array|WP_Error Returns the API response, or WP_Error when API call fails.
303
+ */
304
+ public function update_product_to_beeketing( $post_id ) {
305
+
306
+ // Bail if its not a product / if its trashed
307
+ if ( 'product' !== get_post_type( $post_id ) || in_array( get_post_status( $post_id ), ['trash', 'auto-draft'] ) ) {
308
+ return;
309
+ }
310
+
311
+ $args = $this->get_formatted_product( $post_id );
312
+
313
+ $response = BeeketingWooCommerce()->api->apiPost( 'products/create_update', $args['product'] );
314
+
315
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
316
+ $queue = get_option( '_beeketing_queue', array() );
317
+ $queue['products'][ $post_id ] = array( 'id' => $post_id, 'action' => 'update' );
318
+ update_option( '_beeketing_queue', $queue );
319
+ } elseif (in_array( $response['response']['code'], array( '200', '201' ))) {
320
+ update_post_meta( $post_id, '_beeketing_last_update', time() );
321
+ }
322
+
323
+ return $response;
324
+
325
+ }
326
+
327
+ /**
328
+ * Get all products
329
+ *
330
+ * @since 2.0.0
331
+ * @param string $fields
332
+ * @param string $type
333
+ * @param array $filter
334
+ * @param int $page
335
+ * @return array
336
+ */
337
+ public function get_products( $fields = null, $type = null, $filter = array(), $page = 1 ) {
338
+ if ( ! empty( $type ) ) {
339
+ $filter['type'] = $type;
340
+ }
341
+
342
+ if ( isset( $filter['limit'] ) ) {
343
+ $filter['posts_per_page'] = $filter['limit'];
344
+ unset( $filter['limit'] );
345
+ }
346
+
347
+ if ( isset( $filter['title'] ) ) {
348
+ $filter['search_prod_title'] = $filter['title'];
349
+ unset( $filter['title'] );
350
+ }
351
+
352
+ $query = beeketing_query_products( $filter );
353
+ $products = array();
354
+ foreach ( $query->posts as $product_id ) {
355
+ $product = $this->get_formatted_product( $product_id );
356
+ if ( ! isset( $product['product'] ) ) {
357
+ continue;
358
+ }
359
+ $products[] = $product['product'];
360
+ }
361
+ return array( 'products' => $products );
362
+ }
363
+
364
+ /**
365
+ * Get the product for the given ID
366
+ *
367
+ * @since 2.0.0
368
+ * @param int $id the product ID
369
+ * @param $is_syncing
370
+ * @return array
371
+ */
372
+ public function get_formatted_product( $id, $is_syncing = false ) {
373
+
374
+ $product = wc_get_product( $id );
375
+ if ( ! $product ) {
376
+ return false;
377
+ }
378
+ // add data that applies to every product type
379
+ $product_data = $this->get_product_data( $product );
380
+
381
+ if ( $product->is_type( 'simple' ) ) {
382
+ $product_data['variants'] = $this->get_simple_product_variations( $id, $product_data, $is_syncing );
383
+ }
384
+ // add variations to variable products
385
+ if ( $product->is_type( 'variable' ) && $product->has_child() ) {
386
+ $product_data['variants'] = $this->get_variation_data( $product );
387
+ }
388
+ // Add grouped products data
389
+ if ( $product->is_type( 'grouped' ) && $product->has_child() ) {
390
+ $product_data['grouped_products'] = $this->get_grouped_products_data( $product );
391
+ }
392
+ return array( 'product' => $product_data );
393
+ }
394
+
395
+
396
+ /**
397
+ * Formatted categories.
398
+ *
399
+ * Get the formatted categories array. The return values
400
+ * will be according the Beeketing API endpoint specs.
401
+ *
402
+ * @since 2.0.0
403
+ *
404
+ * @param int $product_id ID of the product currently processing.
405
+ * @return array List of product categories formatted according Beeketing specs.
406
+ */
407
+ public function get_formatted_categories( $product_id ) {
408
+
409
+ $categories = array();
410
+ $product_cats = wp_get_post_terms( $product_id, 'product_cat' );
411
+
412
+ if ( $product_cats ) {
413
+ foreach ( $product_cats as $category ) {
414
+ $categories[] = array(
415
+ 'category_id' => (string) $category->term_id,
416
+ 'title' => $category->name,
417
+ 'description' => $category->description,
418
+ 'url' => get_term_link( $category->term_id, 'product_cat' ),
419
+ );
420
+ }
421
+ }
422
+
423
+ return $categories;
424
+
425
+ }
426
+
427
+
428
+ /**
429
+ * Formatted variants.
430
+ *
431
+ * Get the formatted variants array.
432
+ * are the prices.
433
+ *
434
+ * @since 2.0.0
435
+ *
436
+ * @param int $product_id ID of the product currently processing.
437
+ * @return array
438
+ */
439
+ public function get_formatted_variants( $product_id ) {
440
+
441
+ $variants = array();
442
+ $product = wc_get_product( $product_id );
443
+
444
+ if ( 'variable' == $product->product_type ) {
445
+
446
+ foreach ( $product->get_available_variations() as $key => $variation ) {
447
+
448
+ if ( ! $variation['is_purchasable'] ) {
449
+ continue;
450
+ }
451
+
452
+ $variants[] = array(
453
+ 'price' => (float) number_format( (float) $variation['display_price'], 2, '.', '' ),
454
+ );
455
+
456
+ }
457
+
458
+ } elseif ( null != $product->get_price() ) {
459
+ $variants[] = array(
460
+ 'price' => (float) number_format( (float) $product->get_price(), 2, '.', '' ),
461
+ );
462
+ }
463
+
464
+ return $variants;
465
+
466
+ }
467
+
468
+
469
+ /**
470
+ * Delete product.
471
+ *
472
+ * Delete the product from Beeketing when its deleted in the shop.
473
+ *
474
+ * @since 2.0.0
475
+ *
476
+ * @param int $post_id ID of the post (product) currently being deleted.
477
+ * @param WP_Post $post WP_Post object containing post data.
478
+ * @return array|WP_Error Returns the API response, or WP_Error when API call fails.
479
+ */
480
+ public function delete_product_from_beeketing( $post_id, $post = '' ) {
481
+
482
+ // Bail if its not a product
483
+ if ( 'product' !== get_post_type( $post_id ) ) {
484
+ return;
485
+ }
486
+
487
+ $response = BeeketingWooCommerce()->api->apiDelete( 'products/' . $post_id );
488
+
489
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
490
+ $queue = get_option( '_beeketing_queue', array() );
491
+ $queue['products'][ $post_id ] = array( 'id' => $post_id, 'action' => 'delete' );
492
+ update_option( '_beeketing_queue', $queue );
493
+ }
494
+
495
+ return $response;
496
+
497
+ }
498
+
499
+ /**
500
+ * Recover product
501
+ *
502
+ * @since 2.0.0
503
+ * @param $post_id
504
+ * @return bool
505
+ */
506
+ public function beeketing_recover_product( $post_id ) {
507
+ // Bail if its not a product
508
+ if ( 'product' !== get_post_type( $post_id ) ) {
509
+ return false;
510
+ }
511
+
512
+ $args = $this->get_formatted_product( $post_id );
513
+
514
+ $args['product']['deleted'] = false;
515
+
516
+ $response = BeeketingWooCommerce()->api->apiPost( 'products/create_update', $args['product'] );
517
+
518
+ if ( is_wp_error( $response ) || in_array( $response['response']['code'], array( '401', '500', '503' ) ) ) {
519
+ $queue = get_option( '_beeketing_queue', array() );
520
+ $queue['products'][ $post_id ] = array('id' => $post_id, 'action' => 'recover');
521
+ update_option('_beeketing_queue', $queue);
522
+ } elseif ( in_array( $response['response']['code'], array( '200', '201' ) ) ) {
523
+ update_post_meta( $post_id, '_beeketing_last_update', time() );
524
+ }
525
+
526
+ return $response;
527
+ }
528
+
529
+
530
+ /**
531
+ * Processes product queue.
532
+ *
533
+ * Process the producs that are in the queue.
534
+ *
535
+ * @since 2.0.0
536
+ */
537
+ public function process_queue() {
538
+
539
+ $queue = get_option( '_beeketing_queue', array() );
540
+
541
+ // Process products
542
+ if ( isset( $queue['products'] ) && is_array( $queue['products'] ) ) {
543
+ foreach ( array_slice( $queue['products'], 0, 225, true ) as $key => $product ) {
544
+
545
+ if ( 'delete' == $product['action'] ) {
546
+ $response = $this->delete_product_from_beeketing( $product['id'] );
547
+ } elseif ( 'add' == $product['action'] ) {
548
+ $response = $this->add_product_to_beeketing( $product['id'], true );
549
+ } elseif ( 'add_variant' == $product['action'] ) {
550
+ $wc_product = wc_get_product( $product['id'] );
551
+ $this->create_gift_variation( $product['id'], [
552
+ 'price' => $wc_product->get_price(),
553
+ 'title' => $wc_product->get_title() . ' (BK Variation)',
554
+ 'option1' => $wc_product->get_title() . ' (BK Variation)',
555
+ ]);
556
+
557
+ $response = $this->update_product_to_beeketing( $product['id'] );
558
+ } elseif ( 'recover' == $product['action'] ) {
559
+ $response = $this->beeketing_recover_product( $product['id'] );
560
+ } else {
561
+ $response = $this->update_product_to_beeketing( $product['id'] );
562
+ }
563
+
564
+ if ( ! is_wp_error( $response ) && in_array( $response['response']['code'], array( '200', '201', '204', '400', '404' ) ) ) { // Unset from queue when appropiate
565
+ unset( $queue['products'][ $key ] );
566
+ }
567
+
568
+ }
569
+ }
570
+
571
+ update_option( '_beeketing_queue', $queue );
572
+
573
+ }
574
+
575
+ /**
576
+ * Get standard product data that applies to every product type
577
+ *
578
+ * @since 2.0.0
579
+ * @param WC_Product $product
580
+ * @return WC_Product
581
+ */
582
+ private function get_product_data( $product ) {
583
+ $tags = wp_get_post_terms( $product->id, 'product_tag', array( 'fields' => 'names' ) );
584
+ return [
585
+ 'handle' => $product->get_permalink(),
586
+ 'title' => $product->get_title(),
587
+ 'type' => $product->product_type,
588
+ 'ref_id' => (int) $product->is_type( 'variation' ) ? $product->get_variation_id() : $product->id,
589
+ 'vendor' => '',
590
+ 'published_at' => $product->is_visible() ? beeketing_format_datetime( $product->get_post_data()->post_date_gmt ): null,
591
+ 'out_stock' => !$product->is_in_stock(),
592
+ 'image_source_url' => beeketing_get_product_images( $product )[0]['src'],
593
+ 'price' => $product->get_price(),
594
+ 'price_compare' => $product->get_sale_price() ? $product->get_sale_price() : null,
595
+ 'tags' => $tags ? implode( ', ', $tags ) : null,
596
+ 'variants' => [],
597
+ ];
598
+ }
599
+
600
+ /**
601
+ * Get grouped products data
602
+ *
603
+ * @since 2.0.0
604
+ * @param WC_Product $product
605
+ *
606
+ * @return array
607
+ */
608
+ private function get_grouped_products_data( $product ) {
609
+ $products = array();
610
+ foreach ( $product->get_children() as $child_id ) {
611
+ $_product = $product->get_child( $child_id );
612
+ if ( ! $_product->exists() ) {
613
+ continue;
614
+ }
615
+ $products[] = $this->get_product_data( $_product );
616
+ }
617
+ return $products;
618
+ }
619
+
620
+ /**
621
+ * Get simple product variations
622
+ *
623
+ * @since 2.0.0
624
+ * @param $product_id
625
+ * @param $product_data
626
+ * @param bool $is_syncing
627
+ * @return array
628
+ */
629
+ private function get_simple_product_variations( $product_id, $product_data, $is_syncing = false )
630
+ {
631
+ $args = array(
632
+ 'post_parent' => $product_id,
633
+ 'post_type' => 'product_variation',
634
+ 'orderby' => 'menu_order',
635
+ 'order' => 'ASC',
636
+ 'fields' => 'ids',
637
+ 'post_status' => 'publish',
638
+ 'numberposts' => -1
639
+ );
640
+
641
+ $variation_ids = get_posts( $args );
642
+ $variations = [];
643
+
644
+ $product = wc_get_product( $product_id );
645
+
646
+ $variations[] = $this->get_formatted_variant( $product, $product );
647
+
648
+ foreach ( $variation_ids as $variation_id ) {
649
+ $variation = wc_get_product( $variation_id );
650
+
651
+ if ( ! $variation->exists() ) {
652
+ continue;
653
+ }
654
+ $variations[] = $this->get_formatted_variant( $variation, $product );
655
+ }
656
+
657
+ return $variations;
658
+ }
659
+
660
+ /**
661
+ * Get an individual variation's data
662
+ *
663
+ * @since 2.0.0
664
+ * @param WC_Product $product
665
+ * @return array
666
+ */
667
+ private function get_variation_data( $product ) {
668
+ $variations = array();
669
+ $args = array(
670
+ 'post_parent' => $product->id,
671
+ 'post_type' => 'product_variation',
672
+ 'orderby' => 'menu_order',
673
+ 'order' => 'ASC',
674
+ 'fields' => 'ids',
675
+ 'post_status' => 'publish',
676
+ 'numberposts' => -1
677
+ );
678
+
679
+ $variation_ids = get_posts( $args );
680
+
681
+ foreach ( $variation_ids as $child_id ) {
682
+ $variation = $product->get_child( $child_id );
683
+ if ( ! $variation->exists() ) {
684
+ continue;
685
+ }
686
+
687
+ $variations[] = $this->get_formatted_variant( $variation, $product );
688
+ }
689
+ return $variations;
690
+ }
691
+
692
+
693
+ /**
694
+ * Get formatted variant
695
+ *
696
+ * @since 2.0.0
697
+ * @param $variation
698
+ * @param $product
699
+ * @return array
700
+ */
701
+ public function get_formatted_variant( $variation, $product )
702
+ {
703
+ $variation_id = $variation->is_type( 'variation' ) ? $variation->get_variation_id() : $variation->id;
704
+ $option_1 = get_post_meta( $variation_id, '_bk_option1', true );
705
+ $data = [
706
+ 'ref_id' => $variation_id,
707
+ 'image' => beeketing_get_product_images( $variation )[0]['src'],
708
+ 'title' => $variation->get_title(),
709
+ 'option1' => $option_1 ? $option_1 : $variation->get_title(),
710
+ 'product_ref_id' => (int) $product->is_type( 'variation' ) ? $product->get_variation_id() : $product->id,
711
+ 'price' => $variation->get_price(),
712
+ 'price_compare' => $variation->get_sale_price() ? $variation->get_sale_price() : null,
713
+ 'sku' => $variation->get_sku(),
714
+ 'inventory_management' => $variation->managing_stock() ? 'yes' : 'no',
715
+ 'inventory_quantity' => $variation->get_stock_quantity(),
716
+ 'in_stock' => $variation->is_in_stock(),
717
+ 'weight' => $variation->get_weight() ? $variation->get_weight() : null,
718
+ 'taxable' => $variation->is_taxable(),
719
+ 'visible' => $variation->is_type( 'variation' ) ? $variation->variation_is_visible() : $variation->is_visible(),
720
+ 'attributes' => beeketing_product_get_attributes( $variation ),
721
+ 'updated' => beeketing_format_datetime( $variation->get_post_data()->post_modified_gmt ),
722
+ 'created' => beeketing_format_datetime( $variation->get_post_data()->post_date_gmt ),
723
+ ];
724
+
725
+ return $data;
726
+ }
727
+ }
lib/BeeketingSDK/Api/BeeketingShop.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class BeeketingSDK_Api_BeeketingShop.
5
+ *
6
+ * @class BeeketingSDK_Api_BeeketingShop
7
+ * @version 1.0.0
8
+ * @author Beeketing
9
+ */
10
+ class BeeketingSDK_Api_BeeketingShop
11
+ {
12
+ /**
13
+ * Constructor.
14
+ *
15
+ * @since 2.0.0
16
+ */
17
+ public function __construct()
18
+ {
19
+
20
+ add_action( 'init', array( $this, 'init_shop_info' ) );
21
+ }
22
+
23
+ /**
24
+ * Update shop info to beeketing
25
+ *
26
+ * @since 2.0.0
27
+ */
28
+ public function update_shop_info_to_beeketing()
29
+ {
30
+ $formattedPrice = wc_price( 11.11 );
31
+ $formattedPrice = str_replace( '11.11', '{{amount}}', $formattedPrice );
32
+
33
+ $args = [
34
+ 'absolute_path' => get_site_url(),
35
+ 'currency_format' => $formattedPrice,
36
+ 'currency' => get_woocommerce_currency(),
37
+ ];
38
+
39
+ $response = BeeketingWooCommerce()->api->apiPut( 'shops', $args );
40
+
41
+ return $response;
42
+ }
43
+
44
+ /**
45
+ * Init shop info
46
+ *
47
+ * @since 2.0.0
48
+ */
49
+ public function init_shop_info()
50
+ {
51
+ // Update shop domain
52
+ if ( get_option( 'beeketing_completed_update_shop_info', 0 ) != 1 ) {
53
+
54
+ $response = $this->update_shop_info_to_beeketing();
55
+ if ( in_array( $response['response']['code'], array( '200', '201' ) ) ) {
56
+ update_option( 'beeketing_completed_update_shop_info', 1 );
57
+ }
58
+ }
59
+ }
60
+ }
lib/BeeketingSDK/Config/BeeketingConfig.php ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class BeeketingSDK_Config_BeeketingConfig.
5
+ *
6
+ * Config beeketing plugin
7
+ *
8
+ * @class BeeketingSDK_Config_BeeketingConfig
9
+ * @version 1.0.0
10
+ * @author Beeketing
11
+ * @since 1.0.0
12
+ */
13
+
14
+ class BeeketingSDK_Config_BeeketingConfig
15
+ {
16
+ /**
17
+ * Beeketing format date
18
+ *
19
+ * @since 2.0.0
20
+ */
21
+ const BEEKETING_FORMAT_DATE = 'Y-m-d\TH:i:s\Z';
22
+
23
+ /**
24
+ * Type webhook
25
+ *
26
+ * @since 2.0.0
27
+ */
28
+ const SOURCE_TYPE_WEBHOOK = 'webhook';
29
+
30
+ /**
31
+ * Beeketing path
32
+ *
33
+ * @var string
34
+ * @since 1.0.0
35
+ */
36
+ protected $path;
37
+
38
+ /**
39
+ * Default config
40
+ *
41
+ * @var array
42
+ * @since 1.0.0
43
+ */
44
+ protected $defaultConfig = array(
45
+ 'BEEKETING_PROFILE_URL' => 'user/profile',
46
+ 'BEEKETING_GET_APPS_DATA_API' => 'get-apps-data-by-key/',
47
+ 'BEEKETING_CHECK_STATUS_KEY_API' => 'check-key-exists/',
48
+ 'BEEKETING_SIGN_IN_URL' => 'sign-in?platform='
49
+ );
50
+
51
+ /**
52
+ * @since 1.0.0
53
+ * @var string
54
+ */
55
+ protected $apiKey;
56
+
57
+ /**
58
+ * @since 1.0.0
59
+ * @var string
60
+ */
61
+ protected $env;
62
+
63
+ /**
64
+ * @since 1.0.0
65
+ * @var string
66
+ */
67
+ protected $platform;
68
+
69
+ /**
70
+ * Constructor
71
+ *
72
+ * @since 1.0.0
73
+ */
74
+ public function __construct()
75
+ {
76
+ $this->path = BEEKETING_PATH;
77
+ }
78
+
79
+ /**
80
+ * Set environment
81
+ *
82
+ * @since 1.0.0
83
+ * @param $env
84
+ * @return $this
85
+ * @throws Exception
86
+ */
87
+ public function setEnv( $env )
88
+ {
89
+ $this->env = $env;
90
+
91
+ return $this;
92
+ }
93
+
94
+ /**
95
+ * Get environment
96
+ *
97
+ * @since 1.0.0
98
+ * @return string
99
+ */
100
+ public function getEnv()
101
+ {
102
+ return $this->env;
103
+ }
104
+
105
+ /**
106
+ * Get api key
107
+ *
108
+ * @since 1.0.0
109
+ * @return string
110
+ */
111
+ public function getApiKey()
112
+ {
113
+ return $this->apiKey;
114
+ }
115
+
116
+ /**
117
+ * Set api key
118
+ *
119
+ * @since 1.0.0
120
+ * @param $apiKey
121
+ * @return $this
122
+ */
123
+ public function setApiKey( $apiKey )
124
+ {
125
+ $this->apiKey = $apiKey;
126
+
127
+ return $this;
128
+ }
129
+
130
+ /**
131
+ * Get platform
132
+ *
133
+ * @since 1.0.0
134
+ * @return string
135
+ */
136
+ public function getPlatform()
137
+ {
138
+ return $this->platform;
139
+ }
140
+
141
+ /**
142
+ * Set platform
143
+ *
144
+ * @since 1.0.0
145
+ * @param $platform
146
+ * @return $this
147
+ */
148
+ public function setPlatform( $platform )
149
+ {
150
+ $this->platform = $platform;
151
+
152
+ return $this;
153
+ }
154
+
155
+
156
+ /**
157
+ * Get config by name
158
+ *
159
+ * @since 1.0.0
160
+ * @param $name
161
+ * @return string|bool
162
+ */
163
+ public function getConfigByName( $name )
164
+ {
165
+ // If config not found.
166
+ if ( ! isset( $this->defaultConfig[ $name ] ) ) {
167
+ return false;
168
+ }
169
+
170
+ return $this->defaultConfig[ $name ];
171
+ }
172
+
173
+ /**
174
+ * Get profile url
175
+ *
176
+ * @since 1.0.0
177
+ * @return string
178
+ */
179
+ public function getProfileUrl()
180
+ {
181
+
182
+ return $this->path . $this->getConfigByName( 'BEEKETING_PROFILE_URL' );
183
+ }
184
+
185
+ /**
186
+ * Get sign in url
187
+ *
188
+ * @since 1.0.0
189
+ * @return string
190
+ */
191
+ public function getSignInUrl()
192
+ {
193
+ return $this->path . '/' . $this->getConfigByName( 'BEEKETING_SIGN_IN_URL' ) . $this->getPlatform();
194
+ }
195
+
196
+ /**
197
+ * Get apps data by domain from beeketing.
198
+ *
199
+ * @since 1.0.0
200
+ * @return array
201
+ */
202
+ public function getAppsDataByApiKey()
203
+ {
204
+ $platform = $this->getPlatform();
205
+ $apiKey = $this->getApiKey();
206
+
207
+ $data = @file_get_contents( $this->path . '/' . $this->getConfigByName( 'BEEKETING_GET_APPS_DATA_API' ) . $apiKey . '?platform=' . $platform );
208
+ $data = json_decode( $data, true ); // decode & convert to array
209
+
210
+ if ( json_last_error() === JSON_ERROR_NONE ) {
211
+ return $data;
212
+ }
213
+
214
+ return array();
215
+ }
216
+
217
+ /**
218
+ * Is api key exists?
219
+ *
220
+ * @since 1.0.0
221
+ * @param string
222
+ * @return bool
223
+ */
224
+ public function isApiKeyExists( $apiKey )
225
+ {
226
+ $platform = $this->getPlatform();
227
+
228
+ $data = @file_get_contents( $this->path . '/' . $this->getConfigByName( 'BEEKETING_CHECK_STATUS_KEY_API' ) . $apiKey . '?platform=' . $platform );
229
+ $data = json_decode( $data );
230
+
231
+ return ( isset( $data->status ) ) ? $data->status : false;
232
+ }
233
+
234
+ /**
235
+ * Get path
236
+ *
237
+ * @since 1.0.0
238
+ * @return string
239
+ */
240
+ public function getPath()
241
+ {
242
+ return $this->path;
243
+ }
244
+
245
+ /**
246
+ * Set path
247
+ *
248
+ * @since 1.0.0
249
+ * @param string $path
250
+ */
251
+ public function setPath( $path )
252
+ {
253
+ $this->path = $path;
254
+ }
255
+ }
lib/BeeketingSDK/Helper/beeketing-cron-functions.php ADDED
@@ -0,0 +1,400 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
+
4
+ /**
5
+ * CRONTABs
6
+ *
7
+ *
8
+ * @author Beeketing
9
+ *
10
+ */
11
+
12
+
13
+ if ( ! function_exists( 'beeketing_add_custom_schedules' ) ) {
14
+ /**
15
+ * Custom interval.
16
+ *
17
+ * Add custom interval to the cron schedules.
18
+ *
19
+ * @since 2.0.0
20
+ *
21
+ * @param array $schedules List of current CRON schedules.
22
+ * @return array List of modified CRON schedules.
23
+ */
24
+ function beeketing_add_custom_schedules( $schedules )
25
+ {
26
+ $schedules['quarter_hour'] = array(
27
+ 'interval' => 60 * 15, // 60 seconds * 15 minutes
28
+ 'display' => __( 'Every quarter', 'beeketing' ),
29
+ );
30
+
31
+ $schedules['beeketing_ten_minute'] = array(
32
+ 'interval' => 60 * 10,
33
+ 'display' => __( 'Every ten minute', 'beeketing' ),
34
+ );
35
+
36
+ return $schedules;
37
+
38
+ }
39
+ add_filter( 'cron_schedules', 'beeketing_add_custom_schedules' );
40
+ }
41
+
42
+ if ( ! function_exists( 'beeketing_schedule_events' ) ) {
43
+ /**
44
+ * Schedule events.
45
+ * @since 2.0.0
46
+ */
47
+ function beeketing_schedule_events()
48
+ {
49
+ // Retry queue
50
+ if ( ! wp_next_scheduled( 'beeketing_retry_queue' ) ) {
51
+ wp_schedule_event( BEEKETING_INITIAL_SYNC_TIME, 'beeketing_ten_minute', 'beeketing_retry_queue' );
52
+ }
53
+
54
+ // Initial product sync
55
+ if ( ! wp_next_scheduled( 'beeketing_initial_product_sync' ) && 1 != get_option( 'beeketing_completed_initial_product_sync', 0 ) ) {
56
+ wp_schedule_event( BEEKETING_INITIAL_SYNC_TIME, 'beeketing_ten_minute', 'beeketing_initial_product_sync' );
57
+ } elseif ( wp_next_scheduled( 'beeketing_initial_product_sync' ) && 1 == get_option( 'beeketing_completed_initial_product_sync', 0 ) ) {
58
+ // Remove CRON when we're done with it.
59
+ wp_clear_scheduled_hook( 'beeketing_initial_product_sync' );
60
+ }
61
+
62
+ // Initial order sync
63
+ if ( ! wp_next_scheduled( 'beeketing_initial_orders_sync' ) && 1 != get_option( 'beeketing_completed_initial_order_sync', 0 ) ) {
64
+ wp_schedule_event( BEEKETING_INITIAL_SYNC_TIME, 'beeketing_ten_minute', 'beeketing_initial_orders_sync' );
65
+ } elseif ( wp_next_scheduled( 'beeketing_initial_orders_sync' ) && 1 == get_option( 'beeketing_completed_initial_order_sync', 0 ) ) {
66
+ wp_clear_scheduled_hook( 'beeketing_initial_orders_sync' ); // Remove CRON when we're done with it.
67
+ }
68
+
69
+ // Initial collection sync
70
+ if ( ! wp_next_scheduled( 'beeketing_initial_collections_sync' ) && 1 != get_option( 'beeketing_completed_initial_collection_sync', 0 ) ) {
71
+ wp_schedule_event( BEEKETING_INITIAL_SYNC_TIME, 'beeketing_ten_minute', 'beeketing_initial_collections_sync' );
72
+ } elseif ( wp_next_scheduled( 'beeketing_initial_collections_sync' ) && 1 == get_option( 'beeketing_completed_initial_collection_sync', 0 ) ) {
73
+ wp_clear_scheduled_hook( 'beeketing_initial_collections_sync' ); // Remove CRON when we're done with it.
74
+ }
75
+
76
+ // Initial collect sync
77
+ if ( ! wp_next_scheduled( 'beeketing_initial_collects_sync' ) && 1 != get_option( 'beeketing_completed_initial_collects_sync', 0 ) ) {
78
+ wp_schedule_event( BEEKETING_INITIAL_SYNC_TIME, 'beeketing_ten_minute', 'beeketing_initial_collects_sync' );
79
+ } elseif ( wp_next_scheduled( 'beeketing_initial_collects_sync' ) && 1 == get_option( 'beeketing_completed_initial_collects_sync', 0 ) ) {
80
+ wp_clear_scheduled_hook( 'beeketing_initial_collects_sync' ); // Remove CRON when we're done with it.
81
+ }
82
+
83
+ // Initial sync collects by categories
84
+ if ( ! wp_next_scheduled( 'beeketing_initial_sync_collects_by_collections' ) ) {
85
+ wp_schedule_event( BEEKETING_INITIAL_SYNC_TIME, 'beeketing_ten_minute', 'beeketing_initial_sync_collects_by_collections' );
86
+ }
87
+
88
+ // Initial customers sync
89
+ if ( ! wp_next_scheduled( 'beeketing_initial_customers_sync' ) && 1 != get_option( 'beeketing_completed_initial_customer_sync', 0 ) ) {
90
+ wp_schedule_event( BEEKETING_INITIAL_SYNC_TIME, 'beeketing_ten_minute', 'beeketing_initial_customers_sync' );
91
+ } elseif ( wp_next_scheduled( 'beeketing_initial_customers_sync' ) && 1 == get_option( 'beeketing_completed_initial_customer_sync', 0 ) ) {
92
+ wp_clear_scheduled_hook( 'beeketing_initial_customers_sync' ); // Remove CRON when we're done with it.
93
+ }
94
+
95
+ }
96
+ add_action( 'init', 'beeketing_schedule_events' );
97
+ }
98
+
99
+
100
+ if ( ! function_exists('beeketing_retry_queue') ) {
101
+
102
+ /**
103
+ * Resend queue.
104
+ *
105
+ * @since 2.0.0
106
+ */
107
+ function beeketing_retry_queue()
108
+ {
109
+ // Customers
110
+ BeeketingWooCommerce()->customers->process_queue();
111
+
112
+ // Products queue
113
+ BeeketingWooCommerce()->products->process_queue();
114
+
115
+ // Collections queue
116
+ BeeketingWooCommerce()->collections->process_queue();
117
+
118
+ // Orders queue
119
+ BeeketingWooCommerce()->orders->process_queue();
120
+
121
+ }
122
+ add_action( 'beeketing_retry_queue', 'beeketing_retry_queue' );
123
+ }
124
+
125
+ if ( ! function_exists( 'beeketing_initial_product_sync' ) ) {
126
+
127
+ /**
128
+ * Sync product with Beeketing API
129
+ *
130
+ * @since 2.0.0
131
+ *
132
+ */
133
+ function beeketing_initial_product_sync()
134
+ {
135
+ if ( get_option( 'beeketing_current_sync_time' ) ) {
136
+ $current_sync_time = get_option( 'beeketing_current_sync_time' );
137
+ } else {
138
+ $current_sync_time = time();
139
+ }
140
+
141
+ $query = beeketing_query_products( array(
142
+ 'posts_per_page' => 250,
143
+ 'meta_query' => array(
144
+ 'relation' => 'OR',
145
+ array(
146
+ 'key' => '_beeketing_last_update',
147
+ 'compare' => '<',
148
+ 'value' => $current_sync_time,
149
+ ),
150
+ array(
151
+ 'relation' => 'AND',
152
+ array(
153
+ 'key' => '_beeketing_last_update',
154
+ 'compare' => 'NOT EXISTS',
155
+ 'value' => '',
156
+ ),
157
+ array(
158
+ 'key' => '_visibility',
159
+ 'compare' => '!=',
160
+ 'value' => 'hidden',
161
+ ),
162
+ ),
163
+ ),
164
+ ) );
165
+
166
+ $product_ids = $query->posts;
167
+
168
+ // Update option so the system knows it should stop syncing
169
+ if ( empty( $product_ids ) ) {
170
+ update_option( 'beeketing_completed_initial_product_sync', 1 );
171
+ return;
172
+ }
173
+
174
+ foreach ( $product_ids as $product_id ) {
175
+ BeeketingWooCommerce()->products->add_product_to_beeketing( $product_id, true );
176
+ }
177
+
178
+ }
179
+ add_action( 'beeketing_initial_product_sync', 'beeketing_initial_product_sync' );
180
+ }
181
+
182
+
183
+ if ( ! function_exists( 'beeketing_initial_orders_sync' ) ) {
184
+
185
+ /**
186
+ * Sync Orders data.
187
+ *
188
+ * Sync orders with Beeketing API
189
+ *
190
+ * @since 2.0.0
191
+ *
192
+ */
193
+ function beeketing_initial_orders_sync()
194
+ {
195
+ if ( get_option( 'beeketing_current_sync_time' ) ) {
196
+ $current_sync_time = get_option( 'beeketing_current_sync_time' );
197
+ } else {
198
+ $current_sync_time = time();
199
+ }
200
+
201
+ $query = beeketing_query_orders( array(
202
+ 'posts_per_page' => 250,
203
+ 'meta_query' => array(
204
+ 'relation' => 'OR',
205
+ array(
206
+ 'key' => '_beeketing_last_update',
207
+ 'compare' => 'NOT EXISTS',
208
+ 'value' => '',
209
+ ),
210
+ array(
211
+ 'key' => '_beeketing_last_update',
212
+ 'compare' => '<',
213
+ 'value' => $current_sync_time,
214
+ ),
215
+ )
216
+ ));
217
+
218
+ $order_ids = $query->posts;
219
+ if ( empty( $order_ids ) ) {
220
+ update_option( 'beeketing_completed_initial_order_sync', 1 );
221
+ return;
222
+ }
223
+
224
+ foreach ( $query->posts as $order_id ) {
225
+ BeeketingWooCommerce()->orders->add_order_to_beeketing($order_id);
226
+ }
227
+ }
228
+ add_action( 'beeketing_initial_orders_sync', 'beeketing_initial_orders_sync' );
229
+ }
230
+
231
+ if ( ! function_exists( 'beeketing_initial_collections_sync' ) ) {
232
+ /**
233
+ * Sync product categories
234
+ * @since 2.0.0
235
+ */
236
+ function beeketing_initial_collections_sync()
237
+ {
238
+ $page = 0;
239
+ $count_terms = wp_count_terms( 'product_cat', [
240
+ 'hide_empty' => false,
241
+ ]);
242
+
243
+ if ( $count_terms > 100 ) {
244
+ $count_terms = 100;
245
+ } else {
246
+ $count_terms = $count_terms - 1;
247
+ }
248
+ while ( true ) {
249
+ $terms = get_terms( 'product_cat', array(
250
+ 'hide_empty' => false,
251
+ 'fields' => 'ids',
252
+ 'number' => $count_terms,
253
+ 'offset' => $page * $count_terms
254
+ ) );
255
+
256
+ if ( ! $terms ) {
257
+ break;
258
+ }
259
+
260
+ foreach ( $terms as $term_id ) {
261
+ BeeketingWooCommerce()->collections->add_product_category_to_beeketing( $term_id, null, 'product_cat' );
262
+ }
263
+
264
+ $page ++;
265
+ }
266
+
267
+ update_option( 'beeketing_completed_initial_collection_sync', 1 );
268
+ }
269
+
270
+ add_action( 'beeketing_initial_collections_sync', 'beeketing_initial_collections_sync' );
271
+ }
272
+
273
+ if ( !function_exists( 'beeketing_initial_collects_sync' ) ) {
274
+ /**
275
+ * Sync collects
276
+ *
277
+ * @since 2.0.0
278
+ */
279
+ function beeketing_initial_collects_sync()
280
+ {
281
+ update_option( 'beeketing_syncing_collects', 1 );
282
+
283
+ $startTime = time();
284
+
285
+ while ( true ) {
286
+ // Stop syncing if time is up
287
+ if ( time() - $startTime > 30 * 60 ) {
288
+ update_option( 'beeketing_syncing_collects', 0 );
289
+ break;
290
+ }
291
+
292
+ $count_terms = wp_count_terms( 'product_cat', [
293
+ 'hide_empty' => false,
294
+ ] );
295
+
296
+ if ( $count_terms > 100 ) {
297
+ $count_terms = 100;
298
+ } else {
299
+ $count_terms = $count_terms - 1;
300
+ }
301
+
302
+ $terms_per_page = $count_terms;
303
+
304
+ $offset = get_option( 'beeketing_collections_offset', 0 );
305
+ $terms = get_terms( 'product_cat', array(
306
+ 'hide_empty' => false,
307
+ 'fields' => 'ids',
308
+ 'number' => $terms_per_page,
309
+ 'offset' => $offset * $terms_per_page
310
+ ) );
311
+
312
+ if ( ! $terms ) {
313
+ update_option( 'beeketing_completed_initial_collects_sync', 1 );
314
+ update_option( 'beeketing_collections_offset', 0 );
315
+ update_option( 'beeketing_syncing_collects', 0 );
316
+ break;
317
+ }
318
+
319
+ foreach ( $terms as $term_id ) {
320
+ BeeketingWooCommerce()->collects->sync_collect_by_collection_id( $term_id );
321
+ }
322
+
323
+ update_option( 'beeketing_collections_offset', $offset + 1 );
324
+ }
325
+
326
+ }
327
+
328
+ add_action( 'beeketing_initial_collects_sync', 'beeketing_initial_collects_sync' );
329
+ }
330
+
331
+
332
+ if ( ! function_exists( 'beeketing_initial_sync_collects_by_collections' ) ) {
333
+ /**
334
+ * Sync collects by collections
335
+ *
336
+ * @since 2.0.0
337
+ */
338
+ function beeketing_initial_sync_collects_by_collections()
339
+ {
340
+ $terms = get_option( '_beeketing_updated_categories', [] );
341
+
342
+ foreach ( $terms as $key => $term_id ) {
343
+ BeeketingWooCommerce()->collects->sync_collect_by_collection_id( $term_id );
344
+ unset( $terms[ $key ] );
345
+ update_option( '_beeketing_updated_categories', $terms );
346
+
347
+ }
348
+
349
+ }
350
+
351
+ add_action( 'beeketing_initial_sync_collects_by_collections', 'beeketing_initial_sync_collects_by_collections' );
352
+ }
353
+
354
+ if ( ! function_exists( 'beeketing_initial_customers_sync' ) ) {
355
+ /**
356
+ * Sync customers
357
+ *
358
+ * @since 2.0.0
359
+ */
360
+ function beeketing_initial_customers_sync()
361
+ {
362
+ if ( get_option( 'beeketing_current_sync_time' ) ) {
363
+ $current_sync_time = get_option( 'beeketing_current_sync_time' );
364
+ } else {
365
+ $current_sync_time = time();
366
+ }
367
+
368
+ $query = beeketing_query_customers( array(
369
+ 'number' => 250,
370
+ 'meta_query' => array(
371
+ 'relation' => 'OR',
372
+ array(
373
+ 'key' => '_beeketing_last_update',
374
+ 'compare' => 'NOT EXISTS',
375
+ 'value' => '',
376
+ ),
377
+ array(
378
+ 'key' => '_beeketing_last_update',
379
+ 'compare' => '<',
380
+ 'value' => $current_sync_time,
381
+ ),
382
+ )
383
+ ));
384
+ $user_ids = $query->get_results();
385
+
386
+ if ( empty( $user_ids ) ) {
387
+ update_option( 'beeketing_completed_initial_customer_sync', 1 );
388
+ return;
389
+ }
390
+ foreach ( $user_ids as $user_id ) {
391
+ BeeketingWooCommerce()->customers->beeketing_add_customer( $user_id, null );
392
+ }
393
+ }
394
+
395
+ add_action( 'beeketing_initial_customers_sync', 'beeketing_initial_customers_sync' );
396
+ }
397
+
398
+
399
+
400
+
lib/BeeketingSDK/Helper/beeketing-helper-functions.php ADDED
@@ -0,0 +1,386 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
+
4
+ if ( ! function_exists( 'getallheaders' ) ) {
5
+ function getallheaders()
6
+ {
7
+ $headers = '';
8
+ foreach ( $_SERVER as $name => $value ) {
9
+ if ( substr( $name, 0, 5 ) == 'HTTP_' ) {
10
+ $headers[ str_replace(' ', '-', ucwords( strtolower( str_replace( '_', ' ', substr( $name, 5 ) ) ) ) ) ] = $value;
11
+ }
12
+ }
13
+ return $headers;
14
+ }
15
+ }
16
+
17
+ if ( ! function_exists( 'beeketing_query_customers' ) ) {
18
+ /**
19
+ * Helper method to get customer user objects
20
+ *
21
+ * Note that WP_User_Query does not have built-in pagination so limit & offset are used to provide limited
22
+ * pagination support
23
+ *
24
+ * The filter for role can only be a single role in a string.
25
+ *
26
+ * @since 2.0.0
27
+ * @param array $args request arguments for filtering query
28
+ * @return WP_User_Query
29
+ */
30
+ function beeketing_query_customers( $args = array() ) {
31
+ // Set base query arguments
32
+ $query_args = array(
33
+ 'fields' => 'ID',
34
+ 'role' => 'customer',
35
+ 'orderby' => 'registered',
36
+ );
37
+ // Custom Role
38
+ if ( ! empty( $args['role'] ) ) {
39
+ $query_args['role'] = $args['role'];
40
+ // Show users on all roles
41
+ if ( 'all' === $query_args['role'] ) {
42
+ unset( $query_args['role'] );
43
+ }
44
+ }
45
+ // Search
46
+ if ( ! empty( $args['q'] ) ) {
47
+ $query_args['search'] = $args['q'];
48
+ }
49
+ // Limit number of users returned
50
+ if ( ! empty( $args['limit'] ) ) {
51
+ if ( $args['limit'] == -1 ) {
52
+ unset( $query_args['number'] );
53
+ } else {
54
+ $query_args['number'] = absint( $args['limit'] );
55
+ $users_per_page = absint( $args['limit'] );
56
+ }
57
+ } else {
58
+ $args['limit'] = $query_args['number'];
59
+ }
60
+ // Page
61
+ $page = ( isset( $args['page'] ) ) ? absint( $args['page'] ) : 1;
62
+ // Offset
63
+ if ( ! empty( $args['offset'] ) ) {
64
+ $query_args['offset'] = absint( $args['offset'] );
65
+ } else {
66
+ $query_args['offset'] = $users_per_page * ( $page - 1 );
67
+ }
68
+
69
+ // Order (ASC or DESC, ASC by default)
70
+ if ( ! empty( $args['order'] ) ) {
71
+ $query_args['order'] = $args['order'];
72
+ }
73
+ // Orderby
74
+ if ( ! empty( $args['orderby'] ) ) {
75
+ $query_args['orderby'] = $args['orderby'];
76
+ // Allow sorting by meta value
77
+ if ( ! empty( $args['orderby_meta_key'] ) ) {
78
+ $query_args['meta_key'] = $args['orderby_meta_key'];
79
+ }
80
+ }
81
+ $query = new WP_User_Query( $query_args );
82
+ // Helper members for pagination headers
83
+ $query->total_pages = ( $args['limit'] == -1 ) ? 1 : ceil( $query->get_total() / $users_per_page );
84
+ $query->page = $page;
85
+ return $query;
86
+ }
87
+ }
88
+
89
+ if ( ! function_exists( 'beeketing_query_products' ) ) {
90
+ /**
91
+ * Helper method to get product post objects
92
+ *
93
+ * @since 2.0.0
94
+ * @param array $args request arguments for filtering query
95
+ * @return WP_Query
96
+ */
97
+ function beeketing_query_products( $args ) {
98
+ // Set base query arguments
99
+ $query_args = array(
100
+ 'fields' => 'ids',
101
+ 'post_type' => 'product',
102
+ 'post_status' => 'publish',
103
+ 'cache_results' => false,
104
+ 'meta_query' => array(),
105
+ );
106
+
107
+ $query_args = array_merge( $query_args, $args );
108
+
109
+ return new WP_Query( $query_args );
110
+ }
111
+ }
112
+
113
+ if ( ! function_exists( 'beeketing_format_datetime' ) ) {
114
+ function beeketing_format_datetime( $timestamp, $convert_to_utc = false ) {
115
+
116
+ if ( $convert_to_utc ) {
117
+ $timezone = new DateTimeZone( wc_timezone_string() );
118
+ } else {
119
+ $timezone = new DateTimeZone( 'UTC' );
120
+ }
121
+
122
+ try {
123
+
124
+ if ( is_numeric( $timestamp ) ) {
125
+ $date = new DateTime( "@{$timestamp}" );
126
+ } else {
127
+ $date = new DateTime( $timestamp, $timezone );
128
+ }
129
+
130
+ // convert to UTC by adjusting the time based on the offset of the site's timezone
131
+ if ( $convert_to_utc ) {
132
+ $date->modify( -1 * $date->getOffset() . ' seconds' );
133
+ }
134
+
135
+ } catch ( Exception $e ) {
136
+
137
+ $date = new DateTime( '@0' );
138
+ }
139
+
140
+ return $date->format( 'Y-m-d\TH:i:s\Z' );
141
+ }
142
+ }
143
+
144
+ if ( ! function_exists( 'beeketing_query_orders' ) ) {
145
+ /**
146
+ * Helper method to get order post objects
147
+ *
148
+ * @since 2.0.0
149
+ * @param array $args request arguments for filtering query
150
+ * @return WP_Query
151
+ */
152
+ function beeketing_query_orders( $args ) {
153
+ // set base query arguments
154
+ $query_args = array(
155
+ 'fields' => 'ids',
156
+ 'post_type' => 'shop_order',
157
+ 'post_status' => array_keys( wc_get_order_statuses() )
158
+ );
159
+ // add status argument
160
+ if ( ! empty( $args['status'] ) ) {
161
+ $statuses = 'wc-' . str_replace( ',', ',wc-', $args['status'] );
162
+ $statuses = explode( ',', $statuses );
163
+ $query_args['post_status'] = $statuses;
164
+ unset( $args['status'] );
165
+ }
166
+
167
+ $query_args = array_merge( $query_args, $args );
168
+ return new WP_Query( $query_args );
169
+ }
170
+ }
171
+
172
+ if ( ! function_exists( 'beeketing_get_product_ids_in_collection' ) ) {
173
+ /**
174
+ * Helper method get products ids in collection
175
+ *
176
+ * @since 2.0.0
177
+ * @param $cat_id
178
+ * @param array $query
179
+ * @return mixed
180
+ */
181
+ function beeketing_get_product_ids_in_collection($cat_id, $query = array()) {
182
+
183
+ $args = array(
184
+ 'fields' => 'ids',
185
+ 'post_type' => 'product',
186
+ 'has_password' => false,
187
+ 'post_status' => 'publish',
188
+ 'tax_query' => array(
189
+ array(
190
+ 'taxonomy' => 'product_cat',
191
+ 'terms' => $cat_id,
192
+ ),
193
+ ),
194
+ );
195
+
196
+ $args = array_merge( $args, $query );
197
+
198
+ $products = new WP_Query( $args );
199
+
200
+ return $products->posts;
201
+ }
202
+ }
203
+
204
+ if ( ! function_exists( 'merge_query_args' ) ) {
205
+ /**
206
+ * Merge query args
207
+ *
208
+ * @since 2.0.0
209
+ * @param $base_args
210
+ * @param $request_args
211
+ * @return array
212
+ */
213
+ function merge_query_args( $base_args, $request_args ) {
214
+
215
+ $args = array();
216
+
217
+ // date
218
+ if ( ! empty( $request_args['created_at_min'] ) || ! empty( $request_args['created_at_max'] ) || ! empty( $request_args['updated_at_min'] ) || ! empty( $request_args['updated_at_max'] ) ) {
219
+
220
+ $args['date_query'] = array();
221
+
222
+ // resources created after specified date
223
+ if ( ! empty( $request_args['created_at_min'] ) )
224
+ $args['date_query'][] = array( 'column' => 'post_date_gmt', 'after' => $this->server->parse_datetime( $request_args['created_at_min'] ), 'inclusive' => true );
225
+
226
+ // resources created before specified date
227
+ if ( ! empty( $request_args['created_at_max'] ) )
228
+ $args['date_query'][] = array( 'column' => 'post_date_gmt', 'before' => $this->server->parse_datetime( $request_args['created_at_max'] ), 'inclusive' => true );
229
+
230
+ // resources updated after specified date
231
+ if ( ! empty( $request_args['updated_at_min'] ) )
232
+ $args['date_query'][] = array( 'column' => 'post_modified_gmt', 'after' => $this->server->parse_datetime( $request_args['updated_at_min'] ), 'inclusive' => true );
233
+
234
+ // resources updated before specified date
235
+ if ( ! empty( $request_args['updated_at_max'] ) )
236
+ $args['date_query'][] = array( 'column' => 'post_modified_gmt', 'before' => $this->server->parse_datetime( $request_args['updated_at_max'] ), 'inclusive' => true );
237
+ }
238
+
239
+ // search
240
+ if ( ! empty( $request_args['q'] ) )
241
+ $args['s'] = $request_args['q'];
242
+
243
+ // resources per response
244
+ if ( ! empty( $request_args['limit'] ) )
245
+ $args['posts_per_page'] = $request_args['limit'];
246
+
247
+ // resource offset
248
+ if ( ! empty( $request_args['offset'] ) )
249
+ $args['offset'] = $request_args['offset'];
250
+
251
+ // resource page
252
+ $args['paged'] = ( isset( $request_args['page'] ) ) ? absint( $request_args['page'] ) : 1;
253
+
254
+ return array_merge( $base_args, $args );
255
+ }
256
+ }
257
+
258
+ if (!function_exists('beeketing_get_product_images')) {
259
+ /**
260
+ * Get the images for a product or product variation
261
+ *
262
+ * @since 2.0.0
263
+ * @param WC_Product|WC_Product_Variation $product
264
+ * @return array
265
+ */
266
+ function beeketing_get_product_images( $product ) {
267
+ $images = $attachment_ids = array();
268
+ if ( $product->is_type( 'variation' ) ) {
269
+ if ( has_post_thumbnail( $product->get_variation_id() ) ) {
270
+ // Add variation image if set
271
+ $attachment_ids[] = get_post_thumbnail_id( $product->get_variation_id() );
272
+ } elseif ( has_post_thumbnail( $product->id ) ) {
273
+ // Otherwise use the parent product featured image if set
274
+ $attachment_ids[] = get_post_thumbnail_id( $product->id );
275
+ }
276
+ } else {
277
+ // Add featured image
278
+ if ( has_post_thumbnail( $product->id ) ) {
279
+ $attachment_ids[] = get_post_thumbnail_id( $product->id );
280
+ }
281
+ // Add gallery images
282
+ $attachment_ids = array_merge( $attachment_ids, $product->get_gallery_attachment_ids() );
283
+ }
284
+ // Build image data
285
+ foreach ( $attachment_ids as $position => $attachment_id ) {
286
+ $attachment_post = get_post( $attachment_id );
287
+ if ( is_null( $attachment_post ) ) {
288
+ continue;
289
+ }
290
+ $attachment = wp_get_attachment_image_src( $attachment_id, 'full' );
291
+ if ( ! is_array( $attachment ) ) {
292
+ continue;
293
+ }
294
+ $images[] = array(
295
+ 'id' => (int) $attachment_id,
296
+ 'created_at' => beeketing_format_datetime( $attachment_post->post_date_gmt ),
297
+ 'updated_at' => beeketing_format_datetime( $attachment_post->post_modified_gmt ),
298
+ 'src' => current( $attachment ),
299
+ 'title' => get_the_title( $attachment_id ),
300
+ 'alt' => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ),
301
+ 'position' => (int) $position,
302
+ );
303
+ }
304
+ // Set a placeholder image if the product has no images set
305
+ if ( empty( $images ) ) {
306
+ $images[] = array(
307
+ 'id' => 0,
308
+ 'created_at' => beeketing_format_datetime( time() ), // Default to now
309
+ 'updated_at' => beeketing_format_datetime( time() ),
310
+ 'src' => wc_placeholder_img_src(),
311
+ 'title' => __( 'Placeholder', 'woocommerce' ),
312
+ 'alt' => __( 'Placeholder', 'woocommerce' ),
313
+ 'position' => 0,
314
+ );
315
+ }
316
+ return $images;
317
+ }
318
+ }
319
+
320
+ if ( ! function_exists( 'beeketing_product_get_attributes' ) ) {
321
+ /**
322
+ * Get the attributes for a product or product variation
323
+ *
324
+ * @since 2.0.0
325
+ * @param WC_Product|WC_Product_Variation $product
326
+ * @return array
327
+ */
328
+ function beeketing_product_get_attributes( $product ) {
329
+ $attributes = array();
330
+ if ( $product->is_type( 'variation' ) ) {
331
+ // variation attributes
332
+ foreach ( $product->get_variation_attributes() as $attribute_name => $attribute ) {
333
+ // taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`
334
+ $attributes[] = array(
335
+ 'name' => wc_attribute_label( str_replace( 'attribute_', '', $attribute_name ) ),
336
+ 'slug' => str_replace( 'attribute_', '', str_replace( 'pa_', '', $attribute_name ) ),
337
+ 'option' => $attribute,
338
+ );
339
+ }
340
+ } else {
341
+ foreach ( $product->get_attributes() as $attribute ) {
342
+ // taxonomy-based attributes are comma-separated, others are pipe (|) separated
343
+ if ( $attribute['is_taxonomy'] ) {
344
+ $options = explode( ',', $product->get_attribute( $attribute['name'] ) );
345
+ } else {
346
+ $options = explode( '|', $product->get_attribute( $attribute['name'] ) );
347
+ }
348
+ $attributes[] = array(
349
+ 'name' => wc_attribute_label( $attribute['name'] ),
350
+ 'slug' => str_replace( 'pa_', '', $attribute['name'] ),
351
+ 'position' => (int) $attribute['position'],
352
+ 'visible' => (bool) $attribute['is_visible'],
353
+ 'variation' => (bool) $attribute['is_variation'],
354
+ 'options' => array_map( 'trim', $options ),
355
+ );
356
+ }
357
+ }
358
+ return $attributes;
359
+ }
360
+ }
361
+
362
+ if ( ! function_exists( 'title_filter' ) ) {
363
+ /**
364
+ * Title filter
365
+ *
366
+ * @since 2.0.0
367
+ * @param $where
368
+ * @param $wp_query
369
+ * @return string
370
+ */
371
+ function title_filter($where, &$wp_query) {
372
+ global $wpdb;
373
+
374
+ if ($search_term = $wp_query->get( 'search_prod_title' )) {
375
+ /*using the esc_like() in here instead of other esc_sql()*/
376
+ $search_term = $wpdb->esc_like( $search_term );
377
+ $search_term = ' \'%' . $search_term . '%\'';
378
+ $where .= ' AND ' . $wpdb->posts . '.post_title LIKE ' . $search_term;
379
+ }
380
+
381
+ return $where;
382
+ }
383
+
384
+ add_filter( 'posts_where', 'title_filter', 10, 2 );
385
+ }
386
+
lib/BeeketingSDK/Snippet/DefaultSnippet.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class BeeketingSDK_Snippet_DefaultSnippet.
5
+ *
6
+ * Add default snippet
7
+ *
8
+ * @class BeeketingSDK_Snippet_DefaultSnippet
9
+ * @version 1.0.0
10
+ * @author Beeketing
11
+ * @since 1.0.0
12
+ */
13
+ class BeeketingSDK_Snippet_DefaultSnippet
14
+ {
15
+ /**
16
+ * @since 1.0.0
17
+ * @var BeeketingSDK_Snippet_SnippetManager $snippetManager
18
+ */
19
+ protected $snippetManager;
20
+
21
+ /**
22
+ * @since 1.0.0
23
+ * @var BeeketingSDK_Config_BeeketingConfig $beeketingConfig
24
+ */
25
+ protected $beeketingConfig;
26
+
27
+ /**
28
+ * Constructor
29
+ *
30
+ * @since 1.0.0
31
+ * @param $snippetManager
32
+ * @param $beeketingConfig
33
+ */
34
+ public function __construct( $snippetManager, $beeketingConfig )
35
+ {
36
+ $this->snippetManager = $snippetManager;
37
+ $this->beeketingConfig = $beeketingConfig;
38
+ }
39
+
40
+ /**
41
+ * Start
42
+ *
43
+ * @since 1.0.0
44
+ */
45
+ public function start()
46
+ {
47
+ // Add default snippet
48
+ $couponBoxSnippet = __DIR__.'/Templates/CouponBoxSnippet.html';
49
+
50
+ $this->snippetManager->addSnippet( $couponBoxSnippet );
51
+ $this->snippetManager->addVars( array(
52
+ '{{ bk_script_path }}' => $this->getScriptPath( $this->beeketingConfig->getPlatform() ),
53
+ '{{ bk_shop_api_key }}' => $this->getShopApiKey(),
54
+ ));
55
+ }
56
+
57
+ /**
58
+ * Get shop api key
59
+ *
60
+ * @since 1.0.0
61
+ * @return string
62
+ */
63
+ protected function getShopApiKey()
64
+ {
65
+ return strtolower( $this->beeketingConfig->getApiKey() );
66
+ }
67
+
68
+ /**
69
+ * Get script path
70
+ *
71
+ * @since 1.0.0
72
+ * @param $platform
73
+ * @return string
74
+ */
75
+ protected function getScriptPath( $platform )
76
+ {
77
+ return $this->beeketingConfig->getPath() . '/dist/js/front/loader/' . $platform . '.js';
78
+ }
79
+ }
lib/BeeketingSDK/Snippet/SnippetManager.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class BeeketingSDK_Snippet_SnippetManager.
5
+ *
6
+ * Snippet manager
7
+ *
8
+ * @class BeeketingSDK_Snippet_SnippetManager
9
+ * @version 1.0.0
10
+ * @author Beeketing
11
+ * @since 1.0.0
12
+ */
13
+ class BeeketingSDK_Snippet_SnippetManager
14
+ {
15
+ /**
16
+ * @since 1.0.0
17
+ * @var array
18
+ */
19
+ protected $snippets = array();
20
+
21
+ /**
22
+ * @since 1.0.0
23
+ * @var array
24
+ */
25
+ protected $vars = array(
26
+ 'keys' => array(),
27
+ 'values' => array()
28
+ );
29
+
30
+ /**
31
+ * Add snippet
32
+ *
33
+ * @since 2.0.0
34
+ * @param $snippet
35
+ * @return bool
36
+ * @throws Exception
37
+ */
38
+ public function addSnippet( $snippet )
39
+ {
40
+ // Already added.
41
+ if ( in_array( $snippet, $this->snippets ) ) {
42
+ return true;
43
+ }
44
+
45
+ array_push( $this->snippets, $snippet );
46
+
47
+ return true;
48
+ }
49
+
50
+ /**
51
+ * Remove snippet
52
+ *
53
+ * @since 2.0.0
54
+ * @param string $snippet
55
+ */
56
+ public function removeSnippet( $snippet )
57
+ {
58
+ $this->array_remove( $this->snippets, $snippet );
59
+ }
60
+
61
+ /**
62
+ * Get snippet content
63
+ *
64
+ * @since 2.0.0
65
+ * @param $snippet
66
+ * @return string
67
+ * @throws Exception
68
+ */
69
+ public function getSnippetContent( $snippet )
70
+ {
71
+ return $this->read( $snippet );
72
+ }
73
+
74
+ /**
75
+ * Add variables to snippet
76
+ *
77
+ * @since 2.0.0
78
+ * @param $vars
79
+ * @return $this
80
+ */
81
+ public function addVars( $vars )
82
+ {
83
+ foreach ( $vars as $key => $value ) {
84
+ array_push( $this->vars['keys'], $key );
85
+ array_push( $this->vars['values'], $value );
86
+ }
87
+
88
+ return $this;
89
+ }
90
+
91
+ /**
92
+ * Get all snippet content
93
+ *
94
+ * @since 2.0.0
95
+ * @return string
96
+ * @throws Exception
97
+ */
98
+ public function getAllSnippetContent()
99
+ {
100
+ $content = '';
101
+
102
+ // Read
103
+ if ( count( $this->snippets ) > 0 ) {
104
+ foreach( $this->snippets as $snippet ) {
105
+ $content .= $this->read( $snippet );
106
+ }
107
+ }
108
+
109
+ // Replace variables
110
+ if ( count( $this->vars['keys'] ) > 0 && count( $this->vars['values'] ) > 0 ) {
111
+ $content = str_replace( $this->vars['keys'], $this->vars['values'], $content );
112
+ }
113
+
114
+ if ( function_exists( 'is_shop' ) ) {
115
+ // Tracking script
116
+ if ( is_shop() ) {
117
+ $content .= "<script>var __bkt = {}; __bkt.p = 'home';</script>";
118
+ } elseif (is_product_category()) {
119
+ $cate = get_queried_object();
120
+ $cateID = $cate->term_id;
121
+ $content .= "<script>var __bkt = {}; __bkt.p = 'collection'; __bkt.rid = " . $cateID .";</script>";
122
+ } elseif ( is_product() ) {
123
+ global $product;
124
+ $content .= "<script> var __bkt = {}; __bkt.p = 'product'; __bkt.rid = " . $product->id . ";</script>";
125
+ } elseif ( is_cart() ) {
126
+ $content .= "<script>var __bkt = {}; __bkt.p = 'cart';</script>";
127
+ } elseif ( is_checkout() ) {
128
+ $content .= "<script>var __bkt = {}; __bkt.p = 'checkout';</script>";
129
+ } elseif ( is_account_page() ) {
130
+ $content .= "<script>var __bkt = {}; __bkt.p = 'account';</script>";
131
+ }
132
+ $userId = get_current_user_id();
133
+ if ( $userId > 0 ) {
134
+ $content .= "<script>var BKCustomer = {}; BKCustomer.id = " . $userId . ";</script>";
135
+ }
136
+
137
+ $cartData = BeeketingWooCommerce()->cart->get_formatted_cart_data();
138
+
139
+ $content .= "<script>var bkCartData = JSON.parse('" . json_encode($cartData)."');</script>";
140
+ }
141
+
142
+ return $content;
143
+ }
144
+
145
+ /**
146
+ * Read snippet
147
+ *
148
+ * @since 1.0.0
149
+ * @param $snippet
150
+ * @return string
151
+ * @throws Exception
152
+ */
153
+ protected function read( $snippet )
154
+ {
155
+ // Can't read
156
+ if ( ! is_readable( $snippet ) ) {
157
+ throw new Exception( 'Snippet '.$snippet.' doesn\'t exist.' );
158
+ }
159
+
160
+ $content = file_get_contents( $snippet );
161
+
162
+ return $content;
163
+ }
164
+
165
+ /**
166
+ * array array_remove ( array input, mixed search_value [, bool strict] )
167
+ *
168
+ * @since 1.0.0
169
+ * @param array $a_input
170
+ * @param $m_search_value
171
+ * @param bool $b_strict
172
+ * @return array
173
+ */
174
+ protected function array_remove( array &$a_input, $m_search_value, $b_strict = false )
175
+ {
176
+ $a_Keys = array_keys( $a_input, $m_search_value, $b_strict );
177
+ foreach( $a_Keys as $s_key ) {
178
+ unset( $a_input[ $s_key ] );
179
+ }
180
+ return $a_input;
181
+ }
182
+ }
lib/BeeketingSDK/Snippet/Templates/CouponBoxSnippet.html ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script type="text/javascript">
2
+ (function (doc, scriptPath, apiKey) {
3
+ var sc, node, today=new Date(),dd=today.getDate(),mm=today.getMonth()+1,yyyy=today.getFullYear();if(dd<10)dd='0'+dd;if(mm<10)mm='0'+mm;today=yyyy+mm+dd;
4
+ window.BKShopApiKey = apiKey;
5
+ // Load base script tag
6
+ sc = doc.createElement( "script" );
7
+ sc.type = "text/javascript";
8
+ sc.async = !0;
9
+ sc.src = scriptPath + '?' + today;
10
+ node = doc.getElementsByTagName( "script" )[0];
11
+ node.parentNode.insertBefore( sc, node );
12
+ })(document, '{{ bk_script_path }}', '{{ bk_shop_api_key }}');
13
+ </script>
package.xml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Beeketing_IntegrateApp</name>
4
+ <version>1.0.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="https://beeketing.com/terms-of-service">Beeketing TOS</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Better coupon box for magento</summary>
10
+ <description>Popup a coupon box to turn visitors into social followers and increase sales.</description>
11
+ <notes>Add new apps features:&#xD;
12
+ - Email Automation&#xD;
13
+ - Checkout Boost&#xD;
14
+ - Boost Sales&#xD;
15
+ - Product recommendation&#xD;
16
+ - Happy Email</notes>
17
+ <authors><author><name>Beeketing Inc.</name><user>beeketing</user><email>hi@beeketing.com</email></author></authors>
18
+ <date>2016-02-22</date>
19
+ <time>10:44:12</time>
20
+ <contents><target name="magecommunity"><dir name="Beeketing"><dir name="IntegrateApp"><dir name="Block"><file name="AppsData.php" hash="6461a643a567576f8f1d175fac9278df"/></dir><dir name="Helper"><file name="Collection.php" hash="e28a0d5f779abf0cd86feccdaaa973bc"/><file name="Core.php" hash="0acd00eed4b834b269296687d91fd1b1"/><file name="Customer.php" hash="d3f9a4c6f8e1451f49e2e31e766ce920"/><file name="Data.php" hash="e83e2bab30882694bae849a7f1ee7b16"/><file name="Order.php" hash="9d32ef0744ff4c9d5acce20065097656"/><file name="Product.php" hash="a335727c65516a79b8aec35e86a025a8"/></dir><dir name="Model"><dir name="Observer"><file name="Cart.php" hash="cc9d910bc1d17ba8662f01f799b6b7ec"/><file name="Collection.php" hash="9afe12495f0a7ed5d12adaa60c968356"/><file name="Customer.php" hash="d7439e9a1ddddc943256aa0eec795c7f"/><file name="Order.php" hash="de5f161bffc7c8480f3761214cba4a45"/><file name="Product.php" hash="4c16d6a9c949923c17d150f5a1497e9a"/></dir><file name="Observer.php" hash="f0ed89797bfb6ebd2948ee1ad9418601"/></dir><dir name="controllers"><dir name="Api"><file name="CartController.php" hash="be9153a9ef19345ee9d1e3932801c390"/><file name="CollectionController.php" hash="3a340a80504f5c21058ad5f0aaaebfc9"/><file name="CustomerController.php" hash="1ca877ee2d9f8d721e5f385ff47ddba5"/><file name="OrderController.php" hash="bab8b48b6190c519b5e330235273481d"/><file name="ProductController.php" hash="525bac7b4a9c32acd656d43fb459fe3b"/><file name="ShopController.php" hash="d33836da67a77c6fd676563d4fcc4de3"/></dir><dir name="System"><file name="ConfigController.php" hash="3223c0664664c0a00a9436ba9295df84"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="acad7350f6a65ddcc79aae9633486186"/><file name="config.xml" hash="c833b2cfc5f5bc335703394e3b626b25"/><file name="system.xml" hash="4cdb3cadc13663b7c6d0a797937fd6b4"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Beeketing_IntegrateApp.xml" hash="f3c4c8f3b53d8767fb823611797c434e"/></dir></target><target name="magelib"><dir name="Beeketing"><file name="BeeketingMagento.php" hash="e2541b7ce0f4fda9b09dc85c732c13ee"/><file name="config.php" hash="6e4937ff01b865253a2005a712b0fbba"/><file name="env" hash="59477fcee407fa1b188bd9152683fcf8"/></dir><dir name="BeeketingSDK"><dir name="Api"><file name="BeeketingApi.php" hash="66514ca6c786f1622f28785111432b1b"/><file name="BeeketingCart.php" hash="1bf954917b903e1048c07181ab60c7cf"/><file name="BeeketingCollections.php" hash="6e348074bc4aa523a046259c5b2436aa"/><file name="BeeketingCollects.php" hash="199a4ffd29f19b7cac53d2eafbf13374"/><file name="BeeketingCustomers.php" hash="ab0a7b1f81890a5a8f6ea0bbb1de300b"/><file name="BeeketingOrders.php" hash="0e458799bc7e06b8c79e33b57e1c65c0"/><file name="BeeketingProducts.php" hash="186b4789a9225ea7c1bbf6d01427c1fa"/><file name="BeeketingShop.php" hash="a595a3c12a79e2ae07fa6f668395abfd"/></dir><dir name="Config"><file name="BeeketingConfig.php" hash="0b663bf286a4d4f3238417d306a57416"/></dir><dir name="Helper"><file name="beeketing-cron-functions.php" hash="5b74590060f27c2fb8bc98baf75b1efc"/><file name="beeketing-helper-functions.php" hash="a5c0cde4d28c9eb3ec33f59f8dcbf929"/></dir><dir name="Snippet"><file name="DefaultSnippet.php" hash="2ef0a979af6b2119b3cbe7482a39df78"/><file name="SnippetManager.php" hash="7b8b814517e78aab478732cdcca39a57"/><dir name="Templates"><file name="CouponBoxSnippet.html" hash="2d5d82ad4a2b16ae36b0be8c5ccf0f6c"/></dir></dir></dir></target></contents>
21
+ <compatible/>
22
+ <dependencies><required><php><min>5.3.0</min><max>5.6.18</max></php></required></dependencies>
23
+ </package>