Nosto_Tagging - Version 2.5.0

Version Notes

* Add order status and payment provider info to order tagging
* Add support for account specific sub-domains when configuring Nosto
* Add support for choosing the product image version used in tagging
* Fix product update event observer store scope
* Fix cart/order tagging to always tag the same product ID as on the product page the item was added to the cart/ordered from

Download this release

Release Info

Developer Nosto
Extension Nosto_Tagging
Version 2.5.0
Comparing to
See all releases


Code changes from version 2.4.0 to 2.5.0

Files changed (118) hide show
  1. app/code/community/Nosto/Tagging/Block/Addtocart.php +0 -0
  2. app/code/community/Nosto/Tagging/Block/Adminhtml/Iframe.php +2 -2
  3. app/code/community/Nosto/Tagging/Block/Adminhtml/Wizard.php +0 -0
  4. app/code/community/Nosto/Tagging/Block/Cart.php +108 -30
  5. app/code/community/Nosto/Tagging/Block/Category.php +0 -0
  6. app/code/community/Nosto/Tagging/Block/Customer.php +0 -0
  7. app/code/community/Nosto/Tagging/Block/Element.php +0 -0
  8. app/code/community/Nosto/Tagging/Block/Embed.php +0 -0
  9. app/code/community/Nosto/Tagging/Block/Meta.php +0 -0
  10. app/code/community/Nosto/Tagging/Block/Order.php +0 -0
  11. app/code/community/Nosto/Tagging/Block/Product.php +0 -0
  12. app/code/community/Nosto/Tagging/Helper/Account.php +6 -9
  13. app/code/community/Nosto/Tagging/Helper/Customer.php +0 -0
  14. app/code/community/Nosto/Tagging/Helper/Data.php +20 -0
  15. app/code/community/Nosto/Tagging/Helper/Date.php +0 -0
  16. app/code/community/Nosto/Tagging/Helper/Oauth.php +0 -0
  17. app/code/community/Nosto/Tagging/Helper/Price.php +0 -0
  18. app/code/community/Nosto/Tagging/Helper/Url.php +0 -0
  19. app/code/community/Nosto/Tagging/Model/Base.php +54 -0
  20. app/code/community/Nosto/Tagging/Model/Container/Cart.php +0 -0
  21. app/code/community/Nosto/Tagging/Model/Container/Customer.php +0 -0
  22. app/code/community/Nosto/Tagging/Model/Customer.php +0 -0
  23. app/code/community/Nosto/Tagging/Model/Meta/Account.php +0 -0
  24. app/code/community/Nosto/Tagging/Model/Meta/Account/Billing.php +0 -0
  25. app/code/community/Nosto/Tagging/Model/Meta/Account/Iframe.php +0 -0
  26. app/code/community/Nosto/Tagging/Model/Meta/Account/Owner.php +0 -0
  27. app/code/community/Nosto/Tagging/Model/Meta/Oauth.php +0 -0
  28. app/code/community/Nosto/Tagging/Model/Meta/Order.php +7 -13
  29. app/code/community/Nosto/Tagging/Model/Meta/Order/Buyer.php +0 -0
  30. app/code/community/Nosto/Tagging/Model/Meta/Order/Item.php +115 -15
  31. app/code/community/Nosto/Tagging/Model/Meta/Order/Status.php +0 -0
  32. app/code/community/Nosto/Tagging/Model/Meta/Product.php +43 -11
  33. app/code/community/Nosto/Tagging/Model/Observer.php +12 -5
  34. app/code/community/Nosto/Tagging/Model/Resource/Customer.php +0 -0
  35. app/code/community/Nosto/Tagging/Model/Resource/Customer/Collection.php +0 -0
  36. app/code/community/Nosto/Tagging/Model/Resource/Setup.php +0 -0
  37. app/code/community/Nosto/Tagging/Model/System/Config/Source/Image.php +63 -0
  38. app/code/community/Nosto/Tagging/controllers/Adminhtml/NostoController.php +0 -0
  39. app/code/community/Nosto/Tagging/controllers/ExportController.php +2 -2
  40. app/code/community/Nosto/Tagging/controllers/OauthController.php +0 -0
  41. app/code/community/Nosto/Tagging/etc/adminhtml.xml +11 -0
  42. app/code/community/Nosto/Tagging/etc/cache.xml +0 -0
  43. app/code/community/Nosto/Tagging/etc/config.xml +8 -1
  44. app/code/community/Nosto/Tagging/etc/system.xml +62 -0
  45. app/code/community/Nosto/Tagging/sql/tagging_setup/mysql4-install-1.2.0.php +0 -0
  46. app/code/community/Nosto/Tagging/sql/tagging_setup/mysql4-upgrade-1.1.7-1.2.0.php +0 -0
  47. app/design/adminhtml/default/default/layout/nostotagging.xml +1 -1
  48. app/design/adminhtml/default/default/template/nostotagging/iframe.phtml +0 -0
  49. app/design/adminhtml/default/default/template/nostotagging/wizard.phtml +0 -0
  50. app/design/frontend/base/default/layout/nostotagging.xml +0 -0
  51. app/design/frontend/base/default/template/nostotagging/addtocart.phtml +0 -0
  52. app/design/frontend/base/default/template/nostotagging/cart.phtml +3 -3
  53. app/design/frontend/base/default/template/nostotagging/category.phtml +0 -0
  54. app/design/frontend/base/default/template/nostotagging/category/view.phtml +0 -0
  55. app/design/frontend/base/default/template/nostotagging/customer.phtml +0 -0
  56. app/design/frontend/base/default/template/nostotagging/element.phtml +0 -0
  57. app/design/frontend/base/default/template/nostotagging/embed.phtml +0 -0
  58. app/design/frontend/base/default/template/nostotagging/meta.phtml +0 -0
  59. app/design/frontend/base/default/template/nostotagging/order.phtml +3 -0
  60. app/design/frontend/base/default/template/nostotagging/product.phtml +0 -0
  61. app/etc/modules/Nosto_Tagging.xml +0 -0
  62. js/nosto/{nostotagging-config.js → NostoAdmin.js} +0 -0
  63. js/nosto/NostoIframe.min.js +1 -1
  64. js/nosto/iframeresizer.min.js +0 -0
  65. lib/nosto/php-sdk/src/.env.example +1 -1
  66. lib/nosto/php-sdk/src/classes/Nosto.php +0 -0
  67. lib/nosto/php-sdk/src/classes/NostoAccount.php +81 -19
  68. lib/nosto/php-sdk/src/classes/NostoCipher.php +0 -0
  69. lib/nosto/php-sdk/src/classes/NostoDotEnv.php +0 -0
  70. lib/nosto/php-sdk/src/classes/NostoMessage.php +0 -0
  71. lib/nosto/php-sdk/src/classes/NostoModelValidator.php +0 -90
  72. lib/nosto/php-sdk/src/classes/NostoObject.php +58 -0
  73. lib/nosto/php-sdk/src/classes/NostoOrderConfirmation.php +0 -0
  74. lib/nosto/php-sdk/src/classes/NostoProductReCrawl.php +12 -9
  75. lib/nosto/php-sdk/src/classes/NostoValidator.php +161 -0
  76. lib/nosto/php-sdk/src/classes/api/NostoApiRequest.php +2 -1
  77. lib/nosto/php-sdk/src/classes/api/NostoApiToken.php +64 -7
  78. lib/nosto/php-sdk/src/classes/collection/NostoCollection.php +0 -0
  79. lib/nosto/php-sdk/src/classes/collection/NostoOrderCollection.php +0 -0
  80. lib/nosto/php-sdk/src/classes/collection/NostoProductCollection.php +0 -0
  81. lib/nosto/php-sdk/src/classes/exception/NostoException.php +0 -0
  82. lib/nosto/php-sdk/src/classes/exception/NostoHttpException.php +0 -0
  83. lib/nosto/php-sdk/src/classes/export/NostoExportOrderCollection.php +1 -1
  84. lib/nosto/php-sdk/src/classes/export/NostoExportProductCollection.php +0 -0
  85. lib/nosto/php-sdk/src/classes/export/NostoExporter.php +2 -1
  86. lib/nosto/php-sdk/src/classes/helper/NostoHelper.php +0 -0
  87. lib/nosto/php-sdk/src/classes/helper/NostoHelperDate.php +0 -0
  88. lib/nosto/php-sdk/src/classes/helper/NostoHelperIframe.php +1 -11
  89. lib/nosto/php-sdk/src/classes/helper/NostoHelperPrice.php +0 -0
  90. lib/nosto/php-sdk/src/classes/http/NostoHttpRequest.php +8 -5
  91. lib/nosto/php-sdk/src/classes/http/NostoHttpRequestAdapter.php +0 -0
  92. lib/nosto/php-sdk/src/classes/http/NostoHttpRequestAdapterCurl.php +5 -5
  93. lib/nosto/php-sdk/src/classes/http/NostoHttpRequestAdapterSocket.php +0 -0
  94. lib/nosto/php-sdk/src/classes/http/NostoHttpResponse.php +54 -52
  95. lib/nosto/php-sdk/src/classes/oauth/NostoOAuthClient.php +0 -0
  96. lib/nosto/php-sdk/src/classes/oauth/NostoOAuthToken.php +0 -0
  97. lib/nosto/php-sdk/src/classes/operation/NostoOperationProduct.php +27 -13
  98. lib/nosto/php-sdk/src/config.inc.php +3 -2
  99. lib/nosto/php-sdk/src/interfaces/NostoExportCollectionInterface.php +0 -0
  100. lib/nosto/php-sdk/src/interfaces/NostoOAuthClientMetaDataInterface.php +0 -0
  101. lib/nosto/php-sdk/src/interfaces/NostoProductInterface.php +0 -0
  102. lib/nosto/php-sdk/src/interfaces/{NostoValidatableModelInterface.php → NostoValidatableInterface.php} +3 -3
  103. lib/nosto/php-sdk/src/interfaces/account/NostoAccountInterface.php +1 -1
  104. lib/nosto/php-sdk/src/interfaces/account/NostoAccountMetaDataBillingDetailsInterface.php +0 -0
  105. lib/nosto/php-sdk/src/interfaces/account/NostoAccountMetaDataIframeInterface.php +0 -0
  106. lib/nosto/php-sdk/src/interfaces/account/NostoAccountMetaDataInterface.php +0 -0
  107. lib/nosto/php-sdk/src/interfaces/account/NostoAccountMetaDataOwnerInterface.php +0 -0
  108. lib/nosto/php-sdk/src/interfaces/order/NostoOrderBuyerInterface.php +0 -0
  109. lib/nosto/php-sdk/src/interfaces/order/NostoOrderInterface.php +0 -0
  110. lib/nosto/php-sdk/src/interfaces/order/NostoOrderPurchasedItemInterface.php +0 -0
  111. lib/nosto/php-sdk/src/interfaces/order/NostoOrderStatusInterface.php +0 -0
  112. lib/nosto/php-sdk/src/js/NostoIframe.min.js +1 -1
  113. lib/nosto/php-sdk/src/js/src/NostoIframe.js +3 -2
  114. lib/nosto/php-sdk/src/libs/phpseclib/crypt/NostoCryptAES.php +0 -0
  115. lib/nosto/php-sdk/src/libs/phpseclib/crypt/NostoCryptBase.php +0 -0
  116. lib/nosto/php-sdk/src/libs/phpseclib/crypt/NostoCryptRandom.php +0 -0
  117. lib/nosto/php-sdk/src/libs/phpseclib/crypt/NostoCryptRijndael.php +0 -0
  118. package.xml +9 -7
app/code/community/Nosto/Tagging/Block/Addtocart.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Block/Adminhtml/Iframe.php CHANGED
@@ -35,7 +35,7 @@
35
  */
36
  class Nosto_Tagging_Block_Adminhtml_Iframe extends Mage_Adminhtml_Block_Template
37
  {
38
- const DEFAULT_ADMIN_IFRAME_ORIGIN = 'https://my.nosto.com';
39
 
40
  /**
41
  * @var string the iframe url if SSO to Nosto can be made.
@@ -114,6 +114,6 @@ class Nosto_Tagging_Block_Adminhtml_Iframe extends Mage_Adminhtml_Block_Template
114
  public function getIframeOrigin()
115
  {
116
  return (string)Mage::app()->getRequest()
117
- ->getEnv('NOSTO_IFRAME_ORIGIN', self::DEFAULT_ADMIN_IFRAME_ORIGIN);
118
  }
119
  }
35
  */
36
  class Nosto_Tagging_Block_Adminhtml_Iframe extends Mage_Adminhtml_Block_Template
37
  {
38
+ const DEFAULT_IFRAME_ORIGIN_REGEXP = '(https:\/\/magento-([a-z0-9]+)\.hub\.nosto\.com)|(https:\/\/my\.nosto\.com)';
39
 
40
  /**
41
  * @var string the iframe url if SSO to Nosto can be made.
114
  public function getIframeOrigin()
115
  {
116
  return (string)Mage::app()->getRequest()
117
+ ->getEnv('NOSTO_IFRAME_ORIGIN_REGEXP', self::DEFAULT_IFRAME_ORIGIN_REGEXP);
118
  }
119
  }
app/code/community/Nosto/Tagging/Block/Adminhtml/Wizard.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Block/Cart.php CHANGED
@@ -73,9 +73,8 @@ class Nosto_Tagging_Block_Cart extends Mage_Checkout_Block_Cart_Abstract
73
  }
74
 
75
  /**
76
- * Returns all visible cart items. If it is a bundle product with dynamic
77
- * price settings, we get it's products and return them. Fixed price bundle
78
- * is not supported.
79
  *
80
  * @return Mage_Sales_Model_Quote_Item[]
81
  */
@@ -83,52 +82,131 @@ class Nosto_Tagging_Block_Cart extends Mage_Checkout_Block_Cart_Abstract
83
  {
84
  if (!$this->_items) {
85
  $items = array();
86
- /** @var $visibleItems Mage_Sales_Model_Quote_Item[] */
87
- $visibleItems = parent::getItems();
88
- foreach ($visibleItems as $item) {
89
  $product = $item->getProduct();
90
- if ($product->getTypeId() === Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
91
- if ((int)$product->getPriceType() === Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED) {
92
- continue;
93
- }
94
- $items = array_merge($items, $item->getChildren());
95
- } else {
96
- $items[] = $item;
97
  }
 
98
  }
99
-
100
  $this->_items = $items;
101
  }
102
-
103
  return $this->_items;
104
  }
105
 
106
  /**
107
  * Returns the product id for a quote item.
108
- * If the product type is "grouped", then return the grouped product's id
109
- * and not the id of the actual product.
 
 
 
110
  *
111
  * @param Mage_Sales_Model_Quote_Item $item the quote item model.
112
  *
113
- * @return int
114
  */
115
  public function getProductId($item)
116
  {
117
- switch ($item->getProductType()) {
118
- case Mage_Catalog_Model_Product_Type::TYPE_GROUPED:
119
- $option = $item->getOptionByCode('product_type');
120
- if ($option !== null) {
121
- $productId = $option->getProductId();
122
- } else {
123
- $productId = $item->getProductId();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
125
- break;
 
126
 
127
- default:
128
- $productId = $item->getProductId();
129
- break;
130
  }
131
 
132
- return (int)$productId;
133
  }
134
  }
73
  }
74
 
75
  /**
76
+ * Returns all visible cart items.
77
+ * Fixed price bundle products are not supported.
 
78
  *
79
  * @return Mage_Sales_Model_Quote_Item[]
80
  */
82
  {
83
  if (!$this->_items) {
84
  $items = array();
85
+ foreach (parent::getItems() as $item) {
86
+ /** @var Mage_Sales_Model_Quote_Item $item */
 
87
  $product = $item->getProduct();
88
+ if ($product->getTypeId() === Mage_Catalog_Model_Product_Type::TYPE_BUNDLE
89
+ && (int)$product->getPriceType() === Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED
90
+ ) {
91
+ continue;
 
 
 
92
  }
93
+ $items[] = $item;
94
  }
 
95
  $this->_items = $items;
96
  }
 
97
  return $this->_items;
98
  }
99
 
100
  /**
101
  * Returns the product id for a quote item.
102
+ * Always try to find the "parent" product ID if the product is a child of
103
+ * another product type. We do this because it is the parent product that
104
+ * we tag on the product page, and the child does not always have it's own
105
+ * product page. This is important because it is the tagged info on the
106
+ * product page that is used to generate recommendations and email content.
107
  *
108
  * @param Mage_Sales_Model_Quote_Item $item the quote item model.
109
  *
110
+ * @return int|string
111
  */
112
  public function getProductId($item)
113
  {
114
+ $parentItem = $item->getOptionByCode('product_type');
115
+ if (!is_null($parentItem)) {
116
+ return $parentItem->getProductId();
117
+ } elseif ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) {
118
+ /** @var Mage_Catalog_Model_Product_Type_Configurable $model */
119
+ $model = Mage::getModel('catalog/product_type_configurable');
120
+ $parentIds = $model->getParentIdsByChild($item->getProductId());
121
+ $attributes = $item->getBuyRequest()->getData('super_attribute');
122
+ // If the product has a configurable parent, we assume we should tag
123
+ // the parent. If there are many parent IDs, we are safer to tag the
124
+ // products own ID.
125
+ if (count($parentIds) === 1 && !empty($attributes)) {
126
+ return $parentIds[0];
127
+ }
128
+ }
129
+ return $item->getProductId();
130
+ }
131
+
132
+ /**
133
+ * Returns the name for a quote item.
134
+ * Configurable products will have their chosen options added to their name.
135
+ * Bundle products will have their chosen child product names added.
136
+ * Grouped products will have their parent product name prepended.
137
+ * All others will have their own name only.
138
+ *
139
+ * @param Mage_Sales_Model_Quote_Item $item the quote item model.
140
+ *
141
+ * @return string
142
+ */
143
+ public function getProductName($item)
144
+ {
145
+ $name = $item->getName();
146
+ $optNames = array();
147
+
148
+ if ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) {
149
+ /** @var Mage_Catalog_Model_Product_Type_Configurable $model */
150
+ $model = Mage::getModel('catalog/product_type_configurable');
151
+ $parentIds = $model->getParentIdsByChild($item->getProductId());
152
+ // If the product has a configurable parent, we assume we should tag
153
+ // the parent. If there are many parent IDs, we are safer to tag the
154
+ // products own name alone.
155
+ if (count($parentIds) === 1) {
156
+ $attributes = $item->getBuyRequest()->getData('super_attribute');
157
+ foreach ($attributes as $id => $value) {
158
+ /** @var Mage_Catalog_Model_Resource_Eav_Attribute $attribute */
159
+ $attribute = Mage::getModel('catalog/resource_eav_attribute')
160
+ ->load($id);
161
+ $label = $attribute->getSource()->getOptionText($value);
162
+ if (!empty($label)) {
163
+ $optNames[] = $label;
164
+ }
165
+ }
166
+ }
167
+ } elseif ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) {
168
+ /* @var $helper Mage_Catalog_Helper_Product_Configuration */
169
+ $helper = Mage::helper('catalog/product_configuration');
170
+ foreach ($helper->getConfigurableOptions($item) as $opt) {
171
+ if (isset($opt['value']) && is_string($opt['value'])) {
172
+ $optNames[] = $opt['value'];
173
+ }
174
+ }
175
+ } elseif ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
176
+ $type = $item->getProduct()->getTypeInstance(true);
177
+ $opts = $type->getOrderOptions($item->getProduct());
178
+ if (isset($opts['bundle_options']) && is_array($opts['bundle_options'])) {
179
+ foreach ($opts['bundle_options'] as $opt) {
180
+ if (isset($opt['value']) && is_array($opt['value'])) {
181
+ foreach ($opt['value'] as $val) {
182
+ $qty = '';
183
+ if (isset($val['qty']) && is_int($val['qty'])) {
184
+ $qty .= $val['qty'] . ' x ';
185
+ }
186
+ if (isset($val['title']) && is_string($val['title'])) {
187
+ $optNames[] = $qty . $val['title'];
188
+ }
189
+ }
190
+ }
191
+ }
192
+ }
193
+ } elseif ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_GROUPED) {
194
+ $config = $item->getBuyRequest()->getData('super_product_config');
195
+ if (isset($config['product_id'])) {
196
+ /** @var Mage_Catalog_Model_Product $parent */
197
+ $parent = Mage::getModel('catalog/product')
198
+ ->load($config['product_id']);
199
+ $parentName = $parent->getName();
200
+ if (!empty($parentName)) {
201
+ $name = $parentName.' - '.$name;
202
  }
203
+ }
204
+ }
205
 
