pixlee-for-magento - Version 2.0.0.24

Version Notes

First requires configuration in System > Configuration > Pixlee Account Configuration.

Download this release

Release Info

Developer Awad Sayeed
Extension pixlee-for-magento
Version 2.0.0.24
Comparing to
See all releases


Code changes from version 2.0.0.5 to 2.0.0.24

Files changed (36) hide show
  1. app/code/community/Pixlee/Base/Block/Adminhtml/System/Config/Form/Demo.php +24 -0
  2. app/code/community/Pixlee/Base/Block/CategoryGallery.php +26 -0
  3. app/code/community/Pixlee/Base/Block/Gallery.php +5 -14
  4. app/code/community/Pixlee/Base/Helper/Data.php +319 -23
  5. app/code/community/Pixlee/Base/Helper/RavenAutoLoader.php +43 -0
  6. app/code/community/Pixlee/Base/Model/Observer.php +103 -45
  7. app/code/community/Pixlee/Base/controllers/Pixlee/ExportController.php +37 -12
  8. app/code/community/Pixlee/Base/etc/config.xml +10 -1
  9. app/code/community/Pixlee/Base/etc/config.xml.bak +10 -1
  10. app/code/community/Pixlee/Base/etc/system.xml +118 -15
  11. app/code/community/Pixlee/Base/version.txt +1 -1
  12. app/design/adminhtml/default/default/template/pixlee/system/config/demo_button.phtml +44 -0
  13. app/design/frontend/base/default/layout/pixlee/gallery.xml +14 -26
  14. app/design/frontend/base/default/template/pixlee/category_gallery.phtml +29 -0
  15. app/design/frontend/base/default/template/pixlee/gallery.phtml +2 -5
  16. app/design/frontend/base/default/template/pixlee/pixlee_tracking_pixel.phtml +6 -0
  17. js/pixlee/getAnalyticsCookie.js +0 -37
  18. lib/Pixlee/Pixlee.php +26 -18
  19. lib/Raven/Autoloader.php +43 -0
  20. lib/Raven/Breadcrumbs.php +60 -0
  21. lib/Raven/Breadcrumbs/ErrorHandler.php +47 -0
  22. lib/Raven/Breadcrumbs/MonologHandler.php +94 -0
  23. lib/Raven/Client.php +1155 -0
  24. lib/Raven/Compat.php +135 -0
  25. lib/Raven/Context.php +23 -0
  26. lib/Raven/CurlHandler.php +117 -0
  27. lib/Raven/ErrorHandler.php +183 -0
  28. lib/Raven/Exception.php +4 -0
  29. lib/Raven/Processor.php +20 -0
  30. lib/Raven/ReprSerializer.php +41 -0
  31. lib/Raven/SanitizeDataProcessor.php +120 -0
  32. lib/Raven/Serializer.php +133 -0
  33. lib/Raven/Stacktrace.php +284 -0
  34. lib/Raven/Util.php +33 -0
  35. lib/Raven/data/cacert.pem +5134 -0
  36. package.xml +1 -1