206
+ if (!empty($optNames)) {
207
+ $name .= ' (' . implode(', ', $optNames) . ')';
 
208
  }
209
 
210
+ return $name;
211
  }
212
  }
app/code/community/Nosto/Tagging/Block/Category.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Block/Customer.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Block/Element.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Block/Embed.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Block/Meta.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Block/Order.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Block/Product.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Helper/Account.php CHANGED
@@ -67,11 +67,11 @@ class Nosto_Tagging_Helper_Account extends Mage_Core_Helper_Abstract
67
  /** @var Mage_Core_Model_Config $config */
68
  $config = Mage::getModel('core/config');
69
  $config->saveConfig(
70
- self::XML_PATH_ACCOUNT, $account->name, 'stores', $store->getId()
71
  );
72
  $tokens = array();
73
- foreach ($account->tokens as $token) {
74
- $tokens[$token->name] = $token->value;
75
  }
76
  $config->saveConfig(
77
  self::XML_PATH_TOKENS, json_encode($tokens), 'stores',
@@ -134,17 +134,14 @@ class Nosto_Tagging_Helper_Account extends Mage_Core_Helper_Abstract
134
  }
135
  $accountName = $store->getConfig(self::XML_PATH_ACCOUNT);
136
  if (!empty($accountName)) {
137
- $account = new NostoAccount();
138
- $account->name = $accountName;
139
  $tokens = json_decode(
140
  $store->getConfig(self::XML_PATH_TOKENS), true
141
  );
142
  if (is_array($tokens) && !empty($tokens)) {
143
  foreach ($tokens as $name => $value) {
144
- $token = new NostoApiToken();
145
- $token->name = $name;
146
- $token->value = $value;
147
- $account->tokens[] = $token;
148
  }
149
  }
150
  return $account;
67
  /** @var Mage_Core_Model_Config $config */
68
  $config = Mage::getModel('core/config');
69
  $config->saveConfig(
70
+ self::XML_PATH_ACCOUNT, $account->getName(), 'stores', $store->getId()
71
  );
72
  $tokens = array();
73
+ foreach ($account->getTokens() as $token) {
74
+ $tokens[$token->getName()] = $token->getValue();
75
  }
76
  $config->saveConfig(
77
  self::XML_PATH_TOKENS, json_encode($tokens), 'stores',
134
  }
135
  $accountName = $store->getConfig(self::XML_PATH_ACCOUNT);
136
  if (!empty($accountName)) {
137
+ $account = new NostoAccount($accountName);
 
138
  $tokens = json_decode(
139
  $store->getConfig(self::XML_PATH_TOKENS), true
140
  );
141
  if (is_array($tokens) && !empty($tokens)) {
142
  foreach ($tokens as $name => $value) {
143
+ $token = new NostoApiToken($name, $value);
144
+ $account->addApiToken($token);
 
 
145
  }
146
  }
147
  return $account;
app/code/community/Nosto/Tagging/Helper/Customer.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Helper/Data.php CHANGED
@@ -34,8 +34,16 @@
34
  */
35
  class Nosto_Tagging_Helper_Data extends Mage_Core_Helper_Abstract
36
  {
 
 
 
37
  const XML_PATH_INSTALLATION_ID = 'nosto_tagging/installation/id';
38
 
 
 
 
 
 
39
  /**
40
  * Builds a tagging string of the given category including all its parent
41
  * categories.
@@ -89,4 +97,16 @@ class Nosto_Tagging_Helper_Data extends Mage_Core_Helper_Abstract
89
  }
90
  return $installationId;
91
  }
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
34
  */
35
  class Nosto_Tagging_Helper_Data extends Mage_Core_Helper_Abstract
36
  {
37
+ /**
38
+ * Path to store config installation ID.
39
+ */
40
  const XML_PATH_INSTALLATION_ID = 'nosto_tagging/installation/id';
41
 
42
+ /**
43
+ * Path to store config nosto product image version.
44
+ */
45
+ const XML_PATH_IMAGE_VERSION = 'nosto_tagging/image_options/image_version';
46
+
47
  /**
48
  * Builds a tagging string of the given category including all its parent
49
  * categories.
97
  }
98
  return $installationId;
99
  }
100
+
101
+ /**
102
+ * Return the product image version to include in product tagging.
103
+ *
104
+ * @param Mage_Core_Model_Store|null $store the store model or null.
105
+ *
106
+ * @return string
107
+ */
108
+ public function getProductImageVersion($store = null)
109
+ {
110
+ return Mage::getStoreConfig(self::XML_PATH_IMAGE_VERSION, $store);
111
+ }
112
  }
app/code/community/Nosto/Tagging/Helper/Date.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Helper/Oauth.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Helper/Price.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Helper/Url.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Base.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magentocommerce.com for more information.
20
+ *
21
+ * @category Nosto
22
+ * @package Nosto_Tagging
23
+ * @author Nosto Solutions Ltd <magento@nosto.com>
24
+ * @copyright Copyright (c) 2013-2015 Nosto Solutions Ltd (http://www.nosto.com)
25
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
26
+ */
27
+
28
+ /**
29
+ * Base class for Nosto models that share basic functionality.
30
+ *
31
+ * @category Nosto
32
+ * @package Nosto_Tagging
33
+ * @author Nosto Solutions Ltd <magento@nosto.com>
34
+ */
35
+ class Nosto_Tagging_Model_Base extends Mage_Core_Model_Abstract
36
+ {
37
+ /**
38
+ * Returns a protected/private property value by invoking it's public getter.
39
+ *
40
+ * The getter names are assumed to be the property name in camel case with preceding word "get".
41
+ *
42
+ * @param string $name the property name.
43
+ * @return mixed the property value.
44
+ * @throws NostoException if public getter does not exist.
45
+ */
46
+ public function __get($name)
47
+ {
48
+ $getter = 'get'.str_replace('_', '', $name);
49
+ if (method_exists($this, $getter)) {
50
+ return $this->{$getter}();
51
+ }
52
+ throw new NostoException(sprintf('Property `%s.%s` is not defined.', get_class($this), $name));
53
+ }
54
+ }
app/code/community/Nosto/Tagging/Model/Container/Cart.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Container/Customer.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Customer.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Meta/Account.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Meta/Account/Billing.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Meta/Account/Iframe.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Meta/Account/Owner.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Meta/Oauth.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Meta/Order.php CHANGED
@@ -167,20 +167,14 @@ class Nosto_Tagging_Model_Meta_Order extends Mage_Core_Model_Abstract implements
167
  /** @var Mage_Catalog_Model_Product $product */
168
  $product = Mage::getModel('catalog/product')
169
  ->load($item->getProductId());
170
- if ($product->getTypeId() === Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
171
- if ((int)$product->getPriceType() === Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED) {
172
- continue;
173
- }
174
- foreach ($item->getChildrenItems() as $child) {
175
- $orderItem = new Nosto_Tagging_Model_Meta_Order_Item();
176
- $orderItem->loadData($child);
177
- $this->_items[] = $orderItem;
178
- }
179
- } else {
180
- $orderItem = new Nosto_Tagging_Model_Meta_Order_Item();
181
- $orderItem->loadData($item);
182
- $this->_items[] = $orderItem;
183
  }
 
 
 
184
  }
185
 
186
  if ($this->includeSpecialItems) {
167
  /** @var Mage_Catalog_Model_Product $product */
168
  $product = Mage::getModel('catalog/product')
169
  ->load($item->getProductId());
170
+ if ($product->getTypeId() === Mage_Catalog_Model_Product_Type::TYPE_BUNDLE
171
+ && (int)$product->getPriceType() === Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED
172
+ ) {
173
+ continue;
 
 
 
 
 
 
 
 
 
174
  }
175
+ $orderItem = new Nosto_Tagging_Model_Meta_Order_Item();
176
+ $orderItem->loadData($item);
177
+ $this->_items[] = $orderItem;
178
  }
179
 
180
  if ($this->includeSpecialItems) {
app/code/community/Nosto/Tagging/Model/Meta/Order/Buyer.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Meta/Order/Item.php CHANGED
@@ -178,24 +178,124 @@ class Nosto_Tagging_Model_Meta_Order_Item extends Mage_Core_Model_Abstract imple
178
  */
179
  public function loadData(Mage_Sales_Model_Order_Item $item)
180
  {
181
- switch ($item->getProductType()) {
182
- case Mage_Catalog_Model_Product_Type::TYPE_GROUPED:
183
- $info = $item->getProductOptionByCode('info_buyRequest');
184
- if ($info !== null && isset($info['super_product_config']['product_id'])) {
185
- $this->_productId = (int)$info['super_product_config']['product_id'];
186
- } else {
187
- $this->_productId = (int)$item->getProductId();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  }
189
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
- default:
192
- $this->_productId = (int)$item->getProductId();
193
- break;
194
  }
195
 
196
- $this->_quantity = (int)$item->getQtyOrdered();
197
- $this->_name = $item->getName();
198
- $this->_unitPrice = $item->getPriceInclTax();
199
- $this->_currencyCode = $item->getOrder()->getOrderCurrencyCode();
200
  }
201
  }
178
  */
179
  public function loadData(Mage_Sales_Model_Order_Item $item)
180
  {
181
+ $order = $item->getOrder();
182
+ $this->_productId = (int)$this->fetchProductId($item);
183
+ $this->_quantity = (int)$item->getQtyOrdered();
184
+ $this->_name = $this->fetchProductName($item);
185
+ $this->_unitPrice = $item->getPriceInclTax();
186
+ $this->_currencyCode = strtoupper($order->getOrderCurrencyCode());
187
+ }
188
+
189
+ /**
190
+ * Returns the product id for a quote item.
191
+ * Always try to find the "parent" product ID if the product is a child of
192
+ * another product type. We do this because it is the parent product that
193
+ * we tag on the product page, and the child does not always have it's own
194
+ * product page. This is important because it is the tagged info on the
195
+ * product page that is used to generate recommendations and email content.
196
+ *
197
+ * @param Mage_Sales_Model_Order_Item $item the sales item model.
198
+ *
199
+ * @return int
200
+ */
201
+ protected function fetchProductId(Mage_Sales_Model_Order_Item $item)
202
+ {
203
+ $parent = $item->getProductOptionByCode('super_product_config');
204
+ if (isset($parent['product_id'])) {
205
+ return $parent['product_id'];
206
+ } elseif ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) {
207
+ /** @var Mage_Catalog_Model_Product_Type_Configurable $model */
208
+ $model = Mage::getModel('catalog/product_type_configurable');
209
+ $parentIds = $model->getParentIdsByChild($item->getProductId());
210
+ $attributes = $item->getBuyRequest()->getData('super_attribute');
211
+ // If the product has a configurable parent, we assume we should tag
212
+ // the parent. If there are many parent IDs, we are safer to tag the
213
+ // products own ID.
214
+ if (count($parentIds) === 1 && !empty($attributes)) {
215
+ return $parentIds[0];
216
+ }
217
+ }
218
+ return $item->getProductId();
219
+ }
220
+
221
+ /**
222
+ * Returns the name for a sales item.
223
+ * Configurable products will have their chosen options added to their name.
224
+ * Bundle products will have their chosen child product names added.
225
+ * Grouped products will have their parents name prepended.
226
+ * All others will have their own name only.
227
+ *
228
+ * @param Mage_Sales_Model_Order_Item $item the sales item model.
229
+ *
230
+ * @return string
231
+ */
232
+ protected function fetchProductName(Mage_Sales_Model_Order_Item $item)
233
+ {
234
+ $name = $item->getName();
235
+ $optNames = array();
236
+
237
+ if ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) {
238
+ /** @var Mage_Catalog_Model_Product_Type_Configurable $model */
239
+ $model = Mage::getModel('catalog/product_type_configurable');
240
+ $parentIds = $model->getParentIdsByChild($item->getProductId());
241
+ // If the product has a configurable parent, we assume we should tag
242
+ // the parent. If there are many parent IDs, we are safer to tag the
243
+ // products own name alone.
244
+ if (count($parentIds) === 1) {
245
+ $attributes = $item->getBuyRequest()->getData('super_attribute');
246
+ foreach ($attributes as $id => $value) {
247
+ /** @var Mage_Catalog_Model_Resource_Eav_Attribute $attribute */
248
+ $attribute = Mage::getModel('catalog/resource_eav_attribute')
249
+ ->load($id);
250
+ $label = $attribute->getSource()->getOptionText($value);
251
+ if (!empty($label)) {
252
+ $optNames[] = $label;
253
+ }
254
  }
255
+ }
256
+ } elseif ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) {
257
+ $opts = $item->getProductOptionByCode('attributes_info');
258
+ if (is_array($opts)) {
259
+ foreach ($opts as $opt) {
260
+ if (isset($opt['value']) && is_string($opt['value'])) {
261
+ $optNames[] = $opt['value'];
262
+ }
263
+ }
264
+ }
265
+ } elseif ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
266
+ $opts = $item->getProductOptionByCode('bundle_options');
267
+ if (is_array($opts)) {
268
+ foreach ($opts as $opt) {
269
+ if (isset($opt['value']) && is_array($opt['value'])) {
270
+ foreach ($opt['value'] as $val) {
271
+ $qty = '';
272
+ if (isset($val['qty']) && is_int($val['qty'])) {
273
+ $qty .= $val['qty'] . ' x ';
274
+ }
275
+ if (isset($val['title']) && is_string($val['title'])) {
276
+ $optNames[] = $qty . $val['title'];
277
+ }
278
+ }
279
+ }
280
+ }
281
+ }
282
+ } elseif ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_GROUPED) {
283
+ $config = $item->getProductOptionByCode('super_product_config');
284
+ if (isset($config['product_id'])) {
285
+ /** @var Mage_Catalog_Model_Product $parent */
286
+ $parent = Mage::getModel('catalog/product')
287
+ ->load($config['product_id']);
288
+ $parentName = $parent->getName();
289
+ if (!empty($parentName)) {
290
+ $name = $parentName.' - '.$name;
291
+ }
292
+ }
293
+ }
294
 