app/code/community/Pixlee/Base/Block/Adminhtml/System/Config/Form/Demo.php ADDED
@@ -0,0 +1,24 @@
1
+ <?php
2
+ class Pixlee_Base_Block_Adminhtml_System_Config_Form_Demo extends Mage_Adminhtml_Block_System_Config_Form_Field {
3
+ protected function _construct() {
4
+ parent::_construct();
5
+ $this->setTemplate('pixlee/system/config/demo_button.phtml');
6
+ }
7
+
8
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) {
9
+ return $this->_toHtml();
10
+ }
11
+
12
+ public function getButtonHtml() {
13
+ $buttonData = array(
14
+ 'id' => 'request_demo_button',
15
+ 'label' => $this->helper('adminhtml')->__('Request Demo'),
16
+ 'onclick' => 'javascript:requestDemo(); return false;'
17
+ );
18
+
19
+ $button = $this->getLayout()->createBlock('adminhtml/widget_button')->setData($buttonData);
20
+
21
+ return $button->toHtml();
22
+ }
23
+
24
+ }
app/code/community/Pixlee/Base/Block/CategoryGallery.php ADDED
@@ -0,0 +1,26 @@
1
+ <?php
2
+ class Pixlee_Base_Block_CategoryGallery extends Mage_Core_Block_Template {
3
+
4
+ public function _prepareLayout() {
5
+ $this->setTemplate("pixlee/category_gallery.phtml");
6
+ return parent::_prepareLayout();
7
+ }
8
+
9
+ public function getAccountId() {
10
+ return Mage::getStoreConfig('pixlee/pixlee/account_id', Mage::app()->getStore());
11
+ }
12
+
13
+ public function getAccountApiKey() {
14
+ return Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
15
+ }
16
+
17
+ public function getApiKey() {
18
+ $pixleeApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
19
+ return $pixleeApiKey;
20
+ }
21
+
22
+ public function getCategoryWidgetId() {
23
+ $pixleeWidgetId = Mage::getStoreConfig('pixlee/widget_options/category_widget_id', Mage::app()->getStore());
24
+ return $pixleeWidgetId;
25
+ }
26
+ }
app/code/community/Pixlee/Base/Block/Gallery.php CHANGED
@@ -1,9 +1,6 @@
1
<?php
2
class Pixlee_Base_Block_Gallery extends Mage_Core_Block_Template {
3
4
- const DEFAULT_RECIPE_ID = 155;
5
- const DEFAULT_DISPLAY_OPTIONS_ID = 2012;
6
-
7
public function _prepareLayout() {
8
$product = Mage::registry("current_product");
9
if(!empty($product)) {
@@ -21,19 +18,13 @@ class Pixlee_Base_Block_Gallery extends Mage_Core_Block_Template {
21
return Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
22
}
23
24
- public function getRecipeId() {
25
- $pixleeRecipeId = Mage::getStoreConfig('pixlee/pixlee/recipe_id', Mage::app()->getStore());
26
- return ($pixleeRecipeId) ? $pixleeRecipeId : self::DEFAULT_RECIPE_ID;
27
- }
28
-
29
- public function getDisplayOptionsId() {
30
- $pixleeDisplayOptionsId = Mage::getStoreConfig('pixlee/pixlee/display_options_id', Mage::app()->getStore());
31
- return ($pixleeDisplayOptionsId) ? $pixleeDisplayOptionsId : self::DEFAULT_DISPLAY_OPTIONS_ID;
32
- }
33
-
34
public function getApiKey() {
35
$pixleeApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
36
- return ($pixleeApiKey) ? $pixleeApiKey : self::DEFAULT_DISPLAY_OPTIONS_ID;
37
}
38
39
}
1
<?php
2
class Pixlee_Base_Block_Gallery extends Mage_Core_Block_Template {
3
4
public function _prepareLayout() {
5
$product = Mage::registry("current_product");
6
if(!empty($product)) {
18
return Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
19
}
20
21
public function getApiKey() {
22
$pixleeApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
23
+ return $pixleeApiKey;
24
}
25
26
+ public function getWidgetId() {
27
+ $pixleeWidgetId = Mage::getStoreConfig('pixlee/widget_options/widget_id', Mage::app()->getStore());
28
+ return $pixleeWidgetId;
29
+ }
30
}
app/code/community/Pixlee/Base/Helper/Data.php CHANGED
@@ -1,4 +1,8 @@
1
<?php
2
class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
3
4
protected $_unexportedProducts;
@@ -45,8 +49,10 @@ class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
45
} elseif($this->isActive()) {
46
$pixleeAccountId = Mage::getStoreConfig('pixlee/pixlee/account_id', Mage::app()->getStore());
47
$pixleeAccountApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
48
try {
49
- $this->_pixleeAPI = new Pixlee_Pixlee($pixleeAccountApiKey);
50
return $this->_pixleeAPI;
51
}
52
catch (Exception $e) {
@@ -94,7 +100,7 @@ class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
94
if($this->isInactive()) {
95
return "Save your Pixlee API access information before exporting your products.";
96
} elseif($c > 0) {
97
- return "Export your products to Pixlee and start collecting photos. There ". (($c > 1) ? 'are' : 'is') ." <strong>". $c ." ". (($c > 1) ? 'products' : 'product') ."</strong> to export to Pixlee.";
98
} else {
99
return "All your products have been exported to Pixlee. Congratulations!";
100
}
@@ -116,11 +122,13 @@ class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
116
} else if($product->getTypeId() == "bundle") {
117
$mainProduct = Mage::getModel('catalog/product')->load($product->getId()); // Get original sku as stated in product catalog
118
}
119
Mage::log("*** After _extractActualProduct");
120
Mage::log("Name: {$mainProduct->getName()}");
121
Mage::log("ID: {$mainProduct->getId()}");
122
Mage::log("SKU: {$mainProduct->getSku()}");
123
Mage::log("Type: {$mainProduct->getTypeId()}");
124
return $mainProduct;
125
}
126
@@ -130,12 +138,16 @@ class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
130
// function, but as of 2016/03/11, getAggregateStock is only called after _extractActualProduct
131
// has already been called
132
public function getAggregateStock($actualProduct) {
133
Mage::log("*** In getAggregateStock");
134
$aggregateStock = NULL;
135
// If after calling _extractActualProduct, there is no 'configurable' product, and only
136
// a 'simple' product, we won't get anything back from
137
// getModel('catalog/product_type_configurable')
138
if ($actualProduct->getTypeId() == "simple") {
139
// If the product's not keeping track of inventory, we'll error out when we try
140
// to call the getQty() function on the output of getStockItem()
141
if (is_null($actualProduct->getStockItem())) {
@@ -147,12 +159,25 @@ class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
147
// 'grouped' type products have 'associated products,' which presumably
148
// point to simple products
149
if ($actualProduct->getTypeId() == "grouped") {
150
$childProducts = $actualProduct->getTypeInstance(true)->getAssociatedProducts($actualProduct);
151
// And finally, my original assumption that all 'simple' products are
152
// under the umbrella of some 'configurable' product
153
} else if ($actualProduct->getTypeId() == "configurable") {
154
- $childProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null,$actualProduct);
155
}
156
foreach ($childProducts as $child) {
157
// Sometimes Magento gives a negative inventory quantity
158
// I don't want that to affect the overall count
@@ -175,6 +200,8 @@ class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
175
}
176
177
public function getVariantsDict($actualProduct) {
178
$variantsDict = array();
179
180
// If after calling _extractActualProduct, there is no 'configurable' product, and only
@@ -198,8 +225,18 @@ class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
198
// And finally, my original assumption that all 'simple' products are
199
// under the umbrella of some 'configurable' product
200
} else if ($actualProduct->getTypeId() == "configurable") {
201
- $childProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null,$actualProduct);
202
}
203
foreach ($childProducts as $child) {
204
// Sometimes Magento gives a negative inventory quantity
205
// I don't want that to affect the overall count
@@ -218,44 +255,179 @@ class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
218
);
219
}
220
}
221
- return $variantsDict;
222
}
223
224
// Whether creating a product, updating a product, or just exporting a product,
225
// this function gets called
226
- public function exportProductToPixlee($product) {
227
Mage::log("*** In exportProductToPixlee");
228
- $product = $this->_extractActualProduct($product);
229
- $productName = $product->getName();
230
- if($this->isInactive() || !isset($productName)) {
231
- return false;
232
- }
233
234
$pixlee = $this->getNewPixlee();
235
if($product->getVisibility() != 1) { // Make sure the product is visible in search or catalog
236
try {
237
$aggregateStock = $this->getAggregateStock($product);
238
Mage::log("Total stock is: {$aggregateStock}");
239
$variantsDict = $this->getVariantsDict($product);
240
Mage::log("Variants dict is");
241
Mage::log($variantsDict);
242
243
- $product_mediaurl = Mage::getModel('catalog/product_media_config')->getMediaUrl($product->getImage());
244
- $response = $pixlee->createProduct($product->getName(), $product->getSku(), $product->getProductUrl(), $product_mediaurl, $product->getId(), $aggregateStock, $variantsDict);
245
- $albumId = 0;
246
247
- if(isset($response->data->album->id)) {
248
- $albumId = $response->data->album->id;
249
- } else if(isset($response->data->product->album_id)) {
250
- $albumId = $response->data->product->album_id;
251
- // Distillery returns the product album on the 'create' verb
252
- } else if(isset($response->id)) {
253
- $albumId = $response->id;
254
}
255
256
- if($albumId) {
257
$album = $this->getPixleeAlbum();
258
- $album->setProductId($product->getId())->setPixleeAlbumId($albumId);
259
$album->save();
260
} else {
261
return false;
@@ -264,8 +436,132 @@ class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
264
Mage::log("PIXLEE ERROR: " . $e->getMessage());
265
return false;
266
}
267
}
268
269
return true;
270
}
271
}
1
<?php
2
+
3
+ require_once __DIR__ . '/RavenAutoLoader.php';
4
+ \Raven_Autoloader::register();
5
+
6
class Pixlee_Base_Helper_Data extends Mage_Core_Helper_Abstract {
7
8
protected $_unexportedProducts;
49
} elseif($this->isActive()) {
50
$pixleeAccountId = Mage::getStoreConfig('pixlee/pixlee/account_id', Mage::app()->getStore());
51
$pixleeAccountApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
52
+ $pixleeAccountSecretKey = Mage::getStoreConfig('pixlee/pixlee/account_secret_key', Mage::app()->getStore());
53
+
54
try {
55
+ $this->_pixleeAPI = new Pixlee_Pixlee($pixleeAccountApiKey, $pixleeAccountSecretKey);
56
return $this->_pixleeAPI;
57
}
58
catch (Exception $e) {
100
if($this->isInactive()) {
101
return "Save your Pixlee API access information before exporting your products.";
102
} elseif($c > 0) {
103
+ return "(Re) Export your products to Pixlee and start collecting photos.";
104
} else {
105
return "All your products have been exported to Pixlee. Congratulations!";
106
}
122
} else if($product->getTypeId() == "bundle") {
123
$mainProduct = Mage::getModel('catalog/product')->load($product->getId()); // Get original sku as stated in product catalog
124
}
125
+ $mainProductClass = get_class($mainProduct);
126
Mage::log("*** After _extractActualProduct");
127
Mage::log("Name: {$mainProduct->getName()}");
128
Mage::log("ID: {$mainProduct->getId()}");
129
Mage::log("SKU: {$mainProduct->getSku()}");
130
Mage::log("Type: {$mainProduct->getTypeId()}");
131
+ Mage::log("Class: {$mainProductClass}");
132
return $mainProduct;
133
}
134
138
// function, but as of 2016/03/11, getAggregateStock is only called after _extractActualProduct
139
// has already been called
140
public function getAggregateStock($actualProduct) {
141
+
142
+
143
Mage::log("*** In getAggregateStock");
144
$aggregateStock = NULL;
145
+
146
// If after calling _extractActualProduct, there is no 'configurable' product, and only
147
// a 'simple' product, we won't get anything back from
148
// getModel('catalog/product_type_configurable')
149
if ($actualProduct->getTypeId() == "simple") {
150
+ Mage::log("Product Type: Simple");
151
// If the product's not keeping track of inventory, we'll error out when we try
152
// to call the getQty() function on the output of getStockItem()
153
if (is_null($actualProduct->getStockItem())) {
159
// 'grouped' type products have 'associated products,' which presumably
160
// point to simple products
161
if ($actualProduct->getTypeId() == "grouped") {
162
+ Mage::log("Product Type: Grouped");
163
$childProducts = $actualProduct->getTypeInstance(true)->getAssociatedProducts($actualProduct);
164
// And finally, my original assumption that all 'simple' products are
165
// under the umbrella of some 'configurable' product
166
} else if ($actualProduct->getTypeId() == "configurable") {
167
+ if (!is_a($actualProduct, "Mage_Catalog_Model_Product")) {
168
+ Mage::log("Defaulting to empty children array, actualProduct is " . get_class($actualProduct));
169
+ $childProducts = array();
170
+ } else {
171
+ Mage::log("Product Type: Mage_Catalog_Model_Product");
172
+ $childProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null,$actualProduct);
173
+ }
174
+ } else {
175
+ Mage::log("Product Type: None");
176
+ $childProducts = array();
177
}
178
+
179
+ Mage::log("Child products of length " . sizeof($childProducts));
180
+
181
foreach ($childProducts as $child) {
182
// Sometimes Magento gives a negative inventory quantity
183
// I don't want that to affect the overall count
200
}
201
202
public function getVariantsDict($actualProduct) {
203
+
204
+ Mage::log("*** In getVariantsDict");
205
$variantsDict = array();
206
207
// If after calling _extractActualProduct, there is no 'configurable' product, and only
225
// And finally, my original assumption that all 'simple' products are
226
// under the umbrella of some 'configurable' product
227
} else if ($actualProduct->getTypeId() == "configurable") {
228
+ if (!is_a($actualProduct, "Mage_Catalog_Model_Product")) {
229
+ Mage::log("Defaulting to empty children array, actualProduct is " . get_class($actualProduct));
230
+ $childProducts = array();
231
+ } else {
232
+ $childProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null,$actualProduct);
233
+ }
234
+ } else {
235
+ $childProducts = array();
236
}
237
+
238
+ Mage::log("Child products of length " . sizeof($childProducts));
239
+
240
foreach ($childProducts as $child) {
241
// Sometimes Magento gives a negative inventory quantity
242
// I don't want that to affect the overall count
255
);
256
}
257
}
258
+
259
+ if (empty($variantsDict)) {
260
+ return "{}";
261
+ } else {
262
+ return json_encode($variantsDict);
263
+ }
264
+ }
265
+
266
+ // getter function to retrieve the category_ids and category names for a product
267
+ // one product can have more than one category, hence its a list
268
+ public function getCategories($product) {
269
+ $categoriesList = array();
270
+ $cats = $product->getCategoryIds();
271
+
272
+ foreach ($cats as $category_id) {
273
+ $_cat = Mage::getModel('catalog/category')->load($category_id);
274
+ if (is_null($_cat)) {
275
+ $fields = array();
276
+ } else {
277
+ $fields = array(
278
+ 'category_id' => (int) $_cat->getId(),
279
+ 'category_name' => $_cat->getName()
280
+ );
281
+ }
282
+
283
+ $categoriesList[] = $fields;
284
+ }
285
+
286
+ return $categoriesList;
287
+ }
288
+
289
+ // Verify that an image exists for this product
290
+ private function getImage($product) {
291
+ $image_name = '';
292
+ if ($product->getImage() != "no_selection") {
293
+ $image_name = $product->getImage();
294
+ } else if ($product->getSmallImage() != "no_selection") {
295
+ $image_name = $product->getSmallImage();
296
+ } else if ($product->getThumbnail() != "no_selection") {
297
+ $image_name = $product->getThumbnail();
298
+ }
299
+ return Mage::getModel('catalog/product_media_config')->getMediaUrl($image_name);
300
+ }
301
+
302
+ // Construct some stuff to pass to 'extra_fields'
303
+ public function getExtraFields($actualProduct) {
304
+ Mage::log("Constructing product 'extra_fields'");
305
+
306
+ // If we failed earlier in _extractActualProduct, and still have a
307
+ // Mage_Sales_Model_Order_Item class instance here, we'll error out
308
+ // when trying to call getProductOptionCollection
309
+ if (!is_a($actualProduct, 'Mage_Catalog_Model_Product')) {
310
+ $extraFields = '';
311
+ } else {
312
+
313
+ // Magento's definition of "custom options"
314
+ $customOptionsDict = array();
315
+
316
+ // Each $child here is basically an individual row
317
+ $options = Mage::getModel('catalog/product_option')->getProductOptionCollection($actualProduct);
318
+ foreach ($options as $child) {
319
+ Mage::log("* Product has an option");
320
+ // $child at this point is a PHP object, ->getValues() converts it
321
+ // to an array that we can JSONify and pass to our servers
322
+ foreach ($child->getValues() as $v) {
323
+ Mage::log("* An option:");
324
+ Mage::log($v->getData());
325
+ $customOptionsDict[] = $v->getData();
326
+ }
327
+ }
328
+
329
+ // Additionally, save all photos associated with the product
330
+ $productPhotos = array();
331
+ foreach ($actualProduct->getMediaGalleryImages() as $image) {
332
+ array_push($productPhotos, $image->getUrl());
333
+ }
334
+
335
+ // Only configurable products can do the following
336
+ // NOTE: If it gets called on a non-configurable product WE WILL FATAL ERROR
337
+ // The try/catch will NOT handle the fatal error!
338
+ $configurableAttributes = null;
339
+ try {
340
+ if ($actualProduct->isConfigurable()) {
341
+ $configurableAttributes = $actualProduct->getTypeInstance(true)->getConfigurableAttributesAsArray($actualProduct);
342
+ }
343
+ } catch (Exception $e) {
344
+ Mage::log("Got error trying to get default color, setting to null: " . $e->getMessage());
345
+ }
346
+
347
+ // In addition to Magento's "custom options", we also want to throw
348
+ // a few things in here, for our own sake
349
+ $extraFields = json_encode(array(
350
+ 'magento_custom_options' => $customOptionsDict,
351
+ 'magento_product_type' => $actualProduct->getTypeId(),
352
+ 'magento_product_visibility' => $actualProduct->getVisibility(),
353
+ 'magento_sku' => $actualProduct->getSku(),
354
+ 'magento_configurable_attributes' => $configurableAttributes,
355
+ 'product_photos' => $productPhotos,
356
+ 'categories' => $this->getCategories($actualProduct)
357
+ ));
358
+
359
+ }
360
+
361
+ Mage::log("Made 'extra_fields'");
362
+ Mage::log($extraFields);
363
+ return $extraFields;
364
}
365
366
// Whether creating a product, updating a product, or just exporting a product,
367
// this function gets called
368
+ public function exportProductToPixlee($product, $update_stock_only = False) {
369
Mage::log("*** In exportProductToPixlee");
370
+
371
+ // Whether or not to export child products in addition to the parent
372
+ $separateVariants = Mage::getStoreConfig('pixlee/advanced/export_variants_separately', Mage::app()->getStore());
373
+ // Whether or not to export products when there is no associated image
374
+ $imagelessProducts = Mage::getStoreConfig('pixlee/advanced/export_imageless_products', Mage::app()->getStore());
375
376
$pixlee = $this->getNewPixlee();
377
+ $currencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();
378
+
379
+ // Always export visible products, regardless of whether or not
380
+ // 'pixlee/advanced/export_variants_separately' is set
381
if($product->getVisibility() != 1) { // Make sure the product is visible in search or catalog
382
try {
383
+
384
+ $product = $this->_extractActualProduct($product);
385
+ $productName = $product->getName();
386
+ if($this->isInactive() || !isset($productName)) {
387
+ return false;
388
+ }
389
+
390
$aggregateStock = $this->getAggregateStock($product);
391
Mage::log("Total stock is: {$aggregateStock}");
392
$variantsDict = $this->getVariantsDict($product);
393
Mage::log("Variants dict is");
394
Mage::log($variantsDict);
395
396
+ // In case we're a visible simple product, and instead of actually having
397
+ // 'associated products' here for 'child' products, we have 'custom options' instead
398
+ $extraFields = $this->getExtraFields($product);
399
400
+ $product_mediaurl = $this->getImage($product);
401
+ if ($imagelessProducts) {
402
+ // Could be more concise, but I just wanted to make it clear I'm intentionally
403
+ // passing through here when imagelessProducts is set to true
404
+ } else if ($product_mediaurl == Mage::getModel('catalog/product_media_config')->getMediaUrl('')) {
405
+ Mage::log("PIXLEE ERROR: Could not find a valid image url for {$product->getName()}, SKU: {$product->getSku()}");
406
+ return false;
407
}
408
+ // getPrice() returns a string, need to convert to double before going to distillery
409
+ // PHP regex found here: http://stackoverflow.com/a/18747995
410
+ $product_price = floatval(preg_replace('/[^\d.]/', '', $product->getPrice()));
411
+
412
+ $response = $pixlee->createProduct($product->getName(),
413
+ $product->getSku(),
414
+ $product->getProductUrl(),
415
+ $product_mediaurl,
416
+ $product->getId(),
417
+ $product_price,
418
+ (int) $aggregateStock,
419
+ $variantsDict,
420
+ $extraFields,
421
+ $currencyCode,
422
+ $update_stock_only);
423
+
424
+ $albumId = 0;
425
426
+ // Distillery returns the product album on the 'create' verb
427
+ if(isset($response->id)) {
428
+ // Treat $response->id as the created album_id (because that's what it is)
429
$album = $this->getPixleeAlbum();
430
+ $album->setProductId($product->getId())->setPixleeAlbumId($response->id);
431
$album->save();
432
} else {
433
return false;
436
Mage::log("PIXLEE ERROR: " . $e->getMessage());
437
return false;
438
}
439
+
440
+ // But if 'pixlee/advanced/export_variants_separately' is set, export even 'invisible' product
441
+ // MOST IMPORTANTLY, use the variant-specific SKU and NAME values
442
+ } elseif ($separateVariants) {
443
+
444
+ // Still need the parent for product url
445
+ $parentProduct = $this->_extractActualProduct($product);
446
+
447
+ // $product (NOT parentProduct) at this point will return 0 for ->getQty()
448
+ // Instead: http://stackoverflow.com/a/12937631
449
+ $stockItem = Mage::getModel('cataloginventory/stock_item')
450
+ ->loadByProduct($product->getId());
451
+
452
+ // If the variant doesn't have its own image, use the parent's
453
+ if ($product->getImage() == "no_selection") {
454
+ $product_mediaurl = $this->getImage($parentProduct);
455
+ } else {
456
+ $product_mediaurl = $this->getImage($product);
457
+ }
458
+
459
+ if ($imagelessProducts) {
460
+ // Could be more concise, but I just wanted to make it clear I'm intentionally
461
+ // passing through here when imagelessProducts is set to true
462
+ } else if ($product_mediaurl == Mage::getModel('catalog/product_media_config')->getMediaUrl('')) {
463
+ Mage::log("PIXLEE ERROR: Could not find a valid image url for {$product->getName()}, SKU: {$product->getSku()}");
464
+ return false;
465
+ }
466
+
467
+
468
+ // Some convenience fields when we're an invisible child product
469
+ // (Probably not going to be used)
470
+ $extraFields = $this->getExtraFields($product);
471
+
472
+ // getPrice() returns a string, need to convert to double before going to distillery
473
+ // PHP regex found here: http://stackoverflow.com/a/18747995
474
+ $product_price = floatval(preg_replace('/[^\d.]/', '', $product->getPrice()));
475
+
476
+ // Most things we get from the $product itself, except
477
+ // 1) The product URL is wrong, and we need to get it from the 'configurable' product
478
+ // 2) We need to jump through some hoops to get the stock information
479
+ $response = $pixlee->createProduct($product->getName(),
480
+ $product->getSku(),
481
+ $parentProduct->getProductUrl(),
482
+ $product_mediaurl,
483
+ $product->getId(),
484
+ $product_price,
485
+ (int) $stockItem->getQty(),
486
+ null, // If this is a variant, don't create or send the $variantsDict
487
+ $extraFields,
488
+ $currencyCode,
489
+ $update_stock_only
490
+ );
491
+
492
+ $albumId = 0;
493
+
494
+ // Distillery returns the product album on the 'create' verb
495
+ if(isset($response->id)) {
496
+ // Treat $response->id as the created album_id (because that's what it is)
497
+ $album = $this->getPixleeAlbum();
498
+ $album->setProductId($product->getId())->setPixleeAlbumId($response->id);
499
+ $album->save();
500
+ } else {
501
+ return false;
502
+ }
503
}
504
505
return true;
506
}
507
+
508
+ public function ravenize($apiKey = null) {
509
+ if (is_null($apiKey)) {
510
+ // If I have a '$this->apiKey' property, then I'm probably an instance of
511
+ // \Pixlee\Pixlee\Helper\Pixlee, and can just use that
512
+ if (property_exists($this, 'apiKey')) {
513
+ $apiKey = $this->apiKey;
514
+ }
515
+ // If I am a class that has the 'getApiKey' function, then I'm probably
516
+ // and instance of \Pixlee\Pixlee\Helper\Data, and can call it directly
517
+ elseif (method_exists($this, 'getApiKey')) {
518
+ $apiKey = $this->getApiKey();
519
+ }
520
+ // Most classes using this trait (our Observers) have a $this->_pixleeData,
521
+ // which is an instance of \Pixlee\Pixlee\Helper\Data, and we can call
522
+ // that instance's 'getApiKey' function
523
+ elseif (property_exists($this, '_pixleeData')) {
524
+ $apiKey = $this->_pixleeData->getApiKey();
525
+ }
526
+ // If we didn't find a way to define apiKey, just return here and give
527
+ // up on trying to instantiate a Raven Handler
528
+ else {
529
+ return;
530
+ }
531
+ }
532
+ // Ask this endpoint, which we expect to remain available, for a Sentry URL
533
+ $urlToHit = "https://distillery.pixlee.com/api/v1/getSentryUrl?api_key="
534
+ . $apiKey . "&team=Pixlee&project=Magento+1";
535
+ if (property_exists($this, '_logger') && !is_null($this->_logger)) {
536
+ $this->_logger->addDebug("Asking Pixlee Distillery for Sentry URL at: "
537
+ . $urlToHit);
538
+ }
539
+ // Make the API call
540
+ $ch = curl_init( $urlToHit );
541
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
542
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
543
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
544
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array(
545
+ 'Content-Type: application/json'
546
+ )
547
+ );
548
+ $response = curl_exec($ch);
549
+ // We expect the response to look something like this:
550
+ // {"url":"https://<PUBKEY>:<PRIVKEY>@sentry.io/118103"}
551
+ $sentryUrl = json_decode($response)->{'url'};
552
+ $this->_sentryClient = new \Raven_Client($sentryUrl);
553
+ $this->_sentryClient->install();
554
+ }
555
+ }
556
+
557
+ // Try/catch only works on thrown exceptions
558
+ // Need this to report fatal errors
559
+ function shutDownFunction() {
560
+ $error = error_get_last();
561
+ // fatal error, E_ERROR === 1
562
+ if ($error['type'] === E_ERROR) {
563
+ Mage::log("PIXLEE FATAL ERROR: ");
564
+ Mage::log($error);
565
+ }
566
}
567
+ register_shutdown_function('shutDownFunction');
app/code/community/Pixlee/Base/Helper/RavenAutoLoader.php ADDED
@@ -0,0 +1,43 @@
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Raven.
5
+ *
6
+ * (c) Sentry Team
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Autoloads Raven classes.
14
+ *
15
+ * @package raven
16
+ */
17
+ class Raven_Autoloader
18
+ {
19
+ /**
20
+ * Registers Raven_Autoloader as an SPL autoloader.
21
+ */
22
+ public static function register()
23
+ {
24
+ ini_set('unserialize_callback_func', 'spl_autoload_call');
25
+ spl_autoload_register(array('Raven_Autoloader', 'autoload'));
26
+ }
27
+
28
+ /**
29
+ * Handles autoloading of classes.
30
+ *
31
+ * @param string $class A class name.
32
+ */
33
+ public static function autoload($class)
34
+ {
35
+ if (0 !== strpos($class, 'Raven')) {
36
+ return;
37
+ }
38
+
39
+ if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
40
+ require $file;
41
+ }
42
+ }
43
+ }
app/code/community/Pixlee/Base/Model/Observer.php CHANGED
@@ -1,7 +1,7 @@
1
<?php
2
class Pixlee_Base_Model_Observer {
3
4
- const ANALYTICS_BASE_URL = 'https://limitless-beyond-4328.herokuapp.com/events/';
5
protected $_urls = array();
6
7
public function __construct() {
@@ -10,6 +10,10 @@ class Pixlee_Base_Model_Observer {
10
$this->_urls['removeFromCart'] = self::ANALYTICS_BASE_URL . 'removeFromCart';
11
$this->_urls['checkoutStart'] = self::ANALYTICS_BASE_URL . 'checkoutStart';
12
$this->_urls['checkoutSuccess'] = self::ANALYTICS_BASE_URL . 'conversion';
13
}
14
15
public function isNewProductCheck(Varien_Event_Observer $observer) {
@@ -52,6 +56,9 @@ class Pixlee_Base_Model_Observer {
52
53
// ADD PRODUCT TO CART
54
public function addToCart(Varien_Event_Observer $observer) {
55
$product = $observer->getEvent()->getProduct();
56
$productData = $this->_extractProduct($product);
57
$payload = $this->_preparePayload($productData);
@@ -60,6 +67,9 @@ class Pixlee_Base_Model_Observer {
60
61
// REMOVE PRODUCT FROM CART
62
public function removeFromCart(Varien_Event_Observer $observer) {
63
$product = $observer->getEvent()->getQuoteItem();
64
$productData = $this->_extractProduct($product);
65
$payload = $this->_preparePayload($productData);
@@ -68,6 +78,9 @@ class Pixlee_Base_Model_Observer {
68
69
// CHECKOUT START
70
public function checkoutStart(Varien_Event_Observer $observer) {
71
$quote = Mage::getModel('checkout/cart')->getQuote();
72
$cartData = $this->_extractCart($quote);
73
$payload = array('cart' => $cartData);
@@ -77,6 +90,9 @@ class Pixlee_Base_Model_Observer {
77
78
// CHECKOUT SUCCESS
79
public function checkoutSuccess(Varien_Event_Observer $observer) {
80
$quote = new Mage_Sales_Model_Order();
81
$incrementId = Mage::getSingleton('checkout/session')->getLastRealOrderId();
82
$quote->loadByIncrementId($incrementId);
@@ -92,26 +108,30 @@ class Pixlee_Base_Model_Observer {
92
$helper = Mage::helper('pixlee');
93
foreach ($quote->getAllVisibleItems() as $item) {
94
$product = $helper->_extractActualProduct($item);
95
- $helper->exportProductToPixlee($product);
96
}
97
}
98
99
// CANCEL ORDER
100
public function cancelOrder(Varien_Event_Observer $observer) {
101
// When an order is cancelled, Magento ticks the stock inventory back up
102
$helper = Mage::helper('pixlee');
103
$order = $observer->getEvent()->getOrder();
104
foreach ($order->getAllVisibleItems() as $item) {
105
$product = $helper->_extractActualProduct($item);
106
- $helper->exportProductToPixlee($product);
107
}
108
}
109
110
// VALIDATE CREDENTIALS
111
public function validateCredentials(Varien_Event_Observer $observer){
112
$pixleeAccountApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
113
114
- $this->_pixleeAPI = new Pixlee_Pixlee($pixleeAccountApiKey);
115
try{
116
$this->_pixleeAPI->getAlbums();
117
}catch(Exception $e){
@@ -122,6 +142,11 @@ class Pixlee_Base_Model_Observer {
122
123
// Helper functions
124
125
protected function _getPixleeCookie() {
126
if(isset($_COOKIE['pixlee_analytics_cookie'])){
127
if($cookie = $_COOKIE['pixlee_analytics_cookie']) {
@@ -153,9 +178,6 @@ class Pixlee_Base_Model_Observer {
153
// Required key/value pairs not in the payload by default.
154
$payload['API_KEY']= Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
155
$payload['uid'] = $payload['CURRENT_PIXLEE_USER_ID'];
156
- $payload['pixlee_album_photos_timestamps'] = $payload['CURRENT_PIXLEE_ALBUM_PHOTOS_TIMESTAMP'];
157
- $payload['pixlee_album_photos'] = $payload['CURRENT_PIXLEE_ALBUM_PHOTOS'];
158
- $payload['horizontal_page'] = $payload['HORIZONTAL_PAGE'];
159
Mage::log("** After building payload");
160
$payload['ecommerce_platform'] = 'magento_1';
161
$payload['ecommerce_platform_version'] = '2.0.0';
@@ -169,32 +191,40 @@ class Pixlee_Base_Model_Observer {
169
Mage::log("* In _sendPayload");
170
Mage::log("** Payload: $payload");
171
if($payload && isset($this->_urls[$event])) {
172
- $ch = curl_init($this->_urls[$event]);
173
-
174
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
175
- curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
176
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
177
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
178
-
179
- // Set User Agent
180
- if(isset($_SERVER['HTTP_USER_AGENT'])){
181
- curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
182
- }
183
184
- $response = curl_exec($ch);
185
- $responseInfo = curl_getinfo($ch);
186
- $responseCode = $responseInfo['http_code'];
187
- curl_close($ch);
188
-
189
- if( !$this->isBetween($responseCode, 200, 299) ) {
190
- Mage::log("HTTP $responseCode response from Pixlee API", Zend_Log::ERR);
191
- } elseif ( is_object($response) && is_null( $response->status ) ) {
192
- Mage::log("Pixlee did not return a status", Zend_Log::ERR);
193
- } elseif( is_object($response) && !$this->isBetween( $response->status, 200, 299 ) ) {
194
- $errorMessage = implode(',', (array)$response->message);
195
- Mage::log("$response->status - $errorMessage ", Zend_Log::ERR);
196
- } else {
197
- return true;
198
}
199
}
200
return false;
@@ -219,16 +249,26 @@ class Pixlee_Base_Model_Observer {
219
$productData['variant_id'] = (int) $product->getIdBySku($product->getSku());
220
$productData['variant_sku'] = $product->getSku();
221
$productData['price'] = Mage::helper('core')->currency($product->getPrice(), true, false); // Get price in the main currency of the store. (USD, EUR, etc.)
222
}
223
224
// Moving _extractActualProduct into the helper, because I want to use it
225
// in product exports (when a 'simple' type product is modified in the dashboard)
226
// but don't want to duplicate code
227
$helper = Mage::helper('pixlee');
228
- // Get the actual product
229
- $product = $helper->_extractActualProduct($product);
230
- $productData['product_id'] = (int) $product->getId();
231
- $productData['product_sku'] = $product->getSku();
232
return $productData;
233
}
234
@@ -256,16 +296,34 @@ class Pixlee_Base_Model_Observer {
256
257
protected function _extractCustomer($quote) {
258
if(is_a($quote, 'Mage_Sales_Model_Quote') || is_a($quote, 'Mage_Sales_Model_Order')) {
259
- return array(
260
- 'email' => $quote->getShippingAddress()->getEmail(),
261
- 'customer_id' => $quote->getCustomerId(),
262
- 'billing_address' => $quote->getBillingAddress()->toJson(),
263
- 'shipping_address' => $quote->getShippingAddress()->toJson(),
264
- 'order_id' => (int) $quote->getRealOrderId(),
265
- 'currency' => $quote->getOrderCurrencyCode()
266
- );
267
}
268
- return false;
269
}
270
271
protected function isBetween($theNum, $low, $high){
1
<?php
2
class Pixlee_Base_Model_Observer {
3
4
+ const ANALYTICS_BASE_URL = 'https://inbound-analytics.pixlee.com/events/';
5
protected $_urls = array();
6
7
public function __construct() {
10
$this->_urls['removeFromCart'] = self::ANALYTICS_BASE_URL . 'removeFromCart';
11
$this->_urls['checkoutStart'] = self::ANALYTICS_BASE_URL . 'checkoutStart';
12
$this->_urls['checkoutSuccess'] = self::ANALYTICS_BASE_URL . 'conversion';
13
+
14
+ $raven = Mage::helper('pixlee');
15
+ $pixleeAccountApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
16
+ $raven->ravenize($pixleeAccountApiKey);
17
}
18
19
public function isNewProductCheck(Varien_Event_Observer $observer) {
56
57
// ADD PRODUCT TO CART
58
public function addToCart(Varien_Event_Observer $observer) {
59
+ if (!$this->_checkAnalyticsEnabled())
60
+ return;
61
+
62
$product = $observer->getEvent()->getProduct();
63
$productData = $this->_extractProduct($product);
64
$payload = $this->_preparePayload($productData);
67
68
// REMOVE PRODUCT FROM CART
69
public function removeFromCart(Varien_Event_Observer $observer) {
70
+ if (!$this->_checkAnalyticsEnabled())
71
+ return;
72
+
73
$product = $observer->getEvent()->getQuoteItem();
74
$productData = $this->_extractProduct($product);
75
$payload = $this->_preparePayload($productData);
78
79
// CHECKOUT START
80
public function checkoutStart(Varien_Event_Observer $observer) {
81
+ if (!$this->_checkAnalyticsEnabled())
82
+ return;
83
+
84
$quote = Mage::getModel('checkout/cart')->getQuote();
85
$cartData = $this->_extractCart($quote);
86
$payload = array('cart' => $cartData);
90
91
// CHECKOUT SUCCESS
92
public function checkoutSuccess(Varien_Event_Observer $observer) {
93
+ if (!$this->_checkAnalyticsEnabled())
94
+ return;
95
+
96
$quote = new Mage_Sales_Model_Order();
97
$incrementId = Mage::getSingleton('checkout/session')->getLastRealOrderId();
98
$quote->loadByIncrementId($incrementId);
108
$helper = Mage::helper('pixlee');
109
foreach ($quote->getAllVisibleItems() as $item) {
110
$product = $helper->_extractActualProduct($item);
111
+ $helper->exportProductToPixlee($product, $update_stock_only = True);
112
}
113
}
114
115
// CANCEL ORDER
116
public function cancelOrder(Varien_Event_Observer $observer) {
117
+ if (!$this->_checkAnalyticsEnabled())
118
+ return;
119
+
120
// When an order is cancelled, Magento ticks the stock inventory back up
121
$helper = Mage::helper('pixlee');
122
$order = $observer->getEvent()->getOrder();
123
foreach ($order->getAllVisibleItems() as $item) {
124
$product = $helper->_extractActualProduct($item);
125
+ $helper->exportProductToPixlee($product, $update_stock_only = True);
126
}
127
}
128
129
// VALIDATE CREDENTIALS
130
public function validateCredentials(Varien_Event_Observer $observer){
131
$pixleeAccountApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
132
+ $pixleeAccountSecretKey = Mage::getStoreConfig('pixlee/pixlee/account_secret_key', Mage::app()->getStore());
133
134
+ $this->_pixleeAPI = new Pixlee_Pixlee($pixleeAccountApiKey, $pixleeAccountSecretKey);
135
try{
136
$this->_pixleeAPI->getAlbums();
137
}catch(Exception $e){
142
143
// Helper functions
144
145
+ // Shorthand for having to check the config every time
146
+ protected function _checkAnalyticsEnabled(){
147
+ return Mage::getStoreConfig('pixlee/advanced/enable_analytics', Mage::app()->getStore());
148
+ }
149
+
150
protected function _getPixleeCookie() {
151
if(isset($_COOKIE['pixlee_analytics_cookie'])){
152
if($cookie = $_COOKIE['pixlee_analytics_cookie']) {
178
// Required key/value pairs not in the payload by default.
179
$payload['API_KEY']= Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
180
$payload['uid'] = $payload['CURRENT_PIXLEE_USER_ID'];
181
Mage::log("** After building payload");
182
$payload['ecommerce_platform'] = 'magento_1';
183
$payload['ecommerce_platform_version'] = '2.0.0';
191
Mage::log("* In _sendPayload");
192
Mage::log("** Payload: $payload");
193
if($payload && isset($this->_urls[$event])) {
194
+ // I'm reading that curl won't actually raise an exception, but rather
195
+ // it'll just return false - however, this couldn't hurt
196
+ try {
197
+ $ch = curl_init($this->_urls[$event]);
198
+
199
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
200
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
201
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
202
+ // If the Pixlee server doesn't respond after 3 seconds, close the connection
203
+ curl_setopt($ch, CURLOPT_TIMEOUT_MS, 3000);
204
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
205
+
206
+ // Set User Agent
207
+ if(isset($_SERVER['HTTP_USER_AGENT'])){
208
+ curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
209
+ }
210
211
+ $response = curl_exec($ch);
212
+ $responseInfo = curl_getinfo($ch);
213
+ $responseCode = $responseInfo['http_code'];
214
+ curl_close($ch);
215
+
216
+ if( !$this->isBetween($responseCode, 200, 299) ) {
217
+ Mage::log("HTTP $responseCode response from Pixlee API", Zend_Log::ERR);
218
+ } elseif ( is_object($response) && is_null( $response->status ) ) {
219
+ Mage::log("Pixlee did not return a status", Zend_Log::ERR);
220
+ } elseif( is_object($response) && !$this->isBetween( $response->status, 200, 299 ) ) {
221
+ $errorMessage = implode(',', (array)$response->message);
222
+ Mage::log("$response->status - $errorMessage ", Zend_Log::ERR);
223
+ } else {
224
+ return true;
225
+ }
226
+ } catch (Exception $e) {
227
+ Mage::log("PIXLEE ERROR: " . $e->getMessage());
228
}
229
}
230
return false;
249
$productData['variant_id'] = (int) $product->getIdBySku($product->getSku());
250
$productData['variant_sku'] = $product->getSku();
251
$productData['price'] = Mage::helper('core')->currency($product->getPrice(), true, false); // Get price in the main currency of the store. (USD, EUR, etc.)
252
+ $productData['currency'] = Mage::app()->getStore()->getCurrentCurrencyCode();
253
}
254
255
// Moving _extractActualProduct into the helper, because I want to use it
256
// in product exports (when a 'simple' type product is modified in the dashboard)
257
// but don't want to duplicate code
258
$helper = Mage::helper('pixlee');
259
+
260
+ // Here we need to know whether to pass back the parent product SKU
261
+ // or the variant product SKU, based on 'export_variants_separately'
262
+ $separateVariants = Mage::getStoreConfig('pixlee/advanced/export_variants_separately', Mage::app()->getStore());
263
+
264
+ if ($separateVariants) {
265
+ $productData['product_id'] = (int) $product->getIdBySku($product->getSku());
266
+ $productData['product_sku'] = $product->getSku();
267
+ } else {
268
+ $product = $helper->_extractActualProduct($product);
269
+ $productData['product_id'] = (int) $product->getId();
270
+ $productData['product_sku'] = $product->getSku();
271
+ }
272
return $productData;
273
}
274
296
297
protected function _extractCustomer($quote) {
298
if(is_a($quote, 'Mage_Sales_Model_Quote') || is_a($quote, 'Mage_Sales_Model_Order')) {
299
+
300
+ $result = array();
301
+
302
+ if (method_exists($quote, 'getShippingAddress')) {
303
+ $shippingAddress = $quote->getShippingAddress();
304
+ if (!empty($shippingAddress)) {
305
+ $email = $shippingAddress->getEmail();
306
+ if (!$email && method_exists($quote, 'getCustomerEmail')) $email = $quote->getCustomerEmail();
307
+ }
308
+ $result['email'] = $email;
309
+ }
310
+
311
+ if (method_exists($quote, 'getCustomerId')) { $
312
+ $result['customer_id'] = $quote->getCustomerId();
313
+ }
314
+
315
+ if (method_exists($quote, 'getRealOrderId')) {
316
+ $result['order_id'] = $quote->getRealOrderId();
317
+ }
318
+
319
+ if (method_exists($quote, 'getOrderCurrencyCode')) {
320
+ $result['currency'] = $quote->getOrderCurrencyCode();
321
+ }
322
+
323
+ return $result;
324
+ } else {
325
+ return false;
326
}
327
}
328
329
protected function isBetween($theNum, $low, $high){
app/code/community/Pixlee/Base/controllers/Pixlee/ExportController.php CHANGED
@@ -3,30 +3,55 @@ class Pixlee_Base_Pixlee_ExportController extends Mage_Adminhtml_Controller_Acti
3
4
public function exportAction() {
5
6
$helper = Mage::helper('pixlee');
7
$json = array();
8
9
if($helper->isActive()) {
10
- $products = $helper->getUnexportedProducts();
11
- $products->getSelect()->limit(10); // Set the limit to 10 to prevent lagging out the store or Pixlee's API.
12
foreach($products as $product) {
13
$ids = $product->getStoreIds();
14
if(isset($ids[0])) {
15
$product->setStoreId($ids[0]);
16
}
17
$helper->exportProductToPixlee($product);
18
- }
19
20
- $count = $helper->getUnexportedProducts(false)->count(); // Find out how many products are left to export
21
- if($count) {
22
- $json = array(
23
- 'action' => 'continue',
24
- 'url' => Mage::helper('adminhtml')->getUrl('*/pixlee_export/export'),
25
- 'remaining' => $count
26
- );
27
- } else {
28
- $json = array('action' => 'success');
29
}
30
}
31
32
$json['pixlee_remaining_text'] = $helper->getPixleeRemainingText();
3
4
public function exportAction() {
5
6
+ // The original author of this class relied on limiting selects to 10 and calling
7
+ // the getUnexportedProducts function until it returned no unexported products
8
+ // Instead, we're now going to export the entire product set every time
9
+ // Every 100 exports, sleep for 1 second
10
+ $export_chunk_size = 100;
11
+ $export_sleep_sec = 1;
12
+
13
$helper = Mage::helper('pixlee');
14
$json = array();
15
16
+ $raven = Mage::helper('pixlee');
17
+ $pixleeAccountApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
18
+ $raven->ravenize($pixleeAccountApiKey);
19
+
20
if($helper->isActive()) {
21
+
22
+ $separateVariants = Mage::getStoreConfig('pixlee/advanced/export_variants_separately', Mage::app()->getStore());
23
+
24
+ if ($separateVariants) {
25
+ $products = Mage::getModel('catalog/product')->getCollection();
26
+ } else {
27
+ $products = Mage::getModel('catalog/product')->getCollection()->addAttributeToFilter('visibility', array('neq' => 1));
28
+ }
29
+ $products->getSelect();
30
+ $products->addAttributeToSelect('*');
31
+
32
+ // Manually throttle our exports
33
+ $counter = 0;
34
+
35
foreach($products as $product) {
36
$ids = $product->getStoreIds();
37
if(isset($ids[0])) {
38
$product->setStoreId($ids[0]);
39
}
40
+ $counter += 1;
41
+ if (is_null($product)) {
42
+ // Just a check to be extra sure. We had a customer where $product was null and caused FATAL errors
43
+ continue;
44
+ }
45
$helper->exportProductToPixlee($product);
46
47
+ // Now that we don't have the ->getSelect()->limit(10) to keep ourselves from
48
+ // overloading stuff, we'll have to manage it ourselves
49
+ if($counter % $export_chunk_size == 0) {
50
+ sleep($export_sleep_sec);
51
+ }
52
}
53
+
54
+ $json = array('action' => 'success');
55
}
56
57
$json['pixlee_remaining_text'] = $helper->getPixleeRemainingText();
app/code/community/Pixlee/Base/etc/config.xml CHANGED
@@ -2,9 +2,18 @@
2
<config>
3
<modules>
4
<Pixlee_Base>
5
- <version>2.0.0.5</version>
6
</Pixlee_Base>
7
</modules>
8
<global>
9
<blocks>
10
<pixlee>
2
<config>
3
<modules>
4
<Pixlee_Base>
5
+ <version>2.0.0.24</version>
6
</Pixlee_Base>
7
</modules>
8
+ <default>
9
+ <pixlee>
10
+ <advanced>
11
+ <enable_analytics>1</enable_analytics>
12
+ <export_variants_separately>0</export_variants_separately>
13
+ <export_imageless_products>0</export_imageless_products>
14
+ </advanced>
15
+ </pixlee>
16
+ </default>
17
<global>
18
<blocks>
19
<pixlee>
app/code/community/Pixlee/Base/etc/config.xml.bak CHANGED
@@ -2,9 +2,18 @@
2
<config>
3
<modules>
4
<Pixlee_Base>
5
- <version>2.0.0.5</version>
6
</Pixlee_Base>
7
</modules>
8
<global>
9
<blocks>
10
<pixlee>
2
<config>
3
<modules>
4
<Pixlee_Base>
5
+ <version>2.0.0.24</version>
6
</Pixlee_Base>
7
</modules>
8
+ <default>
9
+ <pixlee>
10
+ <advanced>
11
+ <enable_analytics>1</enable_analytics>
12
+ <export_variants_separately>0</export_variants_separately>
13
+ <export_imageless_products>0</export_imageless_products>
14
+ </advanced>
15
+ </pixlee>
16
+ </default>
17
<global>
18
<blocks>
19
<pixlee>
app/code/community/Pixlee/Base/etc/system.xml CHANGED
@@ -16,10 +16,55 @@
16
<show_in_website>1</show_in_website>
17
<show_in_store>1</show_in_store>
18
<groups>
19
<pixlee translate="label" module="pixlee">
20
<label>API Credentials</label>
21
<frontend_type>text</frontend_type>
22
- <sort_order>1</sort_order>
23
<show_in_default>1</show_in_default>
24
<show_in_website>1</show_in_website>
25
<show_in_store>1</show_in_store>
@@ -41,24 +86,14 @@
41
<show_in_website>1</show_in_website>
42
<show_in_store>1</show_in_store>
43
</account_api_key>
44
- <recipe_id translate="label">
45
- <label>Recipe ID</label>
46
- <frontend_type>text</frontend_type>
47
- <sort_order>40</sort_order>
48
- <show_in_default>1</show_in_default>
49
- <show_in_website>1</show_in_website>
50
- <show_in_store>1</show_in_store>
51
- <comment>You can get this from the "Publish Products" button under "My Albums."</comment>
52
- </recipe_id>
53
- <display_options_id translate="label">
54
- <label>Display Options ID</label>
55
<frontend_type>text</frontend_type>
56
- <sort_order>50</sort_order>
57
<show_in_default>1</show_in_default>
58
<show_in_website>1</show_in_website>
59
<show_in_store>1</show_in_store>
60
- <comment>You can get this from the "Publish Products" button under "My Albums."</comment>
61
- </display_options_id>
62
<check translate="label">
63
<label>Export Products</label>
64
<frontend_type>button</frontend_type>
@@ -70,6 +105,74 @@
70
</check>
71
</fields>
72
</pixlee>
73
</groups>
74
</pixlee>
75
</sections>
16
<show_in_website>1</show_in_website>
17
<show_in_store>1</show_in_store>
18
<groups>
19
+ <demo translate="label" module="pixlee">
20
+ <label>Not a Customer?</label>
21
+ <comment>Please submit the following form and we will get in touch with you shortly</comment>
22
+ <frontend_type>text</frontend_type>
23
+ <sort_order>1</sort_order>
24
+ <show_in_default>1</show_in_default>
25
+ <show_in_website>1</show_in_website>
26
+ <show_in_store>1</show_in_store>
27
+ <fields>
28
+ <name translate="label">
29
+ <label>Your Name</label>
30
+ <frontend_type>text</frontend_type>
31
+ <sort_order>1</sort_order>
32
+ <show_in_default>1</show_in_default>
33
+ <show_in_website>1</show_in_website>
34
+ <show_in_store>1</show_in_store>
35
+ </name>
36
+ <email translate="label">
37
+ <label>Your Email</label>
38
+ <frontend_type>text</frontend_type>
39
+ <sort_order>2</sort_order>
40
+ <show_in_default>1</show_in_default>
41
+ <show_in_website>1</show_in_website>
42
+ <show_in_store>1</show_in_store>
43
+ </email>
44
+ <website translate="label">
45
+ <label>Your Website</label>
46
+ <frontend_type>text</frontend_type>
47
+ <sort_order>3</sort_order>
48
+ <show_in_default>1</show_in_default>
49
+ <show_in_website>1</show_in_website>
50
+ <show_in_store>1</show_in_store>
51
+ </website>
52
+ <request_demo translate="label">
53
+ <label>Request Demo</label>
54
+ <frontend_type>button</frontend_type>
55
+ <frontend_model>pixlee/adminhtml_system_config_form_demo</frontend_model>
56
+ <sort_order>60</sort_order>
57
+ <show_in_default>1</show_in_default>
58
+ <show_in_website>1</show_in_website>
59
+ <show_in_store>1</show_in_store>
60
+ </request_demo>
61
+
62
+ </fields>
63
+ </demo>
64
<pixlee translate="label" module="pixlee">
65
<label>API Credentials</label>
66
<frontend_type>text</frontend_type>
67
+ <sort_order>2</sort_order>
68
<show_in_default>1</show_in_default>
69
<show_in_website>1</show_in_website>
70
<show_in_store>1</show_in_store>
86
<show_in_website>1</show_in_website>
87
<show_in_store>1</show_in_store>
88
</account_api_key>
89
+ <account_secret_key translate="label">
90
+ <label><![CDATA[Account Secret Key <span style="color:#F00">*</span>]]></label>
91
<frontend_type>text</frontend_type>
92
+ <sort_order>30</sort_order>
93
<show_in_default>1</show_in_default>
94
<show_in_website>1</show_in_website>
95
<show_in_store>1</show_in_store>
96
+ </account_secret_key>
97
<check translate="label">
98
<label>Export Products</label>
99
<frontend_type>button</frontend_type>
105
</check>
106
</fields>
107
</pixlee>
108
+ <widget_options translate="label" module="pixlee">
109
+ <label>PDP Widget Options</label>
110
+ <frontend_type>text</frontend_type>
111
+ <sort_order>3</sort_order>
112
+ <show_in_default>1</show_in_default>
113
+ <show_in_website>1</show_in_website>
114
+ <show_in_store>1</show_in_store>
115
+ <fields>
116
+ <widget_id translate="label">
117
+ <label>PDP Widget ID</label>
118
+ <frontend_type>text</frontend_type>
119
+ <sort_order>70</sort_order>
120
+ <show_in_default>1</show_in_default>
121
+ <show_in_website>1</show_in_website>
122
+ <show_in_store>1</show_in_store>
123
+ <comment>You can get this from "Install PDP Widget" (Navigate to "Albums" and then "Products")</comment>
124
+ </widget_id>
125
+ <category_widget_id translate="label">
126
+ <label>Category Widget ID</label>
127
+ <frontend_type>text</frontend_type>
128
+ <sort_order>70</sort_order>
129
+ <show_in_default>1</show_in_default>
130
+ <show_in_website>1</show_in_website>
131
+ <show_in_store>1</show_in_store>
132
+ <comment>You can get this from "Install PDP Widget" (Navigate to "Albums" and then "Products")</comment>
133
+ </category_widget_id>
134
+ </fields>
135
+ </widget_options>
136
+ <advanced translate="label" module="pixlee">
137
+ <label>Advanced</label>
138
+ <frontend_type>text</frontend_type>
139
+ <sort_order>4</sort_order>
140
+ <show_in_default>1</show_in_default>
141
+ <show_in_website>1</show_in_website>
142
+ <show_in_store>1</show_in_store>
143
+ <fields>
144
+ <enable_analytics translate="label">
145
+ <label>Enable Commerce Analytics</label>
146
+ <frontend_type>select</frontend_type>
147
+ <source_model>adminhtml/system_config_source_yesno</source_model>
148
+ <sort_order>90</sort_order>
149
+ <show_in_default>1</show_in_default>
150
+ <show_in_website>1</show_in_website>
151
+ <show_in_store>1</show_in_store>
152
+ <comment>Toggle sending commerce data on a per-store basis.</comment>
153
+ </enable_analytics>
154
+ <export_variants_separately translate="label">
155
+ <label>Export Variants Separately</label>
156
+ <frontend_type>select</frontend_type>
157
+ <source_model>adminhtml/system_config_source_yesno</source_model>
158
+ <sort_order>100</sort_order>
159
+ <show_in_default>1</show_in_default>
160
+ <show_in_website>1</show_in_website>
161
+ <show_in_store>1</show_in_store>
162
+ <comment>Export variants (simple products that exist under a configurable) as their own products (e.g. colors/sizes).</comment>
163
+ </export_variants_separately>
164
+ <export_imageless_products translate="label">
165
+ <label>Export Image-less Products</label>
166
+ <frontend_type>select</frontend_type>
167
+ <source_model>adminhtml/system_config_source_yesno</source_model>
168
+ <sort_order>110</sort_order>
169
+ <show_in_default>1</show_in_default>
170
+ <show_in_website>1</show_in_website>
171
+ <show_in_store>1</show_in_store>
172
+ <comment>Export products even if they don't have images. (Not recommended!)</comment>
173
+ </export_imageless_products>
174
+ </fields>
175
+ </advanced>
176
</groups>
177
</pixlee>
178
</sections>
app/code/community/Pixlee/Base/version.txt CHANGED
@@ -1 +1 @@
1
- bbfc54faea99e144ba914015816822fb4e2c7b37
1
+ 3f657125cdaf7e0a0a4fe37da260176eec674dd1
app/design/adminhtml/default/default/template/pixlee/system/config/demo_button.phtml ADDED
@@ -0,0 +1,44 @@
1
+ <script type="text/javascript">
2
+ //<![CDATA[
3
+ function requestDemo() {
4
+ var name = document.getElementById('pixlee_demo_name').value
5
+ var email = document.getElementById('pixlee_demo_email').value
6
+ var website = document.getElementById('pixlee_demo_website').value
7
+
8
+
9
+ if (name === '') {
10
+ alert('Name cannot be empty. Please try again.');
11
+ return;
12
+ }
13
+ if (email === '') {
14
+ alert('Email cannot be empty. Please try again.');
15
+ return;
16
+
17
+ }
18
+
19
+ var params = "?source=magento_1&name=" + name + "&email=" + email + "&website" + website;
20
+
21
+ var request = new XMLHttpRequest();
22
+ request.onreadystatechange = function() {
23
+ if (this.readyState == 4) {
24
+ if (this.status >= 200 && this.status < 400) {
25
+ var response = JSON.parse(this.responseText);
26
+ if (response && response.result === "Successful") {
27
+ $('request_demo_button').addClassName('disabled');
28
+ alert('Thanks for requesting a demo. We will get in touch with you shortly.');
29
+ } else {
30
+ alert('Opps! Something went wrong. While we are working on resolving the issue, feel free to reach us at hi@pixleeteam.com');
31
+ }
32
+ } else {
33
+ alert('Opps! Something went wrong. While we are working on resolving the issue, feel free to reach us at hi@pixleeteam.com');
34
+ }
35
+ }
36
+ }
37
+
38
+ request.open('POST', "https://app.pixlee.com/leads/add" + params, true);
39
+ request.send();
40
+ }
41
+ //]]>
42
+ </script>
43
+
44
+ <?php echo $this->getButtonHtml() ?>
app/design/frontend/base/default/layout/pixlee/gallery.xml CHANGED
@@ -1,16 +1,7 @@
1
<?xml version="1.0"?>
2
<layout version="0.1.0">
3
<!--
4
- To implement the Pixlee gallery, insert the "pixlee_gallery_tag"
5
- update handle in the layout XML for your page. Example:
6
-
7
- <catalog_product_view translate="label">
8
- <update handle="pixlee_gallery_tag" />
9
- </catalog_product_view>
10
-
11
- Once you've added the update handle, the Pixlee external JS script
12
- will be embedded in the head of the page and you should be able to
13
- make the following call anywhere on that page:
14
15
<?php echo $this->getLayout()->createBlock('pixlee/gallery')->toHtml(); ?>
16
@@ -24,25 +15,22 @@
24
25
<?php echo $this->getLayout()->createBlock('pixlee/gallery')->setProductSku($SKU)->toHtml(); ?>
26
-->
27
- <pixlee_gallery_tag translate="label">
28
- <label>Pixlee gallery and external script</label>
29
-
30
- <reference name="head">
31
- <!-- <block type="core/text" name="pixlee_external_js" as="pixlee_external_js">
32
- <action method="setText"><text><![CDATA[<script src="//assets.pixlee.com/javascripts/embed/widget/pixlee_widget.v2.js"></script>]]></text></action>
33
- </block> -->
34
- </reference>
35
-
36
- </pixlee_gallery_tag>
37
38
- <default translate="label">
39
- <update handle="pixlee_gallery_tag" />
40
- </default>
41
42
- <catalog_product_view>
43
<reference name="head">
44
- <action method="addJs"><script>pixlee/getAnalyticsCookie.js</script></action>
45
</reference>
46
- </catalog_product_view>
47
48
</layout>
1
<?xml version="1.0"?>
2
<layout version="0.1.0">
3
<!--
4
+ You should be able to make the following call on any page:
5
6
<?php echo $this->getLayout()->createBlock('pixlee/gallery')->toHtml(); ?>
7
15
16
<?php echo $this->getLayout()->createBlock('pixlee/gallery')->setProductSku($SKU)->toHtml(); ?>
17
-->
18
19
+ <!-- How to insert your JavaScript on all Magento pages? http://magento.stackexchange.com/questions/59897/load-js-in-footer-in-magento -->
20
21
+ <default>
22
<reference name="head">
23
+ <block type="core/text" name="pixlee_events">
24
+ <action method="setText">
25
+ <text>
26
+ <![CDATA[
27
+ <script type="text/javascript" src="https://assets.pixlee.com/assets/pixlee_events.js"></script>
28
+ ]]>
29
+ </text>
30
+ </action>
31
+ </block>
32
+ <block type="page/html" name="pixlee_events_invocation" template="pixlee/pixlee_tracking_pixel.phtml"/>
33
</reference>
34
+ </default>
35
36
</layout>
app/design/frontend/base/default/template/pixlee/category_gallery.phtml ADDED
@@ -0,0 +1,29 @@
1
+ <?php
2
+ $helper = Mage::helper('pixlee');
3
+ $nativeCategoryId = $this->category_id;
4
+ if($helper->isActive() && !empty($nativeCategoryId)):
5
+ $pixleeCategoryWidgetId = $this->getCategoryWidgetId();
6
+ $pixleeAccountApiKey = $this->getAccountApiKey();
7
+ ?>
8
+ <div id="pixlee_container"></div>
9
+ <div id="pixlee_widget_master_container"></div>
10
+ <script id="pixlee_script">
11
+
12
+ window.PixleeAsyncInit = function() {
13
+ Pixlee.init({
14
+ apiKey: '<?php echo $pixleeAccountApiKey; ?>'
15
+ });
16
+ Pixlee.addCategoryWidget({
17
+ widgetId: <?php echo $pixleeCategoryWidgetId; ?>,
18
+ nativeCategoryId: <?php echo $nativeCategoryId; ?>,
19
+ ecomm_platform: 'magento'
20
+ });
21
+ };
22
+ </script>
23
+ <script src="https://assets.pixlee.com/assets/pixlee_widget_1_0_0.js"></script>
24
+
25
+ <?php elseif(empty($nativeCategoryId)): ?>
26
+ <!-- Could not display the Pixlee gallery. No product SKU found. Try explicitly setting one with the "setProductSku" function after creating the block. -->
27
+ <?php else: ?>
28
+ <!-- Could not display the Pixlee gallery. Make sure all the required credentials are saved in the Magento admin panel! -->
29
+ <?php endif; ?>
app/design/frontend/base/default/template/pixlee/gallery.phtml CHANGED
@@ -3,8 +3,7 @@ $helper = Mage::helper('pixlee');
3
$productSku = $this->getProductSku();
4
if($helper->isActive() && !empty($productSku)):
5
$pixleeAccountId = $this->getAccountId();
6
- $pixleeRecipeId = $this->getRecipeId();
7
- $pixleeDisplayOptionsId = $this->getDisplayOptionsId();
8
$pixleeAccountApiKey = $this->getAccountApiKey();
9
?>
10
<div id="pixlee_container"></div>
@@ -16,10 +15,8 @@ if($helper->isActive() && !empty($productSku)):
16
apiKey: '<?php echo $pixleeAccountApiKey; ?>'
17
});
18
Pixlee.addProductWidget({
19
skuId: '<?php echo $productSku; ?>',
20
- recipeId: <?php echo $pixleeRecipeId; ?>,
21
- displayOptionsId: <?php echo $pixleeDisplayOptionsId; ?>,
22
- type:"horizontal",
23
accountId:<?php echo $pixleeAccountId; ?>
24
});
25
};
3
$productSku = $this->getProductSku();
4
if($helper->isActive() && !empty($productSku)):
5
$pixleeAccountId = $this->getAccountId();
6
+ $pixleeWidgetId = $this->getWidgetId();
7
$pixleeAccountApiKey = $this->getAccountApiKey();
8
?>
9
<div id="pixlee_container"></div>
15
apiKey: '<?php echo $pixleeAccountApiKey; ?>'
16
});
17
Pixlee.addProductWidget({
18
+ widgetId: <?php echo $pixleeWidgetId; ?>,
19
skuId: '<?php echo $productSku; ?>',
20
accountId:<?php echo $pixleeAccountId; ?>
21
});
22
};
app/design/frontend/base/default/template/pixlee/pixlee_tracking_pixel.phtml ADDED
@@ -0,0 +1,6 @@
1
+ <?php
2
+ $pixleeAccountApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
3
+ ?>
4
+ <script id="initialize_pixlee_tracking">
5
+ pixlee_analytics = new Pixlee_Analytics('<?php echo $pixleeAccountApiKey; ?>');
6
+ </script>
js/pixlee/getAnalyticsCookie.js DELETED
@@ -1,37 +0,0 @@
1
- var createPixleeAnalyticsCookie = function() {
2
- var iframe = document.createElement('iframe');
3
- iframe.style.display = "none";
4
- iframe.src = 'https://photos.pixlee.com/getDUH';
5
- document.body.appendChild(iframe);
6
-
7
- window.addEventListener("message", function receiveMessage(event) {
8
- try {
9
- var eventData = JSON.parse(event.data);
10
- if (eventData.function == "pixlee_distinct_user_hash") {
11
- if (eventData.data) {
12
- var distinct_user_hash_linker = eventData.value;
13
- setCookie('pixlee_analytics_cookie', encodeURIComponent(JSON.stringify({
14
- CURRENT_PIXLEE_USER_ID: distinct_user_hash_linker,
15
- CURRENT_PIXLEE_ALBUM_PHOTOS: [],
16
- HORIZONTAL_PAGE: [],
17
- CURRENT_PIXLEE_ALBUM_PHOTOS_TIMESTAMP: []
18
- })), 30);
19
- }
20
- }
21
- } catch(e) {
22
- console.log("Exception " + e);
23
- };
24
- }, false);
25
- }
26
-
27
- var setCookie = function(name, value, days) {
28
- if (days) {
29
- var date = new Date();
30
- date.setTime(date.getTime()+(days*24*60*60*1000));
31
- var expires = "; expires="+date.toGMTString();
32
- }
33
- else var expires = "";
34
- document.cookie = name+"="+value+expires+"; path=/; domain=" + window.location.host.replace('www', '');
35
- };
36
-
37
- window.addEventListener('load', createPixleeAnalyticsCookie);
lib/Pixlee/Pixlee.php CHANGED
@@ -2,16 +2,15 @@
2
class Pixlee_Pixlee {
3
private $apiKey;
4
private $baseURL;
5
6
- // Constructor - distillery no longer REQUIRES secretKey or userID
7
- // Also, make explicit the fact that we're no longer passing the user key,
8
- // but the account key
9
- public function __construct($accountApiKey){
10
if( is_null( $accountApiKey )){
11
throw new Exception("An API Key is required");
12
}
13
$this->apiKey = $accountApiKey;
14
- $this->baseURL = "http://distillery.pixlee.com/api/v2";
15
}
16
17
public function getAlbums(){
@@ -40,7 +39,7 @@ class Pixlee_Pixlee {
40
}
41
*/
42
43
- public function createProduct($product_name, $sku, $product_url , $product_image, $product_id = NULL, $aggregateStock = NULL, $variantsDict = NULL){
44
Mage::log("* In createProduct");
45
/*
46
Converted from Rails API format to distillery API format
@@ -78,12 +77,24 @@ class Pixlee_Pixlee {
78
// Let's hope I'm right.
79
$product_id = (int) $product_id;
80
81
- $product = array('name' => $product_name, 'sku' => $sku, 'buy_now_link_url' => $product_url,
82
- 'product_photo' => $product_image, 'stock' => $aggregateStock,
83
- 'native_product_id' => $product_id, 'variants_json' => $variantsDict);
84
$data = array('title' => $product_name, 'album_type' => 'product', 'live_update' => false, 'num_photo' => 0,
85
'num_inbox_photo' => 0, 'product' => $product);
86
- $payload = $this->signedData($data);
87
return $this->postToAPI( "/albums?api_key=" . $this->apiKey, $payload );
88
}
89
@@ -123,7 +134,9 @@ class Pixlee_Pixlee {
123
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
124
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
125
'Content-Type: application/json',
126
- 'Content-Length: ' . strlen($payload)
127
)
128
);
129
$response = curl_exec($ch);
@@ -132,13 +145,8 @@ class Pixlee_Pixlee {
132
return $this->handleResponse($response, $ch);
133
}
134
135
- // The rails API takes a signature, which was a sha256 of the payload
136
- // we were about to send, JSONified.
137
- // There was also a check for a JSON_UNESCAPED_SLASHES constant, which would
138
- // 'fix' the JSON before encoding, for older PHP versions
139
- // Since distillery doesn't check such a signature, this function is now much simpler
140
- private function signedData($data){
141
- return json_encode($data);
142
}
143
144
private function handleResponse($response, $ch){
2
class Pixlee_Pixlee {
3
private $apiKey;
4
private $baseURL;
5
+ private $secretKey;
6
7
+ public function __construct($accountApiKey, $accountSecretKey){
8
if( is_null( $accountApiKey )){
9
throw new Exception("An API Key is required");
10
}
11
$this->apiKey = $accountApiKey;
12
+ $this->secretKey = $accountSecretKey;
13
+ $this->baseURL = "https://distillery.pixlee.com/api/v2";
14
}
15
16
public function getAlbums(){
39
}
40
*/
41
42
+ public function createProduct($product_name, $sku, $product_url , $product_image, $product_id = NULL, $product_price, $aggregateStock = NULL, $variantsDict = NULL, $extraFields = NULL, $currencyCode, $update_stock_only = False){
43
Mage::log("* In createProduct");
44
/*
45
Converted from Rails API format to distillery API format
77
// Let's hope I'm right.
78
$product_id = (int) $product_id;
79
80
+ // If 'update_stock_only' is True (which it is not by default), do not send the URL along
81
+ if ($update_stock_only == True) {
82
+ $product = array('name' => $product_name, 'sku' => $sku, 'stock' => $aggregateStock);
83
+ } else {
84
+ $product = array('name' => $product_name, 'sku' => $sku, 'buy_now_link_url' => $product_url,
85
+ 'product_photo' => $product_image, 'price' => $product_price, 'stock' => $aggregateStock,
86
+ 'native_product_id' => $product_id, 'variants_json' => $variantsDict,
87
+ 'extra_fields' => $extraFields, 'currency' => $currencyCode);
88
+ }
89
$data = array('title' => $product_name, 'album_type' => 'product', 'live_update' => false, 'num_photo' => 0,
90
'num_inbox_photo' => 0, 'product' => $product);
91
+
92
+ //Fix for php versions that don't support JSON_UNESCAPED_SLASHES (< php 5.4)
93
+ if(defined("JSON_UNESCAPED_SLASHES")){
94
+ $payload = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
95
+ } else {
96
+ $payload = str_replace('\\/', '/', json_encode($data));
97
+ }
98
return $this->postToAPI( "/albums?api_key=" . $this->apiKey, $payload );
99
}
100
134
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
135
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
136
'Content-Type: application/json',
137
+ 'X-Alt-Referer: magento.pixlee.com',
138
+ 'Content-Length: ' . strlen($payload),
139
+ 'Signature: ' . $this->generateSignature($payload)
140
)
141
);
142
$response = curl_exec($ch);
145
return $this->handleResponse($response, $ch);
146
}
147
148
+ private function generateSignature($data) {
149
+ return base64_encode(hash_hmac('sha1', $data, $this->secretKey, true));
150
}
151
152
private function handleResponse($response, $ch){
lib/Raven/Autoloader.php ADDED
@@ -0,0 +1,43 @@
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Raven.
5
+ *
6
+ * (c) Sentry Team
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Autoloads Raven classes.
14
+ *
15
+ * @package raven
16
+ */
17
+ class Raven_Autoloader
18
+ {
19
+ /**
20
+ * Registers Raven_Autoloader as an SPL autoloader.
21
+ */
22
+ public static function register()
23
+ {
24
+ ini_set('unserialize_callback_func', 'spl_autoload_call');
25
+ spl_autoload_register(array('Raven_Autoloader', 'autoload'));
26
+ }
27
+
28
+ /**
29
+ * Handles autoloading of classes.
30
+ *
31
+ * @param string $class A class name.
32
+ */
33
+ public static function autoload($class)
34
+ {
35
+ if (0 !== strpos($class, 'Raven')) {
36
+ return;
37
+ }
38
+
39
+ if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
40
+ require $file;
41
+ }
42
+ }
43
+ }
lib/Raven/Breadcrumbs.php ADDED
@@ -0,0 +1,60 @@
1
+ <?php
2
+ /*
3
+ * This file is part of Raven.
4
+ *
5
+ * (c) Sentry Team
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+
11
+ /**
12
+ * Raven Breadcrumbs
13
+ *
14
+ * @package raven
15
+ */
16
+
17
+ class Raven_Breadcrumbs
18
+ {
19
+ public function __construct($size = 100)
20
+ {
21
+ $this->count = 0;
22
+ $this->pos = 0;
23
+ $this->size = $size;
24
+ $this->buffer = array();
25
+ }
26
+
27
+ public function record($crumb)
28
+ {
29
+ if (empty($crumb['timestamp'])) {
30
+ $crumb['timestamp'] = microtime(true);
31
+ }
32
+ $this->buffer[$this->pos] = $crumb;
33
+ $this->pos = ($this->pos + 1) % $this->size;
34
+ $this->count++;
35
+ }
36
+
37
+ public function fetch()
38
+ {
39
+ $results = array();
40
+ for ($i = 0; $i <= ($this->size - 1); $i++) {
41
+ $idx = ($this->pos + $i) % $this->size;
42
+ if (isset($this->buffer[$idx])) {
43
+ $results[] = $this->buffer[$idx];
44
+ }
45
+ }
46
+ return $results;
47
+ }
48
+
49
+ public function is_empty()
50
+ {
51
+ return $this->count === 0;
52
+ }
53
+
54
+ public function to_json()
55
+ {
56
+ return array(
57
+ 'values' => $this->fetch(),
58
+ );
59
+ }
60
+ }
lib/Raven/Breadcrumbs/ErrorHandler.php ADDED
@@ -0,0 +1,47 @@
1
+ <?php
2
+
3
+ class Raven_Breadcrumbs_ErrorHandler
4
+ {
5
+ private $existingHandler;
6
+
7
+ /**
8
+ * @var Raven_Client the client object that sends the message to the server
9
+ */
10
+ protected $ravenClient;
11
+
12
+ /**
13
+ * @param Raven_Client $ravenClient
14
+ * @param int $level The minimum logging level at which this handler will be triggered
15
+ * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
16
+ */
17
+ public function __construct(Raven_Client $ravenClient)
18
+ {
19
+ $this->ravenClient = $ravenClient;
20
+ }
21
+
22
+ public function handleError($code, $message, $file = '', $line = 0, $context=array())
23
+ {
24
+ $this->ravenClient->breadcrumbs->record(array(
25
+ 'category' => 'error_reporting',
26
+ 'message' => $message,
27
+ 'level' => $this->ravenClient->translateSeverity($code),
28
+ 'data' => array(
29
+ 'code' => $code,
30
+ 'line' => $line,
31
+ 'file' => $file,
32
+ ),
33
+ ));
34
+
35
+ if ($this->existingHandler !== null) {
36
+ return call_user_func($this->existingHandler, $code, $message, $file, $line, $context);
37
+ } else {
38
+ return false;
39
+ }
40
+ }
41
+
42
+ public function install()
43
+ {
44
+ $this->existingHandler = set_error_handler(array($this, 'handleError'), E_ALL);
45
+ return $this;
46
+ }
47
+ }
lib/Raven/Breadcrumbs/MonologHandler.php ADDED
@@ -0,0 +1,94 @@
1
+ <?php
2
+
3
+ use Monolog\Logger;
4
+ use Monolog\Handler\AbstractProcessingHandler;
5
+
6
+ class Raven_Breadcrumbs_MonologHandler extends AbstractProcessingHandler
7
+ {
8
+ /**
9
+ * Translates Monolog log levels to Raven log levels.
10
+ */
11
+ private $logLevels = array(
12
+ Logger::DEBUG => Raven_Client::DEBUG,
13
+ Logger::INFO => Raven_Client::INFO,
14
+ Logger::NOTICE => Raven_Client::INFO,
15
+ Logger::WARNING => Raven_Client::WARNING,
16
+ Logger::ERROR => Raven_Client::ERROR,
17
+ Logger::CRITICAL => Raven_Client::FATAL,
18
+ Logger::ALERT => Raven_Client::FATAL,
19
+ Logger::EMERGENCY => Raven_Client::FATAL,
20
+ );
21
+
22
+ private $excMatch = '/^exception \'([^\']+)\' with message \'(.+)\' in .+#x2F;s';
23
+
24
+ /**
25
+ * @var Raven_Client the client object that sends the message to the server
26
+ */
27
+ protected $ravenClient;
28
+
29
+ /**
30
+ * @param Raven_Client $ravenClient
31
+ * @param int $level The minimum logging level at which this handler will be triggered
32
+ * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
33
+ */
34
+ public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
35
+ {
36
+ parent::__construct($level, $bubble);
37
+
38
+ $this->ravenClient = $ravenClient;
39
+ }
40
+
41
+ protected function parseException($message)
42
+ {
43
+ if (!preg_match($this->excMatch, $message, $matches)) {
44
+ return;
45
+ }
46
+
47
+ return array($matches[1], $matches[2]);
48
+ }
49
+
50
+ /**
51
+ * {@inheritdoc}
52
+ */
53
+ protected function write(array $record)
54
+ {
55
+ // sentry uses the 'nobreadcrumb' attribute to skip reporting
56
+ if (!empty($record['context']['nobreadcrumb'])) {
57
+ return;
58
+ }
59
+
60
+ if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
61
+ $exc = $record['context']['exception'];
62
+ $crumb = array(
63
+ 'type' => 'error',
64
+ 'level' => $this->logLevels[$record['level']],
65
+ 'category' => $record['channel'],
66
+ 'data' => array(
67
+ 'type' => get_class($exc),
68
+ 'value' => $exc->getMessage(),
69
+ ),
70
+ );
71
+ } else {
72
+ // TODO(dcramer): parse exceptions out of messages and format as above
73
+ if ($error = $this->parseException($record['message'])) {
74
+ $crumb = array(
75
+ 'type' => 'error',
76
+ 'level' => $this->logLevels[$record['level']],
77
+ 'category' => $record['channel'],
78
+ 'data' => array(
79
+ 'type' => $error[0],
80
+ 'value' => $error[1],
81
+ ),
82
+ );
83
+ } else {
84
+ $crumb = array(
85
+ 'level' => $this->logLevels[$record['level']],
86
+ 'category' => $record['channel'],
87
+ 'message' => $record['message'],
88
+ );
89
+ }
90
+ }
91
+
92
+ $this->ravenClient->breadcrumbs->record($crumb);
93
+ }
94
+ }
lib/Raven/Client.php ADDED
@@ -0,0 +1,1155 @@