295
+ if (!empty($optNames)) {
296
+ $name .= ' (' . implode(', ', $optNames) . ')';
 
297
  }
298
 
299
+ return $name;
 
 
 
300
  }
301
  }
app/code/community/Nosto/Tagging/Model/Meta/Order/Status.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Meta/Product.php CHANGED
@@ -34,7 +34,7 @@
34
  * @package Nosto_Tagging
35
  * @author Nosto Solutions Ltd <magento@nosto.com>
36
  */
37
- class Nosto_Tagging_Model_Meta_Product extends Mage_Core_Model_Abstract implements NostoProductInterface, NostoValidatableModelInterface
38
  {
39
  /**
40
  * Product "in stock" tagging string.
@@ -328,16 +328,7 @@ class Nosto_Tagging_Model_Meta_Product extends Mage_Core_Model_Abstract implemen
328
 
329
  $this->_productId = $product->getId();
330
  $this->_name = $product->getName();
331
-
332
- $image = $product->getImage();
333
- if (!empty($image) && $image !== 'no_selection') {
334
- // We build the image url manually in order get the correct base url,
335
- // even if this product is populated in the backend.
336
- $baseUrl = rtrim($store->getBaseUrl('media'), '/');
337
- $file = str_replace(DS, '/', $image);
338
- $file = ltrim($file, '/');
339
- $this->_imageUrl = $baseUrl.'/catalog/product/'.$file;
340
- }
341
 
342
  $this->_price = Mage::helper('tax')->getPrice(
343
  $product,
@@ -413,4 +404,45 @@ class Nosto_Tagging_Model_Meta_Product extends Mage_Core_Model_Abstract implemen
413
 
414
  return $data;
415
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  }
34
  * @package Nosto_Tagging
35
  * @author Nosto Solutions Ltd <magento@nosto.com>
36
  */
37
+ class Nosto_Tagging_Model_Meta_Product extends Nosto_Tagging_Model_Base implements NostoProductInterface, NostoValidatableInterface
38
  {
39
  /**
40
  * Product "in stock" tagging string.
328
 
329
  $this->_productId = $product->getId();
330
  $this->_name = $product->getName();
331
+ $this->_imageUrl = $this->buildImageUrl($product, $store);
 
 
 
 
 
 
 
 
 
332
 
333
  $this->_price = Mage::helper('tax')->getPrice(
334
  $product,
404
 
405
  return $data;
406
  }
407
+
408
+ /**
409
+ * Builds the product absolute image url for the store and returns it.
410
+ * The image version is primarily taken from the store config, but falls
411
+ * back the the base image if nothing is configured.
412
+ *
413
+ * @param Mage_Catalog_Model_Product $product the product model.
414
+ * @param Mage_Core_Model_Store $store the store model.
415
+ *
416
+ * @return null|string
417
+ */
418
+ protected function buildImageUrl(Mage_Catalog_Model_Product $product, Mage_Core_Model_Store $store)
419
+ {
420
+ $url = null;
421
+ /** @var Nosto_Tagging_Helper_Data $helper */
422
+ $helper = Mage::helper('nosto_tagging');
423
+ $imageVersion = $helper->getProductImageVersion($store);
424
+ $img = $product->getData($imageVersion);
425
+ $img = $this->isValidImage($img) ? $img : $product->getData('image');
426
+ if ($this->isValidImage($img)) {
427
+ // We build the image url manually in order get the correct base
428
+ // url, even if this product is populated in the backend.
429
+ $baseUrl = rtrim($store->getBaseUrl('media'), '/');
430
+ $file = str_replace(DS, '/', $img);
431
+ $file = ltrim($file, '/');
432
+ $url = $baseUrl.'/catalog/product/'.$file;
433
+ }
434
+ return $url;
435
+ }
436
+
437
+ /**
438
+ * Checks if the given image file path is valid.
439
+ *
440
+ * @param string $image the image file path.
441
+ *
442
+ * @return bool
443
+ */
444
+ protected function isValidImage($image)
445
+ {
446
+ return (!empty($image) && $image !== 'no_selection');
447
+ }
448
  }
app/code/community/Nosto/Tagging/Model/Observer.php CHANGED
@@ -75,9 +75,13 @@ class Nosto_Tagging_Model_Observer
75
  if (Mage::helper('nosto_tagging')->isModuleEnabled()) {
76
  /** @var Mage_Catalog_Model_Product $product */
77
  $product = $observer->getEvent()->getProduct();
78
- $validator = new NostoModelValidator();
79
- /** @var Mage_Core_Model_Store $store */
80
- foreach (Mage::app()->getStores() as $store) {
 
 
 
 
81
  /** @var NostoAccount $account */
82
  $account = Mage::helper('nosto_tagging/account')
83
  ->find($store);
@@ -101,11 +105,12 @@ class Nosto_Tagging_Model_Observer
101
 
102
  // Only send product update if we have all required
103
  // data for the product model.
104
- if ($validator->validate($model)) {
 
105
  try {
106
  $op = new NostoOperationProduct($account);
107
  $op->addProduct($model);
108
- $op->update();
109
  } catch (NostoException $e) {
110
  Mage::log("\n" . $e, Zend_Log::ERR, 'nostotagging.log');
111
  }
@@ -129,6 +134,8 @@ class Nosto_Tagging_Model_Observer
129
  if (Mage::helper('nosto_tagging')->isModuleEnabled()) {
130
  /** @var Mage_Catalog_Model_Product $product */
131
  $product = $observer->getEvent()->getProduct();
 
 
132
  /** @var Mage_Core_Model_Store $store */
133
  foreach (Mage::app()->getStores() as $store) {
134
  /** @var NostoAccount $account */
75
  if (Mage::helper('nosto_tagging')->isModuleEnabled()) {
76
  /** @var Mage_Catalog_Model_Product $product */
77
  $product = $observer->getEvent()->getProduct();
78
+ // Always "upsert" the product for all stores it is available in.
79
+ // This is done to avoid data inconsistencies as even if a product
80
+ // is edited for only one store, the updated data can reflect in
81
+ // other stores as well.
82
+ foreach ($product->getStoreIds() as $storeId) {
83
+ $store = Mage::app()->getStore($storeId);
84
+
85
  /** @var NostoAccount $account */
86
  $account = Mage::helper('nosto_tagging/account')
87
  ->find($store);
105
 
106
  // Only send product update if we have all required
107
  // data for the product model.
108
+ $validator = new NostoValidator($model);
109
+ if ($validator->validate()) {
110
  try {
111
  $op = new NostoOperationProduct($account);
112
  $op->addProduct($model);
113
+ $op->upsert();
114
  } catch (NostoException $e) {
115
  Mage::log("\n" . $e, Zend_Log::ERR, 'nostotagging.log');
116
  }
134
  if (Mage::helper('nosto_tagging')->isModuleEnabled()) {
135
  /** @var Mage_Catalog_Model_Product $product */
136
  $product = $observer->getEvent()->getProduct();
137
+ // Products are always deleted from all store views, regardless of
138
+ // the store view scope switcher on the product edit page.
139
  /** @var Mage_Core_Model_Store $store */
140
  foreach (Mage::app()->getStores() as $store) {
141
  /** @var NostoAccount $account */
app/code/community/Nosto/Tagging/Model/Resource/Customer.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Resource/Customer/Collection.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/Resource/Setup.php CHANGED
File without changes
app/code/community/Nosto/Tagging/Model/System/Config/Source/Image.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magentocommerce.com for more information.
20
+ *
21
+ * @category Nosto
22
+ * @package Nosto_Tagging
23
+ * @author Nosto Solutions Ltd <magento@nosto.com>
24
+ * @copyright Copyright (c) 2013-2015 Nosto Solutions Ltd (http://www.nosto.com)
25
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
26
+ */
27
+
28
+ /**
29
+ * Extension system setting source model for choosing which image version is to
30
+ * be tagged on the product page.
31
+ *
32
+ * @category Nosto
33
+ * @package Nosto_Tagging
34
+ * @author Nosto Solutions Ltd <magento@nosto.com>
35
+ */
36
+ class Nosto_Tagging_Model_System_Config_Source_Image
37
+ {
38
+ /**
39
+ * Returns the image version options to choose from.
40
+ *
41
+ * @return array the options.
42
+ */
43
+ public function toOptionArray()
44
+ {
45
+ $options = array();
46
+
47
+ $entityTypeId = Mage::getSingleton('eav/config')
48
+ ->getEntityType(Mage_Catalog_Model_Product::ENTITY)
49
+ ->getId();
50
+ $collection = Mage::getResourceModel('catalog/product_attribute_collection');
51
+ $collection->setEntityTypeFilter($entityTypeId);
52
+ $collection->setFrontendInputTypeFilter('media_image');
53
+ foreach ($collection as $attribute) {
54
+ /* @var $attribute Mage_Eav_Model_Entity_Attribute */
55
+ $options[] = array(
56
+ 'value' => $attribute->getAttributeCode(),
57
+ 'label' => $attribute->getFrontend()->getLabel(),
58
+ );
59
+ }
60
+
61
+ return $options;
62
+ }
63
+ }
app/code/community/Nosto/Tagging/controllers/Adminhtml/NostoController.php CHANGED
File without changes
app/code/community/Nosto/Tagging/controllers/ExportController.php CHANGED
@@ -97,7 +97,6 @@ class Nosto_tagging_ExportController extends Mage_Core_Controller_Front_Action
97
  if ($currentPage > $products->getLastPageNumber()) {
98
  $products = array();
99
  }
100
- $validator = new NostoModelValidator();
101
  $collection = new NostoExportProductCollection();
102
  foreach ($products as $product) {
103
  if ($product->getTypeId() === Mage_Catalog_Model_Product_Type::TYPE_BUNDLE
@@ -107,7 +106,8 @@ class Nosto_tagging_ExportController extends Mage_Core_Controller_Front_Action
107
  }
108
  $meta = new Nosto_Tagging_Model_Meta_Product();
109
  $meta->loadData($product);
110
- if ($validator->validate($meta)) {
 
111
  $collection[] = $meta;
112
  }
113
  }
97
  if ($currentPage > $products->getLastPageNumber()) {
98
  $products = array();
99
  }
 
100
  $collection = new NostoExportProductCollection();
101
  foreach ($products as $product) {
102
  if ($product->getTypeId() === Mage_Catalog_Model_Product_Type::TYPE_BUNDLE
106
  }
107
  $meta = new Nosto_Tagging_Model_Meta_Product();
108
  $meta->loadData($product);
109
+ $validator = new NostoValidator($meta);
110
+ if ($validator->validate()) {
111
  $collection[] = $meta;
112
  }
113
  }
app/code/community/Nosto/Tagging/controllers/OauthController.php CHANGED
File without changes
app/code/community/Nosto/Tagging/etc/adminhtml.xml CHANGED
@@ -38,6 +38,17 @@
38
  <resources>
39
  <admin>
40
  <children>
 
 
 
 
 
 
 
 
 
 
 
41
  <nosto>
42
  <title translate="title">Nosto</title>
43
  <sort_order>500</sort_order>
38
  <resources>
39
  <admin>
40
  <children>
41
+ <system>
42
+ <children>
43
+ <config>
44
+ <children>
45
+ <nosto_tagging translate="title">
46
+ <title>Nosto</title>
47
+ </nosto_tagging>
48
+ </children>
49
+ </config>
50
+ </children>
51
+ </system>
52
  <nosto>
53
  <title translate="title">Nosto</title>
54
  <sort_order>500</sort_order>
app/code/community/Nosto/Tagging/etc/cache.xml CHANGED
File without changes
app/code/community/Nosto/Tagging/etc/config.xml CHANGED
@@ -29,7 +29,7 @@
29
  <config>
30
  <modules>
31
  <Nosto_Tagging>
32
- <version>2.4.0</version>
33
  </Nosto_Tagging>
34
  </modules>
35
  <global>
@@ -153,4 +153,11 @@
153
  </nosto>
154
  </routers>
155
  </frontend>
 
 
 
 
 
 
 
156
  </config>
29
  <config>
30
  <modules>
31
  <Nosto_Tagging>
32
+ <version>2.5.0</version>
33
  </Nosto_Tagging>
34
  </modules>
35
  <global>
153
  </nosto>
154
  </routers>
155
  </frontend>
156
+ <default>
157
+ <nosto_tagging>
158
+ <image_options>
159
+ <image_version>image</image_version>
160
+ </image_options>
161
+ </nosto_tagging>
162
+ </default>
163
  </config>
app/code/community/Nosto/Tagging/etc/system.xml ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Magento
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * DISCLAIMER
17
+ *
18
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
19
+ * versions in the future. If you wish to customize Magento for your
20
+ * needs please refer to http://www.magentocommerce.com for more information.
21
+ *
22
+ * @category Nosto
23
+ * @package Nosto_Tagging
24
+ * @author Nosto Solutions Ltd <magento@nosto.com>
25
+ * @copyright Copyright (c) 2013-2015 Nosto Solutions Ltd (http://www.nosto.com)
26
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
27
+ */
28
+ -->
29
+ <config>
30
+ <sections>
31
+ <nosto_tagging translate="label">
32
+ <label>Nosto</label>
33
+ <tab>service</tab>
34
+ <sort_order>500</sort_order>
35
+ <show_in_default>1</show_in_default>
36
+ <show_in_website>1</show_in_website>
37
+ <show_in_store>1</show_in_store>
38
+ <groups>
39
+ <image_options translate="label">
40
+ <label>Image Options</label>
41
+ <frontend_type>text</frontend_type>
42
+ <sort_order>10</sort_order>
43
+ <show_in_default>1</show_in_default>
44
+ <show_in_website>1</show_in_website>
45
+ <show_in_store>1</show_in_store>
46
+ <expanded>1</expanded>
47
+ <fields>
48
+ <image_version translate="label">
49
+ <label>Image Version</label>
50
+ <frontend_type>select</frontend_type>
51
+ <source_model>nosto_tagging/system_config_source_image</source_model>
52
+ <sort_order>10</sort_order>
53
+ <show_in_default>1</show_in_default>
54
+ <show_in_website>1</show_in_website>
55
+ <show_in_store>1</show_in_store>
56
+ </image_version>
57
+ </fields>
58
+ </image_options>
59
+ </groups>
60
+ </nosto_tagging>
61
+ </sections>
62
+ </config>
app/code/community/Nosto/Tagging/sql/tagging_setup/mysql4-install-1.2.0.php CHANGED
File without changes
app/code/community/Nosto/Tagging/sql/tagging_setup/mysql4-upgrade-1.1.7-1.2.0.php CHANGED
File without changes
app/design/adminhtml/default/default/layout/nostotagging.xml CHANGED
@@ -33,7 +33,7 @@
33
  <reference name="head">
34
  <action method="addJs"><script>nosto/iframeresizer.min.js</script></action>
35
  <action method="addJs"><script>nosto/NostoIframe.min.js</script></action>
36
- <action method="addJs"><script>nosto/nostotagging-config.js</script></action>
37
  </reference>
38
  <!--Set active menu item-->
39
  <reference name="menu">
33
  <reference name="head">
34
  <action method="addJs"><script>nosto/iframeresizer.min.js</script></action>
35
  <action method="addJs"><script>nosto/NostoIframe.min.js</script></action>
36
+ <action method="addJs"><script>nosto/NostoAdmin.js</script></action>
37
  </reference>
38
  <!--Set active menu item-->
39
  <reference name="menu">
app/design/adminhtml/default/default/template/nostotagging/iframe.phtml CHANGED
File without changes
app/design/adminhtml/default/default/template/nostotagging/wizard.phtml CHANGED
File without changes
app/design/frontend/base/default/layout/nostotagging.xml CHANGED
File without changes
app/design/frontend/base/default/template/nostotagging/addtocart.phtml CHANGED
File without changes
app/design/frontend/base/default/template/nostotagging/cart.phtml CHANGED
@@ -42,11 +42,11 @@ $nostoPriceHelper = Mage::helper('nosto_tagging/price');
42
  <div class="nosto_cart" style="display:none">
43
  <?php foreach ($items as $item): ?>
44
  <div class="line_item">
45
- <span class="product_id"><?php echo $this->getProductId($item); ?></span>
46
  <span class="quantity"><?php echo (int)$item->getQty(); ?></span>
47
- <span class="name"><?php echo $nostoHelper->escapeHtml($item->getName()); ?></span>
48
  <span class="unit_price"><?php echo $nostoPriceHelper->getFormattedPrice($item->getPriceInclTax()); ?></span>
49
- <span class="price_currency_code"><?php echo $currency; ?></span>
50
  </div>
51
  <?php endforeach; ?>
52
  </div>
42
  <div class="nosto_cart" style="display:none">
43
  <?php foreach ($items as $item): ?>
44
  <div class="line_item">
45
+ <span class="product_id"><?php echo (int)$this->getProductId($item); ?></span>
46
  <span class="quantity"><?php echo (int)$item->getQty(); ?></span>
47
+ <span class="name"><?php echo $nostoHelper->escapeHtml($this->getProductName($item)); ?></span>
48
  <span class="unit_price"><?php echo $nostoPriceHelper->getFormattedPrice($item->getPriceInclTax()); ?></span>
49
+ <span class="price_currency_code"><?php echo strtoupper($currency); ?></span>
50
  </div>
51
  <?php endforeach; ?>
52
  </div>
app/design/frontend/base/default/template/nostotagging/category.phtml CHANGED
File without changes
app/design/frontend/base/default/template/nostotagging/category/view.phtml CHANGED
File without changes
app/design/frontend/base/default/template/nostotagging/customer.phtml CHANGED
File without changes
app/design/frontend/base/default/template/nostotagging/element.phtml CHANGED
File without changes
app/design/frontend/base/default/template/nostotagging/embed.phtml CHANGED
File without changes
app/design/frontend/base/default/template/nostotagging/meta.phtml CHANGED
File without changes
app/design/frontend/base/default/template/nostotagging/order.phtml CHANGED
@@ -41,6 +41,9 @@ $priceHelper = Mage::helper('nosto_tagging/price');
41
  <!-- Nosto Order Tagging -->
42
  <div class="nosto_purchase_order" style="display:none">
43
  <span class="order_number"><?php echo $order->getOrderNumber(); ?></span>
 
 
 
44
  <div class="buyer">
45
  <span class="first_name"><?php echo $helper->escapeHtml($order->getBuyerInfo()->getFirstName()); ?></span>
46
  <span class="last_name"><?php echo $helper->escapeHtml($order->getBuyerInfo()->getLastName()); ?></span>
41
  <!-- Nosto Order Tagging -->
42
  <div class="nosto_purchase_order" style="display:none">
43
  <span class="order_number"><?php echo $order->getOrderNumber(); ?></span>
44
+ <span class="order_status_code"><?php echo $helper->escapeHtml($order->getOrderStatus()->getCode()); ?></span>
45
+ <span class="order_status_label"><?php echo $helper->escapeHtml($order->getOrderStatus()->getLabel()); ?></span>
46
+ <span class="payment_provider"><?php echo $helper->escapeHtml($order->getPaymentProvider()); ?></span>
47
  <div class="buyer">
48
  <span class="first_name"><?php echo $helper->escapeHtml($order->getBuyerInfo()->getFirstName()); ?></span>
49
  <span class="last_name"><?php echo $helper->escapeHtml($order->getBuyerInfo()->getLastName()); ?></span>
app/design/frontend/base/default/template/nostotagging/product.phtml CHANGED
File without changes
app/etc/modules/Nosto_Tagging.xml CHANGED
File without changes
js/nosto/{nostotagging-config.js → NostoAdmin.js} RENAMED
File without changes
js/nosto/NostoIframe.min.js CHANGED
@@ -1 +1 @@
1
- if("undefined"==typeof Nosto)var Nosto={};Nosto.iframe=function(a){function b(a){if(a.origin===decodeURIComponent(j.origin)&&"[Nosto]"===(""+a.data).substr(0,7)){var b=(""+a.data).substr(7),d=JSON.parse(b);if("object"==typeof d&&d.type)switch(d.type){case g:c(j.urls.createAccount,{data:{email:d.params.email},success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account creation.");f().src=b.redirect_url}});break;case h:c(j.urls.connectAccount,{success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account connection.");b.success&&b.success===!0?window.location.href=b.redirect_url:f().src=b.redirect_url}});break;case i:c(j.urls.deleteAccount,{success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account deletion.");f().src=b.redirect_url}});break;default:throw new Error("Nosto: invalid postMessage `type`.")}}}function c(a,b){var c=d({method:"POST",async:!0,data:{}},b);d(c.data,j.xhrParams);var f=e(c.data),g=new XMLHttpRequest;"function"==typeof c.success&&g.addEventListener("load",c.success,!1),"function"==typeof c.error&&g.addEventListener("error",c.error,!1),g.open(c.method,decodeURIComponent(a),c.async),g.setRequestHeader("X-Requested-With","XMLHttpRequest"),g.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),g.send(f)}function d(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function e(a){var b="";for(var c in a)a.hasOwnProperty(c)&&(""!==b&&(b+="&"),b+=encodeURIComponent(c)+"="+encodeURIComponent(a[c]));return b}function f(){return document.getElementById(j.iframeId)}var g="newAccount",h="connectAccount",i="removeAccount",j={origin:"https://my.nosto.com",iframeId:"nosto_iframe",urls:{createAccount:"",connectAccount:"",deleteAccount:""},xhrParams:{}};d(j,a),window.addEventListener("message",b,!1)};
1
+ if("undefined"==typeof Nosto)var Nosto={};Nosto.iframe=function(a){function b(a){var b=new RegExp(j.origin);if(b.test(a.origin)&&"[Nosto]"===(""+a.data).substr(0,7)){var d=(""+a.data).substr(7),e=JSON.parse(d);if("object"==typeof e&&e.type)switch(e.type){case g:c(j.urls.createAccount,{data:{email:e.params.email},success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account creation.");f().src=b.redirect_url}});break;case h:c(j.urls.connectAccount,{success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account connection.");b.success&&b.success===!0?window.location.href=b.redirect_url:f().src=b.redirect_url}});break;case i:c(j.urls.deleteAccount,{success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account deletion.");f().src=b.redirect_url}});break;default:throw new Error("Nosto: invalid postMessage `type`.")}}}function c(a,b){var c=d({method:"POST",async:!0,data:{}},b);d(c.data,j.xhrParams);var f=e(c.data),g=new XMLHttpRequest;"function"==typeof c.success&&g.addEventListener("load",c.success,!1),"function"==typeof c.error&&g.addEventListener("error",c.error,!1),g.open(c.method,decodeURIComponent(a),c.async),g.setRequestHeader("X-Requested-With","XMLHttpRequest"),g.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),g.send(f)}function d(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function e(a){var b="";for(var c in a)a.hasOwnProperty(c)&&(""!==b&&(b+="&"),b+=encodeURIComponent(c)+"="+encodeURIComponent(a[c]));return b}function f(){return document.getElementById(j.iframeId)}var g="newAccount",h="connectAccount",i="removeAccount",j={origin:"",iframeId:"nosto_iframe",urls:{createAccount:"",connectAccount:"",deleteAccount:""},xhrParams:{}};d(j,a),window.addEventListener("message",b,!1)};
js/nosto/iframeresizer.min.js CHANGED
File without changes
lib/nosto/php-sdk/src/.env.example CHANGED
@@ -2,4 +2,4 @@ NOSTO_SERVER_URL=connect.nosto.com
2
  NOSTO_API_BASE_URL=https://api.nosto.com
3
  NOSTO_OAUTH_BASE_URL=https://my.nosto.com/oauth
4
  NOSTO_WEB_HOOK_BASE_URL=https://my.nosto.com
5
- NOSTO_IFRAME_ORIGIN=https://my.nosto.com
2
  NOSTO_API_BASE_URL=https://api.nosto.com
3
  NOSTO_OAUTH_BASE_URL=https://my.nosto.com/oauth
4
  NOSTO_WEB_HOOK_BASE_URL=https://my.nosto.com
5
+ NOSTO_IFRAME_ORIGIN_REGEXP=(https:\/\/platform-([a-z0-9]+)\.hub\.nosto\.com)|(https:\/\/my\.nosto\.com)
lib/nosto/php-sdk/src/classes/Nosto.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/NostoAccount.php CHANGED
@@ -36,17 +36,39 @@
36
  /**
37
  * Nosto account class for handling account related actions like, creation, OAuth2 syncing and SSO to Nosto.
38
  */
39
- class NostoAccount implements NostoAccountInterface
40
  {
41
  /**
42
  * @var string the name of the Nosto account.
43
  */
44
- public $name;
45
 
46
  /**
47
  * @var NostoApiToken[] the Nosto API tokens associated with this account.
48
  */
49
- public $tokens = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
  /**
52
  * @inheritdoc
@@ -86,8 +108,7 @@ class NostoAccount implements NostoAccountInterface
86
  Nosto::throwHttpException('Nosto account could not be created.', $request, $response);
87
  }
88
 
89
- $account = new self;
90
- $account->name = $meta->getPlatform().'-'.$meta->getName();
91
  $account->tokens = NostoApiToken::parseTokens($response->getJsonResult(true), '', '_token');
92
  return $account;
93
  }
@@ -122,8 +143,7 @@ class NostoAccount implements NostoAccountInterface
122
  throw new NostoException('Received invalid data from Nosto when trying to sync account');
123
  }
124
 
125
- $account = new self;
126
- $account->name = $token->merchantName;
127
  $account->tokens = NostoApiToken::parseTokens($result, 'api_');
128
  if (!$account->isConnectedToNosto()) {
129
  throw new NostoException('Failed to sync all account details from Nosto');
@@ -143,7 +163,7 @@ class NostoAccount implements NostoAccountInterface
143
 
144
  $request = new NostoHttpRequest();
145
  $request->setUrl(NostoHttpRequest::$baseUrl.NostoHttpRequest::PATH_ACCOUNT_DELETED);
146
- $request->setAuthBasic('', $token->value);
147
  $response = $request->post('');
148
 
149
  if ($response->getCode() !== 200) {
@@ -152,13 +172,25 @@ class NostoAccount implements NostoAccountInterface
152
  }
153
 
154
  /**
155
- * @inheritdoc
 
 
156
  */
157
  public function getName()
158
  {
159
  return $this->name;
160
  }
161
 
 
 
 
 
 
 
 
 
 
 
162
  /**
163
  * @inheritdoc
164
  */
@@ -169,7 +201,7 @@ class NostoAccount implements NostoAccountInterface
169
  }
170
  $countTokens = count($this->tokens);
171
  $foundTokens = 0;
172
- foreach (NostoApiToken::$tokenNames as $name) {
173
  foreach ($this->tokens as $token) {
174
  if ($token->name === $name) {
175
  $foundTokens++;
@@ -180,13 +212,23 @@ class NostoAccount implements NostoAccountInterface
180
  return ($countTokens === $foundTokens);
181
  }
182
 
 
 
 
 
 
 
 
 
 
 
183
  /**
184
  * @inheritdoc
185
  */
186
  public function getApiToken($name)
187
  {
188
  foreach ($this->tokens as $token) {
189
- if ($token->name === $name) {
190
  return $token;
191
  }
192
  }
@@ -211,16 +253,21 @@ class NostoAccount implements NostoAccountInterface
211
  return false;
212
  }
213
 
214
- $request = new NostoApiRequest();
215
- $request->setPath(NostoApiRequest::PATH_SSO_AUTH);
216
- $request->setReplaceParams(array('{email}' => $meta->getEmail()));
217
- $request->setContentType('application/json');
218
- $request->setAuthBasic('', $token->value);
 
 
 
 
 
219
  $response = $request->post(
220
- json_encode(
221
  array(
222
- 'first_name' => $meta->getFirstName(),
223
- 'last_name' => $meta->getLastName(),
224
  )
225
  )
226
  );
@@ -235,4 +282,19 @@ class NostoAccount implements NostoAccountInterface
235
 
236
  return $result->login_url;
237
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  }
36
  /**
37
  * Nosto account class for handling account related actions like, creation, OAuth2 syncing and SSO to Nosto.
38
  */
39
+ class NostoAccount extends NostoObject implements NostoAccountInterface, NostoValidatableInterface
40
  {
41
  /**
42
  * @var string the name of the Nosto account.
43
  */
44
+ protected $name;
45
 
46
  /**
47
  * @var NostoApiToken[] the Nosto API tokens associated with this account.
48
  */
49
+ protected $tokens = array();
50
+
51
+ /**
52
+ * Constructor.
53
+ * Create a new account object with given name.
54
+ *
55
+ * @param $name
56
+ */
57
+ public function __construct($name)
58
+ {
59
+ $this->name = $name;
60
+ $this->validate();
61
+ }
62
+
63
+ /**
64
+ * @inheritdoc
65
+ */
66
+ public function getValidationRules()
67
+ {
68
+ return array(
69
+ array(array('name'), 'required')
70
+ );
71
+ }
72
 
73
  /**
74
  * @inheritdoc
108
  Nosto::throwHttpException('Nosto account could not be created.', $request, $response);
109
  }
110
 
111
+ $account = new self($meta->getPlatform().'-'.$meta->getName());
 
112
  $account->tokens = NostoApiToken::parseTokens($response->getJsonResult(true), '', '_token');
113
  return $account;
114
  }
143
  throw new NostoException('Received invalid data from Nosto when trying to sync account');
144
  }
145
 
146
+ $account = new self($token->merchantName);
 
147
  $account->tokens = NostoApiToken::parseTokens($result, 'api_');
148
  if (!$account->isConnectedToNosto()) {
149
  throw new NostoException('Failed to sync all account details from Nosto');
163
 
164
  $request = new NostoHttpRequest();
165
  $request->setUrl(NostoHttpRequest::$baseUrl.NostoHttpRequest::PATH_ACCOUNT_DELETED);
166
+ $request->setAuthBasic('', $token->getValue());
167
  $response = $request->post('');
168
 
169
  if ($response->getCode() !== 200) {
172
  }
173
 
174
  /**
175
+ * Returns the account name.
176
+ *
177
+ * @return string the name.
178
  */
179
  public function getName()
180
  {
181
  return $this->name;
182
  }
183
 
184
+ /**
185
+ * Returns the account tokens.
186
+ *
187
+ * @return NostoApiToken[] the tokens.
188
+ */
189
+ public function getTokens()
190
+ {
191
+ return $this->tokens;
192
+ }
193
+
194
  /**
195
  * @inheritdoc
196
  */
201
  }
202
  $countTokens = count($this->tokens);
203
  $foundTokens = 0;
204
+ foreach (NostoApiToken::getApiTokenNames() as $name) {
205
  foreach ($this->tokens as $token) {
206
  if ($token->name === $name) {
207
  $foundTokens++;
212
  return ($countTokens === $foundTokens);
213
  }
214
 
215
+ /**
216
+ * Adds an API token to the account.
217
+ *
218
+ * @param NostoApiToken $token the token.
219
+ */
220
+ public function addApiToken(NostoApiToken $token)
221
+ {
222
+ $this->tokens[] = $token;
223
+ }
224
+
225
  /**
226
  * @inheritdoc
227
  */
228
  public function getApiToken($name)
229
  {
230
  foreach ($this->tokens as $token) {
231
+ if ($token->getName() === $name) {
232
  return $token;
233
  }
234
  }
253
  return false;
254
  }
255
 
256
+ $request = new NostoHttpRequest();
257
+ $request->setUrl(NostoHttpRequest::$baseUrl.NostoHttpRequest::PATH_SSO_AUTH);
258
+ $request->setReplaceParams(
259
+ array(
260
+ '{platform}' => $meta->getPlatform(),
261
+ '{email}' => $meta->getEmail(),
262
+ )
263
+ );
264
+ $request->setContentType('application/x-www-form-urlencoded');
265
+ $request->setAuthBasic('', $token->getValue());
266
  $response = $request->post(
267
+ http_build_query(
268
  array(
269
+ 'fname' => $meta->getFirstName(),
270
+ 'lname' => $meta->getLastName(),
271
  )
272
  )
273
  );
282
 
283
  return $result->login_url;
284
  }
285
+
286
+ /**
287
+ * Validates the account attributes.
288
+ *
289
+ * @throws NostoException if any attribute is invalid.
290
+ */
291
+ protected function validate()
292
+ {
293
+ $validator = new NostoValidator($this);
294
+ if (!$validator->validate()) {
295
+ foreach ($validator->getErrors() as $errors) {
296
+ throw new NostoException(sprintf('Invalid Nosto account. %s', $errors[0]));
297
+ }
298
+ }
299
+ }
300
  }
lib/nosto/php-sdk/src/classes/NostoCipher.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/NostoDotEnv.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/NostoMessage.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/NostoModelValidator.php DELETED
@@ -1,90 +0,0 @@
1
- <?php
2
- /**
3
- * Copyright (c) 2015, Nosto Solutions Ltd
4
- * All rights reserved.
5
- *
6
- * Redistribution and use in source and binary forms, with or without modification,
7
- * are permitted provided that the following conditions are met:
8
- *
9
- * 1. Redistributions of source code must retain the above copyright notice,
10
- * this list of conditions and the following disclaimer.
11
- *
12
- * 2. Redistributions in binary form must reproduce the above copyright notice,
13
- * this list of conditions and the following disclaimer in the documentation
14
- * and/or other materials provided with the distribution.
15
- *
16
- * 3. Neither the name of the copyright holder nor the names of its contributors
17
- * may be used to endorse or promote products derived from this software without
18
- * specific prior written permission.
19
- *
20
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
24
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
- *
31
- * @author Nosto Solutions Ltd <contact@nosto.com>
32
- * @copyright 2015 Nosto Solutions Ltd
33
- * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause
34
- */
35
-
36
- /**
37
- * Model validator util that is used to validate `validatable` models.
38
- */
39
- class NostoModelValidator
40
- {
41
- /**
42
- * Validates the `validatable` model based opn it's validation rules.
43
- *
44
- * @param NostoValidatableModelInterface $model the model to validate.
45
- * @return bool true if the model is valid, false otherwise.
46
- * @throws NostoException if the rule validator is not found.
47
- */
48
- public function validate(NostoValidatableModelInterface $model)
49
- {
50
- foreach ($model->getValidationRules() as $rule) {
51
- if (isset($rule[0], $rule[1])) {
52
- $properties = $rule[0];
53
- $validator = 'validate'.$rule[1];
54
- if (!method_exists($this, $validator)) {
55
- throw new NostoException(sprintf('Nosto validator "%s" does not exist.', $validator));
56
- }
57
- $isValid = call_user_func(array($this, $validator), $model, $properties);
58
- if (!$isValid) {
59
- return false;
60
- }
61
- }
62
- }
63
- return true;
64
- }
65
-
66
- /**
67
- * Validates that all the given properties are NOT empty in this instance.
68
- *
69
- * @param NostoValidatableModelInterface $model the model to validate the properties on.
70
- * @param array $properties the list of property names to validate.
71
- * @return bool true if all are valid, false otherwise.
72
- */
73
- protected function validateRequired(NostoValidatableModelInterface $model, array $properties)
74
- {
75
- foreach ($properties as $property) {
76
- // Prefer property getter if available.
77
- // Strip any "_" character at beginning of property name.
78
- $getter = 'get'.trim($property, '_');
79
- if (method_exists($model, $getter)) {
80
- $value = $model->{$getter}();
81
- if (empty($value)) {
82
- return false;
83
- }
84
- } elseif (empty($model->{$property})) {
85
- return false;
86
- }
87
- }
88
- return true;
89
- }
90
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/nosto/php-sdk/src/classes/NostoObject.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2015, Nosto Solutions Ltd
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without modification,
7
+ * are permitted provided that the following conditions are met:
8
+ *
9
+ * 1. Redistributions of source code must retain the above copyright notice,
10
+ * this list of conditions and the following disclaimer.
11
+ *
12
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ * this list of conditions and the following disclaimer in the documentation
14
+ * and/or other materials provided with the distribution.
15
+ *
16
+ * 3. Neither the name of the copyright holder nor the names of its contributors
17
+ * may be used to endorse or promote products derived from this software without
18
+ * specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
24
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ *
31
+ * @author Nosto Solutions Ltd <contact@nosto.com>
32
+ * @copyright 2015 Nosto Solutions Ltd
33
+ * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause
34
+ */
35
+
36
+ /**
37
+ * Base class for Nosto objects to share basic functionality.
38
+ */
39
+ abstract class NostoObject
40
+ {
41
+ /**
42
+ * Returns a protected/private property value by invoking it's public getter.
43
+ *
44
+ * The getter names are assumed to be the property name in camel case with preceding word "get".
45
+ *
46
+ * @param string $name the property name.
47
+ * @return mixed the property value.
48
+ * @throws NostoException if public getter does not exist.
49
+ */
50
+ public function __get($name)
51
+ {
52
+ $getter = 'get'.str_replace('_', '', $name);
53
+ if (method_exists($this, $getter)) {
54
+ return $this->{$getter}();
55
+ }
56
+ throw new NostoException(sprintf('Property `%s.%s` is not defined.', get_class($this), $name));
57
+ }
58
+ }
lib/nosto/php-sdk/src/classes/NostoOrderConfirmation.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/NostoProductReCrawl.php CHANGED
@@ -48,14 +48,17 @@ class NostoProductReCrawl
48
  */
49
  public static function send(NostoProductInterface $product, NostoAccountInterface $account)
50
  {
51
- return self::sendRequest($account, array(
52
- 'products' => array(
53
- array(
54
- 'product_id' => $product->getProductId(),
55
- 'url' => $product->getUrl(),
56
- )
57
- ),
58
- ));
 
 
 
59
  }
60
 
61
  /**
@@ -101,7 +104,7 @@ class NostoProductReCrawl
101
  $request = new NostoApiRequest();
102
  $request->setPath(NostoApiRequest::PATH_PRODUCT_RE_CRAWL);
103
  $request->setContentType('application/json');
104
- $request->setAuthBasic('', $token->value);
105
  $response = $request->post(json_encode($payload));
106
  if ($response->getCode() !== 200) {
107
  Nosto::throwHttpException('Failed to send product re-crawl to Nosto.', $request, $response);
48
  */
49
  public static function send(NostoProductInterface $product, NostoAccountInterface $account)
50
  {
51
+ return self::sendRequest(
52
+ $account,
53
+ array(
54
+ 'products' => array(
55
+ array(
56
+ 'product_id' => $product->getProductId(),
57
+ 'url' => $product->getUrl(),
58
+ )
59
+ ),
60
+ )
61
+ );
62
  }
63
 
64
  /**
104
  $request = new NostoApiRequest();
105
  $request->setPath(NostoApiRequest::PATH_PRODUCT_RE_CRAWL);
106
  $request->setContentType('application/json');
107
+ $request->setAuthBasic('', $token->getValue());
108
  $response = $request->post(json_encode($payload));
109
  if ($response->getCode() !== 200) {
110
  Nosto::throwHttpException('Failed to send product re-crawl to Nosto.', $request, $response);
lib/nosto/php-sdk/src/classes/NostoValidator.php ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2015, Nosto Solutions Ltd
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without modification,
7
+ * are permitted provided that the following conditions are met:
8
+ *
9
+ * 1. Redistributions of source code must retain the above copyright notice,
10
+ * this list of conditions and the following disclaimer.
11
+ *
12
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ * this list of conditions and the following disclaimer in the documentation
14
+ * and/or other materials provided with the distribution.
15
+ *
16
+ * 3. Neither the name of the copyright holder nor the names of its contributors
17
+ * may be used to endorse or promote products derived from this software without
18
+ * specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
24
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ *
31
+ * @author Nosto Solutions Ltd <contact@nosto.com>
32
+ * @copyright 2015 Nosto Solutions Ltd
33
+ * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause
34
+ */
35
+
36
+ /**
37
+ * Validator util that is used to validate `validatable` objects.
38
+ */
39
+ class NostoValidator
40
+ {
41
+ /**
42
+ * @var NostoValidatableInterface the object to validate.
43
+ */
44
+ private $_object;
45
+
46
+ /**
47
+ * @var array map of validation errors per attribute.
48
+ */
49
+ private $_errors = array();
50
+
51
+ /**
52
+ * Constructor.
53
+ * Creates a new validator for the object to validate.
54
+ *
55
+ * @param NostoValidatableInterface $object the object to validate.
56
+ */
57
+ public function __construct(NostoValidatableInterface $object)
58
+ {
59
+ $this->_object = $object;
60
+ }
61
+
62
+ /**
63
+ * Validates the `validatable` object based on it's validation rules.
64
+ *
65
+ * @return bool true if the object is valid, false otherwise.
66
+ * @throws NostoException if the rule validator is not found.
67
+ */
68
+ public function validate()
69
+ {
70
+ foreach ($this->_object->getValidationRules() as $rule) {
71
+ if (isset($rule[0], $rule[1])) {
72
+ $properties = $rule[0];
73
+ $validator = 'validate'.$rule[1];
74
+ if (!method_exists($this, $validator)) {
75
+ throw new NostoException(sprintf('Nosto validator "%s" does not exist.', $validator));
76
+ }
77
+ $params = array_merge(array($properties), array_slice($rule, 2));
78
+ $isValid = call_user_func_array(array($this, $validator), $params);
79
+ if (!$isValid) {
80
+ return false;
81
+ }
82
+ }
83
+ }
84
+ return true;
85
+ }
86
+
87
+ /**
88
+ * Returns if the object contains validation errors.
89
+ *
90
+ * @return bool true if contains errors, false otherwise.
91
+ */
92
+ public function hasErrors()
93
+ {
94
+ return (bool)count($this->_errors);
95
+ }
96
+
97
+ /**
98
+ * Returns the validations errors per attribute.
99
+ *
100
+ * @return array the list of error messages.
101
+ */
102
+ public function getErrors()
103
+ {
104
+ return $this->_errors;
105
+ }
106
+
107
+ /**
108
+ * Adds a new validation error message for the attribute.
109
+ *
110
+ * @param string $attribute the attribute name.
111
+ * @param string $message the error message.
112
+ */
113
+ protected function addError($attribute, $message)
114
+ {
115
+ if (!isset($this->_errors[$attribute])) {
116
+ $this->_errors[$attribute] = array();
117
+ }
118
+ $this->_errors[$attribute][] = $message;
119
+ }
120
+
121
+ /**
122
+ * Validates that all the given properties are NOT empty in this instance.
123
+ *
124
+ * @param array $properties the list of property names to validate.
125
+ * @return bool true if all are valid, false otherwise.
126
+ */
127
+ protected function validateRequired(array $properties)
128
+ {
129
+ foreach ($properties as $property) {
130
+ $value = $this->_object->{$property};
131
+ if (empty($value)) {
132
+ $this->addError($property, sprintf('Property "%s" must not be empty.', $property));
133
+ return false;
134
+ }
135
+ }
136
+ return true;
137
+ }
138
+
139
+ /**
140
+ * Validates that all given properties are IN the list of supplied values.
141
+ *
142
+ * @param array $properties the list of properties to validate.
143
+ * @param array $values the list of valid values the properties must
144
+ * @return bool true if all are valid, false otherwise.
145
+ */
146
+ protected function validateIn(array $properties, array $values)
147
+ {
148
+ $supported = implode('", "', $values);
149
+ foreach ($properties as $property) {
150
+ $value = $this->_object->{$property};
151
+ if (!in_array($value, $values)) {
152
+ $this->addError(
153
+ $property,
154
+ sprintf('Property "%s" must be one of the following: "%s".', $property, $supported)
155
+ );
156
+ return false;
157
+ }
158
+ }
159
+ return true;
160
+ }
161
+ }
lib/nosto/php-sdk/src/classes/api/NostoApiRequest.php CHANGED
@@ -41,8 +41,9 @@ class NostoApiRequest extends NostoHttpRequest
41
  const PATH_ORDER_TAGGING = '/visits/order/confirm/{m}/{cid}';
42
  const PATH_UNMATCHED_ORDER_TAGGING = '/visits/order/unmatched/{m}';
43
  const PATH_SIGN_UP = '/accounts/create/{lang}';
44
- const PATH_SSO_AUTH = '/users/sso/{email}';
45
  const PATH_PRODUCT_RE_CRAWL = '/products/recrawl';
 
 
46
  const PATH_PRODUCTS_UPSERT = '/v1/products/upsert';
47
  const PATH_PRODUCTS_DISCONTINUE = '/v1/products/discontinue';
48
 
41
  const PATH_ORDER_TAGGING = '/visits/order/confirm/{m}/{cid}';
42
  const PATH_UNMATCHED_ORDER_TAGGING = '/visits/order/unmatched/{m}';
43
  const PATH_SIGN_UP = '/accounts/create/{lang}';
 
44
  const PATH_PRODUCT_RE_CRAWL = '/products/recrawl';
45
+ const PATH_PRODUCTS_CREATE = '/v1/products/create';
46
+ const PATH_PRODUCTS_UPDATE = '/v1/products/update';
47
  const PATH_PRODUCTS_UPSERT = '/v1/products/upsert';
48
  const PATH_PRODUCTS_DISCONTINUE = '/v1/products/discontinue';
49
 
lib/nosto/php-sdk/src/classes/api/NostoApiToken.php CHANGED
@@ -36,17 +36,17 @@
36
  /**
37
  * Class representing an API token for the Nosto API's.
38
  */
39
- class NostoApiToken
40
  {
41
  /**
42
  * @var string the token name, must be one of the defined tokens from self::$tokenNames.
43
  */
44
- public $name;
45
 
46
  /**
47
  * @var string the token value, e.g. the actual token string.
48
  */
49
- public $value;
50
 
51
  /**
52
  * @var array list of valid api tokens to request from Nosto.
@@ -56,6 +56,31 @@ class NostoApiToken
56
  'products'
57
  );
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  /**
60
  * Parses a list of token name=>value pairs and creates token instances of them.
61
  *
@@ -70,10 +95,7 @@ class NostoApiToken
70
  foreach (self::$tokenNames as $name) {
71
  $key = $prefix.$name.$postfix;
72
  if (isset($tokens[$key])) {
73
- $token = new self();
74
- $token->name = $name;
75
- $token->value = $tokens[$key];
76
- $parsedTokens[$name] = $token;
77
  }
78
  }
79
  return $parsedTokens;
@@ -88,4 +110,39 @@ class NostoApiToken
88
  {
89
  return self::$tokenNames;
90
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  }
36
  /**
37
  * Class representing an API token for the Nosto API's.
38
  */
39
+ class NostoApiToken extends NostoObject implements NostoValidatableInterface
40
  {
41
  /**
42
  * @var string the token name, must be one of the defined tokens from self::$tokenNames.
43
  */
44
+ protected $name;
45
 
46
  /**
47
  * @var string the token value, e.g. the actual token string.
48
  */
49
+ protected $value;
50
 
51
  /**
52
  * @var array list of valid api tokens to request from Nosto.
56
  'products'
57
  );
58
 
59
+ /**
60
+ * Constructor.
61
+ * Create a new token with name and value.
62
+ *
63
+ * @param string $name the token name (must be one of self::$tokenNames).
64
+ * @param string $value the token value string.
65
+ */
66
+ public function __construct($name, $value)
67
+ {
68
+ $this->name = $name;
69
+ $this->value = $value;
70
+ $this->validate();
71
+ }
72
+
73
+ /**
74
+ * @inheritdoc
75
+ */
76
+ public function getValidationRules()
77
+ {
78
+ return array(
79
+ array(array('name', 'value'), 'required'),
80
+ array(array('name'), 'in', self::$tokenNames)
81
+ );
82
+ }
83
+
84
  /**
85
  * Parses a list of token name=>value pairs and creates token instances of them.
86
  *
95
  foreach (self::$tokenNames as $name) {
96
  $key = $prefix.$name.$postfix;
97
  if (isset($tokens[$key])) {
98
+ $parsedTokens[$name] = new self($name, $tokens[$key]);
 
 
 
99
  }
100
  }
101
  return $parsedTokens;
110
  {
111
  return self::$tokenNames;
112
  }
113
+
114
+ /**
115
+ * Returns the token name.
116
+ *
117
+ * @return string the token name.
118
+ */
119
+ public function getName()
120
+ {
121
+ return $this->name;
122
+ }
123
+
124
+ /**
125
+ * Returns the tokens value.
126
+ *
127
+ * @return string the token value.
128
+ */
129
+ public function getValue()
130
+ {
131
+ return $this->value;
132
+ }
133
+
134
+ /**
135
+ * Validates the token attributes.
136
+ *
137
+ * @throws NostoException if any attribute is invalid.
138
+ */
139
+ protected function validate()
140
+ {
141
+ $validator = new NostoValidator($this);
142
+ if (!$validator->validate()) {
143
+ foreach ($validator->getErrors() as $errors) {
144
+ throw new NostoException(sprintf('Invalid Nosto API token. %s', $errors[0]));
145
+ }
146
+ }
147
+ }
148
  }
lib/nosto/php-sdk/src/classes/collection/NostoCollection.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/collection/NostoOrderCollection.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/collection/NostoProductCollection.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/exception/NostoException.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/exception/NostoHttpException.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/export/NostoExportOrderCollection.php CHANGED
@@ -57,7 +57,7 @@ class NostoExportOrderCollection extends NostoOrderCollection implements NostoEx
57
  'last_name' => $item->getBuyerInfo()->getLastName(),
58
  'email' => $item->getBuyerInfo()->getEmail(),
59
  ),
60
- 'payment_provider' => $item->getPaymentProvider(),
61
  'purchased_items' => array(),
62
  );
63
  foreach ($item->getPurchasedItems() as $orderItem) {
57
  'last_name' => $item->getBuyerInfo()->getLastName(),
58
  'email' => $item->getBuyerInfo()->getEmail(),
59
  ),
60
+ 'payment_provider' => $item->getPaymentProvider(),
61
  'purchased_items' => array(),
62
  );
63
  foreach ($item->getPurchasedItems() as $orderItem) {
lib/nosto/php-sdk/src/classes/export/NostoExportProductCollection.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/export/NostoExporter.php CHANGED
@@ -53,7 +53,8 @@ class NostoExporter
53
  // Use the first 16 chars of the SSO token as secret for encryption.
54
  $token = $account->getApiToken('sso');
55
  if (!empty($token)) {
56
- $secret = substr($token->value, 0, 16);
 
57
  if (!empty($secret)) {
58
  $iv = NostoCryptRandom::getRandomString(16);
59
  $cipher = new NostoCipher();
53
  // Use the first 16 chars of the SSO token as secret for encryption.
54
  $token = $account->getApiToken('sso');
55
  if (!empty($token)) {
56
+ $tokenValue = $token->getValue();
57
+ $secret = substr($tokenValue, 0, 16);
58
  if (!empty($secret)) {
59
  $iv = NostoCryptRandom::getRandomString(16);
60
  $cipher = new NostoCipher();
lib/nosto/php-sdk/src/classes/helper/NostoHelper.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/helper/NostoHelperDate.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/helper/NostoHelperIframe.php CHANGED
@@ -38,7 +38,6 @@
38
  */
39
  class NostoHelperIframe extends NostoHelper
40
  {
41
- const IFRAME_URI_MANAGE = '/hub/{platform}/{merchant}';
42
  const IFRAME_URI_INSTALL = '/hub/{platform}/install';
43
  const IFRAME_URI_UNINSTALL = '/hub/{platform}/uninstall';
44
 
@@ -81,16 +80,7 @@ class NostoHelperIframe extends NostoHelper
81
 
82
  if ($account !== null && $account->isConnectedToNosto()) {
83
  try {
84
- $url = $account->ssoLogin($meta);
85
- $url .= '?r='.urlencode(
86
- NostoHttpRequest::buildUri(
87
- self::IFRAME_URI_MANAGE.'?'.$queryParams,
88
- array(
89
- '{platform}' => $meta->getPlatform(),
90
- '{merchant}' => $account->name,
91
- )
92
- )
93
- );
94
  } catch (NostoException $e) {
95
  // If the SSO fails, we show a "remove account" page to the user in order to
96
  // allow to remove Nosto and start over.
38
  */
39
  class NostoHelperIframe extends NostoHelper
40
  {
 
41
  const IFRAME_URI_INSTALL = '/hub/{platform}/install';
42
  const IFRAME_URI_UNINSTALL = '/hub/{platform}/uninstall';
43
 
80
 
81
  if ($account !== null && $account->isConnectedToNosto()) {
82
  try {
83
+ $url = $account->ssoLogin($meta).'?'.$queryParams;
 
 
 
 
 
 
 
 
 
84
  } catch (NostoException $e) {
85
  // If the SSO fails, we show a "remove account" page to the user in order to
86
  // allow to remove Nosto and start over.
lib/nosto/php-sdk/src/classes/helper/NostoHelperPrice.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/http/NostoHttpRequest.php CHANGED
@@ -42,6 +42,7 @@ class NostoHttpRequest
42
  const AUTH_BEARER = 'bearer';
43
 
44
  const PATH_ACCOUNT_DELETED = '/hub/uninstall';
 
45
 
46
  /**
47
  * @var string base url for the nosto web hook requests.
@@ -423,10 +424,12 @@ class NostoHttpRequest
423
  if (!empty($this->replaceParams)) {
424
  $url = self::buildUri($url, $this->replaceParams);
425
  }
426
- return serialize(array(
427
- 'url' => $url,
428
- 'headers' => $this->headers,
429
- 'body' => $this->content,
430
- ));
 
 
431
  }
432
  }
42
  const AUTH_BEARER = 'bearer';
43
 
44
  const PATH_ACCOUNT_DELETED = '/hub/uninstall';
45
+ const PATH_SSO_AUTH = '/hub/{platform}/load/{email}';
46
 
47
  /**
48
  * @var string base url for the nosto web hook requests.
424
  if (!empty($this->replaceParams)) {
425
  $url = self::buildUri($url, $this->replaceParams);
426
  }
427
+ return serialize(
428
+ array(
429
+ 'url' => $url,
430
+ 'headers' => $this->headers,
431
+ 'body' => $this->content,
432
+ )
433
+ );
434
  }
435
  }
lib/nosto/php-sdk/src/classes/http/NostoHttpRequestAdapter.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/http/NostoHttpRequestAdapterCurl.php CHANGED
@@ -130,11 +130,11 @@ class NostoHttpRequestAdapterCurl extends NostoHttpRequestAdapter
130
  $ch = curl_init();
131
  curl_setopt_array($ch, $curlOptions);
132
  $result = curl_exec($ch);
133
- $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
134
- $headers = explode("\r\n", substr($result, 0, $headerSize));
135
- $body = substr($result, $headerSize);
136
- $message = curl_error($ch);
137
- curl_close($ch);
138
  return new NostoHttpResponse($headers, $body, $message);
139
  }
140
  }
130
  $ch = curl_init();
131
  curl_setopt_array($ch, $curlOptions);
132
  $result = curl_exec($ch);
133
+ $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
134
+ $headers = explode("\r\n", substr($result, 0, $headerSize));
135
+ $body = substr($result, $headerSize);
136
+ $message = curl_error($ch);
137
+ curl_close($ch);
138
  return new NostoHttpResponse($headers, $body, $message);
139
  }
140
  }
lib/nosto/php-sdk/src/classes/http/NostoHttpRequestAdapterSocket.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/http/NostoHttpResponse.php CHANGED
@@ -53,31 +53,31 @@ class NostoHttpResponse
53
  */
54
  protected $message;
55
 
56
- /**
57
- * @var int runtime cache for the http response code.
58
- */
59
- private $_code;
60
 
61
- /**
62
- * Constructor.
63
- * Creates and populates the response object.
64
- *
65
- * @param array $headers the response headers.
66
- * @param string $body the response body.
67
- * @param string $error optional error message.
68
- */
69
- public function __construct($headers, $body, $error = null)
70
- {
71
- if (!empty($headers) && is_array($headers)) {
72
- $this->headers = $headers;
73
- }
74
- if (!empty($body) && is_string($body)) {
75
- $this->result = $body;
76
- }
77
- if (!empty($error) && is_string($error)) {
78
- $this->message = $error;
79
- }
80
- }
81
 
82
  /**
83
  * Getter for the request response data.
@@ -100,15 +100,15 @@ class NostoHttpResponse
100
  return json_decode($this->result, $assoc);
101
  }
102
 
103
- /**
104
- * Getter for the error message of the request.
105
- *
106
- * @return string the message.
107
- */
108
- public function getMessage()
109
- {
110
- return $this->message;
111
- }
112
 
113
  /**
114
  * Returns the `last` http response code.
@@ -117,20 +117,20 @@ class NostoHttpResponse
117
  */
118
  public function getCode()
119
  {
120
- if (is_null($this->_code)) {
121
- $code = 0;
122
- if (!empty($this->headers)) {
123
- foreach ($this->headers as $header) {
124
- $matches = array();
125
- preg_match('|HTTP/\d\.\d\s+(\d+)\s+.*|', $header, $matches);
126
- if (isset($matches[1])) {
127
- $code = (int)$matches[1];
128
- }
129
- }
130
- }
131
- $this->_code = $code;
132
- }
133
- return $this->_code;
134
  }
135
 
136
  /**
@@ -139,10 +139,12 @@ class NostoHttpResponse
139
  */
140
  public function __toString()
141
  {
142
- return serialize(array(
143
- 'headers' => $this->headers,
144
- 'body' => $this->result,
145
- 'error' => $this->message,
146
- ));
 
 
147
  }
148
  }
53
  */
54
  protected $message;
55
 
56
+ /**
57
+ * @var int runtime cache for the http response code.
58
+ */
59
+ private $_code;
60
 
61
+ /**
62
+ * Constructor.
63
+ * Creates and populates the response object.
64
+ *
65
+ * @param array $headers the response headers.
66
+ * @param string $body the response body.
67
+ * @param string $error optional error message.
68
+ */
69
+ public function __construct($headers, $body, $error = null)
70
+ {
71
+ if (!empty($headers) && is_array($headers)) {
72
+ $this->headers = $headers;
73
+ }
74
+ if (!empty($body) && is_string($body)) {
75
+ $this->result = $body;
76
+ }
77
+ if (!empty($error) && is_string($error)) {
78
+ $this->message = $error;
79
+ }
80
+ }
81
 
82
  /**
83
  * Getter for the request response data.
100
  return json_decode($this->result, $assoc);
101
  }
102
 
103
+ /**
104
+ * Getter for the error message of the request.
105
+ *
106
+ * @return string the message.
107
+ */
108
+ public function getMessage()
109
+ {
110
+ return $this->message;
111
+ }
112
 
113
  /**
114
  * Returns the `last` http response code.
117
  */
118
  public function getCode()
119
  {
120
+ if (is_null($this->_code)) {
121
+ $code = 0;
122
+ if (!empty($this->headers)) {
123
+ foreach ($this->headers as $header) {
124
+ $matches = array();
125
+ preg_match('|HTTP/\d\.\d\s+(\d+)\s+.*|', $header, $matches);
126
+ if (isset($matches[1])) {
127
+ $code = (int)$matches[1];
128
+ }
129
+ }
130
+ }
131
+ $this->_code = $code;
132
+ }
133
+ return $this->_code;
134
  }
135
 
136
  /**
139
  */
140
  public function __toString()
141
  {
142
+ return serialize(
143
+ array(
144
+ 'headers' => $this->headers,
145
+ 'body' => $this->result,
146
+ 'error' => $this->message,
147
+ )
148
+ );
149
  }
150
  }
lib/nosto/php-sdk/src/classes/oauth/NostoOAuthClient.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/oauth/NostoOAuthToken.php CHANGED
File without changes
lib/nosto/php-sdk/src/classes/operation/NostoOperationProduct.php CHANGED
@@ -71,6 +71,23 @@ class NostoOperationProduct
71
  $this->collection[] = $product;
72
  }
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  /**
75
  * Sends a POST request to create all the products currently in the collection.
76
  *
@@ -80,7 +97,7 @@ class NostoOperationProduct
80
  public function create()
81
  {
82
  $request = $this->initApiRequest();
83
- $request->setPath(NostoApiRequest::PATH_PRODUCTS_UPSERT);
84
  $response = $request->post($this->getCollectionAsJson());
85
  if ($response->getCode() !== 200) {
86
  Nosto::throwHttpException('Failed to create Nosto product(s).', $request, $response);
@@ -89,7 +106,7 @@ class NostoOperationProduct
89
  }
90
 
91
  /**
92
- * Sends a POST request to update all the products currently in the collection.
93
  *
94
  * @return bool if the request was successful.
95
  * @throws NostoException on failure.
@@ -97,8 +114,8 @@ class NostoOperationProduct
97
  public function update()
98
  {
99
  $request = $this->initApiRequest();
100
- $request->setPath(NostoApiRequest::PATH_PRODUCTS_UPSERT);
101
- $response = $request->post($this->getCollectionAsJson());
102
  if ($response->getCode() !== 200) {
103
  Nosto::throwHttpException('Failed to update Nosto product(s).', $request, $response);
104
  }
@@ -139,7 +156,7 @@ class NostoOperationProduct
139
 
140
  $request = new NostoApiRequest();
141
  $request->setContentType('application/json');
142
- $request->setAuthBasic('', $token->value);
143
  return $request;
144
  }
145
 
@@ -153,7 +170,7 @@ class NostoOperationProduct
153
  {
154
  return array(
155
  'url' => $product->getUrl(),
156
- 'product_id' => (int)$product->getProductId(),
157
  'name' => $product->getName(),
158
  'image_url' => $product->getImageUrl(),
159
  'price' => Nosto::helper('price')->format($product->getPrice()),
@@ -177,10 +194,10 @@ class NostoOperationProduct
177
  protected function getCollectionAsJson()
178
  {
179
  $data = array();
180
- $validator = new NostoModelValidator();
181
  foreach ($this->collection->getArrayCopy() as $item) {
182
- /** @var NostoProductInterface|NostoValidatableModelInterface $item */
183
- if ($validator->validate($item)) {
 
184
  $data[] = $this->getProductAsArray($item);
185
  }
186
  }
@@ -201,10 +218,7 @@ class NostoOperationProduct
201
  $data = array();
202
  foreach ($this->collection->getArrayCopy() as $item) {
203
  /** @var NostoProductInterface $item */
204
- $productId = (int)$item->getProductId();
205
- if ($productId > 0) {
206
- $data[] = $productId;
207
- }
208
  }
209
  if (empty($data)) {
210
  throw new NostoException('No products found in collection.');
71
  $this->collection[] = $product;
72
  }
73
 
74
+ /**
75
+ * Sends a POST request to create or update all the products currently in the collection.
76
+ *
77
+ * @return bool if the request was successful.
78
+ * @throws NostoException on failure.
79
+ */
80
+ public function upsert()
81
+ {
82
+ $request = $this->initApiRequest();
83
+ $request->setPath(NostoApiRequest::PATH_PRODUCTS_UPSERT);
84
+ $response = $request->post($this->getCollectionAsJson());
85
+ if ($response->getCode() !== 200) {
86
+ Nosto::throwHttpException('Failed to upsert Nosto product(s).', $request, $response);
87
+ }
88
+ return true;
89
+ }
90
+
91
  /**
92
  * Sends a POST request to create all the products currently in the collection.
93
  *
97
  public function create()
98
  {
99
  $request = $this->initApiRequest();
100
+ $request->setPath(NostoApiRequest::PATH_PRODUCTS_CREATE);
101
  $response = $request->post($this->getCollectionAsJson());
102
  if ($response->getCode() !== 200) {
103
  Nosto::throwHttpException('Failed to create Nosto product(s).', $request, $response);
106
  }
107
 
108
  /**
109
+ * Sends a PUT request to update all the products currently in the collection.
110
  *
111
  * @return bool if the request was successful.
112
  * @throws NostoException on failure.
114
  public function update()
115
  {
116
  $request = $this->initApiRequest();
117
+ $request->setPath(NostoApiRequest::PATH_PRODUCTS_UPDATE);
118
+ $response = $request->put($this->getCollectionAsJson());
119
  if ($response->getCode() !== 200) {
120
  Nosto::throwHttpException('Failed to update Nosto product(s).', $request, $response);
121
  }
156
 
157
  $request = new NostoApiRequest();
158
  $request->setContentType('application/json');
159
+ $request->setAuthBasic('', $token->getValue());
160
  return $request;
161
  }
162
 
170
  {
171
  return array(
172
  'url' => $product->getUrl(),
173
+ 'product_id' => $product->getProductId(),
174
  'name' => $product->getName(),
175
  'image_url' => $product->getImageUrl(),
176
  'price' => Nosto::helper('price')->format($product->getPrice()),
194
  protected function getCollectionAsJson()
195
  {
196
  $data = array();
 
197
  foreach ($this->collection->getArrayCopy() as $item) {
198
+ /** @var NostoProductInterface|NostoValidatableInterface $item */
199
+ $validator = new NostoValidator($item);
200
+ if ($validator->validate()) {
201
  $data[] = $this->getProductAsArray($item);
202
  }
203
  }
218
  $data = array();
219
  foreach ($this->collection->getArrayCopy() as $item) {
220
  /** @var NostoProductInterface $item */
221
+ $data[] = $item->getProductId();
 
 
 
222
  }
223
  if (empty($data)) {
224
  throw new NostoException('No products found in collection.');
lib/nosto/php-sdk/src/config.inc.php CHANGED
@@ -48,10 +48,11 @@ require_once(dirname(__FILE__).'/interfaces/order/NostoOrderStatusInterface.php'
48
  require_once(dirname(__FILE__).'/interfaces/NostoOAuthClientMetaDataInterface.php');
49
  require_once(dirname(__FILE__).'/interfaces/NostoProductInterface.php');
50
  require_once(dirname(__FILE__).'/interfaces/NostoExportCollectionInterface.php');
51
- require_once(dirname(__FILE__).'/interfaces/NostoValidatableModelInterface.php');
52
 
53
  // Classes
54
  require_once(dirname(__FILE__).'/classes/http/NostoHttpRequest.php'); // Must be loaded before `NostoApiRequest`
 
55
 
56
  require_once(dirname(__FILE__).'/classes/api/NostoApiRequest.php');
57
  require_once(dirname(__FILE__).'/classes/api/NostoApiToken.php');
@@ -89,7 +90,7 @@ require_once(dirname(__FILE__).'/classes/NostoDotEnv.php');
89
  require_once(dirname(__FILE__).'/classes/NostoMessage.php');
90
  require_once(dirname(__FILE__).'/classes/NostoOrderConfirmation.php');
91
  require_once(dirname(__FILE__).'/classes/NostoProductReCrawl.php');
92
- require_once(dirname(__FILE__).'/classes/NostoModelValidator.php');
93
 
94
  // Libs
95
  require_once(dirname(__FILE__).'/libs/phpseclib/crypt/NostoCryptBase.php');
48
  require_once(dirname(__FILE__).'/interfaces/NostoOAuthClientMetaDataInterface.php');
49
  require_once(dirname(__FILE__).'/interfaces/NostoProductInterface.php');
50
  require_once(dirname(__FILE__).'/interfaces/NostoExportCollectionInterface.php');
51
+ require_once(dirname(__FILE__).'/interfaces/NostoValidatableInterface.php');
52
 
53
  // Classes
54
  require_once(dirname(__FILE__).'/classes/http/NostoHttpRequest.php'); // Must be loaded before `NostoApiRequest`
55
+ require_once(dirname(__FILE__).'/classes/NostoObject.php');
56
 
57
  require_once(dirname(__FILE__).'/classes/api/NostoApiRequest.php');
58
  require_once(dirname(__FILE__).'/classes/api/NostoApiToken.php');
90
  require_once(dirname(__FILE__).'/classes/NostoMessage.php');
91
  require_once(dirname(__FILE__).'/classes/NostoOrderConfirmation.php');
92
  require_once(dirname(__FILE__).'/classes/NostoProductReCrawl.php');
93
+ require_once(dirname(__FILE__).'/classes/NostoValidator.php');
94
 
95
  // Libs
96
  require_once(dirname(__FILE__).'/libs/phpseclib/crypt/NostoCryptBase.php');
lib/nosto/php-sdk/src/interfaces/NostoExportCollectionInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/NostoOAuthClientMetaDataInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/NostoProductInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/{NostoValidatableModelInterface.php → NostoValidatableInterface.php} RENAMED
@@ -34,12 +34,12 @@
34
  */
35
 
36
  /**
37
- * Interface for all models that support data validation.
38
  */
39
- interface NostoValidatableModelInterface
40
  {
41
  /**
42
- * Returns an array of validator rules for the model properties.
43
  *
44
  * Example:
45
  *
34
  */
35
 
36
  /**
37
+ * Interface for all objects that support data validation.
38
  */
39
+ interface NostoValidatableInterface
40
  {
41
  /**
42
+ * Returns an array of validator rules for the object properties.
43
  *
44
  * Example:
45
  *
lib/nosto/php-sdk/src/interfaces/account/NostoAccountInterface.php CHANGED
@@ -91,7 +91,7 @@ interface NostoAccountInterface
91
  * Gets the secured iframe url for the account configuration page.
92
  *
93
  * @param NostoAccountMetaDataIframeInterface $meta the iframe meta data to use for fetching the secured url.
94
- * @param array $params optional extra params to add to the iframe url.
95
  * @return bool|string the url or false if could not be fetched.
96
  */
97
  public function getIframeUrl(NostoAccountMetaDataIframeInterface $meta, array $params = array());
91
  * Gets the secured iframe url for the account configuration page.
92
  *
93
  * @param NostoAccountMetaDataIframeInterface $meta the iframe meta data to use for fetching the secured url.
94
+ * @param array $params optional extra params to add to the iframe url.
95
  * @return bool|string the url or false if could not be fetched.
96
  */
97
  public function getIframeUrl(NostoAccountMetaDataIframeInterface $meta, array $params = array());
lib/nosto/php-sdk/src/interfaces/account/NostoAccountMetaDataBillingDetailsInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/account/NostoAccountMetaDataIframeInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/account/NostoAccountMetaDataInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/account/NostoAccountMetaDataOwnerInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/order/NostoOrderBuyerInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/order/NostoOrderInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/order/NostoOrderPurchasedItemInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/interfaces/order/NostoOrderStatusInterface.php CHANGED
File without changes
lib/nosto/php-sdk/src/js/NostoIframe.min.js CHANGED
@@ -1 +1 @@
1
- if("undefined"==typeof Nosto)var Nosto={};Nosto.iframe=function(a){function b(a){if(a.origin===decodeURIComponent(j.origin)&&"[Nosto]"===(""+a.data).substr(0,7)){var b=(""+a.data).substr(7),d=JSON.parse(b);if("object"==typeof d&&d.type)switch(d.type){case g:c(j.urls.createAccount,{data:{email:d.params.email},success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account creation.");f().src=b.redirect_url}});break;case h:c(j.urls.connectAccount,{success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account connection.");b.success&&b.success===!0?window.location.href=b.redirect_url:f().src=b.redirect_url}});break;case i:c(j.urls.deleteAccount,{success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account deletion.");f().src=b.redirect_url}});break;default:throw new Error("Nosto: invalid postMessage `type`.")}}}function c(a,b){var c=d({method:"POST",async:!0,data:{}},b);d(c.data,j.xhrParams);var f=e(c.data),g=new XMLHttpRequest;"function"==typeof c.success&&g.addEventListener("load",c.success,!1),"function"==typeof c.error&&g.addEventListener("error",c.error,!1),g.open(c.method,decodeURIComponent(a),c.async),g.setRequestHeader("X-Requested-With","XMLHttpRequest"),g.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),g.send(f)}function d(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function e(a){var b="";for(var c in a)a.hasOwnProperty(c)&&(""!==b&&(b+="&"),b+=encodeURIComponent(c)+"="+encodeURIComponent(a[c]));return b}function f(){return document.getElementById(j.iframeId)}var g="newAccount",h="connectAccount",i="removeAccount",j={origin:"https://my.nosto.com",iframeId:"nosto_iframe",urls:{createAccount:"",connectAccount:"",deleteAccount:""},xhrParams:{}};d(j,a),window.addEventListener("message",b,!1)};
1
+ if("undefined"==typeof Nosto)var Nosto={};Nosto.iframe=function(a){function b(a){var b=new RegExp(j.origin);if(b.test(a.origin)&&"[Nosto]"===(""+a.data).substr(0,7)){var d=(""+a.data).substr(7),e=JSON.parse(d);if("object"==typeof e&&e.type)switch(e.type){case g:c(j.urls.createAccount,{data:{email:e.params.email},success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account creation.");f().src=b.redirect_url}});break;case h:c(j.urls.connectAccount,{success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account connection.");b.success&&b.success===!0?window.location.href=b.redirect_url:f().src=b.redirect_url}});break;case i:c(j.urls.deleteAccount,{success:function(a){var b=JSON.parse(a.target.response);if(!b.redirect_url)throw new Error("Nosto: failed to handle account deletion.");f().src=b.redirect_url}});break;default:throw new Error("Nosto: invalid postMessage `type`.")}}}function c(a,b){var c=d({method:"POST",async:!0,data:{}},b);d(c.data,j.xhrParams);var f=e(c.data),g=new XMLHttpRequest;"function"==typeof c.success&&g.addEventListener("load",c.success,!1),"function"==typeof c.error&&g.addEventListener("error",c.error,!1),g.open(c.method,decodeURIComponent(a),c.async),g.setRequestHeader("X-Requested-With","XMLHttpRequest"),g.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),g.send(f)}function d(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function e(a){var b="";for(var c in a)a.hasOwnProperty(c)&&(""!==b&&(b+="&"),b+=encodeURIComponent(c)+"="+encodeURIComponent(a[c]));return b}function f(){return document.getElementById(j.iframeId)}var g="newAccount",h="connectAccount",i="removeAccount",j={origin:"",iframeId:"nosto_iframe",urls:{createAccount:"",connectAccount:"",deleteAccount:""},xhrParams:{}};d(j,a),window.addEventListener("message",b,!1)};
lib/nosto/php-sdk/src/js/src/NostoIframe.js CHANGED
@@ -51,7 +51,7 @@ Nosto.iframe = function(options) {
51
  * @type {Object}
52
  */
53
  var settings = {
54
- origin: "https://my.nosto.com",
55
  iframeId: "nosto_iframe",
56
  urls: {
57
  createAccount: "",
@@ -74,7 +74,8 @@ Nosto.iframe = function(options) {
74
  function receiveMessage(event)
75
  {
76
  // Check the origin to prevent cross-site scripting.
77
- if (event.origin !== decodeURIComponent(settings.origin)) {
 
78
  return;
79
  }
80
  // If the message does not start with "[Nosto]", then it is not for us.
51
  * @type {Object}
52
  */
53
  var settings = {
54
+ origin: "",
55
  iframeId: "nosto_iframe",
56
  urls: {
57
  createAccount: "",
74
  function receiveMessage(event)
75
  {
76
  // Check the origin to prevent cross-site scripting.
77
+ var originRegexp = new RegExp(settings.origin);
78
+ if (!originRegexp.test(event.origin)) {
79
  return;
80
  }
81
  // If the message does not start with "[Nosto]", then it is not for us.
lib/nosto/php-sdk/src/libs/phpseclib/crypt/NostoCryptAES.php CHANGED
File without changes
lib/nosto/php-sdk/src/libs/phpseclib/crypt/NostoCryptBase.php CHANGED
File without changes
lib/nosto/php-sdk/src/libs/phpseclib/crypt/NostoCryptRandom.php CHANGED
File without changes
lib/nosto/php-sdk/src/libs/phpseclib/crypt/NostoCryptRijndael.php CHANGED
File without changes
package.xml CHANGED
@@ -1,20 +1,22 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Nosto_Tagging</name>
4
- <version>2.4.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Personalization for Magento</summary>
10
  <description>Increase your conversion rate and average order value by delivering your customers personalized product recommendations throughout their shopping journey.</description>
11
- <notes>* Deprecate product re-crawl feature and implement product update API in it's place&#xD;
12
- * Add JavaScript "add-to-cart" feature to enable adding products to cart directly from recommendations&#xD;
13
- * Refactor order status handling in order confirmations and order exports</notes>
 
 
14
  <authors><author><name>Nosto</name><user>nosto</user><email>magento@nosto.com</email></author></authors>
15
- <date>2015-05-13</date>
16
- <time>10:52:00</time>
17
- <contents><target name="magecommunity"><dir name="Nosto"><dir name="Tagging"><dir name="Block"><file name="Addtocart.php" hash="61d645e5cc9e54a5170ae03797f0426a"/><dir name="Adminhtml"><file name="Iframe.php" hash="158340d20d1a01a0863f24278198c2e5"/><file name="Wizard.php" hash="f98931a1a6e327c0d05e43b73063f672"/></dir><file name="Cart.php" hash="feb9b5d1c84d2301c9f74613559dceb7"/><file name="Category.php" hash="177a5d8d9f1ba9e246d149c228c3aec8"/><file name="Customer.php" hash="d35777ca399244e4fb441456320f8ad7"/><file name="Element.php" hash="e5b12bb118b92eb7075ff7a6e16e0eba"/><file name="Embed.php" hash="e8b628b6bc49fb865697552300d08526"/><file name="Meta.php" hash="1f761e731214b7572ef139d9e0577ea1"/><file name="Order.php" hash="1666d552e61768cfd35860b9472feced"/><file name="Product.php" hash="261cd58ad94daa82d1cf2188179278c0"/></dir><dir name="Helper"><file name="Account.php" hash="afd5f7e1bc61a5ab450e0483db371370"/><file name="Customer.php" hash="92da4f0ae6c2aef635b837635cd74238"/><file name="Data.php" hash="b138748cea6b7c4ccda41e7f2ef1f1cb"/><file name="Date.php" hash="1a108a4ec8169b73411b6c11b86a1d80"/><file name="Oauth.php" hash="08f096ef785d64225ec71d7e2e99f534"/><file name="Price.php" hash="4c21321d10f40c6f985bd934b174a17c"/><file name="Url.php" hash="289294904d246c56e4de96798927a7f6"/></dir><dir name="Model"><dir name="Container"><file name="Cart.php" hash="20d2936693361999575f1e6ac56f2e40"/><file name="Customer.php" hash="b03bca89845b6c939521add8df1f7e9a"/></dir><file name="Customer.php" hash="6d992a43a75f29836ed1450e130df560"/><dir name="Meta"><dir name="Account"><file name="Billing.php" hash="d09b6b6ddc543201ec9485db9bb0a260"/><file name="Iframe.php" hash="f26a7ef337d86cb83c687ba2e0beb45b"/><file name="Owner.php" hash="801c33bbf04bcfbe133654770909d1df"/></dir><file name="Account.php" hash="c01a324111528339ddd71f0046b95ecc"/><file name="Oauth.php" hash="761b0dd6cede8122c715d077b010b927"/><dir name="Order"><file name="Buyer.php" hash="633c6de58a46128bb594d6580d3ffa46"/><file name="Item.php" hash="86baa577302a4791fa68981b06c2957c"/><file name="Status.php" hash="37520c32630aa4bf14d8213f39e80a4b"/></dir><file name="Order.php" hash="5dc6ddaa5e6129ce4fa9928bdcd44c56"/><file name="Product.php" hash="ead9fece42fa1a155a2a5a12f54b1d15"/></dir><file name="Observer.php" hash="d084e9b8beb56e00dab2a1036a7b476d"/><dir name="Resource"><dir name="Customer"><file name="Collection.php" hash="0c99b46d5108a6fe31cad1190d8ef47c"/></dir><file name="Customer.php" hash="f92e4e5334b5e3493e8f04664b20f105"/><file name="Setup.php" hash="506b08bcb10cbe74e95812c5f646429f"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="NostoController.php" hash="6d0825f3190db7734637368c262d3c83"/></dir><file name="ExportController.php" hash="ab178910035ea0ba5524c88c66e73e18"/><file name="OauthController.php" hash="e57a2578535e711ce1bdcb78e3fa1983"/></dir><dir name="etc"><file name="adminhtml.xml" hash="70f3a22856ec6cb31749a92ed4461b6b"/><file name="cache.xml" hash="e874fbbf2eb89b325deb1a62afbcfb4d"/><file name="config.xml" hash="717904bbef1d6fdeeae3f67e4a4f094f"/></dir><dir name="sql"><dir name="tagging_setup"><file name="mysql4-install-1.2.0.php" hash="3cbc52834c44870859562eec7969b9fd"/><file name="mysql4-upgrade-1.1.7-1.2.0.php" hash="0d8eb7990461a9d4b74b479120067aeb"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="nostotagging"><file name="iframe.phtml" hash="c81931adf855a4893e0cf2dc60c390cb"/><file name="wizard.phtml" hash="3f92e94e5ee3d3cd9906a6b0942a3a1b"/></dir></dir><dir name="layout"><file name="nostotagging.xml" hash="5f77c6921f67d08484c6d510b4706c29"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="nostotagging"><file name="addtocart.phtml" hash="e8776f59ec4c7c7b6eea2fae9d56e2a4"/><file name="cart.phtml" hash="c3d560050239066c73b1ec935048dbee"/><dir name="category"><file name="view.phtml" hash="fc09e2770ad6281ec96c8e92accc01f1"/></dir><file name="category.phtml" hash="81f36742cb4e3adbf9f692cc8f0ea8a8"/><file name="customer.phtml" hash="e9bc92bb7f7df989cc706c7eaee3614a"/><file name="element.phtml" hash="e1d38981789e632a3607ccf2e171f0cb"/><file name="embed.phtml" hash="9193ddd1ae373b68c53f8364f511b0a5"/><file name="meta.phtml" hash="c1b862a4993503fae420fb0eba194b00"/><file name="order.phtml" hash="7d65566ba4ee709dab7f2114340742af"/><file name="product.phtml" hash="412b7bd9ed43981f056132ea37719aab"/></dir></dir><dir name="layout"><file name="nostotagging.xml" hash="8adc3eecf5f90feffabee29d6308912b"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Nosto_Tagging.xml" hash="1705cb7e6db28388662ef52882d61701"/></dir></target><target name="magelib"><dir name="nosto"><dir name="php-sdk"><dir name="src"><dir name="classes"><file name="Nosto.php" hash="c595c5f646f6e513b6604848f8d10118"/><file name="NostoAccount.php" hash="e245046832cd1655f456da6e999c1af7"/><file name="NostoCipher.php" hash="a3d7d148311aa0319387c0918e5e26dc"/><file name="NostoDotEnv.php" hash="90b23c1b02095c9368372f1d5346c3f9"/><file name="NostoMessage.php" hash="5933eadd2ad08427010b0bf16657266b"/><file name="NostoModelValidator.php" hash="5c978de7b8df8d06a3f5562b65db605c"/><file name="NostoOrderConfirmation.php" hash="2a3fd5efb196bc0dcb7ad57fb61a81d0"/><file name="NostoProductReCrawl.php" hash="c0c249070fe947e1f99ec67066d1e5cb"/><dir name="api"><file name="NostoApiRequest.php" hash="ce6e27815d268847cf629caf48323b6d"/><file name="NostoApiToken.php" hash="ca42b406a88735ac1565bf13efdf8a04"/></dir><dir name="collection"><file name="NostoCollection.php" hash="35cea0282628354413f629062b58663a"/><file name="NostoOrderCollection.php" hash="db6f517948c1258e1521ceb1ce49d477"/><file name="NostoProductCollection.php" hash="3ae29dbbcb7effa234fa83461d3e6901"/></dir><dir name="exception"><file name="NostoException.php" hash="c4610fb70278d01bd85bc83b8e74df30"/><file name="NostoHttpException.php" hash="dabf4298746db898c8fe709ea9e25818"/></dir><dir name="export"><file name="NostoExportOrderCollection.php" hash="d45096eef64e26e8dc3f5c042e52f938"/><file name="NostoExportProductCollection.php" hash="84349c0a7080a4f154c2d9e29d4e621f"/><file name="NostoExporter.php" hash="b72305e0a18c8afa6a3ee4f2e37049a0"/></dir><dir name="helper"><file name="NostoHelper.php" hash="f4ca6c78e047fec93c32b7eb822b0692"/><file name="NostoHelperDate.php" hash="081a2d8bfec710f2baa52192a99a2658"/><file name="NostoHelperIframe.php" hash="1364153a359dcfdf22f7376aba66da47"/><file name="NostoHelperPrice.php" hash="ee9f217dc1b8e0fc679fb56ca3fd3ca1"/></dir><dir name="http"><file name="NostoHttpRequest.php" hash="7872c46736ef462e5820229d1b16bd0d"/><file name="NostoHttpRequestAdapter.php" hash="d8bf8e5db44ad982b655372529f4d88c"/><file name="NostoHttpRequestAdapterCurl.php" hash="c903ab33e7c326528600c26501e8609a"/><file name="NostoHttpRequestAdapterSocket.php" hash="88f57e6d98de2ac652a235e2786f0be7"/><file name="NostoHttpResponse.php" hash="68a5c65b0bf9a212db0138e7b5d764e1"/></dir><dir name="oauth"><file name="NostoOAuthClient.php" hash="2672d9de80d23c91776d97b9803d01b4"/><file name="NostoOAuthToken.php" hash="f81c1c1e5c4fc2010162d8f69de2cb33"/></dir><dir name="operation"><file name="NostoOperationProduct.php" hash="14b9b8c02a890630df0164a244ae1715"/></dir></dir><file name="config.inc.php" hash="a7ca6d6fb79ae7b5a9fb29b4c7235ed7"/><dir name="interfaces"><file name="NostoExportCollectionInterface.php" hash="63c833c17fe43ce48b45e0f552313a8b"/><file name="NostoOAuthClientMetaDataInterface.php" hash="75a82417bfc27cd82e41ea9810d31428"/><file name="NostoProductInterface.php" hash="110aabc704bed12ddacc304d6d1e1529"/><file name="NostoValidatableModelInterface.php" hash="452d7c40b94573590c9b9f70189931fa"/><dir name="account"><file name="NostoAccountInterface.php" hash="5655c43db9e1e0a8e1fd23753ec5ef06"/><file name="NostoAccountMetaDataBillingDetailsInterface.php" hash="ef31f0c3b41591fd76f85a25021f0fe4"/><file name="NostoAccountMetaDataIframeInterface.php" hash="c739e6a3ef39a308df6852361f2fd1d7"/><file name="NostoAccountMetaDataInterface.php" hash="7395de56fb4e3a1831bc5f7cfeffed8d"/><file name="NostoAccountMetaDataOwnerInterface.php" hash="4c037b8cb1b529c16c91f25cce2b0ed7"/></dir><dir name="order"><file name="NostoOrderBuyerInterface.php" hash="890884e45bcca61f96f0f98cda40b6c1"/><file name="NostoOrderInterface.php" hash="d341b4faf020bfca01336c5d60ca5e48"/><file name="NostoOrderPurchasedItemInterface.php" hash="e33b94290465eea80d614db35144b75a"/><file name="NostoOrderStatusInterface.php" hash="8c89cf4296629b635f52b53a9b800b1f"/></dir></dir><dir name="js"><file name="NostoIframe.min.js" hash="b4508aed29b641e6ad3d1062a54c209f"/><dir name="src"><file name="NostoIframe.js" hash="e9962928ba1cf0ff205e21a0d469f4d8"/></dir></dir><dir name="libs"><dir name="phpseclib"><dir name="crypt"><file name="NostoCryptAES.php" hash="7f16ec6fa7eefa011a27acf4506a3b57"/><file name="NostoCryptBase.php" hash="c78432d428ad8a70be832f91261d4c42"/><file name="NostoCryptRandom.php" hash="eb21a56b9cf6e6ef0b220620dd4d0ebe"/><file name="NostoCryptRijndael.php" hash="9c728d06c0249f8bc24a7c61606ccc89"/></dir></dir></dir><file name=".env.example" hash="ec9fd4d90a792e2c98b10ff8fe7ae984"/></dir></dir></dir></target><target name="mage"><dir name="js"><dir name="nosto"><file name="NostoIframe.min.js" hash="b4508aed29b641e6ad3d1062a54c209f"/><file name="iframeresizer.min.js" hash="163b065c9dd702dc364913a951b81fee"/><file name="nostotagging-config.js" hash="0119fb333233f1f0fa70f4167fb014ef"/></dir></dir></target></contents>
18
  <compatible/>
19
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php><package><name>Mage_Core_Modules</name><channel>community</channel><min>1.6.0.0</min><max>1.9.1.1</max></package></required></dependencies>
20
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Nosto_Tagging</name>
4
+ <version>2.5.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Personalization for Magento</summary>
10
  <description>Increase your conversion rate and average order value by delivering your customers personalized product recommendations throughout their shopping journey.</description>
11
+ <notes>* Add order status and payment provider info to order tagging&#xD;
12
+ * Add support for account specific sub-domains when configuring Nosto&#xD;
13
+ * Add support for choosing the product image version used in tagging&#xD;
14
+ * Fix product update event observer store scope&#xD;
15
+ * Fix cart/order tagging to always tag the same product ID as on the product page the item was added to the cart/ordered from</notes>
16
  <authors><author><name>Nosto</name><user>nosto</user><email>magento@nosto.com</email></author></authors>
17
+ <date>2015-06-09</date>
18
+ <time>07:58:32</time>
19
+ <contents><target name="magecommunity"><dir name="Nosto"><dir name="Tagging"><dir name="Block"><file name="Addtocart.php" hash="61d645e5cc9e54a5170ae03797f0426a"/><dir name="Adminhtml"><file name="Iframe.php" hash="9b089bb3cd733de7a9e7caf2b46793c2"/><file name="Wizard.php" hash="f98931a1a6e327c0d05e43b73063f672"/></dir><file name="Cart.php" hash="9f4a64499d572780d82d4a1d50cb7880"/><file name="Category.php" hash="177a5d8d9f1ba9e246d149c228c3aec8"/><file name="Customer.php" hash="d35777ca399244e4fb441456320f8ad7"/><file name="Element.php" hash="e5b12bb118b92eb7075ff7a6e16e0eba"/><file name="Embed.php" hash="e8b628b6bc49fb865697552300d08526"/><file name="Meta.php" hash="1f761e731214b7572ef139d9e0577ea1"/><file name="Order.php" hash="1666d552e61768cfd35860b9472feced"/><file name="Product.php" hash="261cd58ad94daa82d1cf2188179278c0"/></dir><dir name="Helper"><file name="Account.php" hash="631bc5302664889d6784270a1b129f2e"/><file name="Customer.php" hash="92da4f0ae6c2aef635b837635cd74238"/><file name="Data.php" hash="9fcbd75579c671f1ae84d989f936755a"/><file name="Date.php" hash="1a108a4ec8169b73411b6c11b86a1d80"/><file name="Oauth.php" hash="08f096ef785d64225ec71d7e2e99f534"/><file name="Price.php" hash="4c21321d10f40c6f985bd934b174a17c"/><file name="Url.php" hash="289294904d246c56e4de96798927a7f6"/></dir><dir name="Model"><file name="Base.php" hash="c0b3c4a6f68a0b707bf85ceff50e3c4b"/><dir name="Container"><file name="Cart.php" hash="20d2936693361999575f1e6ac56f2e40"/><file name="Customer.php" hash="b03bca89845b6c939521add8df1f7e9a"/></dir><file name="Customer.php" hash="6d992a43a75f29836ed1450e130df560"/><dir name="Meta"><dir name="Account"><file name="Billing.php" hash="d09b6b6ddc543201ec9485db9bb0a260"/><file name="Iframe.php" hash="f26a7ef337d86cb83c687ba2e0beb45b"/><file name="Owner.php" hash="801c33bbf04bcfbe133654770909d1df"/></dir><file name="Account.php" hash="c01a324111528339ddd71f0046b95ecc"/><file name="Oauth.php" hash="761b0dd6cede8122c715d077b010b927"/><dir name="Order"><file name="Buyer.php" hash="633c6de58a46128bb594d6580d3ffa46"/><file name="Item.php" hash="ba8a2782d3e7ef577deb47a0c9825afa"/><file name="Status.php" hash="37520c32630aa4bf14d8213f39e80a4b"/></dir><file name="Order.php" hash="1f166cb28ff71ea092203f6fd0c91696"/><file name="Product.php" hash="9cdb3f3980a66167f83f4ea643d82566"/></dir><file name="Observer.php" hash="64b7cf2c54b7322839570c039de29911"/><dir name="Resource"><dir name="Customer"><file name="Collection.php" hash="0c99b46d5108a6fe31cad1190d8ef47c"/></dir><file name="Customer.php" hash="f92e4e5334b5e3493e8f04664b20f105"/><file name="Setup.php" hash="506b08bcb10cbe74e95812c5f646429f"/></dir><dir name="System"><dir name="Config"><dir name="Source"><file name="Image.php" hash="d1fcc96aab01342627b96edf6fad1dd1"/></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="NostoController.php" hash="6d0825f3190db7734637368c262d3c83"/></dir><file name="ExportController.php" hash="2de4f180d194344563dbfb4e53a80958"/><file name="OauthController.php" hash="e57a2578535e711ce1bdcb78e3fa1983"/></dir><dir name="etc"><file name="adminhtml.xml" hash="7ea210738a77630f299a14b442f3b8d0"/><file name="cache.xml" hash="e874fbbf2eb89b325deb1a62afbcfb4d"/><file name="config.xml" hash="b010ab77d201b346129a51f3254613d8"/><file name="system.xml" hash="1c96c631b30ae296bb23a4f87137de77"/></dir><dir name="sql"><dir name="tagging_setup"><file name="mysql4-install-1.2.0.php" hash="3cbc52834c44870859562eec7969b9fd"/><file name="mysql4-upgrade-1.1.7-1.2.0.php" hash="0d8eb7990461a9d4b74b479120067aeb"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="nostotagging"><file name="iframe.phtml" hash="c81931adf855a4893e0cf2dc60c390cb"/><file name="wizard.phtml" hash="3f92e94e5ee3d3cd9906a6b0942a3a1b"/></dir></dir><dir name="layout"><file name="nostotagging.xml" hash="29eb82c1a28e9c4d398239c765a3f5fd"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="nostotagging"><file name="addtocart.phtml" hash="e8776f59ec4c7c7b6eea2fae9d56e2a4"/><file name="cart.phtml" hash="3c4e80cdcebf63c56dc14a6594e167b8"/><dir name="category"><file name="view.phtml" hash="fc09e2770ad6281ec96c8e92accc01f1"/></dir><file name="category.phtml" hash="81f36742cb4e3adbf9f692cc8f0ea8a8"/><file name="customer.phtml" hash="e9bc92bb7f7df989cc706c7eaee3614a"/><file name="element.phtml" hash="e1d38981789e632a3607ccf2e171f0cb"/><file name="embed.phtml" hash="9193ddd1ae373b68c53f8364f511b0a5"/><file name="meta.phtml" hash="c1b862a4993503fae420fb0eba194b00"/><file name="order.phtml" hash="e15b11ff1cb20aafaab0dc134ddd1a9b"/><file name="product.phtml" hash="412b7bd9ed43981f056132ea37719aab"/></dir></dir><dir name="layout"><file name="nostotagging.xml" hash="8adc3eecf5f90feffabee29d6308912b"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Nosto_Tagging.xml" hash="1705cb7e6db28388662ef52882d61701"/></dir></target><target name="magelib"><dir name="nosto"><dir name="php-sdk"><dir name="src"><dir name="classes"><file name="Nosto.php" hash="c595c5f646f6e513b6604848f8d10118"/><file name="NostoAccount.php" hash="3c7a82174cf700370e144c79573c7fd9"/><file name="NostoCipher.php" hash="a3d7d148311aa0319387c0918e5e26dc"/><file name="NostoDotEnv.php" hash="90b23c1b02095c9368372f1d5346c3f9"/><file name="NostoMessage.php" hash="5933eadd2ad08427010b0bf16657266b"/><file name="NostoObject.php" hash="187808f0c55d02294d41e9395f4c5d58"/><file name="NostoOrderConfirmation.php" hash="2a3fd5efb196bc0dcb7ad57fb61a81d0"/><file name="NostoProductReCrawl.php" hash="f370c539409dd74fc98b7aa1ea0f6387"/><file name="NostoValidator.php" hash="2096ddc9979ec77f8f0b1ec58b459329"/><dir name="api"><file name="NostoApiRequest.php" hash="37db50c0d35ff9a848afe6a4bb871b6f"/><file name="NostoApiToken.php" hash="2febdbec0fd3609162845aa678b36b38"/></dir><dir name="collection"><file name="NostoCollection.php" hash="35cea0282628354413f629062b58663a"/><file name="NostoOrderCollection.php" hash="db6f517948c1258e1521ceb1ce49d477"/><file name="NostoProductCollection.php" hash="3ae29dbbcb7effa234fa83461d3e6901"/></dir><dir name="exception"><file name="NostoException.php" hash="c4610fb70278d01bd85bc83b8e74df30"/><file name="NostoHttpException.php" hash="dabf4298746db898c8fe709ea9e25818"/></dir><dir name="export"><file name="NostoExportOrderCollection.php" hash="91bdd99a2be75be062fe5c7cde1803e4"/><file name="NostoExportProductCollection.php" hash="84349c0a7080a4f154c2d9e29d4e621f"/><file name="NostoExporter.php" hash="72ad0af4bce8e57ada5a29e3634df94f"/></dir><dir name="helper"><file name="NostoHelper.php" hash="f4ca6c78e047fec93c32b7eb822b0692"/><file name="NostoHelperDate.php" hash="081a2d8bfec710f2baa52192a99a2658"/><file name="NostoHelperIframe.php" hash="303668f25103c245396b43811a15c28d"/><file name="NostoHelperPrice.php" hash="ee9f217dc1b8e0fc679fb56ca3fd3ca1"/></dir><dir name="http"><file name="NostoHttpRequest.php" hash="2c5b96a56d33b33e334d4d3772c2b14d"/><file name="NostoHttpRequestAdapter.php" hash="d8bf8e5db44ad982b655372529f4d88c"/><file name="NostoHttpRequestAdapterCurl.php" hash="945a4357578f91291d09f1e2850da580"/><file name="NostoHttpRequestAdapterSocket.php" hash="88f57e6d98de2ac652a235e2786f0be7"/><file name="NostoHttpResponse.php" hash="9982d3ed15bfcc8f0147b2b4cc400223"/></dir><dir name="oauth"><file name="NostoOAuthClient.php" hash="2672d9de80d23c91776d97b9803d01b4"/><file name="NostoOAuthToken.php" hash="f81c1c1e5c4fc2010162d8f69de2cb33"/></dir><dir name="operation"><file name="NostoOperationProduct.php" hash="cd305ae242e6c79d8ec1ed77c316f52b"/></dir></dir><file name="config.inc.php" hash="b46a56f8d61ff2cf69cedb4281719e00"/><dir name="interfaces"><file name="NostoExportCollectionInterface.php" hash="63c833c17fe43ce48b45e0f552313a8b"/><file name="NostoOAuthClientMetaDataInterface.php" hash="75a82417bfc27cd82e41ea9810d31428"/><file name="NostoProductInterface.php" hash="110aabc704bed12ddacc304d6d1e1529"/><file name="NostoValidatableInterface.php" hash="57ad8b28225344127843b97049f5868d"/><dir name="account"><file name="NostoAccountInterface.php" hash="063da0d25a5420f4e727938467c078f3"/><file name="NostoAccountMetaDataBillingDetailsInterface.php" hash="ef31f0c3b41591fd76f85a25021f0fe4"/><file name="NostoAccountMetaDataIframeInterface.php" hash="c739e6a3ef39a308df6852361f2fd1d7"/><file name="NostoAccountMetaDataInterface.php" hash="7395de56fb4e3a1831bc5f7cfeffed8d"/><file name="NostoAccountMetaDataOwnerInterface.php" hash="4c037b8cb1b529c16c91f25cce2b0ed7"/></dir><dir name="order"><file name="NostoOrderBuyerInterface.php" hash="890884e45bcca61f96f0f98cda40b6c1"/><file name="NostoOrderInterface.php" hash="d341b4faf020bfca01336c5d60ca5e48"/><file name="NostoOrderPurchasedItemInterface.php" hash="e33b94290465eea80d614db35144b75a"/><file name="NostoOrderStatusInterface.php" hash="8c89cf4296629b635f52b53a9b800b1f"/></dir></dir><dir name="js"><file name="NostoIframe.min.js" hash="5fd9f5b418dd796c469aaa0c58b34aaa"/><dir name="src"><file name="NostoIframe.js" hash="ca03585215f846258d2dbb58724e48fa"/></dir></dir><dir name="libs"><dir name="phpseclib"><dir name="crypt"><file name="NostoCryptAES.php" hash="7f16ec6fa7eefa011a27acf4506a3b57"/><file name="NostoCryptBase.php" hash="c78432d428ad8a70be832f91261d4c42"/><file name="NostoCryptRandom.php" hash="eb21a56b9cf6e6ef0b220620dd4d0ebe"/><file name="NostoCryptRijndael.php" hash="9c728d06c0249f8bc24a7c61606ccc89"/></dir></dir></dir><file name=".env.example" hash="42aa9514d8b3f65e9df96b0df601f63c"/></dir></dir></dir></target><target name="mage"><dir name="js"><dir name="nosto"><file name="NostoAdmin.js" hash="0119fb333233f1f0fa70f4167fb014ef"/><file name="NostoIframe.min.js" hash="5fd9f5b418dd796c469aaa0c58b34aaa"/><file name="iframeresizer.min.js" hash="163b065c9dd702dc364913a951b81fee"/></dir></dir></target></contents>
20
  <compatible/>
21
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php><package><name>Mage_Core_Modules</name><channel>community</channel><min>1.6.0.0</min><max>1.9.1.1</max></package></required></dependencies>
22
  </package>