Antidot_Antidot - Version 1.2.1

Version Notes

Fix facet with ampersand configuration for search engine > facets
Replace "-" with "&afs:feed" to separate feeds in url (compatibility with AFS 7.7)
Fix empty facet id sent when performing an empty query to afs to get facets list
Add description node for variants
Add cdata for variant name
Prevent to export empty categories node
Add cdata for variant name
Add variant details for grouped products

Download this release

Release Info

Developer Antidot
Extension Antidot_Antidot
Version 1.2.1
Comparing to
See all releases


Code changes from version 1.1.4 to 1.2.1

Files changed (43) hide show
  1. app/code/community/MDN/Antidot/Block/Catalogsearch/Banner.php +67 -0
  2. app/code/community/MDN/Antidot/Block/System/Config/Button/Forward.php +39 -0
  3. app/code/community/MDN/Antidot/Helper/Data.php +16 -1
  4. app/code/community/MDN/Antidot/Model/Export/Abstract.php +29 -43
  5. app/code/community/MDN/Antidot/Model/Export/Article.php +3 -3
  6. app/code/community/MDN/Antidot/Model/Export/Category.php +14 -12
  7. app/code/community/MDN/Antidot/Model/Export/Context.php +357 -0
  8. app/code/community/MDN/Antidot/Model/Export/Model/Product.php +412 -0
  9. app/code/community/MDN/Antidot/Model/Export/Model/Product/Link.php +40 -0
  10. app/code/community/MDN/Antidot/Model/Export/Model/Product/Type/Configurable.php +92 -0
  11. app/code/community/MDN/Antidot/Model/Export/Model/Product/Type/Grouped.php +69 -0
  12. app/code/community/MDN/Antidot/Model/Export/Product.php +128 -248
  13. app/code/community/MDN/Antidot/Model/Observer.php +31 -36
  14. app/code/community/MDN/Antidot/Model/Resource/Advanced.php +2 -1
  15. app/code/community/MDN/Antidot/Model/Resource/Catalog/Product/Collection.php +40 -3
  16. app/code/community/MDN/Antidot/Model/Resource/Engine/Abstract.php +3 -2
  17. app/code/community/MDN/Antidot/Model/Resource/Engine/Antidot.php +9 -0
  18. app/code/community/MDN/Antidot/Model/Resource/Export/Product.php +138 -0
  19. app/code/community/MDN/Antidot/Model/Resource/Export/Product/Collection.php +59 -0
  20. app/code/community/MDN/Antidot/Model/Resource/Export/Product/Link/Product/Collection.php +102 -0
  21. app/code/community/MDN/Antidot/Model/Resource/Export/Product/Type/Configurable/Product/Collection.php +64 -0
  22. app/code/community/MDN/Antidot/Model/Search/Search.php +2 -10
  23. app/code/community/MDN/Antidot/Model/System/Config/{Engine.php → Source/Acpengine.php} +14 -8
  24. app/code/community/MDN/Antidot/Model/System/Config/Source/Engine.php +64 -0
  25. app/code/community/MDN/Antidot/Model/Transport/Ftp.php +2 -1
  26. app/code/community/MDN/Antidot/Test/Model/Export/Abstract.php +26 -0
  27. app/code/community/MDN/Antidot/Test/Model/Export/Article.php +4 -2
  28. app/code/community/MDN/Antidot/Test/Model/Export/Category.php +8 -10
  29. app/code/community/MDN/Antidot/Test/Model/Export/Context.php +83 -0
  30. app/code/community/MDN/Antidot/Test/Model/Export/Context/fixtures/testContext.yaml +129 -0
  31. app/code/community/MDN/Antidot/Test/Model/Export/Product.php +121 -119
  32. app/code/community/MDN/Antidot/Test/Model/Export/Product/fixtures/testGetProductCategories.yaml +0 -101
  33. app/code/community/MDN/Antidot/Test/Model/Export/Product/fixtures/testWritePricesFixedtax.yaml +3 -1
  34. app/code/community/MDN/Antidot/Test/Model/Export/Product/fixtures/testWriteXml.yaml +3 -0
  35. app/code/community/MDN/Antidot/Test/Model/Observer.php +19 -30
  36. app/code/community/MDN/Antidot/Test/Model/Resource/Engine/Antidot.php +27 -0
  37. app/code/community/MDN/Antidot/Test/Model/System/Config/Source/Engine.php +43 -0
  38. app/code/community/MDN/Antidot/etc/config.xml +17 -2
  39. app/code/community/MDN/Antidot/etc/system.xml +20 -3
  40. app/design/frontend/base/default/layout/antidot.xml +2 -1
  41. app/design/frontend/base/default/template/antidot/catalogsearch/result.phtml +5 -1
  42. app/design/frontend/base/default/template/antidot/catalogsearch/result/banner.phtml +6 -0
  43. package.xml +4 -4
app/code/community/MDN/Antidot/Block/Catalogsearch/Banner.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Block_Catalogsearch_Banner extends Mage_Core_Block_Template
17
+ {
18
+ protected $_banners = null;
19
+
20
+ /**
21
+ * Return banners
22
+ * @return type
23
+ */
24
+ public function getBanners()
25
+ {
26
+ if ($this->_banners == null)
27
+ {
28
+ $this->loadBanners();
29
+ }
30
+ return $this->_banners;
31
+ }
32
+
33
+ /**
34
+ * Return banners
35
+ * @return boolean
36
+ */
37
+ public function hasBanner()
38
+ {
39
+ return count($this->getBanners())>0;
40
+ }
41
+
42
+ /**
43
+ * Load banners based on antidot results
44
+ */
45
+ protected function loadBanners()
46
+ {
47
+
48
+ $this->_banners = $this->getLayer()->getProductCollection()->getBanners();
49
+
50
+ }
51
+
52
+ /**
53
+ * Returns current catalog layer.
54
+ *
55
+ * @return MDN_Antidot_Model_Catalogsearch_Layer|Mage_Catalog_Model_Layer
56
+ */
57
+ public function getLayer()
58
+ {
59
+ $helper = Mage::helper('Antidot');
60
+ if ($helper->isActiveEngine()) {
61
+ return Mage::getSingleton('Antidot/catalogsearch_layer');
62
+ }
63
+
64
+ return parent::getLayer();
65
+ }
66
+
67
+ }
app/code/community/MDN/Antidot/Block/System/Config/Button/Forward.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Block_System_Config_Button_Forward
17
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
18
+ {
19
+
20
+ /**
21
+ * {@inherit}
22
+ */
23
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
24
+ {
25
+ $this->setElement($element);
26
+ $url = Mage::helper("adminhtml")->getUrl('adminhtml/system_config/edit/', array( "section" => "antidot"));
27
+
28
+ $html = $this->getLayout()->createBlock('adminhtml/widget_button')
29
+ ->setType('button')
30
+ ->setClass('scalable')
31
+ ->setLabel(Mage::helper('Antidot')->__('Configure AFS@Store'))
32
+ ->setOnClick("setLocation('$url')")
33
+ ->toHtml();
34
+
35
+ return $html.'<input type="hidden" id="catalog_search_antidot_config_forward" />';
36
+ //add input hidden with id , use by javascript show/hide function
37
+ }
38
+
39
+ }
app/code/community/MDN/Antidot/Helper/Data.php CHANGED
@@ -179,7 +179,7 @@ class MDN_Antidot_Helper_Data extends Mage_Core_Helper_Abstract
179
  */
180
  public function sendMail($subject, $message)
181
  {
182
- if(!$email = Mage::getStoreConfig('antidot/general/email')) {
183
  return;
184
  }
185
 
@@ -285,4 +285,19 @@ class MDN_Antidot_Helper_Data extends Mage_Core_Helper_Abstract
285
  return (int) $val;
286
  }
287
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  }
179
  */
180
  public function sendMail($subject, $message)
181
  {
182
+ if(!$email = Mage::getStoreConfig('antidot/general/email', Mage_Core_Model_App::ADMIN_STORE_ID)) {
183
  return;
184
  }
185
 
285
  return (int) $val;
286
  }
287
 
288
+ const EDITION_COMMUNITY = 'Community';
289
+ const EDITION_ENTERPRISE = 'Enterprise';
290
+
291
+ public function getMagentoEdition() {
292
+ if (method_exists('Mage','getEdition')) {
293
+ $mageEdition = Mage::getEdition();
294
+ } else {
295
+ if (Mage::helper('core')->isModuleEnabled('Enterprise_Enterprise')) {
296
+ $mageEdition = 'Enterprise';
297
+ } else {
298
+ $mageEdition = 'Community';
299
+ }
300
+ }
301
+ return $mageEdition;
302
+ }
303
  }
app/code/community/MDN/Antidot/Model/Export/Abstract.php CHANGED
@@ -22,15 +22,6 @@ class MDN_Antidot_Model_Export_Abstract extends Mage_Core_Model_Abstract
22
  */
23
  protected $xml;
24
 
25
- /**
26
- * List website loaded
27
- *
28
- * @var array
29
- */
30
- protected $website = array();
31
-
32
- protected $storeLang = array();
33
-
34
  /**
35
  * The fields to load
36
  *
@@ -52,21 +43,28 @@ class MDN_Antidot_Model_Export_Abstract extends Mage_Core_Model_Abstract
52
  {
53
  if($this->xml === null) {
54
  $this->xml = Mage::helper('Antidot/xmlWriter');
55
- $this->xml->init();
 
56
  }
57
  }
58
 
59
  /**
60
- * Extract the uri from an url
61
- *
 
 
62
  * @param string $url
 
63
  * @return string
64
  */
65
- protected function getUri($url)
66
  {
67
- $urls = parse_url($url);
 
 
 
68
  //replace all antidotExport*.php script by index.php in uri (in case of cron export) :
69
- return preg_replace('#\/(.*)\.php#', '/index.php', $urls['path']);
70
  }
71
 
72
  /**
@@ -112,52 +110,40 @@ class MDN_Antidot_Model_Export_Abstract extends Mage_Core_Model_Abstract
112
 
113
  return $entity->$method();
114
  }
115
-
116
- /**
117
- * Get website by store
118
- *
119
- * @param Store $store
120
- * @return WebSite
121
- */
122
- protected function getWebSiteByStore($store)
123
- {
124
- if(!isset($this->website[$store->getId()])) {
125
- $this->website[$store->getId()] = Mage::getModel('core/website')->load($store->getWebSiteId());
126
- }
127
-
128
- return $this->website[$store->getId()];
129
- }
130
-
131
- protected function getStoreLang($storeId)
132
- {
133
- if(!isset($this->storeLang[$storeId])) {
134
- list($this->storeLang[$storeId]) = explode('_', Mage::getStoreConfig('general/locale/code', $storeId));
135
- }
136
-
137
- return $this->storeLang[$storeId];
138
- }
139
 
140
  /**
141
  * Write the xml header
142
- *
143
  */
144
  protected function writeHeader($context)
145
  {
146
  $this->xml->push('header');
147
- $this->xml->element('owner', $context['owner']);
148
  $this->xml->element('feed', $this->getFeed($context));
149
  $this->xml->element('generated_at', date('c', Mage::getModel('core/date')->timestamp(time())));
150
  $this->xml->pop();
151
  }
152
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  /**
154
  * Get the value to insert in the feed tag
155
  * @param $type (product, category, article)
156
- * @param $context
157
  * @return string
158
  */
159
  public function getFeed($context) {
160
- return strtolower($this::TYPE) . ' ' . $context['run'] . ' v' . Mage::getConfig()->getNode()->modules->MDN_Antidot->version;
161
  }
162
 
163
  /**
22
  */
23
  protected $xml;
24
 
 
 
 
 
 
 
 
 
 
25
  /**
26
  * The fields to load
27
  *
43
  {
44
  if($this->xml === null) {
45
  $this->xml = Mage::helper('Antidot/xmlWriter');
46
+ $debug = Mage::getStoreConfig('antidot/export/debug_xml_enabled');
47
+ $this->xml->init($debug);
48
  }
49
  }
50
 
51
  /**
52
+ * Extract the exact uri from an url
53
+ * (When executed from cron script magento can generate url whith the script name instead of index.php)
54
+ * (MCNX-253)
55
+ *
56
  * @param string $url
57
+ * $param boolean $onlyPath
58
  * @return string
59
  */
60
+ protected function getExactUrl($url, $onlyPath = true)
61
  {
62
+ if ($onlyPath) {
63
+ $urls = parse_url($url);
64
+ $url = $urls['path'];
65
+ }
66
  //replace all antidotExport*.php script by index.php in uri (in case of cron export) :
67
+ return preg_replace('#\/antidotExport(.*)\.php#', '/index.php', $url);
68
  }
69
 
70
  /**
110
 
111
  return $entity->$method();
112
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
  /**
115
  * Write the xml header
116
+ * @param MDN_Antidot_Model_Export_Context $context
117
  */
118
  protected function writeHeader($context)
119
  {
120
  $this->xml->push('header');
121
+ $this->xml->element('owner', $this->getOwner());
122
  $this->xml->element('feed', $this->getFeed($context));
123
  $this->xml->element('generated_at', date('c', Mage::getModel('core/date')->timestamp(time())));
124
  $this->xml->pop();
125
  }
126
 
127
+ /**
128
+ * Get the value to insert in the owner tag
129
+ * @return string
130
+ */
131
+ public function getOwner() {
132
+ $owner = 'AFS@Store for Magento v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version;
133
+ if (Mage::getStoreConfig('antidot/general/owner', Mage_Core_Model_App::ADMIN_STORE_ID)) {
134
+ $owner = Mage::getStoreConfig('antidot/general/owner', Mage_Core_Model_App::ADMIN_STORE_ID);
135
+ }
136
+ return $owner;
137
+ }
138
+
139
  /**
140
  * Get the value to insert in the feed tag
141
  * @param $type (product, category, article)
142
+ * @param MDN_Antidot_Model_Export_Context $context
143
  * @return string
144
  */
145
  public function getFeed($context) {
146
+ return strtolower($this::TYPE) . ' ' . $context->getRunType() . ' v' . Mage::getConfig()->getNode()->modules->MDN_Antidot->version;
147
  }
148
 
149
  /**
app/code/community/MDN/Antidot/Model/Export/Article.php CHANGED
@@ -43,12 +43,12 @@ class MDN_Antidot_Model_Export_Article extends MDN_Antidot_Model_Export_Product
43
  $this->writeHeader($context);
44
  $this->writePart($this->xml->flush());
45
 
46
- foreach($context['store_id'] as $storeId) {
47
- $store = Mage::getModel('core/store')->load($storeId);
48
  $page = 1;
49
  while($articles = $this->getProducts($store, $page, self::ARTICLE_LIMIT)) {
50
  foreach($articles as $article) {
51
- $this->xml->push('article', array('id' => $article->getId(), 'xml:lang' => $context['lang']));
52
 
53
  $this->xml->push('websites');
54
  $this->xml->element('website', $store->getWebsite()->getName(), array('id' => $store->getWebsite()->getId()));
43
  $this->writeHeader($context);
44
  $this->writePart($this->xml->flush());
45
 
46
+ foreach($context->getWebsiteAndStores() as $ws) {
47
+ $store = $ws['store'];
48
  $page = 1;
49
  while($articles = $this->getProducts($store, $page, self::ARTICLE_LIMIT)) {
50
  foreach($articles as $article) {
51
+ $this->xml->push('article', array('id' => $article->getId(), 'xml:lang' => $context->getLang()));
52
 
53
  $this->xml->push('websites');
54
  $this->xml->element('website', $store->getWebsite()->getName(), array('id' => $store->getWebsite()->getId()));
app/code/community/MDN/Antidot/Model/Export/Category.php CHANGED
@@ -23,16 +23,17 @@ class MDN_Antidot_Model_Export_Category extends MDN_Antidot_Model_Export_Abstrac
23
  /**
24
  * Get xml
25
  *
26
- * @param type $context
27
  */
28
  public function writeXml($context, $filename)
29
  {
30
  $nbTotalCategories = 0;
31
- $context['categories'] = array();
32
- foreach($context['stores'] as $store) {
33
- $categories = $this->getCategories($store);
34
- $nbTotalCategories += $categories->getSize();
35
- $context['categories'][$store->getId()] = $categories;
 
36
  }
37
 
38
  if ($nbTotalCategories == 0) {
@@ -47,13 +48,14 @@ class MDN_Antidot_Model_Export_Category extends MDN_Antidot_Model_Export_Abstrac
47
  $this->writeHeader($context);
48
 
49
  $nbItems = 0;
50
- foreach($context['stores'] as $store) {
51
- foreach($context['categories'][$store->getId()] as $cat) {
 
52
 
53
  if (!$this->getField($cat, 'name'))
54
  continue;
55
 
56
- $this->xml->push('category', array('id' => $cat->getId(), 'xml:lang' => $context['lang']));
57
 
58
  $this->xml->element('name', $this->xml->encloseCData($this->getField($cat, 'name')));
59
 
@@ -64,7 +66,7 @@ class MDN_Antidot_Model_Export_Category extends MDN_Antidot_Model_Export_Abstrac
64
  } else {
65
  $cat->getUrlInstance()->setStore($store->getId());
66
  }
67
- $this->xml->element('url', $this->getUri($cat->getUrl()));
68
 
69
  if ($cat->getImageUrl()) {
70
  $this->xml->element('image', $cat->getImageUrl());
@@ -86,10 +88,10 @@ class MDN_Antidot_Model_Export_Category extends MDN_Antidot_Model_Export_Abstrac
86
  $this->xml->emptyelement('broader', array('idref' => $cat->getParentId()));
87
  }
88
 
89
- $storeIds = array_intersect($context['store_id'], $cat->getStoreIds());
90
  $this->xml->push('websites');
91
  foreach($storeIds as $storeId) {
92
- $website = $this->getWebSiteByStore($context['stores'][$storeId]);
93
  $this->xml->element('website', '', array('id' => $website->getId(), 'name' => $website->getName()));
94
  }
95
  $this->xml->pop();
23
  /**
24
  * Get xml
25
  *
26
+ * @param MDN_Antidot_Model_Export_Context $context
27
  */
28
  public function writeXml($context, $filename)
29
  {
30
  $nbTotalCategories = 0;
31
+ $categories = array();
32
+ foreach($context->getWebsiteAndStores() as $ws) {
33
+ $store = $ws['store'];
34
+ $categoriesColl = $this->getCategories($store);
35
+ $nbTotalCategories += $categoriesColl->getSize();
36
+ $categories[$store->getId()] = $categoriesColl;
37
  }
38
 
39
  if ($nbTotalCategories == 0) {
48
  $this->writeHeader($context);
49
 
50
  $nbItems = 0;
51
+ foreach($context->getWebsiteAndStores() as $ws) {
52
+ $store = $ws['store'];
53
+ foreach($categories[$store->getId()] as $cat) {
54
 
55
  if (!$this->getField($cat, 'name'))
56
  continue;
57
 
58
+ $this->xml->push('category', array('id' => $cat->getId(), 'xml:lang' => $context->getLang()));
59
 
60
  $this->xml->element('name', $this->xml->encloseCData($this->getField($cat, 'name')));
61
 
66
  } else {
67
  $cat->getUrlInstance()->setStore($store->getId());
68
  }
69
+ $this->xml->element('url', $this->getExactUrl($cat->getUrl()));
70
 
71
  if ($cat->getImageUrl()) {
72
  $this->xml->element('image', $cat->getImageUrl());
88
  $this->xml->emptyelement('broader', array('idref' => $cat->getParentId()));
89
  }
90
 
91
+ $storeIds = array_intersect($context->getStoreIds(), $cat->getStoreIds());
92
  $this->xml->push('websites');
93
  foreach($storeIds as $storeId) {
94
+ $website = $context->getWebSiteByStore($storeId);
95
  $this->xml->element('website', '', array('id' => $website->getId(), 'name' => $website->getName()));
96
  }
97
  $this->xml->pop();
app/code/community/MDN/Antidot/Model/Export/Context.php ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Model_Export_Context extends Mage_Core_Model_Abstract
17
+ {
18
+ /**
19
+ * @var string $runType
20
+ */
21
+ protected $runType;
22
+ /**
23
+ * @var string $lang
24
+ */
25
+ protected $lang;
26
+ /**
27
+ * Array of the websites, key=websiteId
28
+ *
29
+ * @var array
30
+ */
31
+ protected $websites = array();
32
+ /**
33
+ * MultiDimentional Array of the stores, key=websiteId, storeId
34
+ * @var array
35
+ */
36
+ protected $stores = array();
37
+ /**
38
+ * Array of store ids
39
+ * @var array
40
+ */
41
+ protected $storeIds = array();
42
+ /**
43
+ * Array of categoryTrees
44
+ *
45
+ * @var array
46
+ */
47
+ protected $categoryTrees = array();
48
+ /**
49
+ * Array of rootCategoryIds
50
+ *
51
+ * @var array
52
+ */
53
+ protected $rootCategoryIds = array();
54
+
55
+ /**
56
+ * Array of attributes to load in products
57
+ *
58
+ * @var array $attributesToLoad
59
+ */
60
+ protected $attributesToLoad = array();
61
+
62
+ /**
63
+ * @param $runType
64
+ * @param $lang
65
+ */
66
+ function __construct($args) {
67
+ $this->lang = $args[0];
68
+ $this->runType = $args[1];
69
+ }
70
+
71
+ function getLang() {
72
+ return $this->lang;
73
+ }
74
+
75
+ function getRunType() {
76
+ return $this->runType;
77
+ }
78
+
79
+ /**
80
+ * Add a store to the current Export context
81
+ *
82
+ * @param $store Mage_Core_Model_Store
83
+ */
84
+ function addStore($store) {
85
+ if ($store->getIsActive()) {
86
+ $website = $store->getWebsite();
87
+ if (!isset($this->websites[$website->getId()])) {
88
+ $this->websites[$website->getId()] = $website;
89
+ }
90
+ if (!isset($this->stores[$website->getId()][$store->getId()])) {
91
+ //construct lists of stores grouped by websiteid
92
+ $this->stores[$website->getId()][$store->getId()] = $store;
93
+ //construct list of all storeids
94
+ $this->storeIds[] = $store->getId();
95
+ //construct list of rootcategoryIds
96
+ if (!isset($this->rootCategoryIds[$store->getRootCategoryId()])) {
97
+ $this->rootCategoryIds[$store->getRootCategoryId()] = array();
98
+ }
99
+ $this->rootCategoryIds[$store->getRootCategoryId()][] = $store;
100
+ }
101
+ }
102
+
103
+ }
104
+
105
+ /**
106
+ * Load and init the category tree corresponding to the stores
107
+ * of the current export context
108
+ */
109
+ function initCategoryTree() {
110
+
111
+ Varien_Profiler::start("export_product_initCategoryTree");
112
+
113
+ foreach ($this->rootCategoryIds as $rootId => $stores) {
114
+ /**
115
+ * define the store tu used to load the category tree :
116
+ * use default store first
117
+ */
118
+ $defaultStoreId = null;
119
+ //first take the default store of the default website
120
+ foreach ($stores as $store) {
121
+ $website = $store->getWebsite();
122
+ if ($website->getIsDefault() && $website->getDefautStore() && $website->getDefautStore()->getId() == $store->getId()) {
123
+ $defaultStoreId = $store->getId();
124
+ }
125
+ }
126
+ //if not found take the first store of the default website
127
+ if ($defaultStoreId == null) {
128
+ foreach ($stores as $store) {
129
+ $website = $store->getWebsite();
130
+ if ($website->getIsDefault() && $defaultStoreId == null) {
131
+ $defaultStoreId = $store->getId();
132
+ }
133
+ }
134
+ }
135
+ //if not found take the first store of the first website
136
+ if ($defaultStoreId == null) {
137
+ $store = current($stores);
138
+ $defaultStoreId = $store->getId();
139
+ }
140
+
141
+ //LOAD TREE with $rootId and $defaultStoreId
142
+ $tree = Mage::getResourceModel('catalog/category_tree')
143
+ ->load($rootId);
144
+
145
+ $collection = Mage::getModel('catalog/category')->getCollection();
146
+ /** @var $collection Mage_Catalog_Model_Resource_Category_Collection */
147
+
148
+ //Set Store Id
149
+ $collection->setStoreId($defaultStoreId);
150
+
151
+ //add attributes to display
152
+ $collection->addAttributeToSelect(array('name', 'image'));
153
+
154
+ //exclude categories not actives and without name
155
+ $collection->addAttributeToFilter('name', array('neq' => '')); //Exclude empty name categories
156
+ $collection->addAttributeToFilter('is_active', 1);
157
+
158
+ //filter on the tree categories
159
+ $nodeIds = array();
160
+ foreach ($tree->getNodes() as $node) {
161
+ $nodeIds[] = $node->getId();
162
+ }
163
+ $collection->addIdFilter($nodeIds);
164
+
165
+ //join url-rewrite table
166
+ if (class_exists ('Mage_Catalog_Model_Factory', false)) {
167
+ Mage::getSingleton('catalog/factory')->getCategoryUrlRewriteHelper()
168
+ ->joinTableToEavCollection($collection, $defaultStoreId);
169
+ } else {
170
+ /**
171
+ * Join url rewrite table to eav collection
172
+ *
173
+ * @param Mage_Eav_Model_Entity_Collection_Abstract $collection
174
+ * @param int $storeId
175
+ * @return Mage_Catalog_Helper_Category_Url_Rewrite
176
+ */
177
+
178
+ $collection->joinTable(
179
+ 'core/url_rewrite',
180
+ 'category_id=entity_id',
181
+ array('request_path'),
182
+ "{{table}}.is_system=1 AND " .
183
+ "{{table}}.store_id='{$defaultStoreId}' AND " .
184
+ "{{table}}.id_path LIKE 'category/%'",
185
+ 'left'
186
+ );
187
+
188
+ }
189
+
190
+ //Add collection data to the tre nodes see Mage_Catalog_Model_Resource_Category_Tree#addCollectionData
191
+ foreach ($collection as $category) {
192
+ if ($node = $tree->getNodeById($category->getId())) {
193
+
194
+ /* Calculate the url to export */
195
+ if (method_exists($category, 'getUrlModel')) { //compatibility with older magento version where category#getUrlModel doesn't exist
196
+ $category->getUrlModel()->getUrlInstance()->setStore($defaultStoreId);
197
+ } else {
198
+ $category->getUrlInstance()->setStore($defaultStoreId);
199
+ }
200
+ $category->setData('url', $category->getUrl());
201
+
202
+ $node->addData($category->getData());
203
+ }
204
+ }
205
+
206
+ foreach ($tree->getNodes() as $node) {
207
+ //if the node is not in the collection (not active), remove it and all his descendant from the tree (except if it's the root node)
208
+ if ($collection->getItemById($node->getId()) == null && $node->getLevel() > 1) {
209
+ $this->removeBranch($tree, $node);
210
+ }
211
+ }
212
+
213
+ //Mage::log("LOAD TREE ".$rootId. " ". $defaultStoreId . ' '. spl_object_hash($tree), null, 'antidot.log');
214
+ //Mage::log($collection->getSelect()->__toString() , null, 'antidot.log');
215
+ //$i=0;
216
+ //foreach ($tree->getNodes() as $node) {
217
+ // $i++;
218
+ //}
219
+ //Mage::log('Tree nodes '.$i , null, 'antidot.log');
220
+
221
+ $this->categoryTrees[] = $tree;
222
+
223
+ }
224
+
225
+ Varien_Profiler::stop("export_product_initCategoryTree");
226
+
227
+ }
228
+
229
+ /**
230
+ * recursive call of removeNode on tree
231
+ */
232
+ private function removeBranch($tree, $node) {
233
+ foreach ($node->getChildren() as $child) {
234
+ $this->removeBranch($tree, $child);
235
+ }
236
+ $tree->removeNode($node);
237
+ }
238
+
239
+
240
+ /**
241
+ * Get the category trees
242
+ *
243
+ * @return array
244
+ */
245
+ function getCategoryTrees() {
246
+ return $this->categoryTrees;
247
+ }
248
+
249
+ /* non utilisé pour l'instant
250
+ function getWebsites() {
251
+ $this->websites;
252
+ }*/
253
+
254
+ /**
255
+ * Get the list of the pair website/store of the current context
256
+ *
257
+ * @return array
258
+ */
259
+ function getWebsiteAndStores() {
260
+ $list = array();
261
+ foreach($this->stores as $websiteId => $stores) {
262
+ $website = $this->websites[$websiteId];
263
+ foreach ($stores as $store) {
264
+ $list[] = array('website' => $website, 'store' => $store);
265
+ }
266
+ }
267
+ return $list;
268
+ }
269
+
270
+ /**
271
+ * Get the website corresponding to the storeId
272
+ *
273
+ * @return Mage_Core_Model_Website
274
+ */
275
+ function getWebSiteByStore($storeId) {
276
+ foreach($this->stores as $websiteId => $stores) {
277
+ foreach($stores as $store) {
278
+ if ($store->getId() == $storeId) {
279
+ return $this->websites[$websiteId];
280
+ }
281
+ }
282
+ }
283
+ return null;
284
+ }
285
+
286
+ /**
287
+ * Get the list of website ids of the current context
288
+ *
289
+ * @return array
290
+ */
291
+ function getWebsiteIds() {
292
+ return array_keys($this->websites);
293
+ }
294
+
295
+ /**
296
+ * Get the list of store ids of the current context
297
+ *
298
+ * @return array
299
+ */
300
+ function getStoreIds() {
301
+ return $this->storeIds;
302
+ }
303
+
304
+ /**
305
+ *
306
+ */
307
+ function addAttributeToLoad($fields) {
308
+
309
+ //Theses attributes are configured in BO System > config > AfsStore :
310
+ $this->attributesToLoad = array();
311
+ foreach ($fields as $afsCode => $attributeCode) {
312
+ if ($afsCode == 'in_stock_only') {
313
+ continue; //not an attribute
314
+ }
315
+
316
+ if (is_array($attributeCode)) { //description, identifier, properties
317
+ foreach ($attributeCode as $code) {
318
+ if ($afsCode == 'properties') {
319
+ $this->attributesToLoad[] = array('code' => $code['value'], 'on_store' => false);
320
+ } else {
321
+ $this->attributesToLoad[] = array('code' => $code, 'on_store' => false);
322
+ }
323
+ }
324
+ } else {
325
+
326
+ if ($attributeCode) {
327
+ //Theses attributes must be reloaded on each stores
328
+ if (in_array($afsCode, array('is_new', 'is_best_sale', 'is_featured'))) {
329
+ $this->attributesToLoad[] = array('code' => $attributeCode, 'on_store' => true);
330
+ } else {
331
+ $this->attributesToLoad[] = array('code' => $attributeCode, 'on_store' => false);
332
+ }
333
+ }
334
+ }
335
+ }
336
+
337
+ //Theses attributes must be reloaded on each stores
338
+ $this->attributesToLoad[] = array('code' => 'image', 'on_store' => true);
339
+ $this->attributesToLoad[] = array('code' => 'thumbnail', 'on_store' => true);
340
+
341
+ }
342
+
343
+ function getAttributesToLoad($forStore = false) {
344
+
345
+ $attributes = array();
346
+ foreach ($this->attributesToLoad as $attribute) {
347
+ if ($attribute['on_store'] || !$forStore) {
348
+ if ($attribute['code'] != 'sku') { //sku already loaded on catalog_product_entity
349
+ $attributes[] = $attribute['code'];
350
+ }
351
+ }
352
+ }
353
+ return $attributes;
354
+
355
+ }
356
+
357
+ }
app/code/community/MDN/Antidot/Model/Export/Model/Product.php ADDED
@@ -0,0 +1,412 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Model_Export_Model_Product extends Mage_Catalog_Model_Product
17
+ {
18
+
19
+ /**
20
+ * The export context
21
+ * @var MDN_Antidot_Model_Export_Context $context
22
+ */
23
+ protected $context;
24
+
25
+ /**
26
+ * The stores of the current export product
27
+ * @var array $storeIds
28
+ */
29
+ protected $stores;
30
+
31
+ /**
32
+ * The websites of the current export product
33
+ * @var array $websites
34
+ */
35
+ protected $websites;
36
+
37
+ /**
38
+ * The id of the store to use for loading data attributes
39
+ * @var integer $currentStoreId
40
+ */
41
+ protected $currentStoreId;
42
+
43
+ /**
44
+ * The category tree
45
+ * @var Varien_Data_tree $categoryTree
46
+ */
47
+ protected $categoryTree;
48
+
49
+ /**
50
+ * Constructor
51
+ *
52
+ *
53
+ * @param $args
54
+ */
55
+ public function __construct($args = array()) {
56
+
57
+ if (count($args)>0) {
58
+ $this->context = $args[0];
59
+ }
60
+ $this->stores= array();
61
+ $this->websites= array();
62
+ $this->currentStoreId=null;
63
+ $this->categoryTree=null;
64
+
65
+ //initialise model with MDN_Antidot_Model_Resource_Export_Product resource
66
+ $this->_init('Antidot/export_product');
67
+
68
+ }
69
+
70
+ public function setContext($context, $forVariant = false) {
71
+ $this->context = $context;
72
+ return $this->initWebsitesStores($forVariant);
73
+ }
74
+
75
+ /**
76
+ *
77
+ * Define the stores of the current export where the product
78
+ * is visible and searcheable
79
+ *
80
+ */
81
+ public function initWebsitesStores($forVariant = false)
82
+ {
83
+ foreach ($this->context->getWebsiteAndStores() as $wstore) {
84
+
85
+ $website = $wstore['website'];
86
+ $store = $wstore['store'];
87
+
88
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); //USE EAV table
89
+ $collection = Mage::getModel('catalog/product')->getCollection();
90
+ $collection->addWebsiteFilter($website->getId());
91
+ $collection->setStoreId($store->getId());
92
+ if (!$forVariant) {
93
+ $collection->addAttributeToFilter(
94
+ 'visibility',
95
+ array(
96
+ Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_SEARCH,
97
+ Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
98
+ )
99
+ );
100
+ }
101
+ $collection->addAttributeToFilter('status', 1);
102
+ $collection->addAttributeToFilter('entity_id', $this->getId());
103
+
104
+ //Mage::log($collection->getSelect()->__toString(), null, 'antidot.log');
105
+
106
+ if ($collection->getSize()>0) {
107
+ $this->stores[$store->getId()] = $store;
108
+ if (!isset($this->websites[$website->getId()])) {
109
+ $this->websites[$website->getId()] = $website;
110
+ }
111
+ //define the default store for this context :
112
+ //take the magento default store if it is this export context
113
+ if ($website->getIsDefault()) {
114
+ if ($website->getDefaultStore() &&
115
+ $website->getDefaultStore()->getId() == $store->getId()) {
116
+ $this->currentStoreId = $store->getId();
117
+ }
118
+ }
119
+ }
120
+
121
+ }
122
+
123
+ //if the magento default store is not in this context
124
+ //take the default store of the first website
125
+ if ($this->currentStoreId == null) {
126
+ $website = current($this->websites);
127
+ if ($website && $website->getDefaultStore()
128
+ && in_array($website->getDefaultStore()->getId(), array_keys($this->stores))) {
129
+ $this->currentStoreId = $website->getDefaultStore()->getId();
130
+ }
131
+ }
132
+
133
+ //if default store is still not defined
134
+ if ($this->currentStoreId == null) {
135
+ if ($store = current($this->stores)) {
136
+ $this->currentStoreId = $store->getId();
137
+ }
138
+ }
139
+
140
+ //if the product is not active on any store of the context, don't export it
141
+ if ($this->currentStoreId == null) {
142
+ return false;
143
+ }
144
+
145
+ return true;
146
+
147
+ }
148
+
149
+
150
+ /**
151
+ * The current export context
152
+ * @return MDN_Antidot_Model_Export_Context
153
+ */
154
+ public function getContext() {
155
+ return $this->context;
156
+ }
157
+
158
+ /**
159
+ * The stores of the current export
160
+ * @return array
161
+ */
162
+ public function getStores() {
163
+ return $this->stores;
164
+ }
165
+
166
+ /**
167
+ * get the websites of the current export
168
+ * @return array
169
+ */
170
+ function getWebsites() {
171
+ return $this->websites;
172
+ }
173
+
174
+ /**
175
+ * Get the category tree
176
+ */
177
+ function getCategoryTree() {
178
+
179
+ if (!$this->categoryTree) {
180
+
181
+ /**
182
+ * Create the Tree with the root node
183
+ */
184
+ $this->categoryTree = new Varien_Data_Tree();
185
+ $rootNode = new Varien_Data_Tree_Node(
186
+ array(
187
+ 'entity_id' => 1,
188
+ 'parent_id' => 0,
189
+ 'path' => 1,
190
+ 'position' => 0,
191
+ 'level' => 0,
192
+ 'path_id' => 1,
193
+ 'name' => 'Root',
194
+ 'is_active' => 1),
195
+ 'entity_id', $this->categoryTree, null);
196
+ $rootNode->setLevel(0);
197
+ $rootNode->setPathId(1);
198
+ $this->categoryTree->addNode($rootNode, null);
199
+
200
+ /**
201
+ * Get the category ids linked to the product
202
+ */
203
+ $categoryIds = $this->getCategoryIds();
204
+
205
+ /**
206
+ * Run through the context category trees and extract the nodes corresponding
207
+ * to the product categories and construct his category tree
208
+ */
209
+ $trees = $this->context->getCategoryTrees();
210
+ foreach ($trees as $tree) {
211
+ foreach ($categoryIds as $categoryId) {
212
+ /** @var Varien_Data_Tree_Node $node */
213
+ if ($node = $tree->getNodeById($categoryId)) {
214
+
215
+ //Add this category to the product category tree:
216
+ $path = array();
217
+ while ($node != null) {
218
+ $path[] = $node;
219
+ $node = $node->getParent();
220
+ }
221
+
222
+ $parentNode = $rootNode;
223
+ foreach (array_reverse($path) as $node) {
224
+ if ($node->getLevel() > $parentNode->getLevel()) {
225
+ $productTreeNode = $this->categoryTree->getNodeById($node->getId());
226
+ if ($productTreeNode == null) {
227
+ $parentNode = $this->categoryTree->appendChild($node->getData(), $parentNode);
228
+ } else {
229
+ $parentNode = $productTreeNode;
230
+ }
231
+ }
232
+ }
233
+
234
+ }
235
+ }
236
+ }
237
+
238
+ }
239
+
240
+ return $this->categoryTree;
241
+ }
242
+
243
+ /**
244
+ *
245
+ */
246
+ public function loadNeededAttributes($forStore = false) {
247
+
248
+ $attributeIds = array();
249
+ foreach ($this->context->getAttributesToLoad($forStore) as $attrCode) {
250
+ if ($attribute = $this->getResource()->getAttribute($attrCode)) {
251
+ $attributeIds[] = $attribute->getId();
252
+ }
253
+ }
254
+ $this->getResource()->loadModelAttributes($this, $attributeIds);
255
+
256
+ }
257
+
258
+ protected function _beforeLoad($id, $field = null)
259
+ {
260
+ //don't dispatch before load events
261
+ return $this;
262
+ }
263
+
264
+ /**
265
+ * Load object data
266
+ *
267
+ * @param integer $id
268
+ * @return Mage_Core_Model_Abstract
269
+ */
270
+ public function load($id, $field=null)
271
+ {
272
+ $this->_beforeLoad($id, $field);
273
+ $this->_getResource()->load($this, $id, $this->context->getAttributesToLoad(false));
274
+ $this->_afterLoad();
275
+ //don't set origin data (reduce memory consumtion)
276
+ //$this->setOrigData();
277
+ $this->_hasDataChanges = false;
278
+ return $this;
279
+ }
280
+
281
+ protected function _afterLoad()
282
+ {
283
+ //Don't dispatch after load events
284
+ return $this;
285
+ }
286
+
287
+ public function afterLoad()
288
+ {
289
+ // don't call after load
290
+ //$this->getResource()->afterLoad($this);
291
+ $this->_afterLoad();
292
+ return $this;
293
+ }
294
+
295
+ /**
296
+ * Retrieve link instance
297
+ *
298
+ * @return Mage_Catalog_Model_Product_Link
299
+ */
300
+ public function getLinkInstance()
301
+ {
302
+ if (!$this->_linkInstance) {
303
+ $this->_linkInstance = Mage::getSingleton('Antidot/export_model_product_link');
304
+ }
305
+ return $this->_linkInstance;
306
+ }
307
+
308
+ /**
309
+ * Retrieve type instance
310
+ *
311
+ * Type instance implement type depended logic
312
+ *
313
+ * @param bool $singleton
314
+ * @return Mage_Catalog_Model_Product_Type_Abstract
315
+ */
316
+ public function getTypeInstance($singleton = false)
317
+ {
318
+ //configure the type model in config.xml to let developper implement their own product types
319
+ if ($model = (string) Mage::getConfig()->getNode('default/antidot/export/product_type_'.$this->getTypeID())) {
320
+ return Mage::getSingleton($model);
321
+ }
322
+ return parent::getTypeInstance($singleton = false);
323
+ }
324
+
325
+ /**
326
+ * Return qty
327
+ *
328
+ * qty is loaded by product collection join with inventory table
329
+ *
330
+ * @return int
331
+ */
332
+ public function getQty() {
333
+ if (!$this->hasData('qty')) {
334
+ if ($this->hasData('stock_item')) {
335
+ $this->setData('stock_item', Mage::getModel('cataloginventory/stock_item')->loadByProduct($this));
336
+ }
337
+ $this->setData('qty', $this->getStockItem()->getQty());
338
+ }
339
+ return $this->getData('qty');
340
+ }
341
+
342
+ /**
343
+ * Return is_in_stock status
344
+ *
345
+ * is_in_stock is loaded by product collection join with inventory table
346
+ *
347
+ * @return int
348
+ */
349
+ public function getIsInStock() {
350
+ if (!$this->hasData('is_in_stock')) {
351
+ if ($this->hasData('stock_item')) {
352
+ $this->setData('stock_item', Mage::getModel('cataloginventory/stock_item')->loadByProduct($this));
353
+ }
354
+ $this->setData('is_in_stock', $this->getStockItem()->getIsInStock());
355
+ }
356
+ return $this->getData('is_in_stock');
357
+ }
358
+
359
+ /**
360
+ * Retrieve Product URL
361
+ *
362
+ * @param bool $useSid
363
+ * @return string
364
+ */
365
+ public function getProductUrl($useSid = null)
366
+ {
367
+ Mage::app()->setCurrentStore($this->getStoreId()); //to avoid ?___store param
368
+ if (method_exists($this, 'getUrlModel')) { //compatibility with older magento version where category#getUrlModel doesn't exist
369
+ $this->getUrlModel()->getUrlInstance()->setStore($this->getStoreId());
370
+ } else {
371
+ $this->getUrlInstance()->setStore($this->getStoreId());
372
+ }
373
+ $url = parent::getProductUrl(false);
374
+ $this->unsetData('url'); //unset data in order to force re-generation of product url on next store
375
+ return $url;
376
+ }
377
+
378
+ /**
379
+ * release memory
380
+ */
381
+ public function clearInstanceFull() {
382
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
383
+ $this->clearInstance();
384
+ $this->stores= array();
385
+ $this->websites= array();
386
+ $this->currentStoreId=null;
387
+ $this->categoryTree=null;
388
+ }
389
+
390
+ /**
391
+ * Retrieve Store Id
392
+ *
393
+ * @return int
394
+ */
395
+ public function getStoreId()
396
+ {
397
+ return $this->currentStoreId;
398
+ }
399
+
400
+ /**
401
+ * set Store Id
402
+ *
403
+ * @param int
404
+ */
405
+ public function setStoreId($storeId)
406
+ {
407
+ parent::setStoreId($storeId);
408
+ $this->currentStoreId = $storeId;
409
+ return $this;
410
+ }
411
+
412
+ }
app/code/community/MDN/Antidot/Model/Export/Model/Product/Link.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Model_Export_Model_Product_Link extends Mage_Catalog_Model_Product_Link
17
+ {
18
+
19
+ /**
20
+ * Retrieve linked product collection
21
+ *
22
+ * add join invenory table to load qty and is_in_stock
23
+ *
24
+ */
25
+ public function getProductCollection()
26
+ {
27
+ $onlyProductsWithStock = !(boolean)Mage::getStoreConfig('antidot/fields_product/in_stock_only');
28
+ $productsInStock = $onlyProductsWithStock ? ' AND is_in_stock = 1' : '';
29
+
30
+ $collection = Mage::getResourceModel('Antidot/export_product_link_product_collection')
31
+ ->joinTable('cataloginventory/stock_item',
32
+ 'product_id=entity_id', // warning : no spaces between = and entity_id , magento1.5 isn't robust enought
33
+ array('qty', 'is_in_stock'),
34
+ '{{table}}.stock_id = 1'.$productsInStock)
35
+ ->setLinkModel($this);
36
+
37
+ return $collection;
38
+ }
39
+
40
+ }
app/code/community/MDN/Antidot/Model/Export/Model/Product/Type/Configurable.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Model_Export_Model_Product_Type_Configurable extends Mage_Catalog_Model_Product_Type_Configurable
17
+ {
18
+
19
+
20
+ /**
21
+ * Retrieve array of "subproducts"
22
+ *
23
+ * @param array
24
+ * @param Mage_Catalog_Model_Product $product
25
+ * @return array
26
+ */
27
+ public function getUsedProducts($requiredAttributeIds = null, $product = null)
28
+ {
29
+
30
+ Varien_Profiler::start('EXPORT_PRODUCT_CONFIGURABLE:'.__METHOD__);
31
+ if (!$this->getProduct($product)->hasData($this->_usedProducts)) {
32
+ if (is_null($requiredAttributeIds)
33
+ and is_null($this->getProduct($product)->getData($this->_configurableAttributes))) {
34
+ // If used products load before attributes, we will load attributes.
35
+ $this->getConfigurableAttributes($product);
36
+ // After attributes loading products loaded too.
37
+ Varien_Profiler::stop('EXPORT_PRODUCT_CONFIGURABLE:'.__METHOD__);
38
+ return $this->getProduct($product)->getData($this->_usedProducts);
39
+ }
40
+
41
+ $usedProducts = array();
42
+ $collection = $this->getUsedProductCollection($product)
43
+ //->addAttributeToSelect('*')
44
+ ->addFilterByRequiredOptions();
45
+
46
+ if (is_array($requiredAttributeIds)) {
47
+ foreach ($requiredAttributeIds as $attributeId) {
48
+ $attribute = $this->getAttributeById($attributeId, $product);
49
+ if (!is_null($attribute))
50
+ $collection->addAttributeToFilter($attribute->getAttributeCode(), array('notnull'=>1));
51
+ }
52
+ }
53
+
54
+ foreach ($collection as $item) {
55
+ $usedProducts[] = $item;
56
+ }
57
+
58
+ $this->getProduct($product)->setData($this->_usedProducts, $usedProducts);
59
+ }
60
+ Varien_Profiler::stop('EXPORT_PRODUCT_CONFIGURABLE:'.__METHOD__);
61
+ return $this->getProduct($product)->getData($this->_usedProducts);
62
+ }
63
+
64
+ /**
65
+ * Retrieve related products collection
66
+ *
67
+ * @param Mage_Catalog_Model_Product $product
68
+ * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Product_Collection
69
+ */
70
+ public function getUsedProductCollection($product = null)
71
+ {
72
+
73
+ /**
74
+ * list the products which are available in stock (according to configuration)
75
+ */
76
+ $onlyProductsWithStock = !(boolean)Mage::getStoreConfig('antidot/fields_product/in_stock_only');
77
+ $productsInStock = $onlyProductsWithStock ? ' AND is_in_stock = 1' : '';
78
+
79
+ $collection = Mage::getResourceModel('Antidot/export_product_type_configurable_product_collection')
80
+ ->joinTable('cataloginventory/stock_item',
81
+ 'product_id=entity_id', // warning : no spaces between = and entity_id , magento1.5 isn't robust enought
82
+ array('qty', 'is_in_stock'),
83
+ '{{table}}.stock_id = 1'.$productsInStock)
84
+ ->setProductFilter($this->getProduct($product));
85
+ if (!is_null($this->getStoreFilter($product))) {
86
+ $collection->addStoreFilter($this->getStoreFilter($product));
87
+ }
88
+
89
+ return $collection;
90
+ }
91
+
92
+ }
app/code/community/MDN/Antidot/Model/Export/Model/Product/Type/Grouped.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Model_Export_Model_Product_Type_Grouped extends Mage_Catalog_Model_Product_Type_Grouped
17
+ {
18
+
19
+
20
+ /**
21
+ * Retrieve array of associated products
22
+ *
23
+ * @param Mage_Catalog_Model_Product $product
24
+ * @return array
25
+ */
26
+ public function getAssociatedProducts($product = null)
27
+ {
28
+ if (!$this->getProduct($product)->hasData($this->_keyAssociatedProducts)) {
29
+ $associatedProducts = array();
30
+
31
+ $this->setSaleableStatus($product);
32
+
33
+ $collection = $this->getAssociatedProductCollection($product)
34
+ /*->addAttributeToSelect('*') don't load every attribute in collection */
35
+ ->addFilterByRequiredOptions()
36
+ ->setPositionOrder()
37
+ ->addStoreFilter($this->getStoreFilter($product))
38
+ ->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
39
+
40
+ //FILTER only enabled product */
41
+ foreach ($collection as $item) {
42
+ $associatedProducts[] = $item;
43
+ }
44
+
45
+ $this->getProduct($product)->setData($this->_keyAssociatedProducts, $associatedProducts);
46
+ }
47
+ return $this->getProduct($product)->getData($this->_keyAssociatedProducts);
48
+ }
49
+
50
+
51
+ /**
52
+ * Retrieve collection of associated products
53
+ *
54
+ * @param Mage_Catalog_Model_Product $product
55
+ * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection
56
+ */
57
+ public function getAssociatedProductCollection($product = null)
58
+ {
59
+ $collection = $this->getProduct($product)->getLinkInstance()->useGroupedLinks()
60
+ ->getProductCollection()
61
+ //->setFlag('require_stock_items', true)
62
+ //->setFlag('product_children', true)
63
+ ->setIsStrongMode();
64
+ $collection->setProduct($this->getProduct($product));
65
+ return $collection;
66
+ }
67
+
68
+
69
+ }
app/code/community/MDN/Antidot/Model/Export/Product.php CHANGED
@@ -23,19 +23,18 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
23
  const XSD = 'http://ref.antidot.net/store/latest/catalog.xsd';
24
 
25
  /*
26
- * Maximum length for the facet values accepted by AFSStore
27
- * (actually 120)
28
  */
29
  const FACET_MAX_LENGTH = 119;
 
 
 
 
30
 
31
  protected $file;
32
 
33
  protected $productGenerated = array();
34
 
35
- protected $categories = array();
36
-
37
- protected $enabledStores = null;
38
-
39
  protected $onlyProductsWithStock;
40
 
41
  protected $autoCompleteProducts;
@@ -58,7 +57,7 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
58
  /**
59
  * Write the xml file
60
  *
61
- * @param array $context
62
  * @param string $filename
63
  * @param string $type Incremantal or full
64
  * @return int nb items generated
@@ -66,7 +65,7 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
66
  public function writeXml($context, $filename, $type)
67
  {
68
 
69
- if (count($context['store_id']) == 0) {
70
  return 0;
71
  }
72
 
@@ -85,18 +84,19 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
85
  $this->onlyProductsWithStock = !(boolean)Mage::getStoreConfig('antidot/fields_product/in_stock_only');
86
  $this->autoCompleteProducts = Mage::getStoreConfig('antidot/suggest/enable') === 'Antidot/engine_antidot' ? 'on' : 'off';
87
 
 
 
 
88
  $productsInStock = $this->onlyProductsWithStock ? ' AND is_in_stock = 1' : '';
89
- $collection = Mage::getModel('catalog/product')
90
  ->getCollection()
91
- ->setStoreId($context['store_id'][0]) //take the first store
92
- ->addWebsiteFilter($context['website_ids'])
93
  ->addAttributeToFilter('visibility', $this->productVisible)
94
  ->addAttributeToFilter('status', 1)
95
- ->joinField('qty',
96
- 'cataloginventory/stock_item',
97
- 'qty',
98
- 'product_id=entity_id', // warning : no spaces between = and entity_id , magento1.5 isn't robust enought
99
- '{{table}}.stock_id = 1'.$productsInStock)
100
  ;
101
 
102
  if ($type === MDN_Antidot_Model_Observer::GENERATE_INC) {
@@ -113,6 +113,7 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
113
  $collection->setPageSize($chunkSize);
114
 
115
  $productsCount = $collection->getSize();
 
116
  Mage::log('Products to export : '.$productsCount, null, 'antidot.log');
117
  $chunkCount = $collection->getLastPageNumber();
118
 
@@ -127,14 +128,14 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
127
  $this->initPropertyLabel();
128
  $this->initProductsWithOperations();
129
  $this->initFields('product');
130
- $this->initEnabledStores();
131
- $this->setFilename($filename);
132
 
133
  $this->xml->push('catalog', array('xmlns' => "http://ref.antidot.net/store/afs#"));
134
  $this->writeHeader($context);
135
  $this->writePart($this->xml->flush());
136
 
137
- $this->lang = $context['lang'];
138
 
139
 
140
  $lastExecutionTime = time();
@@ -148,20 +149,19 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
148
 
149
  foreach($collection as $product) {
150
 
151
- $stores = $this->getProductStores($product, $context);
152
- if ($store = current($stores)) { //we take the "first" store of the current lang
153
- $product = Mage::getModel('catalog/product')->setStoreId($store->getId())->load(
154
- $product->getId()
155
- );
156
 
157
- $this->writeProduct($product, $stores);
 
158
 
159
- $product->clearInstance(); //memory flush
160
- $product = null;
161
- unset($product);
162
- $this->garbageCollection();
163
  }
164
 
 
 
 
 
 
165
  }
166
  $this->writePart($this->xml->flush());
167
 
@@ -182,20 +182,7 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
182
 
183
  Varien_Profiler::stop("export_product_writeXml");
184
 
185
- return $productsCount;
186
- }
187
-
188
- /**
189
- * List only enabled stores
190
- */
191
- protected function initEnabledStores()
192
- {
193
- $stores = Mage::getModel('core/store')->getCollection();
194
- foreach($stores as $store)
195
- {
196
- if ($store->getis_active())
197
- $this->enabledStores[] = $store->getId();
198
- }
199
  }
200
 
201
  /**
@@ -239,17 +226,18 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
239
  /**
240
  * Write the product
241
  *
242
- * @param Product $product
243
- * @param Array $stores
244
  */
245
- protected function writeProduct($product, $stores)
246
  {
247
  Varien_Profiler::start("export_product_writeProduct");
248
 
249
  //skip product if no websites
250
- if (count($stores) == 0)
251
- return;
252
 
 
253
  /**
254
  * MCNX-211 : check if grouped/configurables product has variant before begin export product
255
  */
@@ -257,8 +245,6 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
257
  if ($product->getTypeID() == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE
258
  || $product->getTypeID() == Mage_Catalog_Model_Product_Type::TYPE_GROUPED) {
259
 
260
- Mage::app()->setCurrentStore($product->getStoreId()); //Set store id in order to exclude not in stock products
261
-
262
  switch ($product->getTypeID()) {
263
  case Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE:
264
  $variantProductsColl = $product->getTypeInstance(true)->getUsedProducts(null, $product);
@@ -270,8 +256,14 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
270
 
271
  foreach ($variantProductsColl as $variantProduct) {
272
  //Do not include product if status is not enabled
273
- if ($variantProduct->getStatus() == Mage_Catalog_Model_Product_Status::STATUS_ENABLED && $variantProduct->isSalable() ) {
274
- $variantProducts[] = $variantProduct;
 
 
 
 
 
 
275
  }
276
  }
277
 
@@ -280,35 +272,24 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
280
  return;
281
  }
282
  }
 
283
 
 
284
  $this->xml->push('product', array('id' => $product->getId(), 'xml:lang' => $this->lang, 'autocomplete' => $this->autoCompleteProducts));
285
 
286
  $this->xml->push('websites');
287
- $websites = array();
288
- $rootCategoriesIds = array(); //the root categories of the stores of this context, used for exporting only the categories within theses roots
289
- foreach($stores as $store) {
290
- $rootCategoriesIds[] = $store->getRootCategoryId();
291
- $website = $this->getWebSiteByStore($store);
292
- if (!array_key_exists($website->getId(), $websites))
293
- {
294
- $websites[$website->getId()] = $website->getName();
295
- $this->xml->element('website', $website->getName(), array('id' => $website->getId()));
296
- }
297
  }
298
  $this->xml->pop();
299
 
300
  //$this->xml->writeElement('created_at', $product->getCreated_at()); AFM-83
301
  //$this->xml->writeElement('last_updated_at', $product->getUpdated_at()); AFM-92
302
 
303
- $this->xml->element('name', $this->xml->encloseCData($this->utf8CharacterValidation($this->getField($product, 'name'))));
304
- if($shortName = $this->getField($product, 'short_name')) {
305
- $this->xml->element('short_name', $this->xml->encloseCData(mb_substr($shortName, 0, 45, 'UTF-8')), array('autocomplete' => 'off'));
306
- }
307
-
308
- if ($keywords = $this->getField($product, 'keywords')) {
309
- $this->xml->element('keywords', $this->xml->encloseCData($keywords));
310
- }
311
- $this->writeClassification($product, $rootCategoriesIds);
312
  $this->writeBrand($product);
313
  $this->writeMaterials($product);
314
  $this->writeColors($product);
@@ -317,9 +298,10 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
317
  $this->writeGenders($product);
318
  $this->writeMisc($product);
319
 
320
- $this->writeVariants($product, $variantProducts, $stores);
321
 
322
  $this->xml->pop();
 
323
 
324
  Varien_Profiler::stop("export_product_writeProduct");
325
 
@@ -328,87 +310,83 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
328
  /**
329
  * Write the store's informations
330
  *
331
- * @param Product $product
332
- * @param array $stores
333
  */
334
- protected function writeStore($product, $stores, $variantProduct)
335
  {
336
  Varien_Profiler::start("export_product_writeStore");
337
 
338
  $this->xml->push('stores');
339
 
340
  /* Qty is the same for all stores, better compute it outside the loop: */
341
- $qty = Mage::getModel('cataloginventory/stock_item')->loadByProduct($variantProduct)->getQty();
342
  $qty = ($qty > 0 ? $qty : 0);
343
 
344
- foreach($stores as $store) {
345
  Mage::app()->setCurrentStore($store->getId());
346
-
347
  /*
348
  * reload the $variantProduct if this is a real variant or if we are on a different store
349
  */
350
- $reloaded = false;
351
- if ($product->getId() != $variantProduct->getId() || $store->getId() != $product->getStoreId()) {
352
- $reloadedVariantProduct = Mage::getModel('catalog/product')->setStoreId($store->getId())->load(
353
- $variantProduct->getId()
354
- );
355
- $reloaded = true;
356
- } else {
357
- $reloadedVariantProduct = $variantProduct;
358
  }
359
 
360
  $this->xml->push('store', array('id' => $store->getId(), 'name' => $store->getName()));
361
- $storeContext['currency'] = $store->getCurrentCurrencyCode();
362
- $storeContext['country'] = $this->getStoreLang($store->getId());
363
 
364
- $operations = $this->getOperations($product, $store);
365
- $this->writePrices($reloadedVariantProduct, $product, $storeContext, $store);
366
- $this->writeMarketing($reloadedVariantProduct, $operations);
367
 
368
- $isAvailable = $reloadedVariantProduct->isSalable() || (in_array($reloadedVariantProduct->getTypeId(), $this->productMultiple) && $product->isInStock());
 
369
  $this->xml->element('is_available', (int)$isAvailable);
370
 
371
  $this->xml->element('stock', (int)$qty);
372
 
373
- $this->writeProductUrl($reloadedVariantProduct);
374
- $this->writeImageUrl($reloadedVariantProduct);
375
 
376
  $this->xml->pop();
377
 
378
- if ($reloaded) {
379
- $reloadedVariantProduct->clearInstance(); //memory flush
380
- $reloadedVariantProduct = null;
381
- unset($reloadedVariantProduct);
382
- $this->garbageCollection();
383
- }
384
-
385
 
386
  }
 
387
  $this->xml->pop();
388
 
389
  Varien_Profiler::stop("export_product_writeStore");
390
 
391
  }
392
-
393
  /**
394
- * Get product stores
395
- *
396
  * @param Product $product
397
- * @param array $context
398
  */
399
- protected function getProductStores($product, $context)
400
  {
401
- $stores = array();
402
-
403
- $storeIds = array_intersect($product->getStoreIds(), $context['store_id']);
404
- foreach($storeIds as $storeId) {
405
- if (in_array($storeId, $this->enabledStores))
406
- $stores[] = $context['stores'][$storeId];
407
  }
 
408
 
409
- return $stores;
 
 
 
 
 
 
 
 
 
410
  }
411
-
412
  /**
413
  * Write the product descriptions
414
  *
@@ -476,7 +454,7 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
476
  if(!empty($this->fields['identifier'])) {
477
  foreach($this->fields['identifier'] as $identifier) {
478
  if ($value = $this->getField($product, $identifier)) {
479
- $identifiers[$identifier] = mb_substr($value, 0, 40, 'UTF-8');
480
  }
481
  }
482
  }
@@ -512,10 +490,10 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
512
  if ($manufacturer = $this->getField($product, 'manufacturer')) {
513
  if(!empty($manufacturer)) {
514
  $field = empty($this->fields['manufacturer']) ? 'manufacturer' : $this->fields['manufacturer'];
515
- $brand = mb_substr($product->getAttributeText($field), 0, 40, 'UTF-8');
516
  $brandUrl = Mage::helper('catalogsearch')->getResultUrl($brand, $product->getStoreId());
517
  $brandUrl = parse_url($brandUrl, PHP_URL_PATH).'?'.parse_url($brandUrl, PHP_URL_QUERY);
518
- $brandUrl = str_replace('antidotExport.php', 'index.php', $brandUrl);
519
  if(!empty($brand)) {
520
  $this->xml->element('brand', $this->xml->encloseCData($brand), array('id' => $manufacturer, 'url' => $brandUrl));
521
  }
@@ -529,13 +507,13 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
529
  /**
530
  * Write the product urls
531
  *
532
- * @param Product $product
533
  * @param string $urlImg
534
  */
535
  protected function writeProductUrl($product)
536
  {
537
  Varien_Profiler::start("export_product_writeProductUrl");
538
- $this->xml->element('url', $this->xml->encloseCData($product->getProductUrl(false)));
539
  Varien_Profiler::stop("export_product_writeProductUrl");
540
 
541
  }
@@ -560,7 +538,7 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
560
  $this->xml->element('url_thumbnail', $this->xml->encloseCData(Mage::getModel('catalog/product_media_config')->getMediaUrl($product->getThumbnail())));
561
  }
562
  } catch(Exception $e) {
563
- Mage::log("writeImageUrl Exception : " . $e->getMessage(), Zend_Log::ERR, 'antidot.log');
564
  }
565
 
566
  try {
@@ -568,7 +546,7 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
568
  $this->xml->element('url_image', $this->xml->encloseCData(Mage::getModel('catalog/product_media_config')->getMediaUrl($product->getImage())));
569
  }
570
  } catch(Exception $e) {
571
- Mage::log("writeImageUrl Exception : " .$e->getMessage(), Zend_Log::ERR, 'antidot.log');
572
  }
573
 
574
  Varien_Profiler::stop("export_product_writeImageUrl");
@@ -578,34 +556,18 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
578
  /**
579
  * Write the product classification
580
  *
581
- * @param Product $product
582
  */
583
- protected function writeClassification($product, $rootCategoriesIds)
584
  {
585
  Varien_Profiler::start("export_product_writeClassification");
586
- $categories = $this->getProductCategories($product, $rootCategoriesIds);
587
- $exportCategory = false;
588
- foreach($categories as $category) {
589
- $exportCategory = true;
590
- $path = array($category);
591
- while ($category = $this->getCategoryParent($category, $rootCategoriesIds)) {
592
- $path[] = $category;
593
- }
594
- //if one of the ancestor of the category is inactive, rise flag to not export the category
595
- foreach ($path as $cat) {
596
- if (!$cat->getName() || !$cat->getIsActive()) {
597
- $exportCategory = false;
598
- }
599
- }
600
- }
601
- if ($exportCategory) {
602
  $this->xml->push('classification');
603
- foreach (array_reverse($path) as $cat) {
604
- $this->writeCategory($cat);
605
- }
606
- foreach ($path as $cat) {
607
- $this->xml->pop();
608
- }
609
  $this->xml->pop();
610
  }
611
  Varien_Profiler::stop("export_product_writeClassification");
@@ -616,108 +578,24 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
616
  * get parent category node
617
  *
618
  * @param $category
619
- * @param array $rootCategoriesIds
620
- */
621
- protected function getCategoryParent($category, $rootCategoriesIds)
622
- {
623
-
624
- //if the parent is the root node, don't export it
625
- if ($category->getParentId() == 1 || $category->getParentId() == 0 || in_array($category->getParentId(), $rootCategoriesIds)) {
626
- return false;
627
- }
628
-
629
- return $this->getCategoryById($category->getStoreId(), $category->getParentId());
630
-
631
- }
632
-
633
-
634
- /**
635
- * Write category node
636
- *
637
- * @param $category
638
  */
639
  protected function writeCategory($category)
640
  {
641
 
642
- $categoryUrl = $this->getUri($category->getUrl());
643
- $categoryUrl = str_replace('antidotExport.php', 'index.php', $categoryUrl);
644
- $attributes = array('id' => $category->getId(), 'label' => substr($category->getName(), 0, self::FACET_MAX_LENGTH), 'url' => $categoryUrl);
645
  if ($category->getImage()) {
646
  $attributes['img'] = $category->getImage();
647
  }
648
  $this->xml->push('category', $attributes);
649
 
650
- }
651
-
652
- /**
653
- * Get category by id
654
- *
655
- * @param int $categoryId
656
- * @return Category
657
- */
658
- protected function getCategoryById($storeId, $categoryId)
659
- {
660
- if(!isset($this->categories[$storeId][$categoryId])) {
661
- $category = Mage::getModel('catalog/category')->setStoreId($storeId)->load($categoryId);
662
- if (method_exists($category, 'getUrlModel')) { //compatibility with older magento version where category#getUrlModel doesn't exist
663
- $category->getUrlModel()->getUrlInstance()->setStore($storeId);
664
- } else {
665
- $category->getUrlInstance()->setStore($storeId);
666
- }
667
- $this->categories[$storeId][$categoryId] = $category;
668
- }
669
-
670
- return $this->categories[$storeId][$categoryId];
671
- }
672
-
673
- /**
674
- * Return the top level category
675
- *
676
- * @param Product $product
677
- * @return array
678
- */
679
- protected function getProductCategories($product, $rootCategoriesIds)
680
- {
681
- $categories = $product->getCategoryCollection();
682
- $categories->setStoreId($product->getStoreId());
683
- $categories->addAttributeToSelect('name');
684
- $categories->addAttributeToSelect('image');
685
- $categories->addAttributeToSelect('url_key');
686
- $categories->addAttributeToFilter('name', array('neq' => ''));
687
-
688
- //Add a filter on the path in order to export only the categories whose root category is used on the exported stores
689
- $rootCategoryCondition = array();
690
- foreach ($rootCategoriesIds as $rootCategoryId) {
691
- $rootCategoryCondition[] = array('like' => '1/'.$rootCategoryId.'/%');
692
  }
693
- $categories->addAttributeToFilter('path', $rootCategoryCondition);
694
- $categories->addAttributeToFilter('is_active', 1); //MCNX-236
695
 
696
- //Mage::log($categories->getSelect()->__toString(), null, 'antidot.log');
697
-
698
- $productCategories = array();
699
- foreach($categories as $category) {
700
- //Force the store on the url in order to generate the store code in url if it is configured in system > config
701
- $category->setStoreId($product->getStoreId());
702
- if (method_exists($category, 'getUrlModel')) { //compatibility with older magento version where category#getUrlModel doesn't exist
703
- $category->getUrlModel()->getUrlInstance()->setStore($product->getStoreId());
704
- } else {
705
- $category->getUrlInstance()->setStore($product->getStoreId());
706
- }
707
- if (($category->getparent_id() == 0) || ($category->getparent_id() == 1))
708
- continue;
709
- $productCategories[$category->getId()] = $category;
710
- $this->categories[$product->getStoreId()][$category->getId()] = $category; //cache categories already loaded here to avoid full load in getCategoryById()
711
- $parentCategory[] = $category->getParentId();
712
- }
713
-
714
- foreach($productCategories as $category) {
715
- if(in_array($category->getParentId(), $parentCategory)) {
716
- unset($productCategories[$category->getParentId()]);
717
- }
718
- }
719
 
720
- return $productCategories;
721
  }
722
 
723
  /**
@@ -897,7 +775,7 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
897
  *
898
  * @param Product $product
899
  */
900
- protected function writePrices($product, $parentProduct, $context, $store)
901
  {
902
  Varien_Profiler::start("export_product_writePrices");
903
 
@@ -929,10 +807,12 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
929
  $price = Mage::helper('tax')->getPrice($product, $prices['final_price'] + $weeeAmount, true);
930
  }
931
 
932
- $price = Mage::helper('directory')->currencyConvert($price, Mage::app()->getStore()->getCurrentCurrencyCode(), $store->getCurrentCurrencyCode());
933
-
 
 
934
  $this->xml->push('prices');
935
- $attributes = array('currency' => $context['currency'], 'type' => 'PRICE_FINAL', 'vat_included' => 'true', 'country' => strtoupper($context['country']));
936
  if (isset($priceCut))
937
  {
938
  $off = $this->computePriceOff($priceCut, $price);
@@ -950,7 +830,7 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
950
  $this->xml->element(
951
  'price',
952
  Mage::helper('Antidot')->round($priceCut),
953
- array('currency' => $context['currency'], 'type' => 'PRICE_CUT', 'vat_included' => 'true', 'country' => strtoupper($context['country']))
954
  );
955
 
956
  }
@@ -1135,19 +1015,19 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
1135
  * @param array $variantProducts
1136
  * @param array $stores
1137
  */
1138
- protected function writeVariants($product, $variantProducts, $stores)
1139
  {
1140
  Varien_Profiler::start("export_product_writeVariants");
1141
  $this->xml->push('variants');
1142
 
1143
  $this->xml->push('variant', array('id' => 'fake'));
1144
- $this->writeVariant($product, $product, $stores);
1145
  $this->xml->pop();
1146
 
1147
  foreach($variantProducts as $variantProduct) {
1148
 
1149
  $this->xml->push('variant', array('id' => $variantProduct->getId()));
1150
- $this->writeVariant($variantProduct, $product, $stores);
1151
  $this->xml->pop();
1152
  }
1153
 
@@ -1160,23 +1040,23 @@ class MDN_Antidot_Model_Export_Product extends MDN_Antidot_Model_Export_Abstract
1160
  * Write variant
1161
  *
1162
  * @param Product $variantProduct
1163
- * @param Product $product
1164
  * @param array $stores
1165
  */
1166
- protected function writeVariant($variantProduct, $product, $stores)
1167
  {
1168
  Varien_Profiler::start("export_product_writeVariant");
1169
 
1170
  $this->xml->element('name', $this->xml->encloseCData($this->utf8CharacterValidation($variantProduct->getName())));
1171
  $this->writeDescriptions($variantProduct);
1172
- $this->writeStore($product, $stores, $variantProduct);
1173
  $this->writeIdentifiers($variantProduct);
1174
- $this->writeProperties($variantProduct, ($variantProduct->getId()==$product->getId()));
1175
  $this->writeMaterials($variantProduct);
1176
  $this->writeColors($variantProduct);
1177
  $this->writeModels($variantProduct);
1178
  $this->writeSizes($variantProduct);
1179
- $this->writeGenders($product);
1180
  $this->writeMisc($variantProduct);
1181
 
1182
  Varien_Profiler::stop("export_product_writeVariant");
23
  const XSD = 'http://ref.antidot.net/store/latest/catalog.xsd';
24
 
25
  /*
26
+ * Maximum length for the values accepted by AFSStore
 
27
  */
28
  const FACET_MAX_LENGTH = 119;
29
+ const NAME_MAX_LENGTH = 255;
30
+ const SHORT_NAME_MAX_LENGTH = 45;
31
+ const IDENTIFIER_MAX_LENGTH = 40;
32
+ const BRAND_MAX_LENGTH = 40;
33
 
34
  protected $file;
35
 
36
  protected $productGenerated = array();
37
 
 
 
 
 
38
  protected $onlyProductsWithStock;
39
 
40
  protected $autoCompleteProducts;
57
  /**
58
  * Write the xml file
59
  *
60
+ * @param MDN_Antidot_Model_Export_Context $context
61
  * @param string $filename
62
  * @param string $type Incremantal or full
63
  * @return int nb items generated
65
  public function writeXml($context, $filename, $type)
66
  {
67
 
68
+ if (count($context->getStoreIds()) == 0) {
69
  return 0;
70
  }
71
 
84
  $this->onlyProductsWithStock = !(boolean)Mage::getStoreConfig('antidot/fields_product/in_stock_only');
85
  $this->autoCompleteProducts = Mage::getStoreConfig('antidot/suggest/enable') === 'Antidot/engine_antidot' ? 'on' : 'off';
86
 
87
+ /**
88
+ * This first collect list the products of the exported websites which are available in stock (according to configuration)
89
+ */
90
  $productsInStock = $this->onlyProductsWithStock ? ' AND is_in_stock = 1' : '';
91
+ $collection = Mage::getModel('Antidot/export_model_product')
92
  ->getCollection()
93
+ ->addWebsiteFilter($context->getWebsiteIds())
 
94
  ->addAttributeToFilter('visibility', $this->productVisible)
95
  ->addAttributeToFilter('status', 1)
96
+ ->joinTable('cataloginventory/stock_item',
97
+ 'product_id=entity_id', // warning : no spaces between = and entity_id , magento1.5 isn't robust enought
98
+ array('qty', 'is_in_stock'),
99
+ '{{table}}.stock_id = 1'.$productsInStock)
 
100
  ;
101
 
102
  if ($type === MDN_Antidot_Model_Observer::GENERATE_INC) {
113
  $collection->setPageSize($chunkSize);
114
 
115
  $productsCount = $collection->getSize();
116
+ $productsExported = 0;
117
  Mage::log('Products to export : '.$productsCount, null, 'antidot.log');
118
  $chunkCount = $collection->getLastPageNumber();
119
 
128
  $this->initPropertyLabel();
129
  $this->initProductsWithOperations();
130
  $this->initFields('product');
131
+ $context->addAttributeToLoad($this->fields);
132
+ $this->setFilename($filename);
133
 
134
  $this->xml->push('catalog', array('xmlns' => "http://ref.antidot.net/store/afs#"));
135
  $this->writeHeader($context);
136
  $this->writePart($this->xml->flush());
137
 
138
+ $this->lang = $context->getLang();
139
 
140
 
141
  $lastExecutionTime = time();
149
 
150
  foreach($collection as $product) {
151
 
152
+ /** @var $product MDN_Antidot_Model_Export_Model_Product */
153
+ if ($product->setContext($context)) {
 
 
 
154
 
155
+ $product->loadNeededAttributes();
156
+ $productsExported += $this->writeProduct($product);
157
 
 
 
 
 
158
  }
159
 
160
+ $product->clearInstanceFull(); //memory flush
161
+ $product = null;
162
+ unset($product);
163
+ $this->garbageCollection();
164
+
165
  }
166
  $this->writePart($this->xml->flush());
167
 
182
 
183
  Varien_Profiler::stop("export_product_writeXml");
184
 
185
+ return $productsExported;
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  }
187
 
188
  /**
226
  /**
227
  * Write the product
228
  *
229
+ * @param MDN_Antidot_Model_Export_Model_Product $product
230
+ *
231
  */
232
+ protected function writeProduct($product)
233
  {
234
  Varien_Profiler::start("export_product_writeProduct");
235
 
236
  //skip product if no websites
237
+ if (count($product->getStores()) == 0)
238
+ return 0;
239
 
240
+ Varien_Profiler::start("export_product_getVariantsProduct");
241
  /**
242
  * MCNX-211 : check if grouped/configurables product has variant before begin export product
243
  */
245
  if ($product->getTypeID() == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE
246
  || $product->getTypeID() == Mage_Catalog_Model_Product_Type::TYPE_GROUPED) {
247
 
 
 
248
  switch ($product->getTypeID()) {
249
  case Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE:
250
  $variantProductsColl = $product->getTypeInstance(true)->getUsedProducts(null, $product);
256
 
257
  foreach ($variantProductsColl as $variantProduct) {
258
  //Do not include product if status is not enabled
259
+ if ($variantProduct->getStatus() == 1) {
260
+
261
+ /** @var $product MDN_Antidot_Model_Export_Model_Product */
262
+ if ($variantProduct->setContext($product->getContext(), true)) {
263
+ $variantProduct->loadNeededAttributes();
264
+ $variantProducts[] = $variantProduct;
265
+ }
266
+
267
  }
268
  }
269
 
272
  return;
273
  }
274
  }
275
+ Varien_Profiler::stop("export_product_getVariantsProduct");
276
 
277
+ Varien_Profiler::start("export_writeProductWebsites");
278
  $this->xml->push('product', array('id' => $product->getId(), 'xml:lang' => $this->lang, 'autocomplete' => $this->autoCompleteProducts));
279
 
280
  $this->xml->push('websites');
281
+ foreach($product->getWebsites() as $website) {
282
+ $this->xml->element('website', $website->getName(), array('id' => $website->getId()));
 
 
 
 
 
 
 
 
283
  }
284
  $this->xml->pop();
285
 
286
  //$this->xml->writeElement('created_at', $product->getCreated_at()); AFM-83
287
  //$this->xml->writeElement('last_updated_at', $product->getUpdated_at()); AFM-92
288
 
289
+ $this->writeName($product);
290
+ $this->writeKeywords($product);
291
+ Varien_Profiler::stop("export_writeProductWebsites");
292
+ $this->writeClassification($product);
 
 
 
 
 
293
  $this->writeBrand($product);
294
  $this->writeMaterials($product);
295
  $this->writeColors($product);
298
  $this->writeGenders($product);
299
  $this->writeMisc($product);
300
 
301
+ $this->writeVariants($product, $variantProducts);
302
 
303
  $this->xml->pop();
304
+ return 1;
305
 
306
  Varien_Profiler::stop("export_product_writeProduct");
307
 
310
  /**
311
  * Write the store's informations
312
  *
313
+ * @param Product $parentProduct
314
+ * @param Product $variantProduct
315
  */
316
+ protected function writeStore($parentProduct, $variantProduct)
317
  {
318
  Varien_Profiler::start("export_product_writeStore");
319
 
320
  $this->xml->push('stores');
321
 
322
  /* Qty is the same for all stores, better compute it outside the loop: */
323
+ $qty = $variantProduct->getQty();
324
  $qty = ($qty > 0 ? $qty : 0);
325
 
326
+ foreach($parentProduct->getStores() as $store) {
327
  Mage::app()->setCurrentStore($store->getId());
 
328
  /*
329
  * reload the $variantProduct if this is a real variant or if we are on a different store
330
  */
331
+ if ($store->getId() != $parentProduct->getStoreId()) {
332
+ $parentProduct->setStoreId($store->getId());
333
+ $variantProduct->setStoreId($store->getId());
334
+ //$parentProduct->loadNeededAttributes(true);
335
+ $variantProduct->loadNeededAttributes(true);
 
 
 
336
  }
337
 
338
  $this->xml->push('store', array('id' => $store->getId(), 'name' => $store->getName()));
 
 
339
 
340
+ $operations = $this->getOperations($parentProduct, $store);
341
+ $this->writePrices($variantProduct, $parentProduct, $store);
342
+ $this->writeMarketing($variantProduct, $operations);
343
 
344
+ $isAvailable = ($variantProduct->isInStock()/* status*/ && $variantProduct->getIsInStock()/* stock status */)
345
+ || (in_array($variantProduct->getTypeId(), $this->productMultiple) && $parentProduct->isInStock());
346
  $this->xml->element('is_available', (int)$isAvailable);
347
 
348
  $this->xml->element('stock', (int)$qty);
349
 
350
+ $this->writeProductUrl($variantProduct);
351
+ $this->writeImageUrl($variantProduct);
352
 
353
  $this->xml->pop();
354
 
 
 
 
 
 
 
 
355
 
356
  }
357
+
358
  $this->xml->pop();
359
 
360
  Varien_Profiler::stop("export_product_writeStore");
361
 
362
  }
363
+
364
  /**
365
+ * Write the product name
366
+ *
367
  * @param Product $product
 
368
  */
369
+ protected function writeName($product)
370
  {
371
+ $name = $this->utf8CharacterValidation($this->getField($product, 'name'));
372
+ $this->xml->element('name', $this->xml->encloseCData(mb_substr($name, 0, self::NAME_MAX_LENGTH, 'UTF-8')));
373
+ if($shortName = $this->getField($product, 'short_name')) {
374
+ $this->xml->element('short_name', $this->xml->encloseCData(mb_substr($shortName, 0, self::SHORT_NAME_MAX_LENGTH, 'UTF-8')), array('autocomplete' => 'off'));
 
 
375
  }
376
+ }
377
 
378
+ /**
379
+ * Write the product keywords
380
+ *
381
+ * @param Product $product
382
+ */
383
+ protected function writeKeywords($product)
384
+ {
385
+ if ($keywords = $this->getField($product, 'keywords')) {
386
+ $this->xml->element('keywords', $this->xml->encloseCData($keywords));
387
+ }
388
  }
389
+
390
  /**
391
  * Write the product descriptions
392
  *
454
  if(!empty($this->fields['identifier'])) {
455
  foreach($this->fields['identifier'] as $identifier) {
456
  if ($value = $this->getField($product, $identifier)) {
457
+ $identifiers[$identifier] = mb_substr($value, 0, self::IDENTIFIER_MAX_LENGTH, 'UTF-8');
458
  }
459
  }
460
  }
490
  if ($manufacturer = $this->getField($product, 'manufacturer')) {
491
  if(!empty($manufacturer)) {
492
  $field = empty($this->fields['manufacturer']) ? 'manufacturer' : $this->fields['manufacturer'];
493
+ $brand = mb_substr($product->getAttributeText($field), 0, self::BRAND_MAX_LENGTH, 'UTF-8');
494
  $brandUrl = Mage::helper('catalogsearch')->getResultUrl($brand, $product->getStoreId());
495
  $brandUrl = parse_url($brandUrl, PHP_URL_PATH).'?'.parse_url($brandUrl, PHP_URL_QUERY);
496
+ $brandUrl = $this->getExactUrl($brandUrl);
497
  if(!empty($brand)) {
498
  $this->xml->element('brand', $this->xml->encloseCData($brand), array('id' => $manufacturer, 'url' => $brandUrl));
499
  }
507
  /**
508
  * Write the product urls
509
  *
510
+ * @param MDN_Antidot_Model_Export_Model_Product $product
511
  * @param string $urlImg
512
  */
513
  protected function writeProductUrl($product)
514
  {
515
  Varien_Profiler::start("export_product_writeProductUrl");
516
+ $this->xml->element('url', $this->xml->encloseCData($this->getExactUrl($product->getProductUrl(false), false)));
517
  Varien_Profiler::stop("export_product_writeProductUrl");
518
 
519
  }
538
  $this->xml->element('url_thumbnail', $this->xml->encloseCData(Mage::getModel('catalog/product_media_config')->getMediaUrl($product->getThumbnail())));
539
  }
540
  } catch(Exception $e) {
541
+ //Mage::log("writeImageUrl Exception : " . $e->getMessage(), Zend_Log::ERR, 'antidot.log');
542
  }
543
 
544
  try {
546
  $this->xml->element('url_image', $this->xml->encloseCData(Mage::getModel('catalog/product_media_config')->getMediaUrl($product->getImage())));
547
  }
548
  } catch(Exception $e) {
549
+ //Mage::log("writeImageUrl Exception : " .$e->getMessage(), Zend_Log::ERR, 'antidot.log');
550
  }
551
 
552
  Varien_Profiler::stop("export_product_writeImageUrl");
556
  /**
557
  * Write the product classification
558
  *
559
+ * @param MDN_Antidot_Model_Export_Model_Product $product
560
  */
561
+ protected function writeClassification($product)
562
  {
563
  Varien_Profiler::start("export_product_writeClassification");
564
+ $tree = $product->getCategoryTree();
565
+ $rootNode = $tree->getNodeById(1);
566
+ if($rootNode->hasChildren()) {
 
 
 
 
 
 
 
 
 
 
 
 
 
567
  $this->xml->push('classification');
568
+ foreach ($rootNode->getChildren() as $node) {
569
+ $this->writeCategory($node);
570
+ }
 
 
 
571
  $this->xml->pop();
572
  }
573
  Varien_Profiler::stop("export_product_writeClassification");
578
  * get parent category node
579
  *
580
  * @param $category
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
  */
582
  protected function writeCategory($category)
583
  {
584
 
585
+ //antidot_url is set in the Context initCategoryTree
586
+ $attributes = array('id' => $category->getId(), 'label' => substr($category->getName(), 0, self::FACET_MAX_LENGTH), 'url' => $this->getExactUrl($category->getUrl()));
 
587
  if ($category->getImage()) {
588
  $attributes['img'] = $category->getImage();
589
  }
590
  $this->xml->push('category', $attributes);
591
 
592
+ foreach ($category->getChildren() as $child) {
593
+ $this->writeCategory($child);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
  }
 
 
595
 
596
+ $this->xml->pop();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
 
598
+ return true;
599
  }
600
 
601
  /**
775
  *
776
  * @param Product $product
777
  */
778
+ protected function writePrices($product, $parentProduct, $store)
779
  {
780
  Varien_Profiler::start("export_product_writePrices");
781
 
807
  $price = Mage::helper('tax')->getPrice($product, $prices['final_price'] + $weeeAmount, true);
808
  }
809
 
810
+ $currentCurrencyCode = $store->getCurrentCurrencyCode();
811
+
812
+ $price = Mage::helper('directory')->currencyConvert($price, Mage::app()->getStore()->getCurrentCurrencyCode(), $currentCurrencyCode);
813
+
814
  $this->xml->push('prices');
815
+ $attributes = array('currency' => $currentCurrencyCode, 'type' => 'PRICE_FINAL', 'vat_included' => 'true');
816
  if (isset($priceCut))
817
  {
818
  $off = $this->computePriceOff($priceCut, $price);
830
  $this->xml->element(
831
  'price',
832
  Mage::helper('Antidot')->round($priceCut),
833
+ array('currency' => $currentCurrencyCode, 'type' => 'PRICE_CUT', 'vat_included' => 'true')
834
  );
835
 
836
  }
1015
  * @param array $variantProducts
1016
  * @param array $stores
1017
  */
1018
+ protected function writeVariants($product, $variantProducts)
1019
  {
1020
  Varien_Profiler::start("export_product_writeVariants");
1021
  $this->xml->push('variants');
1022
 
1023
  $this->xml->push('variant', array('id' => 'fake'));
1024
+ $this->writeVariant($product, $product);
1025
  $this->xml->pop();
1026
 
1027
  foreach($variantProducts as $variantProduct) {
1028
 
1029
  $this->xml->push('variant', array('id' => $variantProduct->getId()));
1030
+ $this->writeVariant($variantProduct, $product);
1031
  $this->xml->pop();
1032
  }
1033
 
1040
  * Write variant
1041
  *
1042
  * @param Product $variantProduct
1043
+ * @param Product $parentProduct
1044
  * @param array $stores
1045
  */
1046
+ protected function writeVariant($variantProduct, $parentProduct)
1047
  {
1048
  Varien_Profiler::start("export_product_writeVariant");
1049
 
1050
  $this->xml->element('name', $this->xml->encloseCData($this->utf8CharacterValidation($variantProduct->getName())));
1051
  $this->writeDescriptions($variantProduct);
1052
+ $this->writeStore($parentProduct, $variantProduct);
1053
  $this->writeIdentifiers($variantProduct);
1054
+ $this->writeProperties($variantProduct, ($variantProduct->getId()==$parentProduct->getId()));
1055
  $this->writeMaterials($variantProduct);
1056
  $this->writeColors($variantProduct);
1057
  $this->writeModels($variantProduct);
1058
  $this->writeSizes($variantProduct);
1059
+ $this->writeGenders($parentProduct);
1060
  $this->writeMisc($variantProduct);
1061
 
1062
  Varien_Profiler::stop("export_product_writeVariant");
app/code/community/MDN/Antidot/Model/Observer.php CHANGED
@@ -92,7 +92,7 @@ class MDN_Antidot_Model_Observer extends Mage_Core_Model_Abstract
92
  /**
93
  * Generate the full catalog file
94
  */
95
- public function catalogFullExport($runContext = 'cron')
96
  {
97
  $this->log('FULL EXPORT');
98
  return $this->generate(Mage::getModel('Antidot/export_product'), self::GENERATE_FULL, $runContext);
@@ -101,7 +101,7 @@ class MDN_Antidot_Model_Observer extends Mage_Core_Model_Abstract
101
  /**
102
  * Generate the inc catalog file
103
  */
104
- public function catalogIncExport($runContext = 'cron')
105
  {
106
  return $this->generate(Mage::getModel('Antidot/export_product'), self::GENERATE_INC, $runContext);
107
  }
@@ -109,7 +109,7 @@ class MDN_Antidot_Model_Observer extends Mage_Core_Model_Abstract
109
  /**
110
  * Generate the category file
111
  */
112
- public function categoriesFullExport($runContext = 'cron')
113
  {
114
  return $this->generate(Mage::getModel('Antidot/export_category'), self::GENERATE_FULL, $runContext);
115
  }
@@ -123,6 +123,12 @@ class MDN_Antidot_Model_Observer extends Mage_Core_Model_Abstract
123
  */
124
  protected function generate($exportModel, $type, $runContext)
125
  {
 
 
 
 
 
 
126
  $this->type = $exportModel::TYPE;
127
  $this->log('start');
128
  $log['begin'] = time();
@@ -132,14 +138,14 @@ class MDN_Antidot_Model_Observer extends Mage_Core_Model_Abstract
132
 
133
  try
134
  {
135
-
136
- $owner = $this->getOwnerForFilename(Mage::getStoreConfig('antidot/general/owner'));
137
  $files = array();
138
  foreach($this->getDefaultContext($runContext) as $context) {
139
- $this->log('generate '.$exportModel::TYPE.' '.$context['owner']);
140
- $context['store_id'] = array_keys($context['stores']);
141
 
142
- $filename = $this->tmpDirectory.sprintf($exportModel::FILENAME_XML, $owner, $type, $context['lang']);
 
 
143
  $items = $exportModel->writeXml($context, $filename, $type);
144
  if($items === 0) {
145
  $this->log('No items to export');
@@ -171,7 +177,7 @@ class MDN_Antidot_Model_Observer extends Mage_Core_Model_Abstract
171
  if(!empty($files)) {
172
  $this->log('Compress files');
173
  $filenameZip = $type === self::GENERATE_INC ? $exportModel::FILENAME_ZIP_INC : $exportModel::FILENAME_ZIP;
174
- $filenameZip = sprintf($filenameZip, date('YmdHis'), $owner);
175
  $filename = $this->compress($files, $filenameZip);
176
  $log['reference'] = md5($filename);
177
  $this->send($filename);
@@ -200,7 +206,7 @@ class MDN_Antidot_Model_Observer extends Mage_Core_Model_Abstract
200
  }
201
 
202
  $log['end'] = time();
203
- $this->log('generate '.$exportModel::TYPE.' '.$context['owner']);
204
  $this->log('end');
205
 
206
  Mage::helper('Antidot/logExport')->add($log['reference'], $type, $exportModel::TYPE, $log['begin'], $log['end'], $log['items'], $log['status'], implode(',', $log['error']));
@@ -335,49 +341,38 @@ class MDN_Antidot_Model_Observer extends Mage_Core_Model_Abstract
335
 
336
  /**
337
  * Return the context default values
338
- *
339
- * @todo retrieve these data from the db
340
  * @return array
341
  */
342
  private function getDefaultContext($runContext)
343
  {
344
- $listStore = array();
 
345
  foreach (Mage::app()->getStores() as $store) {
346
  if ($store->getIsActive()) {
347
  list($lang) = explode('_', Mage::getStoreConfig('general/locale/code', $store->getId()));
348
- $listStore[$lang][$store->getId()] = $store;
 
 
 
 
 
 
 
349
  }
350
  }
351
- $owner = 'AFS@Store for Magento v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version;
352
- if (Mage::getStoreConfig('antidot/general/owner')) {
353
- $owner = Mage::getStoreConfig('antidot/general/owner');
354
  }
355
 
356
- $listContext = array();
357
- foreach($listStore as $lang => $stores) {
358
- $context['website_ids'] = array();
359
- $context['owner'] = $owner;
360
- $context['run'] = $runContext;
361
- $context['lang'] = $lang;
362
- $context['stores'] = $stores;
363
- foreach ($stores as $store) {
364
- $websiteId = $store->getWebsite()->getId();
365
- if (!in_array($websiteId, $context['website_ids'])) {
366
- $context['website_ids'][] = $websiteId;
367
- }
368
- }
369
- $context['langs'] = count($listStore);
370
-
371
- $listContext[] = $context;
372
- }
373
-
374
  return $listContext;
 
375
  }
376
 
377
  /**
378
  * Write message to log
379
  *
380
- * @param string $action
381
  */
382
  private function log($action)
383
  {
92
  /**
93
  * Generate the full catalog file
94
  */
95
+ public function catalogFullExport($runContext)
96
  {
97
  $this->log('FULL EXPORT');
98
  return $this->generate(Mage::getModel('Antidot/export_product'), self::GENERATE_FULL, $runContext);
101
  /**
102
  * Generate the inc catalog file
103
  */
104
+ public function catalogIncExport($runContext)
105
  {
106
  return $this->generate(Mage::getModel('Antidot/export_product'), self::GENERATE_INC, $runContext);
107
  }
109
  /**
110
  * Generate the category file
111
  */
112
+ public function categoriesFullExport($runContext)
113
  {
114
  return $this->generate(Mage::getModel('Antidot/export_category'), self::GENERATE_FULL, $runContext);
115
  }
123
  */
124
  protected function generate($exportModel, $type, $runContext)
125
  {
126
+ if ($runContext instanceof Mage_Cron_Model_Schedule) {
127
+ $runContext = 'cron';
128
+ }
129
+
130
+ Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
131
+
132
  $this->type = $exportModel::TYPE;
133
  $this->log('start');
134
  $log['begin'] = time();
138
 
139
  try
140
  {
141
+ $owner = Mage::getStoreConfig('antidot/general/owner', Mage_Core_Model_App::ADMIN_STORE_ID);
142
+ $ownerForFilename = $this->getOwnerForFilename($owner);
143
  $files = array();
144
  foreach($this->getDefaultContext($runContext) as $context) {
 
 
145
 
146
+ $this->log('generate '.$exportModel::TYPE.' '.$exportModel->getOwner());
147
+
148
+ $filename = $this->tmpDirectory.sprintf($exportModel::FILENAME_XML, $ownerForFilename, $type, $context->getLang());
149
  $items = $exportModel->writeXml($context, $filename, $type);
150
  if($items === 0) {
151
  $this->log('No items to export');
177
  if(!empty($files)) {
178
  $this->log('Compress files');
179
  $filenameZip = $type === self::GENERATE_INC ? $exportModel::FILENAME_ZIP_INC : $exportModel::FILENAME_ZIP;
180
+ $filenameZip = sprintf($filenameZip, date('YmdHis'), $ownerForFilename);
181
  $filename = $this->compress($files, $filenameZip);
182
  $log['reference'] = md5($filename);
183
  $this->send($filename);
206
  }
207
 
208
  $log['end'] = time();
209
+ $this->log('generate '.$exportModel::TYPE.' '.$exportModel->getOwner());
210
  $this->log('end');
211
 
212
  Mage::helper('Antidot/logExport')->add($log['reference'], $type, $exportModel::TYPE, $log['begin'], $log['end'], $log['items'], $log['status'], implode(',', $log['error']));
341
 
342
  /**
343
  * Return the context default values
344
+ *
 
345
  * @return array
346
  */
347
  private function getDefaultContext($runContext)
348
  {
349
+
350
+ $listContext = array();
351
  foreach (Mage::app()->getStores() as $store) {
352
  if ($store->getIsActive()) {
353
  list($lang) = explode('_', Mage::getStoreConfig('general/locale/code', $store->getId()));
354
+ /* @var $context \MDN_Antidot_Model_Export_Context */
355
+ if (isset($listContext[$lang])) {
356
+ $context = $listContext[$lang];
357
+ } else {
358
+ $context = Mage::getModel('Antidot/export_context', array($lang, $runContext));
359
+ $listContext[$lang] = $context;
360
+ }
361
+ $context->addStore($store);
362
  }
363
  }
364
+ foreach ($listContext as $context) {
365
+ $context->initCategoryTree();
 
366
  }
367
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  return $listContext;
369
+
370
  }
371
 
372
  /**
373
  * Write message to log
374
  *
375
+ * @param string $actiong
376
  */
377
  private function log($action)
378
  {
app/code/community/MDN/Antidot/Model/Resource/Advanced.php CHANGED
@@ -13,7 +13,8 @@
13
  * @author : Antidot devmagento@antidot.net
14
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
  */
16
- class MDN_Antidot_Model_Resource_Advanced extends Mage_CatalogSearch_Model_Resource_Advanced
 
17
  {
18
 
19
  }
13
  * @author : Antidot devmagento@antidot.net
14
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
  */
16
+ class MDN_Antidot_Model_Resource_Advanced extends Mage_CatalogSearch_Model_Mysql4_Advanced
17
+ // instead of Mage_CatalogSearch_Model_Resource_Advanced for compatibility with magento < 1.6
18
  {
19
 
20
  }
app/code/community/MDN/Antidot/Model/Resource/Catalog/Product/Collection.php CHANGED
@@ -34,6 +34,11 @@ class MDN_Antidot_Model_Resource_Catalog_Product_Collection extends Mage_Catalog
34
  */
35
  protected $_categoryIds = false;
36
 
 
 
 
 
 
37
  /**
38
  * @var array Facets conditions.
39
  */
@@ -210,6 +215,16 @@ class MDN_Antidot_Model_Resource_Catalog_Product_Collection extends Mage_Catalog
210
  return $this->_categoryIds;
211
  }
212
 
 
 
 
 
 
 
 
 
 
 
213
  /**
214
  * Returns collection size
215
  *
@@ -310,6 +325,7 @@ class MDN_Antidot_Model_Resource_Catalog_Product_Collection extends Mage_Catalog
310
  $this->_facetedData = isset($this->queryResult['faceted_data']) ? $this->queryResult['faceted_data'] : array();
311
  $this->_searchedEntityIds = isset($this->queryResult['ids']) ? $this->queryResult['ids'] : array();
312
  $this->_categoryIds = isset($this->queryResult['category_ids']) ? $this->queryResult['category_ids'] : array();
 
313
  }
314
  }
315
 
@@ -346,8 +362,11 @@ class MDN_Antidot_Model_Resource_Catalog_Product_Collection extends Mage_Catalog
346
 
347
  return $this->_params;
348
  }
349
-
350
  /**
 
 
 
351
  * Load entities records into items
352
  *
353
  * @throws Exception
@@ -355,10 +374,27 @@ class MDN_Antidot_Model_Resource_Catalog_Product_Collection extends Mage_Catalog
355
  */
356
  public function _loadEntities($printQuery = false, $logQuery = false)
357
  {
 
 
 
 
 
 
358
  $this->printLogQuery($printQuery, $logQuery);
 
359
  try {
360
- $query = $this->_prepareSelect($this->getSelect());
 
 
 
 
 
 
 
 
 
361
  $query = str_replace('INNER JOIN `catalog_category_product_index`', 'LEFT JOIN `catalog_category_product_index`', $query);
 
362
  $rows = $this->_fetchAll($query);
363
  } catch (Exception $e) {
364
  Mage::printException($e, $query);
@@ -367,7 +403,8 @@ class MDN_Antidot_Model_Resource_Catalog_Product_Collection extends Mage_Catalog
367
  }
368
 
369
  foreach ($rows as $v) {
370
- $object = $this->getNewEmptyItem()->setData($v);
 
371
  $this->addItem($object);
372
  if (isset($this->_itemsById[$object->getId()])) {
373
  $this->_itemsById[$object->getId()][] = $object;
34
  */
35
  protected $_categoryIds = false;
36
 
37
+ /**
38
+ * @var array banners
39
+ */
40
+ protected $_banners = false;
41
+
42
  /**
43
  * @var array Facets conditions.
44
  */
215
  return $this->_categoryIds;
216
  }
217
 
218
+ /**
219
+ * Returh the banners
220
+ *
221
+ * @return array
222
+ */
223
+ public function getBanners()
224
+ {
225
+ return $this->_banners;
226
+ }
227
+
228
  /**
229
  * Returns collection size
230
  *
325
  $this->_facetedData = isset($this->queryResult['faceted_data']) ? $this->queryResult['faceted_data'] : array();
326
  $this->_searchedEntityIds = isset($this->queryResult['ids']) ? $this->queryResult['ids'] : array();
327
  $this->_categoryIds = isset($this->queryResult['category_ids']) ? $this->queryResult['category_ids'] : array();
328
+ $this->_banners = isset($this->queryResult['banners']) ? $this->queryResult['banners'] : array();
329
  }
330
  }
331
 
362
 
363
  return $this->_params;
364
  }
365
+
366
  /**
367
+ *
368
+ * Override Mage_Eav_Model_Entity_Collection_Abstract#_loadEntities
369
+ *
370
  * Load entities records into items
371
  *
372
  * @throws Exception
374
  */
375
  public function _loadEntities($printQuery = false, $logQuery = false)
376
  {
377
+
378
+ //ANTIDOT : don't paginate
379
+ //if ($this->_pageSize) {
380
+ // $this->getSelect()->limitPage($this->getCurPage(), $this->_pageSize);
381
+ //}
382
+
383
  $this->printLogQuery($printQuery, $logQuery);
384
+
385
  try {
386
+ /**
387
+ * Prepare select query
388
+ * @var string $query
389
+ */
390
+ // ANTIDOT
391
+ if (method_exists($this, '_prepareSelect')) { //This method only exist after magento 1.5
392
+ $query = $this->_prepareSelect($this->getSelect());
393
+ } else {
394
+ $query = (string)$this->getSelect();
395
+ }
396
  $query = str_replace('INNER JOIN `catalog_category_product_index`', 'LEFT JOIN `catalog_category_product_index`', $query);
397
+ // FIN ANTIDOT
398
  $rows = $this->_fetchAll($query);
399
  } catch (Exception $e) {
400
  Mage::printException($e, $query);
403
  }
404
 
405
  foreach ($rows as $v) {
406
+ $object = $this->getNewEmptyItem()
407
+ ->setData($v);
408
  $this->addItem($object);
409
  if (isset($this->_itemsById[$object->getId()])) {
410
  $this->_itemsById[$object->getId()][] = $object;
app/code/community/MDN/Antidot/Model/Resource/Engine/Abstract.php CHANGED
@@ -97,12 +97,13 @@ abstract class MDN_Antidot_Model_Resource_Engine_Abstract
97
  $ids[] = $id['id'];
98
  }
99
  }
100
-
101
- $this->_idsByQuery[$paramsHash] = array(
102
  'ids' => $ids,
103
  'total_count' => (isset($resultTmp['total_count'])) ? $resultTmp['total_count'] : null,
104
  'faceted_data' => (isset($resultTmp['facets'])) ? $resultTmp['facets'] : array(),
105
  'category_ids' => (isset($resultTmp['category_ids'])) ? $resultTmp['category_ids'] : array(),
 
106
  );
107
  }
108
 
97
  $ids[] = $id['id'];
98
  }
99
  }
100
+
101
+ $this->_idsByQuery[$paramsHash] = array(
102
  'ids' => $ids,
103
  'total_count' => (isset($resultTmp['total_count'])) ? $resultTmp['total_count'] : null,
104
  'faceted_data' => (isset($resultTmp['facets'])) ? $resultTmp['facets'] : array(),
105
  'category_ids' => (isset($resultTmp['category_ids'])) ? $resultTmp['category_ids'] : array(),
106
+ 'banners' => (isset($resultTmp['banners'])) ? $resultTmp['banners'] : array(),
107
  );
108
  }
109
 
app/code/community/MDN/Antidot/Model/Resource/Engine/Antidot.php CHANGED
@@ -377,6 +377,15 @@ class MDN_Antidot_Model_Resource_Engine_Antidot extends MDN_Antidot_Model_Resour
377
  $result['redirect'] = $redirectUrl;
378
  }
379
  }
 
 
 
 
 
 
 
 
 
380
  }
381
 
382
  if (!$this->addedNote && $result['total_count'] == 0 && isset($resultAntidot->spellcheck)) {
377
  $result['redirect'] = $redirectUrl;
378
  }
379
  }
380
+ $result['banners'] = array();
381
+ foreach ($replies as $promote) {
382
+ if ($promote->get_type() == 'banner') {
383
+ $bannerObject = new Varien_Object();
384
+ $bannerObject->setData('url', $promote->get_url());
385
+ $bannerObject->setData('image', $promote->get_image_url());
386
+ $result['banners'][] = $bannerObject;
387
+ }
388
+ }
389
  }
390
 
391
  if (!$this->addedNote && $result['total_count'] == 0 && isset($resultAntidot->spellcheck)) {
app/code/community/MDN/Antidot/Model/Resource/Export/Product.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Model_Resource_Export_Product extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product
17
+ // instead of Mage_Catalog_Model_Resource_Product for compatibility with magento < 1.6
18
+ {
19
+
20
+ /**
21
+ * Reset firstly loaded attributes
22
+ *
23
+ * @param Varien_Object $object
24
+ * @param integer $entityId
25
+ * @param array|null $attributes
26
+ * @return Mage_Catalog_Model_Resource_Abstract
27
+ */
28
+ public function load($object, $entityId, $attributes = array())
29
+ {
30
+
31
+
32
+ $this->_attributes = array();
33
+
34
+ Varien_Profiler::start('__EXPORT_PRODUCT_LOAD_MODEL__');
35
+ /**
36
+ * Load object base row data
37
+ */
38
+ $select = $this->_getLoadRowSelect($object, $entityId);
39
+ $row = $this->_getReadAdapter()->fetchRow($select);
40
+
41
+ if (is_array($row)) {
42
+ $object->addData($row);
43
+ } else {
44
+ $object->isObjectNew(true);
45
+ }
46
+
47
+ $attributesIds = array();
48
+ if (empty($attributes)) {
49
+ $this->loadAllAttributes($object);
50
+ } else {
51
+ foreach ($attributes as $attrCode) {
52
+ $attribute = $this->getAttribute($attrCode);
53
+ $attributesIds[] = $attribute->getId();
54
+ }
55
+ }
56
+
57
+ //ADD : load only attributes needed
58
+ $this->loadModelAttributes($object, $attributesIds);
59
+
60
+ //$object->setOrigData();
61
+ Varien_Profiler::start('__EXPORT_PRODUCT_LOAD_MODEL_AFTER_LOAD__');
62
+
63
+ $this->_afterLoad($object);
64
+ Varien_Profiler::stop('__EXPORT_PRODUCT_LOAD_MODEL_AFTER_LOAD__');
65
+
66
+ Varien_Profiler::stop('__EXPORT_PRODUCT_LOAD_MODEL__');
67
+ return $this;
68
+ }
69
+
70
+ /**
71
+ * Load model attributes data
72
+ *
73
+ * Only attributes passed by parameters
74
+ *
75
+ * @param Mage_Core_Model_Abstract $object
76
+ * @param array $attributesIds
77
+ * @return Mage_Eav_Model_Entity_Abstract
78
+ */
79
+ public function loadModelAttributes($object, $attributesIds = array())
80
+ {
81
+ if (!$object->getId()) {
82
+ return $this;
83
+ }
84
+
85
+ Varien_Profiler::start('__EXPORT_PRODUCT_LOAD_MODEL_ATTRIBUTES__');
86
+
87
+ if (method_exists($this, '_addLoadAttributesSelectFields')) { // magento > 1.5
88
+
89
+ $selects = array();
90
+ foreach (array_keys($this->getAttributesByTable()) as $table) {
91
+ $attribute = current($this->_attributesByTable[$table]);
92
+ $eavType = $attribute->getBackendType();
93
+ $select = $this->_getLoadAttributesSelect($object, $table);
94
+ //ADD : load only needed attributes
95
+ if (count($attributesIds)) {
96
+ $select->where("attr_table.attribute_id IN (?)", $attributesIds);
97
+ }
98
+ //ADD : load only needed attributes
99
+ $selects[$eavType][] = $this->_addLoadAttributesSelectFields($select, $table, $eavType);
100
+ }
101
+ $selectGroups = Mage::getResourceHelper('eav')->getLoadAttributesSelectGroups($selects);
102
+ foreach ($selectGroups as $selects) {
103
+ if (!empty($selects)) {
104
+ $select = $this->_prepareLoadSelect($selects);
105
+ $values = $this->_getReadAdapter()->fetchAll($select);
106
+ foreach ($values as $valueRow) {
107
+ $this->_setAttributeValue($object, $valueRow);
108
+ }
109
+ }
110
+ }
111
+
112
+ } else { // magento 1.5
113
+ $selects = array();
114
+ foreach ($this->getAttributesByTable() as $table => $attributes) {
115
+ $selects[] = $this->_getLoadAttributesSelect($object, $table);
116
+ //ADD : load only needed attributes
117
+ foreach ($selects as $select) {
118
+ if (count($attributesIds)) {
119
+ $select->where("attr_table.attribute_id IN (?)", $attributesIds);
120
+ }
121
+ }
122
+ //ADD : load only needed attributes
123
+ }
124
+ if (!empty($selects)) {
125
+ $select = $this->_prepareLoadSelect($selects);
126
+ $values = $this->_getReadAdapter()->fetchAll($select);
127
+ foreach ($values as $valueRow) {
128
+ $this->_setAttribteValue($object, $valueRow);
129
+ }
130
+ }
131
+ }
132
+
133
+ Varien_Profiler::stop('__EXPORT_PRODUCT_LOAD_MODEL_ATTRIBUTES__');
134
+
135
+ return $this;
136
+ }
137
+
138
+ }
app/code/community/MDN/Antidot/Model/Resource/Export/Product/Collection.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Model_Resource_Export_Product_Collection
17
+ extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
18
+ // instead of Mage_Catalog_Model_Resource_Product_Collection for compatibility with magento <1.6
19
+ {
20
+
21
+ /**
22
+ * Initialize resources :
23
+ * Model object is MDN_Antidot_Model_Export_Model_Product
24
+ * Resource Model Object is MDN_Antidot_Model_Resource_Export_Product
25
+ */
26
+ protected function _construct()
27
+ {
28
+ $this->_init('Antidot/export_model_product', 'Antidot/export_product');
29
+ }
30
+
31
+ /**
32
+ * Processing collection items after loading
33
+ * Adding url rewrites, minimal prices, final prices, tax percents
34
+ *
35
+ * FOR Export : don't add all theses infos
36
+ *
37
+ * @return Mage_Catalog_Model_Resource_Product_Collection
38
+ */
39
+ protected function _afterLoad()
40
+ {
41
+ // if ($this->_addUrlRewrite) {
42
+ // $this->_addUrlRewrite($this->_urlRewriteCategory);
43
+ // }
44
+ //
45
+ // $this->_prepareUrlDataObject();
46
+
47
+ // if (count($this) > 0) {
48
+ // Mage::dispatchEvent('catalog_product_collection_load_after', array('collection' => $this));
49
+ // }
50
+
51
+ // foreach ($this as $product) {
52
+ // if ($product->isRecurring() && $profile = $product->getRecurringProfile()) {
53
+ // $product->setRecurringProfile(unserialize($profile));
54
+ // }
55
+ // }
56
+
57
+ return $this;
58
+ }
59
+ }
app/code/community/MDN/Antidot/Model/Resource/Export/Product/Link/Product/Collection.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Model_Resource_Export_Product_Link_Product_Collection
17
+ extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection
18
+ //instead of Mage_Catalog_Model_Resource_Product_Link_Product_Collection for compatibility with magento < 1.6
19
+ {
20
+
21
+ /**
22
+ * Initialize resources
23
+ *
24
+ * Initialize resources :
25
+ * Model object is MDN_Antidot_Model_Export_Model_Product
26
+ * Resource Model Object is MDN_Antidot_Model_Resource_Export_Product
27
+ *
28
+ */
29
+ protected function _construct()
30
+ {
31
+ $this->_init('Antidot/export_model_product', 'Antidot/export_product');
32
+ }
33
+
34
+ /**
35
+ * Processing collection items after loading
36
+ * Adding url rewrites, minimal prices, final prices, tax percents
37
+ *
38
+ * FOR Export : don't add all theses infos
39
+ *
40
+ * @return Mage_Catalog_Model_Resource_Product_Collection
41
+ */
42
+ protected function _afterLoad()
43
+ {
44
+ // if ($this->_addUrlRewrite) {
45
+ // $this->_addUrlRewrite($this->_urlRewriteCategory);
46
+ // }
47
+ //
48
+ // $this->_prepareUrlDataObject();
49
+
50
+ // if (count($this) > 0) {
51
+ // Mage::dispatchEvent('catalog_product_collection_load_after', array('collection' => $this));
52
+ // }
53
+
54
+ // foreach ($this as $product) {
55
+ // if ($product->isRecurring() && $profile = $product->getRecurringProfile()) {
56
+ // $product->setRecurringProfile(unserialize($profile));
57
+ // }
58
+ // }
59
+
60
+ return $this;
61
+ }
62
+
63
+ /**
64
+ * Join attributes
65
+ *
66
+ * @return Mage_Catalog_Model_Resource_Product_Link_Product_Collection
67
+ */
68
+ public function joinAttributes()
69
+ {
70
+ if (!$this->getLinkModel()) {
71
+ return $this;
72
+ }
73
+ $attributes = $this->getLinkModel()->getAttributes();
74
+
75
+ $attributesByType = array();
76
+ foreach ($attributes as $attribute) {
77
+ /**
78
+ * Don't add qty link attribute because it's already in the request from
79
+ * inventory table
80
+ */
81
+ if ($attribute['code'] != 'qty') {
82
+ $table = $this->getLinkModel()->getAttributeTypeTable($attribute['type']);
83
+ $alias = sprintf('link_attribute_%s_%s', $attribute['code'], $attribute['type']);
84
+
85
+ $joinCondiotion = array(
86
+ "{$alias}.link_id = links.link_id",
87
+ $this->getSelect()->getAdapter()->quoteInto(
88
+ "{$alias}.product_link_attribute_id = ?",
89
+ $attribute['id']
90
+ )
91
+ );
92
+ $this->getSelect()->joinLeft(
93
+ array($alias => $table),
94
+ implode(' AND ', $joinCondiotion),
95
+ array($attribute['code'] => 'value')
96
+ );
97
+ }
98
+ }
99
+
100
+ return $this;
101
+ }
102
+ }
app/code/community/MDN/Antidot/Model/Resource/Export/Product/Type/Configurable/Product/Collection.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+ class MDN_Antidot_Model_Resource_Export_Product_Type_Configurable_Product_Collection
17
+ extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Product_Collection
18
+ // instead of Mage_Catalog_Model_Resource_Product_Type_Configurable_Product_Collection for compatibility with magento < 1.6
19
+ {
20
+
21
+
22
+ /**
23
+ * Assign link table name
24
+ *
25
+ * Initialize resources :
26
+ * Model object is MDN_Antidot_Model_Export_Model_Product
27
+ * Resource Model Object is MDN_Antidot_Model_Resource_Export_Product
28
+ *
29
+ */
30
+ protected function _construct()
31
+ {
32
+ $this->_init('Antidot/export_model_product', 'Antidot/export_product');
33
+ $this->_linkTable = $this->getTable('catalog/product_super_link');
34
+ }
35
+
36
+ /**
37
+ * Processing collection items after loading
38
+ * Adding url rewrites, minimal prices, final prices, tax percents
39
+ *
40
+ * FOR Export : don't add all theses infos
41
+ *
42
+ * @return Mage_Catalog_Model_Resource_Product_Collection
43
+ */
44
+ protected function _afterLoad()
45
+ {
46
+ // if ($this->_addUrlRewrite) {
47
+ // $this->_addUrlRewrite($this->_urlRewriteCategory);
48
+ // }
49
+ //
50
+ // $this->_prepareUrlDataObject();
51
+
52
+ // if (count($this) > 0) {
53
+ // Mage::dispatchEvent('catalog_product_collection_load_after', array('collection' => $this));
54
+ // }
55
+
56
+ // foreach ($this as $product) {
57
+ // if ($product->isRecurring() && $profile = $product->getRecurringProfile()) {
58
+ // $product->setRecurringProfile(unserialize($profile));
59
+ // }
60
+ // }
61
+
62
+ return $this;
63
+ }
64
+ }
app/code/community/MDN/Antidot/Model/Search/Search.php CHANGED
@@ -244,16 +244,8 @@ class MDN_Antidot_Model_Search_Search extends MDN_Antidot_Model_Search_Abstract
244
  }
245
 
246
  $query = $query->add_log('AFS@Store for Magento v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version);
247
-
248
- if (method_exists('Mage','getEdition')) {
249
- $mageEdition = Mage::getEdition();
250
- } else {
251
- if (Mage::helper('core')->isModuleEnabled('Enterprise_Enterprise')) {
252
- $mageEdition = 'Enterprise';
253
- } else {
254
- $mageEdition = 'Community';
255
- }
256
- }
257
  $query = $query->add_log('Magento '.$mageEdition.' '.Mage::getVersion());
258
 
259
  $query = $this->setSelectionFacets($query);
244
  }
245
 
246
  $query = $query->add_log('AFS@Store for Magento v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version);
247
+
248
+ $mageEdition = Mage::helper('Antidot')-> getMagentoEdition();
 
 
 
 
 
 
 
 
249
  $query = $query->add_log('Magento '.$mageEdition.' '.Mage::getVersion());
250
 
251
  $query = $this->setSelectionFacets($query);
app/code/community/MDN/Antidot/Model/System/Config/{Engine.php → Source/Acpengine.php} RENAMED
@@ -13,20 +13,26 @@
13
  * @author : Antidot devmagento@antidot.net
14
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
  */
16
- class MDN_Antidot_Model_System_Config_Engine
 
 
17
  {
18
  /**
19
  * {@inherit}
20
  */
21
  public function toOptionArray()
22
  {
23
- return array(
24
- array(
25
- 'value' => 'Antidot/engine_antidot',
26
- 'label' => Mage::helper('adminhtml')->__('AFS@Store')),
27
- array(
28
- 'value' => 'catalogsearch/fulltext_engine',
29
- 'label' => Mage::helper('adminhtml')->__('Magento'))
30
  );
 
 
 
 
 
 
 
 
31
  }
32
  }
13
  * @author : Antidot devmagento@antidot.net
14
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
  */
16
+
17
+
18
+ class MDN_Antidot_Model_System_Config_Source_Acpengine
19
  {
20
  /**
21
  * {@inherit}
22
  */
23
  public function toOptionArray()
24
  {
25
+ $engines = array(
26
+ 'Antidot/engine_antidot' => Mage::helper('adminhtml')->__('AFS@Store'),
27
+ 'catalogsearch/fulltext_engine' => Mage::helper('adminhtml')->__('Magento'),
 
 
 
 
28
  );
29
+ $options = array();
30
+ foreach ($engines as $k => $v) {
31
+ $options[] = array(
32
+ 'value' => $k,
33
+ 'label' => $v
34
+ );
35
+ }
36
+ return $options;
37
  }
38
  }
app/code/community/MDN/Antidot/Model/System/Config/Source/Engine.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ * @copyright Copyright (c) 2015 Antidot (http://www.antidot.net)
13
+ * @author : Antidot devmagento@antidot.net
14
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
15
+ */
16
+
17
+
18
+ /**
19
+ * MCNX-249 : synchronise dropdownlist between AFSTore config and Catalog Seach config :
20
+ *
21
+ * Enterprise Edition allow to modify catalog/search/engine system config in System > Config > Catalog > Catalog > Catalog Search,
22
+ * like Afsstore module allow to modify catalog/search/engine system config in System > Config > Catalog > AFS@Store
23
+ * (see MDN_Antidot_Model_System_Config_Backend_Engine)
24
+ *
25
+ * Then the sources of the dropdownlist must be identical, otherwise the value can be crushed
26
+ *
27
+ * Community Edition doesn't allow to modify this value, it hasn't source class for that, then we simulate it :
28
+ */
29
+ if ((string)Mage::getConfig()->getModuleConfig('Enterprise_Search')->active != 'true') {
30
+
31
+ class Enterprise_Search_Model_Adminhtml_System_Config_Source_Engine {
32
+ public function toOptionArray()
33
+ {
34
+ $engines = array(
35
+ 'catalogsearch/fulltext_engine' => Mage::helper('adminhtml')->__('Magento'),
36
+ );
37
+ $options = array();
38
+ foreach ($engines as $k => $v) {
39
+ $options[] = array(
40
+ 'value' => $k,
41
+ 'label' => $v
42
+ );
43
+ }
44
+ return $options;
45
+ }
46
+ }
47
+ }
48
+ class MDN_Antidot_Model_System_Config_Source_Engine extends Enterprise_Search_Model_Adminhtml_System_Config_Source_Engine
49
+ {
50
+ /**
51
+ * {@inherit}
52
+ */
53
+ public function toOptionArray()
54
+ {
55
+ $options = array_reverse(parent::toOptionArray());
56
+
57
+ $options[] = array(
58
+ 'value' => 'Antidot/engine_antidot',
59
+ 'label' => Mage::helper('adminhtml')->__('AFS@Store')
60
+ );
61
+
62
+ return array_reverse($options);
63
+ }
64
+ }
app/code/community/MDN/Antidot/Model/Transport/Ftp.php CHANGED
@@ -31,7 +31,7 @@ class MDN_Antidot_Model_Transport_Ftp extends MDN_Antidot_Model_Transport_Abstra
31
  }
32
  }
33
  Mage::log('Send file '.$file, null, 'antidot.log');
34
-
35
  if(!$fHandle = fopen($file, 'r')) {
36
  throw new Exception("Can't read file ".$file);
37
  }
@@ -52,6 +52,7 @@ class MDN_Antidot_Model_Transport_Ftp extends MDN_Antidot_Model_Transport_Abstra
52
  curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
53
  curl_setopt($curl, CURLOPT_INFILE, $fHandle);
54
  curl_setopt($curl, CURLOPT_INFILESIZE, filesize($file));
 
55
  curl_exec($curl);
56
 
57
  $errorNo = curl_errno($curl);
31
  }
32
  }
33
  Mage::log('Send file '.$file, null, 'antidot.log');
34
+
35
  if(!$fHandle = fopen($file, 'r')) {
36
  throw new Exception("Can't read file ".$file);
37
  }
52
  curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
53
  curl_setopt($curl, CURLOPT_INFILE, $fHandle);
54
  curl_setopt($curl, CURLOPT_INFILESIZE, filesize($file));
55
+ curl_setopt($curl, CURLOPT_TIMEOUT, 0);
56
  curl_exec($curl);
57
 
58
  $errorNo = curl_errno($curl);
app/code/community/MDN/Antidot/Test/Model/Export/Abstract.php CHANGED
@@ -31,4 +31,30 @@ class MDN_Antidot_Test_Model_Export_Abstract extends EcomDev_PHPUnit_Test_Case
31
  ini_set('memory_limit', $initialLimit);
32
  }
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
31
  ini_set('memory_limit', $initialLimit);
32
  }
33
 
34
+ /**
35
+ * test correction of url generated by magento when executed from cron script
36
+ * (MCNX-253)
37
+ */
38
+ public function testExactUrl() {
39
+
40
+ $export = Mage::getModel('Antidot/export_product');
41
+
42
+ $url = "http://magento.jmale.local.amg-dev.fr/antidotExport.php/essai-1.html";
43
+ $url = MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export, 'getExactUrl', array($url));
44
+ $this->assertEquals("/index.php/essai-1.html", $url);
45
+
46
+ $url = "http://magento.jmale.local.amg-dev.fr/antidotExportProduct.php/essai-1.html";
47
+ $url = MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export, 'getExactUrl', array($url, false));
48
+ $this->assertEquals("http://magento.jmale.local.amg-dev.fr/index.php/essai-1.html", $url);
49
+
50
+ $url = "http://magento.jmale.local.amg-dev.fr/antidotExportCategory.php/essai-1.html";
51
+ $url = MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export, 'getExactUrl', array($url));
52
+ $this->assertEquals("/index.php/essai-1.html", $url);
53
+
54
+ $url = "http://magento.jmale.local.amg-dev.fr/antidotExportInc.php/essai-1.html";
55
+ $url = MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export, 'getExactUrl', array($url, false));
56
+ $this->assertEquals("http://magento.jmale.local.amg-dev.fr/index.php/essai-1.html", $url);
57
+
58
+
59
+ }
60
  }
app/code/community/MDN/Antidot/Test/Model/Export/Article.php CHANGED
@@ -11,10 +11,12 @@ class MDN_Antidot_Test_Model_Export_Article extends EcomDev_PHPUnit_Test_Case
11
 
12
  $export = Mage::getModel('Antidot/export_article');
13
 
14
- $feed = $export->getFeed(array('run'=>'UI'));
 
 
15
 
16
  $this->assertEquals(
17
- 'article UI v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version,
18
  $feed
19
  );
20
 
11
 
12
  $export = Mage::getModel('Antidot/export_article');
13
 
14
+ $context = Mage::getModel('Antidot/export_context', array('fr', 'phpunit'));
15
+
16
+ $feed = $export->getFeed($context);
17
 
18
  $this->assertEquals(
19
+ 'article phpunit v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version,
20
  $feed
21
  );
22
 
app/code/community/MDN/Antidot/Test/Model/Export/Category.php CHANGED
@@ -16,10 +16,12 @@ class MDN_Antidot_Test_Model_Export_Category extends EcomDev_PHPUnit_Test_Case
16
 
17
  $export = Mage::getModel('Antidot/export_category');
18
 
19
- $feed = $export->getFeed(array('run'=>'UI'));
 
 
20
 
21
  $this->assertEquals(
22
- 'category UI v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version,
23
  $feed
24
  );
25
 
@@ -34,14 +36,10 @@ class MDN_Antidot_Test_Model_Export_Category extends EcomDev_PHPUnit_Test_Case
34
 
35
  $export = Mage::getModel('Antidot/export_category');
36
 
37
- $context = array();
38
- $context['store_id'] = array(2);
39
- $context['website_ids'] = array(2);
40
- $context['stores'] = array(Mage::getModel('core/store')->load(2));
41
- $context['owner'] = 'JETPULP';
42
- $context['run'] = 'phpunit';
43
- $context['lang'] = 'en';
44
- $nbItem = $export->writeXml($context, 'categories-magento_jetpulp_FULL-en.xml', MDN_Antidot_Model_Observer::GENERATE_FULL);
45
 
46
  $this->assertEquals($nbItem, 0);
47
 
16
 
17
  $export = Mage::getModel('Antidot/export_category');
18
 
19
+ $context = Mage::getModel('Antidot/export_context', array('fr', 'phpunit'));
20
+
21
+ $feed = $export->getFeed($context);
22
 
23
  $this->assertEquals(
24
+ 'category phpunit v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version,
25
  $feed
26
  );
27
 
36
 
37
  $export = Mage::getModel('Antidot/export_category');
38
 
39
+ $context = Mage::getModel('Antidot/export_context', array('en', 'phpunit'));
40
+ $context->addStore(Mage::getModel('core/store')->load(2));
41
+
42
+ $nbItem = $export->writeXml($context, 'categories-magento_jetpulp_FULL-en.xml');
 
 
 
 
43
 
44
  $this->assertEquals($nbItem, 0);
45
 
app/code/community/MDN/Antidot/Test/Model/Export/Context.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class MDN_Antidot_Test_Model_Export_Context extends EcomDev_PHPUnit_Test_Case
5
+ {
6
+
7
+ public static function setUpBeforeClass()
8
+ {
9
+
10
+ //avoid errors when session_start is called during the test
11
+ @session_start();
12
+
13
+ }
14
+
15
+ /**
16
+ *
17
+ * Test Context Object construction
18
+ *
19
+ * @loadFixture
20
+ */
21
+ public function testContext() {
22
+
23
+ $lang = 'fr';
24
+ $runtype = 'phpunit';
25
+
26
+ /**
27
+ * Initialize context object with 2 stores 2 websites
28
+ *
29
+ * @var $context MDN_Antidot_Model_Export_Context */
30
+ $context = Mage::getModel('Antidot/export_context', array($lang, $runtype));
31
+
32
+ $this->assertEquals($lang, $context->getLang());
33
+ $this->assertEquals($runtype, $context->getRunType());
34
+
35
+ $store = Mage::getModel('core/store')->load(3);
36
+ $context->addStore($store);
37
+ $storeDiscount = Mage::getModel('core/store')->load(5);
38
+ $context->addStore($storeDiscount);
39
+
40
+ $ws = $context->getWebsiteAndStores();
41
+ $this->assertEquals(2, count($ws));
42
+ foreach($ws as $webstore) {
43
+ $store = $webstore['store'];
44
+ $website = $webstore['website'];
45
+ $this->assertEquals($website->getId(), $store->getWebsite()->getId());
46
+ }
47
+
48
+ $this->assertEquals(array(3,5), $context->getStoreIds());
49
+
50
+ $this->assertEquals(array(3,5), $context->getWebsiteIds());
51
+
52
+ $this->assertEquals(3, $context->getWebSiteByStore(3)->getId());
53
+ $this->assertEquals(5, $context->getWebSiteByStore(5)->getId());
54
+
55
+ /**
56
+ * Initialize context tree, test it exclude non active categories and their childrens
57
+ */
58
+ $context->initCategoryTree();
59
+
60
+ $trees = $context->getCategoryTrees();
61
+
62
+ $this->assertEquals(1, count($trees));
63
+
64
+ $tree = $trees[0];
65
+
66
+ $this->assertEquals(3, $tree->getNodes()->count());
67
+
68
+ /**
69
+ * Add attributes to load, test it restitute correct list
70
+ */
71
+ $context->addAttributeToLoad(array('in_stock_only' => 'nope', 'is_new' => 'attr_new', 'is_best_sale'=> 'attr_best',
72
+ 'is_featured'=> 'attr_featured', 'color' => 'attr_color', 'identifier' => array('sku'),
73
+ 'properties' => array(array('value'=>'attr_facet'))));
74
+
75
+ $attributeForAll = $context->getAttributesToLoad();
76
+ $this->assertEquals(array('attr_new', 'attr_best', 'attr_featured', 'attr_color', 'attr_facet', 'image','thumbnail',), $attributeForAll);
77
+
78
+ $attributeForStore = $context->getAttributesToLoad(true);
79
+ $this->assertEquals(array('attr_new', 'attr_best', 'attr_featured', 'image','thumbnail'), $attributeForStore);
80
+
81
+ }
82
+
83
+ }
app/code/community/MDN/Antidot/Test/Model/Export/Context/fixtures/testContext.yaml ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ scope:
2
+ website: # Initialize websites
3
+ - website_id: 2
4
+ code: usa_website
5
+ name: USA Website
6
+ default_group_id: 2
7
+ - website_id: 3
8
+ code: french_website
9
+ name: French Website
10
+ default_group_id: 3
11
+ - website_id: 4
12
+ code: german_website
13
+ name: German Website
14
+ default_group_id: 4
15
+ - website_id: 5
16
+ code: french_website_discount
17
+ name: France Website_discount
18
+ default_group_id: 5
19
+ group: # Initializes store groups
20
+ - group_id: 2
21
+ website_id: 2
22
+ name: USA Store Group
23
+ default_store_id: 2
24
+ root_category_id: 2 # Default Category
25
+ - group_id: 3
26
+ website_id: 3
27
+ name: French Store Group
28
+ default_store_id: 3
29
+ root_category_id: 2 # Default Category
30
+ - group_id: 4
31
+ website_id: 4
32
+ name: German Store Group
33
+ default_store_id: 4
34
+ root_category_id: 2 # Default Category
35
+ - group_id: 5
36
+ website_id: 5
37
+ name: French Store Group Discount
38
+ default_store_id: 5
39
+ root_category_id: 2 # Default Category
40
+ store: # Initializes store views
41
+ - store_id: 2
42
+ website_id: 2
43
+ group_id: 2
44
+ code: usa
45
+ name: USA Store
46
+ is_active: 1
47
+ - store_id: 3
48
+ website_id: 3
49
+ group_id: 3
50
+ code: france
51
+ name: France Store
52
+ is_active: 1
53
+ - store_id: 4
54
+ website_id: 4
55
+ group_id: 4
56
+ code: germany
57
+ name: Germany Store
58
+ is_active: 1
59
+ - store_id: 5
60
+ website_id: 5
61
+ group_id: 5
62
+ code: france_discount
63
+ name: France Store Discount
64
+ is_active: 1
65
+
66
+ config:
67
+ default/antidot/general/owner: JETPULP
68
+ default/web/secure/base_url: http://www.mywebsite.com/
69
+ default/web/unsecure/base_url: http://www.mywebsite.com/
70
+ default/general/locale/code: zz_ZZ
71
+ stores/usa/web/secure/base_url: http://www.mywebsite.com/
72
+ stores/usa/web/unsecure/base_url: http://www.mywebsite.com/
73
+ stores/usa/general/locale/code: en_US
74
+ stores/france/web/secure/base_url: http://www.monsiteweb.fr/
75
+ stores/france/web/unsecure/base_url: http://www.monsiteweb.fr/
76
+ stores/france/general/locale/code: fr_FR
77
+ stores/germany/web/secure/base_url: http://www.meinwebseite.de/
78
+ stores/germany/web/unsecure/base_url: http://www.meinwebseite.de/
79
+ stores/germany/general/locale/code: de_DE
80
+ stores/france_discount/web/secure/base_url: http://www.monsitediscount.fr/
81
+ stores/france_discount/web/unsecure/base_url: http://www.monsitediscount.fr/
82
+ stores/france_discount/general/locale/code: fr_FR
83
+ stores/france/currency/options/default: EUR
84
+
85
+ eav:
86
+ catalog_category:
87
+ - entity_id: 2
88
+ parent_id: 1
89
+ path: 1/2
90
+ name: Root
91
+ is_active: 1
92
+ level: 0
93
+ - entity_id: 3
94
+ parent_id: 2
95
+ path: 1/2/3
96
+ name: Level 1 Actif
97
+ is_active: 1
98
+ level: 1
99
+ - entity_id: 4
100
+ parent_id: 3
101
+ path: 1/2/3/4
102
+ name: Level 2 Actif
103
+ level: 2
104
+ is_active: 1
105
+ - entity_id: 5
106
+ parent_id: 4
107
+ path: 1/2/3/4/5
108
+ name: Level 3 Actif
109
+ is_active: 1
110
+ level: 3
111
+ - entity_id: 6
112
+ parent_id: 4
113
+ path: 1/2/3/4/6
114
+ name: Level 3 Inactif
115
+ is_active: 0
116
+ level: 3
117
+ - entity_id: 7
118
+ parent_id: 3
119
+ path: 1/2/3/7
120
+ name: Level 2 Inactif
121
+ is_active: 0
122
+ level: 2
123
+ - entity_id: 8
124
+ parent_id: 3
125
+ path: 1/2/3/7/8
126
+ name: Level 3 actif mais au sein d'une catégorie inactive
127
+ is_active: 1
128
+ level: 3
129
+
app/code/community/MDN/Antidot/Test/Model/Export/Product.php CHANGED
@@ -206,10 +206,12 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
206
  /** @var $export MDN_Antidot_Model_Export_Product */
207
  $export = Mage::getModel('Antidot/export_product');
208
 
209
- $feed = $export->getFeed(array('run'=>'UI'));
 
 
210
 
211
  $this->assertEquals(
212
- 'catalog UI v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version,
213
  $feed
214
  );
215
 
@@ -223,9 +225,9 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
223
 
224
  $export = Mage::getModel('Antidot/export_product');
225
 
226
- $context = array();
227
- $context['store_id'] = array(1);
228
- $context['website_ids'] = array(1);
229
  $nbItem = $export->writeXml($context, 'catalog-magento_jetpulp_FULL-en.xml', MDN_Antidot_Model_Observer::GENERATE_INC);
230
 
231
  $this->assertEquals(0, $nbItem);
@@ -256,6 +258,37 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
256
 
257
  }
258
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  /**
260
  * MCNX-30 test the properties tag generation
261
  * @test
@@ -478,7 +511,7 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
478
  $storeId = 3;
479
  $store = Mage::getModel('core/store')->load($storeId);
480
  $product = $this->loadProduct(1, $storeId);
481
- $context = array('currency'=>'EUR', 'country'=>'FR');
482
 
483
  MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'initXml', array('product'));
484
  /* @var $export \MDN_Antidot_Helper_Xml_Writer */
@@ -487,17 +520,18 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
487
 
488
  /*
489
  * The writePrices is called without fixed tax price activated
490
- * expected data also in dataProvider
491
  */
492
- MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'writePrices', array($product, $product, $context, $store));
493
 
494
- $expected='<prices><price currency="EUR" type="PRICE_FINAL" vat_included="true" country="FR">12.99</price></prices>';
495
- $this->assertEquals($expected, $xmlWriter->getXml());
 
 
 
496
  $xmlWriter->flush();
497
 
498
  /*
499
- * The writePrices is called witout fixed tax price activated
500
- * expected data also in dataProvider
501
  */
502
  $mockHelper = $this->getHelperMock('weee', array('isEnabled', 'getAmount', 'getPriceDisplayType'));
503
  $mockHelper->expects($this->any())
@@ -511,66 +545,33 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
511
  ->will($this->returnValue(3)); //Set a fixed tax price of 3 EUR in the mock helper
512
  $this->replaceByMock('helper', 'weee', $mockHelper);
513
 
514
- /*
515
- * The writePrices is called with fixed tax price activated
516
- * expected data also in dataProvider
517
- */
518
- MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'writePrices', array($product, $product, $context, $store));
519
 
520
- $expected='<prices><price currency="EUR" type="PRICE_FINAL" vat_included="true" country="FR">15.99</price></prices>';
521
- $this->assertEquals($expected, $xmlWriter->getXml());
522
  $xmlWriter->flush();
523
 
 
 
 
524
  $mockHelper = $this->getHelperMock('weee', array('isEnabled', 'getAmount', 'getPriceDisplayType'));
525
  $mockHelper->expects($this->any())
526
  ->method('isEnabled')
527
  ->will($this->returnValue(true)); //activate fixed tax in the mock helper
528
  $mockHelper->expects($this->any())
529
  ->method('getPriceDisplayType')
530
- ->will($this->returnValue(3)); //activate display included fixed tax in the mock helper
531
  $mockHelper->expects($this->any())
532
  ->method('getAmount')
533
  ->will($this->returnValue(3)); //Set a fixed tax price of 3 EUR in the mock helper
534
  $this->replaceByMock('helper', 'weee', $mockHelper);
535
 
536
 
537
- MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'writePrices', array($product, $product, $context, $store));
538
-
539
- $expected='<prices><price currency="EUR" type="PRICE_FINAL" vat_included="true" country="FR">12.99</price></prices>';
540
- $this->assertEquals($expected, $xmlWriter->getXml());
541
 
542
- }
543
-
544
- /**
545
- * MCNX-236 : test getProductCategories
546
- * @loadFixture
547
- */
548
- public function testGetProductCategories()
549
- {
550
-
551
- /* @var $export \MDN_Antidot_Model_Export_Product */
552
- $export = Mage::getModel('Antidot/export_product');
553
-
554
- /**
555
- * create mock product to simulate getCategoryCollection returning list of the two categories of the product
556
- * because fixture doesn't simulate it...
557
- */
558
- $mockModel = $this->getModelMock('catalog/product', array('getCategoryCollection', 'getStoreId'));
559
- $mockModel->expects($this->any())
560
- ->method('getCategoryCollection')
561
- ->will($this->returnValue(Mage::getResourceModel('catalog/category_collection')->addAttributeToFilter('entity_id', array(10,11))));
562
- $mockModel->expects($this->any())
563
- ->method('getStoreId')
564
- ->will($this->returnValue(3));
565
-
566
- /**
567
- * Categories 10 and 11 are affected to the product in fixtures
568
- * Category 11 is not active.
569
- * We expect one category associated to the product
570
- */
571
- $categories = MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'getProductCategories', array($mockModel, array(2)));
572
-
573
- $this->assertEquals(1, count($categories));
574
 
575
  }
576
 
@@ -589,25 +590,15 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
589
  $xmlWriter = MDN_Antidot_Test_PHPUnitUtil::getPrivateProperty($export, 'xml');
590
  $xmlWriter->flush();
591
 
592
- /**
593
- * create mock product to simulate getCategoryCollection returning the category of the product
594
- * because fixture doesn't simulate it... :
595
- * product is linked to category id=11 active, parent_id=10 is inactive
596
- */
597
- $mockModel = $this->getModelMock('catalog/product', array('getCategoryCollection'));
598
- $mockModel->expects($this->any())
599
- ->method('getCategoryCollection')
600
- ->will($this->returnValue(Mage::getResourceModel('catalog/category_collection')->addAttributeToFilter('entity_id', array(11))));
601
 
602
- MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'writeClassification', array($mockModel, array(2)));
603
 
604
  $this->assertEquals("", $xmlWriter->getXml());
605
 
606
 
607
  }
608
-
609
-
610
-
611
  /**
612
  *
613
  * @param $productId
@@ -617,24 +608,34 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
617
  */
618
  private function loadProduct($productId, $storeId, $forceAvailabilityIndexing = false) {
619
 
620
- $product = Mage::getModel('catalog/product');
 
 
 
 
 
 
 
621
  if ($storeId) {
 
622
  $product->setStoreId($storeId);
623
  }
624
- $product->load($productId);
625
-
626
- if ($forceAvailabilityIndexing){
627
- /**
628
- * HACK EcomDev : There's obviously a bug in the EcomDev Module with magento Enterprise 1.13 and 1.14
629
- * (https://github.com/EcomDev/EcomDev_PHPUnit/issues/253 )
630
- * The product fixture is not well indexed
631
- * We force the stock reindexation by loading/update/saving the product
632
- */
633
- if (Mage::helper('core')->isModuleEnabled('Enterprise_Catalog')) {
634
- $stockItem = $product->getStockItem()->setQty(100)->save();
635
- }
636
  }
637
 
 
 
 
 
 
 
 
 
 
 
 
 
638
  /**
639
  * HACK EcomDev : with the product fixture, there's no data in core_url_rewrite, set request_path
640
  * here in order to have rewrited URLs
@@ -660,27 +661,15 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
660
 
661
  /* @var $export \MDN_Antidot_Model_Export_Product */
662
  $export = Mage::getModel('Antidot/export_product');
663
-
664
- $context = array();
665
- $context['owner'] = 'JETPULP';
666
- $context['run'] = 'PHPUNIT';
667
- $context['lang'] = 'fr';
668
 
669
- $context['stores'] = array();
670
- $context['website_ids'] = array();
671
  //Store id 3 : site FR, id5 : site FR discount
672
- $storeIds = array(3, 5);
673
- foreach ($storeIds as $storeId) {
674
- $store = Mage::getModel('core/store')->load($storeId);
675
- $context['stores'][$storeId] = $store;
676
- $context['website_ids'][] = $store->getWebsite()->getId();
677
- }
678
- $context['store_id'] = array_keys($context['stores']);
679
- $context['langs'] = 1;
680
-
681
  $type = MDN_Antidot_Model_Observer::GENERATE_FULL;
682
 
683
- $filename = sys_get_temp_dir().DS.sprintf(MDN_Antidot_Model_Export_Product::FILENAME_XML, 'jetpulp', $type, $context['lang']);
684
 
685
  $items = $export->writeXml($context, $filename, $type);
686
 
@@ -703,76 +692,89 @@ class MDN_Antidot_Test_Model_Export_Product extends EcomDev_PHPUnit_Test_Case
703
  // $valid = $xml->schemaValidate(MDN_Antidot_Model_Export_Product::XSD);
704
  // $this->assertTrue($valid);
705
 
 
706
  /**
707
  * test the xml contains the correct owner tag
708
  */
709
- $this->assertContains('<owner>JETPULP</owner>', $result);
 
710
 
711
  /**
712
  * test the xml contains the correct feed tag
713
  */
714
- $this->assertContains('<feed>catalog PHPUNIT v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version.'</feed>', $result);
715
 
716
  /**
717
  * test the xml contains the correct websites tag
718
  */
719
- $this->assertContains('<websites><website id="3">French Website</website><website id="5">France Website_discount</website></websites>', $result);
 
 
 
720
 
721
  /**
722
  * test the xml contains the correct name tag
723
  */
724
- $this->assertContains('<name><![CDATA[Book]]></name>', $result);
725
 
726
  /**
727
  * test the xml contains the variants variant fake tag
728
  */
729
- $this->assertContains('<variants><variant id="fake">', $result);
730
 
731
  /**
732
  * test the xml contains the correct descriptions tag
733
  */
734
- $this->assertContains('<descriptions><description type="short_description"><![CDATA[Book]]></description></descriptions>', $result);
735
 
736
  /**
737
  * test the xml contains the correct store tags
738
  */
739
- $this->assertContains('<store id="3" name="France Store">', $result);
740
- $this->assertContains('<store id="5" name="France Store Discount">', $result);
 
 
741
 
742
  /**
743
  * test the xml contains the price tag
744
  */
745
- $this->assertContains('<prices><price currency="USD" type="PRICE_FINAL" vat_included="true" country="FR">12.99</price></prices>', $result);
 
 
 
746
 
747
  /**
748
- * test the xml contains the price tag
749
  */
750
- $this->assertContains('<marketing><is_new>0</is_new><is_best_sale>0</is_best_sale><is_featured>0</is_featured><is_promotional>0</is_promotional></marketing>', $result);
 
 
 
751
 
752
  /**
753
  * test the xml contains the stock tags
754
  */
755
- $this->assertContains('<stock>100</stock>', $result);
756
-
757
 
758
  /**
759
  * test the xml contains the correct url tags
760
  */
761
- $this->assertContains('<url><![CDATA[http://www.monsiteweb.fr/catalog/product/view/id/1/s/book/]]></url>', $result);
762
- $this->assertContains('<url><![CDATA[http://www.monsitediscount.fr/catalog/product/view/id/1/s/book/]]></url>', $result);
763
 
764
  /**
765
  * test the xml contains the correct images url tags
766
  */
767
- $this->assertContains('<url_thumbnail><![CDATA[http://www.monsiteweb.fr/media/catalog/product/b/o/book_small.jpg]]></url_thumbnail>', $result);
768
- $this->assertContains('<url_image><![CDATA[http://www.monsiteweb.fr/media/catalog/product/b/o/book.jpg]]>', $result);
769
- $this->assertContains('<url_thumbnail><![CDATA[http://www.monsitediscount.fr/media/catalog/product/b/o/book_small.jpg]]></url_thumbnail>', $result);
770
- $this->assertContains('<url_image><![CDATA[http://www.monsitediscount.fr/media/catalog/product/b/o/book.jpg]]>', $result);
771
 
772
  /**
773
  * test the xml contains the identifier
774
  */
775
- $this->assertContains('<identifiers><identifier type="sku"><![CDATA[book]]></identifier></identifiers>', $result);
 
776
 
777
 
778
 
206
  /** @var $export MDN_Antidot_Model_Export_Product */
207
  $export = Mage::getModel('Antidot/export_product');
208
 
209
+ $context = Mage::getModel('Antidot/export_context', array('fr', 'phpunit'));
210
+
211
+ $feed = $export->getFeed($context);
212
 
213
  $this->assertEquals(
214
+ 'catalog phpunit v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version,
215
  $feed
216
  );
217
 
225
 
226
  $export = Mage::getModel('Antidot/export_product');
227
 
228
+ $context = Mage::getModel('Antidot/export_context', array('en', 'phpunit'));
229
+ $context->addStore(Mage::getModel('core/store')->load(1));
230
+
231
  $nbItem = $export->writeXml($context, 'catalog-magento_jetpulp_FULL-en.xml', MDN_Antidot_Model_Observer::GENERATE_INC);
232
 
233
  $this->assertEquals(0, $nbItem);
258
 
259
  }
260
 
261
+ /**
262
+ * MCNX-51 : limit name length under 255 in order to pass xsd validation
263
+ * @test
264
+ */
265
+ public function testWriteName() {
266
+
267
+ /* @var $export \MDN_Antidot_Model_Export_Product */
268
+ $export = Mage::getModel('Antidot/export_product');
269
+
270
+ MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'initXml', array('product'));
271
+ /* @var $export \MDN_Antidot_Helper_Xml_Writer */
272
+ $xmlWriter = MDN_Antidot_Test_PHPUnitUtil::getPrivateProperty($export, 'xml');
273
+ $xmlWriter->flush();
274
+
275
+ /** @var $mockProduct Mage_Catalog_Model_Product */
276
+ $mockProduct = $this->getModelMock('catalog/product', array('getName'));
277
+ $mockProduct->expects($this->any())
278
+ ->method('getName')
279
+ ->will($this->returnValue("Nom à ralonge qui dépasse les 255 caractères de long , vraiement très très long,"
280
+ ."voir extrèmement long, carrément trop long, quelle idée d'avoir un nom aussi long ?? jamais vu ça un nom "
281
+ ."aussi long , et vous ? mois jamais, ah ça y est on atteint presque les 255 !"));
282
+ $this->replaceByMock('model', 'catalog/product', $mockProduct);
283
+
284
+ MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'writeName', array($mockProduct));
285
+
286
+ $xml = new SimpleXMLElement($xmlWriter->getXml());
287
+ $this->assertTrue( mb_strlen((string)$xml, "UTF-8") <= MDN_Antidot_Model_Export_Product::NAME_MAX_LENGTH);
288
+
289
+
290
+ }
291
+
292
  /**
293
  * MCNX-30 test the properties tag generation
294
  * @test
511
  $storeId = 3;
512
  $store = Mage::getModel('core/store')->load($storeId);
513
  $product = $this->loadProduct(1, $storeId);
514
+ Mage::app()->setCurrentStore($store);
515
 
516
  MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'initXml', array('product'));
517
  /* @var $export \MDN_Antidot_Helper_Xml_Writer */
520
 
521
  /*
522
  * The writePrices is called without fixed tax price activated
 
523
  */
524
+ MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'writePrices', array($product, $product, $store));
525
 
526
+ $xml = new SimpleXMLElement($xmlWriter->getXml());
527
+ $this->assertEquals("EUR", $xml->price[0]['currency']);
528
+ $this->assertEquals("PRICE_FINAL", $xml->price[0]['type']);
529
+ $this->assertEquals("true", $xml->price[0]['vat_included']);
530
+ $this->assertEquals("12.99", $xml->price[0]);
531
  $xmlWriter->flush();
532
 
533
  /*
534
+ * The writePrices is called with fixed tax price activated
 
535
  */
536
  $mockHelper = $this->getHelperMock('weee', array('isEnabled', 'getAmount', 'getPriceDisplayType'));
537
  $mockHelper->expects($this->any())
545
  ->will($this->returnValue(3)); //Set a fixed tax price of 3 EUR in the mock helper
546
  $this->replaceByMock('helper', 'weee', $mockHelper);
547
 
548
+ MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'writePrices', array($product, $product, $store));
 
 
 
 
549
 
550
+ $xml = new SimpleXMLElement($xmlWriter->getXml());
551
+ $this->assertEquals("15.99", $xml->price[0]);
552
  $xmlWriter->flush();
553
 
554
+ /*
555
+ * The writePrices is called with fixed tax price activated
556
+ */
557
  $mockHelper = $this->getHelperMock('weee', array('isEnabled', 'getAmount', 'getPriceDisplayType'));
558
  $mockHelper->expects($this->any())
559
  ->method('isEnabled')
560
  ->will($this->returnValue(true)); //activate fixed tax in the mock helper
561
  $mockHelper->expects($this->any())
562
  ->method('getPriceDisplayType')
563
+ ->will($this->returnValue(3)); //activate display excluded fixed tax in the mock helper
564
  $mockHelper->expects($this->any())
565
  ->method('getAmount')
566
  ->will($this->returnValue(3)); //Set a fixed tax price of 3 EUR in the mock helper
567
  $this->replaceByMock('helper', 'weee', $mockHelper);
568
 
569
 
570
+ MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'writePrices', array($product, $product, $store));
 
 
 
571
 
572
+ $xml = new SimpleXMLElement($xmlWriter->getXml());
573
+ $this->assertEquals("12.99", $xml->price[0]);
574
+ $xmlWriter->flush();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
575
 
576
  }
577
 
590
  $xmlWriter = MDN_Antidot_Test_PHPUnitUtil::getPrivateProperty($export, 'xml');
591
  $xmlWriter->flush();
592
 
593
+ $product = $this->loadProduct(1, 3);
 
 
 
 
 
 
 
 
594
 
595
+ MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($export,'writeClassification', array($product));
596
 
597
  $this->assertEquals("", $xmlWriter->getXml());
598
 
599
 
600
  }
601
+
 
 
602
  /**
603
  *
604
  * @param $productId
608
  */
609
  private function loadProduct($productId, $storeId, $forceAvailabilityIndexing = false) {
610
 
611
+ $context = Mage::getModel('Antidot/export_context', array('fr', 'phpunit'));
612
+ $context->addAttributeToLoad(array('url_key' => 'url_key'));
613
+
614
+ $collection = Mage::getModel('Antidot/export_model_product')
615
+ ->getCollection();
616
+ $collection->addAttributeToFilter('entity_id', $productId);
617
+
618
+ $product = $collection->getFirstItem();
619
  if ($storeId) {
620
+ $context->addStore(Mage::getModel('core/store')->load($storeId));
621
  $product->setStoreId($storeId);
622
  }
623
+ if ($product->setContext($context)) {
624
+ $product->loadNeededAttributes();
 
 
 
 
 
 
 
 
 
 
625
  }
626
 
627
+ // if ($forceAvailabilityIndexing){
628
+ // /**
629
+ // * HACK EcomDev : There's obviously a bug in the EcomDev Module with magento Enterprise 1.13 and 1.14
630
+ // * (https://github.com/EcomDev/EcomDev_PHPUnit/issues/253 )
631
+ // * The product fixture is not well indexed
632
+ // * We force the stock reindexation by loading/update/saving the product
633
+ // */
634
+ // if (Mage::helper('core')->isModuleEnabled('Enterprise_Catalog')) {
635
+ // $stockItem = $product->getStockItem()->setQty(100)->save();
636
+ // }
637
+ // }
638
+
639
  /**
640
  * HACK EcomDev : with the product fixture, there's no data in core_url_rewrite, set request_path
641
  * here in order to have rewrited URLs
661
 
662
  /* @var $export \MDN_Antidot_Model_Export_Product */
663
  $export = Mage::getModel('Antidot/export_product');
 
 
 
 
 
664
 
665
+ $context = Mage::getModel('Antidot/export_context', array('fr', 'PHPUNIT'));
 
666
  //Store id 3 : site FR, id5 : site FR discount
667
+ $context->addStore(Mage::getModel('core/store')->load(3));
668
+ $context->addStore(Mage::getModel('core/store')->load(5));
669
+
 
 
 
 
 
 
670
  $type = MDN_Antidot_Model_Observer::GENERATE_FULL;
671
 
672
+ $filename = sys_get_temp_dir().DS.sprintf(MDN_Antidot_Model_Export_Product::FILENAME_XML, 'jetpulp', $type, $context->getLang());
673
 
674
  $items = $export->writeXml($context, $filename, $type);
675
 
692
  // $valid = $xml->schemaValidate(MDN_Antidot_Model_Export_Product::XSD);
693
  // $this->assertTrue($valid);
694
 
695
+ //echo ($result);
696
  /**
697
  * test the xml contains the correct owner tag
698
  */
699
+ $xml = new SimpleXMLElement($result);
700
+ $this->assertEquals("JETPULP", (string)$xml->header->owner);
701
 
702
  /**
703
  * test the xml contains the correct feed tag
704
  */
705
+ $this->assertEquals('catalog PHPUNIT v'.Mage::getConfig()->getNode()->modules->MDN_Antidot->version, (string)$xml->header->feed);
706
 
707
  /**
708
  * test the xml contains the correct websites tag
709
  */
710
+ $this->assertEquals('3', $xml->product->websites->website[0]['id']);
711
+ $this->assertEquals('French Website', (string)$xml->product->websites->website[0]);
712
+ $this->assertEquals('5', $xml->product->websites->website[1]['id']);
713
+ $this->assertEquals('France Website_discount', (string)$xml->product->websites->website[1]);
714
 
715
  /**
716
  * test the xml contains the correct name tag
717
  */
718
+ $this->assertEquals('Book', (string)$xml->product->name);
719
 
720
  /**
721
  * test the xml contains the variants variant fake tag
722
  */
723
+ $this->assertEquals('fake', $xml->product->variants->variant[0]['id']);
724
 
725
  /**
726
  * test the xml contains the correct descriptions tag
727
  */
728
+ $this->assertEquals('Book', (string)$xml->product->variants->variant[0]->descriptions->description[0]);
729
 
730
  /**
731
  * test the xml contains the correct store tags
732
  */
733
+ $this->assertEquals('3', $xml->product->variants->variant[0]->stores->store[0]['id']);
734
+ $this->assertEquals('France Store', $xml->product->variants->variant[0]->stores->store[0]['name']);
735
+ $this->assertEquals('5', $xml->product->variants->variant[0]->stores->store[1]['id']);
736
+ $this->assertEquals('France Store Discount', $xml->product->variants->variant[0]->stores->store[1]['name']);
737
 
738
  /**
739
  * test the xml contains the price tag
740
  */
741
+ $this->assertEquals('EUR', $xml->product->variants->variant[0]->stores->store[0]->prices->price[0]['currency']);
742
+ $this->assertEquals('PRICE_FINAL', $xml->product->variants->variant[0]->stores->store[0]->prices->price[0]['type']);
743
+ $this->assertEquals('true', $xml->product->variants->variant[0]->stores->store[0]->prices->price[0]['vat_included']);
744
+ $this->assertEquals('12.99', (string)$xml->product->variants->variant[0]->stores->store[0]->prices->price[0]);
745
 
746
  /**
747
+ * test the xml contains the marketing tag
748
  */
749
+ $this->assertEquals('0', $xml->product->variants->variant[0]->stores->store[0]->marketing->is_new);
750
+ $this->assertEquals('0', $xml->product->variants->variant[0]->stores->store[0]->marketing->is_best_sale);
751
+ $this->assertEquals('0', $xml->product->variants->variant[0]->stores->store[0]->marketing->is_featured);
752
+ $this->assertEquals('0', $xml->product->variants->variant[0]->stores->store[0]->marketing->is_promotional);
753
 
754
  /**
755
  * test the xml contains the stock tags
756
  */
757
+ $this->assertEquals('100', $xml->product->variants->variant[0]->stores->store[0]->stock);
 
758
 
759
  /**
760
  * test the xml contains the correct url tags
761
  */
762
+ $this->assertEquals('http://www.monsiteweb.fr/catalog/product/view/id/1/', (string)$xml->product->variants->variant[0]->stores->store[0]->url);
763
+ $this->assertEquals('http://www.monsitediscount.fr/catalog/product/view/id/1/', (string)$xml->product->variants->variant[0]->stores->store[1]->url);
764
 
765
  /**
766
  * test the xml contains the correct images url tags
767
  */
768
+ $this->assertEquals('http://www.monsiteweb.fr/media/catalog/product/b/o/book_small.jpg', (string)$xml->product->variants->variant[0]->stores->store[0]->url_thumbnail);
769
+ $this->assertEquals('http://www.monsiteweb.fr/media/catalog/product/b/o/book.jpg', (string)$xml->product->variants->variant[0]->stores->store[0]->url_image);
770
+ $this->assertEquals('http://www.monsitediscount.fr/media/catalog/product/b/o/book_small.jpg', (string)$xml->product->variants->variant[0]->stores->store[1]->url_thumbnail);
771
+ $this->assertEquals('http://www.monsitediscount.fr/media/catalog/product/b/o/book.jpg', (string)$xml->product->variants->variant[0]->stores->store[1]->url_image);
772
 
773
  /**
774
  * test the xml contains the identifier
775
  */
776
+ $this->assertEquals('sku', $xml->product->variants->variant[0]->identifiers->identifier[0]['type']);
777
+ $this->assertEquals('book', $xml->product->variants->variant[0]->identifiers->identifier[0]);
778
 
779
 
780
 
app/code/community/MDN/Antidot/Test/Model/Export/Product/fixtures/testGetProductCategories.yaml DELETED
@@ -1,101 +0,0 @@
1
- scope:
2
- website: # Initialize websites
3
- - website_id: 2
4
- code: usa_website
5
- name: USA Website
6
- default_group_id: 2
7
- - website_id: 3
8
- code: french_website
9
- name: French Website
10
- default_group_id: 3
11
- - website_id: 4
12
- code: german_website
13
- name: German Website
14
- default_group_id: 4
15
- group: # Initializes store groups
16
- - group_id: 2
17
- website_id: 2
18
- name: USA Store Group
19
- default_store_id: 2
20
- root_category_id: 2 # Default Category
21
- - group_id: 3
22
- website_id: 3
23
- name: French Store Group
24
- default_store_id: 3
25
- root_category_id: 2 # Default Category
26
- - group_id: 4
27
- website_id: 4
28
- name: German Store Group
29
- default_store_id: 4
30
- root_category_id: 2 # Default Category
31
- store: # Initializes store views
32
- - store_id: 2
33
- website_id: 2
34
- group_id: 2
35
- code: usa
36
- name: USA Store
37
- is_active: 1
38
- - store_id: 3
39
- website_id: 3
40
- group_id: 3
41
- code: france
42
- name: France Store
43
- is_active: 1
44
- - store_id: 4
45
- website_id: 4
46
- group_id: 4
47
- code: germany
48
- name: Germany Store
49
- is_active: 1
50
- config:
51
- default/web/secure/base_url: http://www.mywebsite.com/
52
- default/web/unsecure/base_url: http://www.mywebsite.com/
53
- stores/usa/web/secure/base_url: http://www.mywebsite.com/
54
- stores/france/web/secure/base_url: http://www.monsiteweb.fr/
55
- stores/germany/web/secure/base_url: http://www.meinwebseite.de/
56
- stores/usa/web/unsecure/base_url: http://www.mywebsite.com/
57
- stores/france/web/unsecure/base_url: http://www.monsiteweb.fr/
58
- stores/germany/web/unsecure/base_url: http://www.meinwebseite.de/
59
- eav:
60
- catalog_product:
61
- - entity_id: 1
62
- type_id: simple
63
- attribute_set_id: 4 # Default
64
- sku: book
65
- name: Book
66
- short_description: Book
67
- description: Book
68
- url_key: book
69
- image: b/o/book.jpg
70
- thumbnail: b/o/book_small.jpg
71
- stock:
72
- qty: 100.00
73
- is_in_stock: 1
74
- website_ids:
75
- - usa_website
76
- - french_website
77
- - german_website
78
- category_ids:
79
- - 10,11
80
- price: 12.99
81
- tax_class_id: 2 # Taxable Goods
82
- status: 1 # Enabled
83
- visibility: 4 # Visible in Catalog & Search
84
- /websites: # Set different prices per website
85
- usa_website:
86
- special_price: 9.99
87
- german_website:
88
- price: 9.99
89
- special_price: 5.99
90
- eav:
91
- catalog_category:
92
- - entity_id: 10
93
- path: 1/2/10
94
- name: Categorie active
95
- is_active: 1
96
- parent_id: 2
97
- - entity_id: 11
98
- path: 1/2/11
99
- name: Categorie inactive
100
- is_active: 0
101
- parent_id: 2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/MDN/Antidot/Test/Model/Export/Product/fixtures/testWritePricesFixedtax.yaml CHANGED
@@ -56,7 +56,9 @@ config:
56
  stores/germany/web/secure/base_url: http://www.meinwebseite.de/
57
  stores/usa/web/unsecure/base_url: http://www.mywebsite.com/
58
  stores/france/web/unsecure/base_url: http://www.monsiteweb.fr/
59
- stores/germany/web/unsecure/base_url: http://www.meinwebseite.de/
 
 
60
  eav:
61
  catalog_product:
62
  - entity_id: 1
56
  stores/germany/web/secure/base_url: http://www.meinwebseite.de/
57
  stores/usa/web/unsecure/base_url: http://www.mywebsite.com/
58
  stores/france/web/unsecure/base_url: http://www.monsiteweb.fr/
59
+ stores/germany/web/unsecure/base_url: http://www.meinwebseite.de/
60
+ stores/france/currency/options/default: EUR
61
+
62
  eav:
63
  catalog_product:
64
  - entity_id: 1
app/code/community/MDN/Antidot/Test/Model/Export/Product/fixtures/testWriteXml.yaml CHANGED
@@ -64,6 +64,7 @@ scope:
64
  is_active: 1
65
 
66
  config:
 
67
  default/antidot/fields_product/model:
68
  default/antidot/fields_product/gender:
69
  default/antidot/fields_product/properties: a:2:{s:18:"_1426953698813_813";a:2:{s:5:"value";s:7:"authors";s:12:"autocomplete";s:1:"0";}s:18:"_1426953714346_346";a:2:{s:5:"value";s:6:"editor";s:12:"autocomplete";s:1:"0";}}
@@ -82,6 +83,8 @@ config:
82
  stores/france_discount/web/secure/base_url: http://www.monsitediscount.fr/
83
  stores/france_discount/web/unsecure/base_url: http://www.monsitediscount.fr/
84
  stores/france_discount/general/locale/code: fr_FR
 
 
85
  eav:
86
  catalog_product:
87
  - entity_id: 1
64
  is_active: 1
65
 
66
  config:
67
+ default/antidot/general/owner: JETPULP
68
  default/antidot/fields_product/model:
69
  default/antidot/fields_product/gender:
70
  default/antidot/fields_product/properties: a:2:{s:18:"_1426953698813_813";a:2:{s:5:"value";s:7:"authors";s:12:"autocomplete";s:1:"0";}s:18:"_1426953714346_346";a:2:{s:5:"value";s:6:"editor";s:12:"autocomplete";s:1:"0";}}
83
  stores/france_discount/web/secure/base_url: http://www.monsitediscount.fr/
84
  stores/france_discount/web/unsecure/base_url: http://www.monsitediscount.fr/
85
  stores/france_discount/general/locale/code: fr_FR
86
+ stores/france/currency/options/default: EUR
87
+
88
  eav:
89
  catalog_product:
90
  - entity_id: 1
app/code/community/MDN/Antidot/Test/Model/Observer.php CHANGED
@@ -4,6 +4,12 @@
4
  class MDN_Antidot_Test_Model_Observer extends EcomDev_PHPUnit_Test_Case
5
  {
6
 
 
 
 
 
 
 
7
  /**
8
  * MCNX-27 : Test owner for filename generation
9
  *
@@ -86,38 +92,21 @@ class MDN_Antidot_Test_Model_Observer extends EcomDev_PHPUnit_Test_Case
86
 
87
  $listContext= MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($observer, 'getDefaultContext', array('phpunit'));
88
 
89
- $this->assertEquals(
90
- 2,
91
- count($listContext[0]['stores'])
92
- );
93
- unset($listContext[0]['stores']);
94
 
95
- $this->assertEquals(
96
- 1,
97
- count($listContext[1]['stores'])
98
- );
99
- unset($listContext[1]['stores']);
100
-
101
- $expected = array();
102
- $expected[] = array (
103
- 'website_ids' => array ('3', '5'),
104
- 'owner' => 'JETPULP',
105
- 'run' => 'phpunit',
106
- 'lang' => 'fr',
107
- 'langs' => 2
108
- );
109
- $expected[] = array (
110
- 'website_ids' => array ('2'),
111
- 'owner' => 'JETPULP',
112
- 'run' => 'phpunit',
113
- 'lang' => 'en',
114
- 'langs' => 2
115
- );
116
 
117
- $this->assertEquals(
118
- $expected,
119
- $listContext
120
- );
 
 
 
 
 
121
 
122
  }
123
 
4
  class MDN_Antidot_Test_Model_Observer extends EcomDev_PHPUnit_Test_Case
5
  {
6
 
7
+ public static function setUpBeforeClass()
8
+ {
9
+ //avoid errors when session_start is called during the test
10
+ @session_start();
11
+ }
12
+
13
  /**
14
  * MCNX-27 : Test owner for filename generation
15
  *
92
 
93
  $listContext= MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($observer, 'getDefaultContext', array('phpunit'));
94
 
95
+ $this->assertEquals(2, count($listContext));
 
 
 
 
96
 
97
+ if (count($listContext)> 1) {
98
+ $firstContext = $listContext['fr'];
99
+ $secondContext = $listContext['en'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
+ $this->assertEquals(array('3', '5') , $firstContext->getStoreIds());
102
+ $this->assertEquals(array('2') , $secondContext->getStoreIds());
103
+
104
+ $this->assertEquals('phpunit' , $firstContext->getRunType());
105
+
106
+ $this->assertEquals('fr' , $firstContext->getLang());
107
+ $this->assertEquals('en' , $secondContext->getLang());
108
+
109
+ }
110
 
111
  }
112
 
app/code/community/MDN/Antidot/Test/Model/Resource/Engine/Antidot.php CHANGED
@@ -126,6 +126,33 @@ class MDN_Antidot_Test_Model_Resource_Engine_Antidot extends EcomDev_PHPUnit_Tes
126
 
127
  $this->assertEquals('http://antidot.net/redirect', $result['redirect']);
128
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  }
130
 
131
  }
126
 
127
  $this->assertEquals('http://antidot.net/redirect', $result['redirect']);
128
 
129
+ /**
130
+ * 4rd test : Promote of banner type (MCNX-63)
131
+ */
132
+ $mockAFSPromoteBannerHelper = $this->getMockBuilder('AfsPromoteBannerReplyHelper')->disableOriginalConstructor()->getMock(); //AfsPromoteRedirectReplyHelper
133
+ $mockAFSPromoteBannerHelper
134
+ ->method('get_type')
135
+ ->willReturn('banner');
136
+ $mockAFSPromoteBannerHelper
137
+ ->method('get_url')
138
+ ->willReturn('http://antidot.net/banner_target');
139
+ $mockAFSPromoteBannerHelper
140
+ ->method('get_image_url')
141
+ ->willReturn('http://antidot.net/banner.jpg');
142
+
143
+ $mockAFSPromoteReplysetHelper = $this->getMockBuilder('AfsPromoteReplysetHelper')->disableOriginalConstructor()->getMock();//AfsPromoteReplysetHelper
144
+ $mockAFSPromoteReplysetHelper
145
+ ->method('get_replies')
146
+ ->willReturn(array($mockAFSPromoteBannerHelper)); //return array with one standard promote
147
+ $resultAntidot = new stdClass();
148
+ $resultAntidot->promote = $mockAFSPromoteReplysetHelper;
149
+
150
+ $result = MDN_Antidot_Test_PHPUnitUtil::callPrivateMethod($antidotEngine, 'formatResult', array($resultAntidot));
151
+
152
+ $this->assertCount(1, $result['banners']);
153
+ $this->assertEquals('http://antidot.net/banner_target', $result['banners'][0]->getUrl());
154
+ $this->assertEquals('http://antidot.net/banner.jpg', $result['banners'][0]->getImage());
155
+
156
  }
157
 
158
  }
app/code/community/MDN/Antidot/Test/Model/System/Config/Source/Engine.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class MDN_Antidot_Test_Model_System_Config_Source_Engine extends EcomDev_PHPUnit_Test_Case
5
+ {
6
+
7
+
8
+ /**
9
+ * Test toOptionArray method
10
+ *
11
+ * MCNX-249 : synchronise dropdownlist between AFSTore config and Catalog Seach config
12
+ */
13
+ public function testToOptionArray()
14
+ {
15
+
16
+ /** @var $configSort MDN_Antidot_Model_System_Config_Source_Engine */
17
+ $configSourceEngine = Mage::getModel('Antidot/system_config_source_engine');
18
+
19
+ $values = $configSourceEngine->toOptionArray();
20
+
21
+ $mageEdition = Mage::helper('Antidot')-> getMagentoEdition();
22
+ if ($mageEdition == MDN_Antidot_Helper_Data::EDITION_COMMUNITY) {
23
+ $this->assertEquals(
24
+ array(
25
+ array('value' => 'Antidot/engine_antidot', 'label' => Mage::helper('adminhtml')->__('AFS@Store')),
26
+ array('value' => 'catalogsearch/fulltext_engine', 'label' => Mage::helper('adminhtml')->__('Magento')),
27
+ ),
28
+ $values
29
+ );
30
+ } else {
31
+ $this->assertEquals(
32
+ array(
33
+ array('value' => 'Antidot/engine_antidot', 'label' => Mage::helper('adminhtml')->__('AFS@Store')),
34
+ array('value' => 'catalogsearch/fulltext_engine', 'label' => Mage::helper('enterprise_search')->__('MySql Fulltext')),
35
+ array('value' => 'enterprise_search/engine', 'label' => Mage::helper('enterprise_search')->__('Solr')),
36
+ ),
37
+ $values
38
+ );
39
+ }
40
+
41
+ }
42
+
43
+ }
app/code/community/MDN/Antidot/etc/config.xml CHANGED
@@ -18,7 +18,7 @@
18
  </crontab>
19
  <modules>
20
  <MDN_Antidot>
21
- <version>1.1.4</version>
22
  </MDN_Antidot>
23
  </modules>
24
  <global>
@@ -68,6 +68,11 @@
68
  <search>MDN_Antidot_Block_Catalogsearch_Layer</search>
69
  </rewrite>
70
  </mana_filters>
 
 
 
 
 
71
  </blocks>
72
  <models>
73
 
@@ -80,7 +85,12 @@
80
  <class>MDN_Antidot_Model_Resource</class>
81
  <entities></entities>
82
  </Antidot_engine>
83
-
 
 
 
 
 
84
  </models>
85
  <resources>
86
  <Antidot_setup>
@@ -634,6 +644,11 @@
634
  <profiler_varien_quota>0.001</profiler_varien_quota>
635
  <!-- include fixed tax in exported price (somecommercant may have modified magento in order to use it but not include it (ie mooovin) -->
636
  <include_fixed_tax>1</include_fixed_tax>
 
 
 
 
 
637
  </export>
638
  </antidot>
639
  </default>
18
  </crontab>
19
  <modules>
20
  <MDN_Antidot>
21
+ <version>1.2.1</version>
22
  </MDN_Antidot>
23
  </modules>
24
  <global>
68
  <search>MDN_Antidot_Block_Catalogsearch_Layer</search>
69
  </rewrite>
70
  </mana_filters>
71
+ <amshopby>
72
+ <rewrite>
73
+ <search_layer>MDN_Antidot_Block_Catalogsearch_Layer</search_layer>
74
+ </rewrite>
75
+ </amshopby>
76
  </blocks>
77
  <models>
78
 
85
  <class>MDN_Antidot_Model_Resource</class>
86
  <entities></entities>
87
  </Antidot_engine>
88
+
89
+ <enterprise_search>
90
+ <rewrite>
91
+ <adminhtml_system_config_source_engine>MDN_Antidot_Model_System_Config_Source_Engine</adminhtml_system_config_source_engine>
92
+ </rewrite>
93
+ </enterprise_search>
94
  </models>
95
  <resources>
96
  <Antidot_setup>
644
  <profiler_varien_quota>0.001</profiler_varien_quota>
645
  <!-- include fixed tax in exported price (somecommercant may have modified magento in order to use it but not include it (ie mooovin) -->
646
  <include_fixed_tax>1</include_fixed_tax>
647
+ <!-- it will generate xml indentation -->
648
+ <debug_xml_enabled>0</debug_xml_enabled>
649
+ <!-- class model of product type used for export -->
650
+ <product_type_configurable>Antidot/export_model_product_type_configurable</product_type_configurable>
651
+ <product_type_grouped>Antidot/export_model_product_type_grouped</product_type_grouped>
652
  </export>
653
  </antidot>
654
  </default>
app/code/community/MDN/Antidot/etc/system.xml CHANGED
@@ -369,7 +369,7 @@
369
  <enable translate="label">
370
  <label>Enable</label>
371
  <frontend_type>select</frontend_type>
372
- <source_model>Antidot/System_Config_Engine</source_model>
373
  <sort_order>1</sort_order>
374
  <show_in_default>1</show_in_default>
375
  <show_in_website>1</show_in_website>
@@ -516,8 +516,8 @@
516
  <engine translate="label">
517
  <label>Search Engine</label>
518
  <frontend_type>select</frontend_type>
519
- <source_model>Antidot/System_Config_Engine</source_model>
520
- <backend_model>Antidot/System_Config_backend_engine</backend_model>
521
  <sort_order>19</sort_order>
522
  <show_in_default>1</show_in_default>
523
  <show_in_website>1</show_in_website>
@@ -665,5 +665,22 @@
665
  </generation>
666
  </groups>
667
  </antidot>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
668
  </sections>
669
  </config>
369
  <enable translate="label">
370
  <label>Enable</label>
371
  <frontend_type>select</frontend_type>
372
+ <source_model>Antidot/system_config_source_acpengine</source_model>
373
  <sort_order>1</sort_order>
374
  <show_in_default>1</show_in_default>
375
  <show_in_website>1</show_in_website>
516
  <engine translate="label">
517
  <label>Search Engine</label>
518
  <frontend_type>select</frontend_type>
519
+ <source_model>Antidot/system_config_source_engine</source_model>
520
+ <backend_model>Antidot/system_config_backend_engine</backend_model>
521
  <sort_order>19</sort_order>
522
  <show_in_default>1</show_in_default>
523
  <show_in_website>1</show_in_website>
665
  </generation>
666
  </groups>
667
  </antidot>
668
+ <catalog>
669
+ <groups>
670
+ <search>
671
+ <fields>
672
+ <antidot_config_forward translate="label">
673
+ <label>AFS@Store Configuration</label>
674
+ <frontend_model>Antidot/system_config_button_forward</frontend_model>
675
+ <sort_order>101</sort_order>
676
+ <show_in_default>1</show_in_default>
677
+ <show_in_website>0</show_in_website>
678
+ <show_in_store>0</show_in_store>
679
+ <depends><engine>Antidot/engine_antidot</engine></depends>
680
+ </antidot_config_forward>
681
+ </fields>
682
+ </search>
683
+ </groups>
684
+ </catalog>
685
  </sections>
686
  </config>
app/design/frontend/base/default/layout/antidot.xml CHANGED
@@ -5,7 +5,8 @@
5
  <catalogsearch_result_index>
6
  <reference name="search.result">
7
  <action method="setTemplate"><template>antidot/catalogsearch/result.phtml</template></action>
8
- <block type="Antidot/Catalogsearch_Category" name="search_result_category" as="search_result_category" template="antidot/catalogsearch/result/category.phtml" />
 
9
  </reference>
10
 
11
  <!-- MCNX-230 ManaDev module manadev compatibility : don't show positioning right or above_product-->
5
  <catalogsearch_result_index>
6
  <reference name="search.result">
7
  <action method="setTemplate"><template>antidot/catalogsearch/result.phtml</template></action>
8
+ <block type="Antidot/catalogsearch_category" name="search_result_category" as="search_result_category" template="antidot/catalogsearch/result/category.phtml" />
9
+ <block type="Antidot/catalogsearch_banner" name="search_result_banner" as="search_result_banner" template="antidot/catalogsearch/result/banner.phtml" />
10
  </reference>
11
 
12
  <!-- MCNX-230 ManaDev module manadev compatibility : don't show positioning right or above_product-->
app/design/frontend/base/default/template/antidot/catalogsearch/result.phtml CHANGED
@@ -41,13 +41,17 @@
41
  <?php endif; ?>
42
  <?php $productHtml = $this->getProductListHtml(); ?>
43
  <?php if($this->helper('Antidot')->isActiveEngine()): ?>
44
- <?php echo $this->getChildHtml('search_result_category'); ?>
 
45
  <?php endif; ?>
46
  <?php echo $productHtml; ?>
47
  <?php else: ?>
48
  <div class="page-title">
49
  <h1><?php echo ($this->getHeaderText() || $this->getHeaderText() === false) ? $this->getHeaderText() : $this->__("Search results for '%s'", $this->helper('catalogsearch')->getEscapedQueryText()) ?></h1>
50
  </div>
 
 
 
51
  <p class="note-msg">
52
  <?php echo ($this->getNoResultText()) ? $this->getNoResultText() : $this->__('Your search returns no results.') ?>
53
  <?php if ($messages = $this->getNoteMessages()):?>
41
  <?php endif; ?>
42
  <?php $productHtml = $this->getProductListHtml(); ?>
43
  <?php if($this->helper('Antidot')->isActiveEngine()): ?>
44
+ <?php echo $this->getChildHtml('search_result_banner'); ?>
45
+ <?php echo $this->getChildHtml('search_result_category'); ?>
46
  <?php endif; ?>
47
  <?php echo $productHtml; ?>
48
  <?php else: ?>
49
  <div class="page-title">
50
  <h1><?php echo ($this->getHeaderText() || $this->getHeaderText() === false) ? $this->getHeaderText() : $this->__("Search results for '%s'", $this->helper('catalogsearch')->getEscapedQueryText()) ?></h1>
51
  </div>
52
+ <?php if($this->helper('Antidot')->isActiveEngine()): ?>
53
+ <?php echo $this->getChildHtml('search_result_banner'); ?>
54
+ <?php endif; ?>
55
  <p class="note-msg">
56
  <?php echo ($this->getNoResultText()) ? $this->getNoResultText() : $this->__('Your search returns no results.') ?>
57
  <?php if ($messages = $this->getNoteMessages()):?>
app/design/frontend/base/default/template/antidot/catalogsearch/result/banner.phtml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php if ($this->hasBanner()): ?>
2
+ <?php $banner = current($this->getBanners()); ?>
3
+ <div style="width: 100%; margin-left: 0%; margin-bottom: 10px;" >
4
+ <a href="<?php echo $banner->getUrl(); ?>"><img src="<?php echo $banner->getImage(); ?>" /></a>
5
+ </div>
6
+ <?php endif; ?>
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Antidot_Antidot</name>
4
- <version>1.1.4</version>
5
  <stability>stable</stability>
6
  <license>LGPL</license>
7
  <channel>community</channel>
@@ -17,9 +17,9 @@ Prevent to export empty categories node&amp;#xD;
17
  Add cdata for variant name&amp;#xD;
18
  Add variant details for grouped products</notes>
19
  <authors><author><name>Antidot</name><user>antidot</user><email>contact@antidot.net</email></author><author><name>Antidot</name><user>antidot</user><email>contact@antidot.net</email></author></authors>
20
- <date>2015-07-06</date>
21
- <time>14:28:49</time>
22
- <contents><target name="mage"><dir name="shell"><file name="antidotExport.php" hash="a4e184cdf1add5d42484e6997ea6f59c"/><file name="antidotExportCategory.php" hash="10de34988223fc8ca26e6f30c4070733"/><file name="antidotExportInc.php" hash="18f1b60b93245e2daf423c614dcd7efa"/><file name="antidotExportProduct.php" hash="9ddd7f0ba8e54b24665a32d26e5231b4"/></dir><dir name="i18n"><file name="de_DE" hash="f166a5ff29213a44fca77277b053897e"/><file name="en_US" hash="63c821044fda6f7c2a26dc84670b25bd"/><file name="es_ES" hash="f9319039054998955d63d51ed0930f3f"/><file name="fr_FR" hash="632367797f2fa9fef06e0b0c69377e01"/><file name="i18n.php" hash="0780b44563432f6e70de78f7a9d60f54"/></dir></target><target name="magecommunity"><dir name="MDN"><dir name="Antidot"><dir name="Block"><dir name="Catalog"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="2158b991ccdf394c8cd47cab00829e4d"/><file name="Boolean.php" hash="d17b08e1ec9047cf4050442ababd0808"/><file name="Category.php" hash="78cb53233ad74a2b5496d6f7857d8837"/><file name="Decimal.php" hash="75b31617bca2a8f20ee7fe113e3534f2"/><file name="Price.php" hash="244068a33e8ba64423c126baf883d2b5"/></dir><file name="View.php" hash="bbdd9bb31663415001ab3751c6737cde"/></dir></dir><dir name="Catalogsearch"><file name="Category.php" hash="e9605415ba85929115a443b1b4f00ab0"/><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="2b274bf7d8f8dbd915bdf73f65e694fc"/></dir></dir><file name="Layer.php" hash="3ba32c0f20c4b7447229843f45b06d3f"/><file name="Result.php" hash="82e928664d7f1e0688f377cfbb5700bb"/></dir><dir name="Html"><file name="Select.php" hash="fc7fb19df1dd378d4e9e0860d2d47d07"/></dir><dir name="System"><dir name="Config"><dir name="Button"><file name="AfsStore.php" hash="4f00570d46d27d1cf89785e8db42a332"/><file name="PushArticles.php" hash="a0cae65b4aba9b539421c0a6d06fb406"/><file name="PushCategories.php" hash="50e4b74388e1c5a65249c71dfae69400"/><file name="PushProducts.php" hash="bac543e1b17f91a558adef5da3012e28"/><file name="RestoreTemplate.php" hash="ffbbb0a73ff1ede611262a6a4da1a188"/><file name="ShowXml.php" hash="417ba0c9c62d8070b63f90397887dcc0"/></dir><dir name="Fieldset"><file name="Notice.php" hash="86e29b37d2c2390d5714ca99b45f4d6c"/></dir><dir name="Form"><dir name="Field"><dir name="Array"><file name="Additional.php" hash="d62316e3631c1c2b6a0119134c8002a8"/><file name="AdditionalFeed.php" hash="dcfb6d37d765a10e4a07465e70133dda"/><file name="ArticleAdditional.php" hash="38c62d610f585c460151841f7350348b"/><file name="ArticleIdentifier.php" hash="ec9479fd1ca087a1fe924795cc9ff5f6"/><file name="DefaultSort.php" hash="4989d99a73f57bed1fb994060cc38a72"/><file name="Facet.php" hash="7217f2296afaf11f514e4212a7a82cb9"/><file name="Identifier.php" hash="a9fa99227182bd72e59c9a315d580247"/><file name="ProductAdditionalFacet.php" hash="8d46e427d9efbac7e6ba04fdc88d4728"/><file name="ProductAdditionalField.php" hash="9c9f9c9c1c940963e1a24c039a392cc4"/><file name="ProductIdentifier.php" hash="d30809119cb35018697533075f7ee485"/><file name="Sort.php" hash="f986fbb048bf3f6aec813cdc1c70ec15"/></dir><file name="CategoryAttribute.php" hash="c119ca65f23950e7abb1f0d60e8b4755"/><file name="ProductAttribute.php" hash="6a61b98a9f6ac883a5e162e3edab300d"/></dir></dir><dir name="Html"><file name="Export.php" hash="f36beeca11c51e1a2e9678955d8cf1b8"/><file name="ShowXml.php" hash="7b70f39937aa9d24336edde6bdbdf97c"/><file name="Version.php" hash="34c624c382f3061cf322cfed52c416ac"/></dir></dir></dir></dir><dir name="Helper"><file name="Antidot.php" hash="7bbd2866c65a847e1415badb1ef0d015"/><dir name="CatalogSearch"><file name="Data.php" hash="81cc908609e68035d5714488f913e688"/></dir><file name="Compress.php" hash="12fa64a9c9f519a3f249954ab780e01c"/><file name="Data.php" hash="ef571e1089eb0166ba463e2a564636c7"/><dir name="Enterprise"><dir name="Search"><file name="Data.php" hash="8bfe0146c64511f86cb796638b65112f"/></dir></dir><file name="LogExport.php" hash="6d6b262327bf1d920fc2b5b112edfef6"/><dir name="ManaFilters"><file name="Data.php" hash="f4f4e92c5e33c6142904cf27a75f6d23"/></dir><file name="Url.php" hash="1d2ee02a8e135bfc4b866f5219f62acd"/><file name="XmlWriter.php" hash="66cf65d950caddf895c823c5575a1912"/></dir><dir name="Model"><dir name="Catalog"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="3cd18414abccea60c5497931bc95e21e"/><file name="Boolean.php" hash="dd0414e0d96833bec6e32aac321c2763"/><file name="Category.php" hash="4dea470cb36708e0ae4b95bd0a24a85f"/><file name="Decimal.php" hash="b9b1e2cff1d0332fab77d101dca4c3d2"/><file name="Item.php" hash="c89bbca267af18a0447e0daf3e7cc8eb"/><file name="Price.php" hash="7529be0313a19896993f92eeb9dfc8a9"/></dir></dir><file name="Layer.php" hash="706000dd944a45f30826eccba2942862"/></dir><dir name="Catalogsearch"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="a83d6761a949c8196cba33948a48c8bf"/></dir></dir><file name="Layer.php" hash="b5aa8e2cc24f1b1362749049f1cdec32"/><dir name="Resource"><file name="Attribute.php" hash="80d2a34d746f307109b6bf910b0f2958"/></dir></dir><dir name="Export"><file name="Abstract.php" hash="8c180f1d84dc88771885115348cc5dde"/><file name="Article.php" hash="b723ff65293cd517d247757ad43040d8"/><file name="Category.php" hash="a326b576f9a5f0f90cb5f57f3f155b26"/><file name="Product.php" hash="207d8b8d02fcd372068801d5d5d933a7"/></dir><file name="Observer.php" hash="e03106bc6632ca063ccbb60e55cd2d66"/><dir name="Resource"><file name="Advanced.php" hash="f4810c1af8d5a15f7a424d7baf5fc777"/><dir name="Catalog"><dir name="Product"><file name="Collection.php" hash="b7858c060b9e605b189ccea21156f2da"/></dir></dir><dir name="Engine"><file name="Abstract.php" hash="d778e69b54df4513f6dc63b3bc40b143"/><file name="Antidot.php" hash="72f2a01def54a9f13f0eb3a52382ec66"/></dir></dir><dir name="Search"><file name="Abstract.php" hash="fd71154b987b16f8d13bc3e10a3faeac"/><file name="Search.php" hash="aed2de6c2d73b4a7336f689287f0659a"/><file name="Suggest.php" hash="6caac0bb7683b1d330049ed0d606f36f"/></dir><dir name="System"><dir name="Config"><file name="ArticleAttribute.php" hash="f3a9596d45f275299f16530a56845c96"/><dir name="Backend"><file name="Engine.php" hash="68c93651655a77c74fd79d1de6d19be3"/></dir><file name="CategoryAttribute.php" hash="9f19b99e16c99b0e8052b1e31d2a6317"/><file name="Dir.php" hash="c80d83280ebc5ab91fd45d246ec47ba3"/><file name="DisableEnable.php" hash="6d08f33a1580b2fd1d58d87248104166"/><file name="Engine.php" hash="a3703b427ee777ce4ea58c8b31604158"/><file name="Facet.php" hash="8b771072a32f32e81a087581ace7fd72"/><file name="Number.php" hash="7985ea6c495a35173d68291389319f93"/><file name="Options.php" hash="06930da994dec4bb05ebc3f3e8c8abb8"/><file name="ProductAttribute.php" hash="c74ad00177c3a12b03c8684928d12c40"/><file name="PromoteRedirect.php" hash="c167973ea7a0ef09f0e5fa0fd0a08926"/><file name="Sort.php" hash="e0d2c1e72f56894b75baebcb6c4b8609"/><dir name="Suggest"><file name="Type.php" hash="cef491efdb9fcef86d0df75030206a78"/></dir><file name="WSStatus.php" hash="ff4954e15d75dd3139290d96773d0abf"/></dir></dir><dir name="Transport"><file name="Abstract.php" hash="3272c44b08523a9836aa15c835e2ed25"/><file name="File.php" hash="0941fd452279605a2ea6a5d40f857000"/><file name="Ftp.php" hash="8d1aa862bb8f3656bd199d5ce592e0b1"/><file name="Http.php" hash="fb80d47a6d991b9f706418061a2cbd7e"/><file name="Interface.php" hash="32d1d3958e0cd726bc34cae482464ef8"/></dir><file name="Transport.php" hash="96c10d2ff359849de991d8a045cc9353"/></dir><dir name="Test"><dir name="Block"><dir name="Catalogsearch"><file name="Layer.php" hash="49725570e661d72db50daab46e0e18af"/></dir><dir name="System"><dir name="Config"><dir name="Button"><file name="AfsStore.php" hash="dcbfefb440b8512b1298b624a3582076"/></dir></dir></dir></dir><dir name="Helper"><dir name="CatalogSearch"><file name="Data.php" hash="a40c1e58b5000432763aa07dd49d4b5d"/></dir><file name="Data.php" hash="9c21bd8bfa43dab48d95a886812587e6"/></dir><dir name="Model"><dir name="Export"><dir name="Abstract"><dir name="fixtures"><file name="testGarbageCollection.yaml" hash="de6c8672be0c24a102ebfed004f2361b"/></dir></dir><file name="Abstract.php" hash="f9ed7f39ba478e9e8e81b93684a8ffbe"/><file name="Article.php" hash="c2d43ccf7c9b6648b633d122c657f27d"/><dir name="Category"><dir name="fixtures"><file name="testEmptyFile.yaml" hash="9573e620466cfe8260f8a87e274c8261"/></dir></dir><file name="Category.php" hash="4f3e57931e5cffca23648acab82cf08e"/><dir name="Product"><dir name="fixtures"><file name="testGetProductCategories.yaml" hash="4c9aa76866c740bcd44bdbbdf98ac2f5"/><file name="testInactiveParentCategory.yaml" hash="3ef9bcefae6399ccdc23e026746a1743"/><file name="testWriteImageUrl.yaml" hash="a4e08b8f1565eba67a16553cf57e1004"/><file name="testWritePricesFixedtax.yaml" hash="a4e08b8f1565eba67a16553cf57e1004"/><file name="testWriteProductNoVariant.yaml" hash="626a27b35977e5a52b02f85011c5e216"/><file name="testWriteProductNoVariantInStock.yaml" hash="9aa7736a422276842350ac73c6f4ba55"/><file name="testWriteProductUrl.yaml" hash="a4e08b8f1565eba67a16553cf57e1004"/><file name="testWriteProperties.yaml" hash="d434749b80908bbceefd5781e2d0e998"/><file name="testWriteXml.yaml" hash="790c0ecc8aaf15cc1d6b80a2328f2280"/></dir><dir name="providers"><file name="testWriteImageUrl.yaml" hash="666c33585c611bcc0b0ebe6e87dce1fc"/><file name="testWriteProductUrl.yaml" hash="18f511460efea04586fc888f5c85b3ea"/></dir></dir><file name="Product.php" hash="32a8e48422e2d3328365b8e4ac039f29"/></dir><dir name="Observer"><dir name="fixtures"><file name="testGetDefaultContext.yaml" hash="5b3998808a9667ba79e8138104e24b00"/></dir><dir name="providers"><file name="testGetOwnerForFilename.yaml" hash="c5c07e73f536f9ffacc0c3ff6b5a13d1"/></dir></dir><file name="Observer.php" hash="86536c523b1249b9d100a5dc40ea7793"/><dir name="Resource"><dir name="Catalog"><dir name="Product"><file name="Collection.php" hash="2ad006d8e096ade9043a9a370177782d"/></dir></dir><dir name="Engine"><dir name="Antidot"><dir name="fixtures"><file name="testFormatResult.yaml" hash="a1a684d4f08b4d3e3b7f3711e7563010"/></dir></dir><file name="Antidot.php" hash="7b021f1cac89c0afb67663a5ca97b3cc"/></dir></dir><dir name="Search"><dir name="Suggest"><dir name="fixtures"><file name="testSuggest.yaml" hash="e845f0311d93608e3221fb0678f429cc"/></dir></dir><file name="Suggest.php" hash="d97172c8ec094146f953a9704f8e1936"/></dir><dir name="System"><dir name="Config"><dir name="Facet"><dir name="fixtures"><file name="testToOptionArray.yaml" hash="b76143bd57f68be024a31d905da9cabe"/></dir></dir><file name="Facet.php" hash="3e3ef7aa45b4226df9eaf177ed69326f"/><dir name="Sort"><dir name="expectations"><file name="testToOptionArray.yaml" hash="13fc5b4c17962fb267f443d03a2219b2"/></dir><dir name="fixtures"><file name="testToOptionArray1.yaml" hash="3160d541123737644dfea5c70db35f41"/><file name="testToOptionArray2.yaml" hash="74fd97f93892920908ab7eab0124eeb6"/><file name="testToOptionArray3.yaml" hash="fe9c8a5da75f3c0d66304a39c473a3bb"/></dir></dir><file name="Sort.php" hash="3435402ae9aa30d18c8265433d643d21"/></dir></dir></dir><file name="PHPUnitUtil.php" hash="2a128a7c19f4c37cb9dd7fc60e679693"/></dir><dir name="controllers"><dir name="Admin"><file name="PushController.php" hash="3f7be8a53c7a01cfd11aa5a8a8fcfac6"/></dir><dir name="Front"><file name="SearchController.php" hash="d220bd4628830ea238775ed9788e0674"/></dir></dir><dir name="etc"><file name="config.xml" hash="8eca55ffd591e2e858d505f88be5b4a1"/><file name="system.xml" hash="a636f06591b6c01e1e5375aa46a644fb"/></dir><dir name="sql"><dir name="Antidot_setup"><file name="mysql4-install-0.9.php" hash="62672bc47ea92dbd46966fb76e4251e0"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="antidot.xml" hash="ac0dcdc06f12db5245fbc10aacf64d89"/></dir><dir name="template"><dir name="antidot"><dir name="catalog"><dir name="layer"><file name="category.phtml" hash="3ec81f7b3e3b947317da8664c8e15927"/><file name="filter.phtml" hash="2304baebff9b798e0ebd977fbc891346"/></dir></dir><dir name="catalogsearch"><dir name="result"><file name="category.phtml" hash="7413580b825508f2cfc08566d62369ae"/></dir><file name="result.phtml" hash="12c082ddff0e6c4fef74630b8253face"/></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="MDN_Antidot.xml" hash="988c6b7e9da4e50f1727956833ab1696"/></dir></target><target name="magelocale"><dir name="de_AT"><file name="MDN_Antidot.csv" hash="6d55b32bb063457c70296109170f944c"/></dir><dir name="de_CH"><file name="MDN_Antidot.csv" hash="6d55b32bb063457c70296109170f944c"/></dir><dir name="de_DE"><file name="MDN_Antidot.csv" hash="6d55b32bb063457c70296109170f944c"/></dir><dir name="es_AR"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_CL"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_CO"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_CR"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_ES"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_MX"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_PA"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_PE"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_VE"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="fr_CA"><file name="MDN_Antidot.csv" hash="cb32f785ce819fe925347b7863d8de36"/></dir><dir name="fr_FR"><file name="MDN_Antidot.csv" hash="cb32f785ce819fe925347b7863d8de36"/></dir></target><target name="mageweb"><dir name="js"><dir name="mdn"><dir name="antidot"><file name="CollapsibleLists.js" hash="86792ecde0c2759ba85e0d863dd147ce"/></dir></dir></dir></target><target name="magelib"><dir name="antidot"><dir name="AFS"><dir name="ACP"><file name="Makefile" hash="0f76232bfabc275a3dac973666fb5dae"/><dir name="TEST"><file name="Makefile" hash="ce56cc786e1df50148e1d3222c05e5f8"/><file name="acpConnectorTest.php" hash="25a8194f3dc8895640df4f4bba895d8e"/><file name="acpQueryTest.php" hash="74ad65a4af639a409ee72a75a2a043d6"/><file name="acpReplysetHelperTest.php" hash="4f0a0d471a06e139cd11c715b67ebe81"/><file name="acpResponseHelperTest.php" hash="6d30f99108db0d9956aef9ba5e1d88df"/><file name="acpTest.php" hash="d6119d150543e7943ba4e9907901ae5d"/></dir><file name="afs_acp.php" hash="78dbfbc92f68469c92898f1da4263e68"/><file name="afs_acp_configuration.php" hash="2d644cc6c5bf2cdaeca5780576c4bf0e"/><file name="afs_acp_connector.php" hash="b72439562b02024e0b9629c18394985d"/><file name="afs_acp_exception.php" hash="f610d2cc37a15d4b981d7b43939414ad"/><file name="afs_acp_query.php" hash="ced0629355f5d4fc1c219d1adb03297d"/><file name="afs_acp_query_manager.php" hash="b3348972a850c904fc664b4e27671439"/><file name="afs_acp_reply_helper.php" hash="b0259f24f10d2e92ed6e3b8cdaaacc44"/><file name="afs_acp_replyset_helper.php" hash="07e7fdb88a42a399c96261c47ffb0231"/><file name="afs_acp_response_helper.php" hash="33a66106fd3a94194514a0d8d39af1cd"/></dir><file name="Makefile" hash="7bb31592939024f74745d6b6cb7fec0b"/><dir name="SEARCH"><dir name="FILTER"><file name="Makefile" hash="d42338199c6857ded179af2117b9f571"/><dir name="TEST"><file name="Makefile" hash="ab37090c6c5e7af1b260376237737700"/><file name="filterBuilderTest.php" hash="161ff5c8e73914eef884d17456afa133"/><file name="filterCombinationTest.php" hash="2162288d5255d3b24fe94d75b939aa51"/><file name="filterTest.php" hash="1682c0a4d50158a8d2c9369d30e45a18"/><file name="groupFilterTest.php" hash="1ebe8ce7344ed64b93cf94632d3b0184"/></dir><file name="afs_combinable_filter.php" hash="336e6c6bc9ebae3f58602d23ef734182"/><file name="afs_combinator_filter.php" hash="e2fc560b9c0c31f20c73f2057a8b7b69"/><file name="afs_filter.php" hash="6dbfc8c668cd48510cc9a9243d1bf4c3"/><file name="afs_filter_exception.php" hash="ccce583c63a4a65f7f0a27fc4a487505"/><file name="afs_filter_wrapper.php" hash="30dec104456abc037019ad93922b5afd"/><file name="afs_group_filter.php" hash="b95fa3bc0e26bc39dfc53a6010bce32f"/><file name="afs_native_function_filter.php" hash="37176bdbc66cc3dca18149132921f0a5"/><file name="afs_operator_filter.php" hash="c7ea43c8d64eedbe33397f61737e0226"/><file name="afs_valued_filter.php" hash="483653071734f77972c9b9771e187d82"/></dir><file name="Makefile" hash="0f76232bfabc275a3dac973666fb5dae"/><dir name="TEST"><file name="Makefile" hash="ce56cc786e1df50148e1d3222c05e5f8"/><file name="clientDataHelperTest.php" hash="1556ab047e1df23447586d529768befd"/><file name="clusterHelperTest.php" hash="e112e7c756f63c8e8ceb554281b418c9"/><file name="conceptHelperTest.php" hash="b44e39b62d0537bf1f7b7feb23f8111f"/><file name="facetDefaultTest.php" hash="382e4ea35e1c7173371b4a84046a38e5"/><file name="facetHelperTest.php" hash="d51a714bc116e77f5f115c26e9640f10"/><file name="facetManagerTest.php" hash="bbef8e207c387dbe6a26142fd55264d5"/><file name="facetTest.php" hash="26123aa75cb2597a3ededfa9d778095d"/><file name="facetValuesSortOrderTest.php" hash="b650080bf9b2cce2ac42a245cb84c911"/><file name="feedCoderTest.php" hash="f2b5dfdd4fa3c4e5d14c790d15235146"/><file name="filterCoderTest.php" hash="46249fa13edccf1e5d5000daf2573b77"/><file name="headerHelperTest.php" hash="8eb9450972ce082c35d7b66be7735d79"/><file name="helperConfigurationTest.php" hash="be3f74e53e27744e8214f3c341172796"/><file name="intervalTest.php" hash="912389dad049853f6bf0b4eab2af5034"/><file name="metaHelperTest.php" hash="080f160b54636c4eee743544a6a12bee"/><file name="pagerHelperTest.php" hash="d96a9891523e453647493f3219e86357"/><file name="promoteBannerReplyHelper.php" hash="94c3c14517536437e9800eaa706fbe29"/><file name="promoteRedirectReplyHelper.php" hash="ed00c66be5127d8b374f6416abf328ef"/><file name="promoteReplyHelperTest.php" hash="7cbb68a7f50c2bd2ef11a085ac94deb2"/><file name="promoteReplysetHelperTest.php" hash="ac2f1e3073015143dc7b2b705711c845"/><file name="queryCoderTest.php" hash="03983a114c6697464f8bf016822ff4a3"/><file name="queryTest.php" hash="338264d8e6dbbc09e88bd9a8179e8be4"/><file name="replyHelperTest.php" hash="4d86f19ea7de2aece5d7fd9c143c3dbc"/><file name="replysetHelperTest.php" hash="897f074b8382c6853f51b06a5ee50b0a"/><file name="responseHelperTest.php" hash="ebb167e1c330af6aa0e6a2b917431040"/><file name="searchConnectorTest.php" hash="9201de573884b643041b6c32bc535e7e"/><file name="searchQueryManagerTest.php" hash="2188b262a1c11422bcc8133f68fa6dd9"/><file name="searchTest.php" hash="fa47a7819b5c7c71172d6b1f1e7a02f7"/><file name="spellcheckHelperTest.php" hash="49960fb90055dcf265ef41e491c11325"/><file name="spellcheckTextVisitorTest.php" hash="203f0d08f548a39135517a41f6e9e43a"/><file name="textVisitorTest.php" hash="b722845dd0f5f953574cb51284ad025b"/></dir><file name="afs_base_reply_helper.php" hash="57abe4828b7ed7126db963764faa718a"/><file name="afs_base_replyset_helper.php" hash="096b124a3ebdc6e8d6beb359bd8bb7c5"/><file name="afs_client_data_exception.php" hash="899957af974d04aa7eaca44903a7f86c"/><file name="afs_client_data_helper.php" hash="4700218e2400350014fde428bc86806b"/><file name="afs_cluster_exception.php" hash="86d97623db7aebaa28a20857ce2cf17f"/><file name="afs_cluster_helper.php" hash="60b7fbcc869a672929ef9fc6d840d2b2"/><file name="afs_cluster_parameter.php" hash="20ed527d3ed1a6cf2bc80e032ecd2c7e"/><file name="afs_coder_base.php" hash="fb87fbea43d12695154b3b6102e2a019"/><file name="afs_coder_interface.php" hash="3b179b2513e215751ee4edd190b2a719"/><file name="afs_concept_helper.php" hash="982cf3d2063c565cf19cc6136b049066"/><file name="afs_count.php" hash="9f83f3baa3cf4462c0db786f4eea479a"/><file name="afs_facet.php" hash="1b4d7d35ebe8ed4894fda4881d0b168f"/><file name="afs_facet_combination.php" hash="005e9742ee032194b86856195dd59f7d"/><file name="afs_facet_default.php" hash="cbcb5d28b7b00815ce5248017065e84b"/><file name="afs_facet_exception.php" hash="f1f0afdbf9a727b53c4731e5a40ac417"/><file name="afs_facet_helper.php" hash="fe1ca1e7242c319bac96488b1f5e2063"/><file name="afs_facet_helper_retriever.php" hash="5628cc41c50ab25fd3336df302d903f4"/><file name="afs_facet_layout.php" hash="c83f6fef1c13ba3cda667c611841ff87"/><file name="afs_facet_manager.php" hash="a3fabb34d56a9614d4a0a2917f6fea0c"/><file name="afs_facet_mode.php" hash="8dcac389a37f8267a367400377631dba"/><file name="afs_facet_sort.php" hash="0d7ba4059b10da9981b9c801355cb874"/><file name="afs_facet_type.php" hash="6df82cbfa627629f9523437994d1fbb1"/><file name="afs_facet_value_formatter.php" hash="d6580281f9ef5c0820615ac385aae863"/><file name="afs_facet_values_sort_mode.php" hash="17def98365132c810515f8cf3c6fb006"/><file name="afs_facet_values_sort_order.php" hash="f95f77cb5dd7015e4f2e6094ddba49a6"/><file name="afs_feed_coder.php" hash="ed7b40e872a7ed5aa30adbcffc05de56"/><file name="afs_filter_coder.php" hash="4edbdcf6760d80465e5d2533014ba307"/><file name="afs_filter_parameter.php" hash="2b03c2c83ffe2e2968aaf50ad4903921"/><file name="afs_fts_mode.php" hash="edbd9342cd9625183e1e01ed81b79fc3"/><file name="afs_header_helper.php" hash="3b30d839efe9128773c82d47cbd591b8"/><file name="afs_helper_configuration.php" hash="dbd0378574fbc5729babfbddfef0fd67"/><file name="afs_interval.php" hash="dbf9749881be0a2b063f8a33dff214f3"/><file name="afs_interval_exception.php" hash="40f223de231df03aae59596c1a493065"/><file name="afs_meta_helper.php" hash="8403689868c98db725ebd11748508c8b"/><file name="afs_pager_helper.php" hash="077052931e0cffb1e589c21b57156b38"/><file name="afs_producer.php" hash="7c8c515ccb8126523fa0d09a7f759dd5"/><file name="afs_promote_banner_reply_helper.php" hash="418702b3c053029b3aa8fcb2775c65bd"/><file name="afs_promote_redirect_reply_helper.php" hash="be17eda6f8b4552b9ec21183362171a2"/><file name="afs_promote_reply_helper.php" hash="0e2a4f67cd307f74e8b64cd3b158235c"/><file name="afs_promote_replyset_helper.php" hash="fdefc6f8a686addb31ea9b6c0a3fa5ad"/><file name="afs_query.php" hash="bd969a62cd4bbbcb5b9996eaa19353f7"/><file name="afs_query_coder.php" hash="ca0bfad66b8d8549ab3f33380d716732"/><file name="afs_query_coder_interface.php" hash="dd16f17b3606a7418c1c714475b19b51"/><file name="afs_query_object_interface.php" hash="a9af13e2c856e4136ccadfff60f72d36"/><file name="afs_raw_text_visitor.php" hash="fd574583c4c9110165c1cadc67b832de"/><file name="afs_reply_helper.php" hash="3919f9e83cba62be9bc67117b1087b03"/><file name="afs_reply_helper_factory.php" hash="f159f7d0ef7e5a209fb872a970d0d582"/><file name="afs_replyset_helper.php" hash="cb8f81391d9a59904dcb0c3d6ae31999"/><file name="afs_response_exception.php" hash="0a865bb92fb700ae555dcb5ae675f644"/><file name="afs_response_helper.php" hash="2fec8d101712087660dc6aba5119e3c2"/><file name="afs_search.php" hash="3f2e3ef447515a2fa05b270654ef2969"/><file name="afs_search_connector.php" hash="17242fb6536f4596b2c0198a16986310"/><file name="afs_search_query_manager.php" hash="77e30683ee4ba9e004e9c7c12d9c811d"/><file name="afs_sort_builtins.php" hash="0cc1617a62f1a834a28d7d2ac249b081"/><file name="afs_sort_coder.php" hash="1dfe2d32278383d8465df67535cb91dd"/><file name="afs_sort_order.php" hash="7755deb99386650c9974871474168cda"/><file name="afs_sort_parameter.php" hash="bfb8c59c1560ec8a3b597dc45aa8ecd5"/><file name="afs_spellcheck_helper.php" hash="bb5465848ada7a9df9875f2565fb9686"/><file name="afs_spellcheck_text_helper.php" hash="3ca5c3118660aa600aadb504ceff6c4c"/><file name="afs_spellcheck_text_visitor.php" hash="c44c23ae21f61b065e457911bbc45ed2"/><file name="afs_text_helper.php" hash="59c4ae24560948c3af0f4adbf6bd1803"/><file name="afs_text_visitor.php" hash="867b44a280403cd4567358ec6d59588a"/></dir><file name="afs_configuration_base.php" hash="f26dd9efda4923cc2c71057f21be97d9"/><file name="afs_connector.php" hash="aa04a21163b57ef338bf96bd55e95882"/><file name="afs_exception.php" hash="c1840fe279f9cb313cec151012ed4513"/><file name="afs_feed.php" hash="005305cace79a3aa7719a3c942df9da7"/><file name="afs_multiple_values_parameter.php" hash="96dc30f1fbf137cbfd73c2b195d9f9ef"/><file name="afs_origin.php" hash="a6b7e39a687210572c116afcbea0e7cb"/><file name="afs_query_base.php" hash="7209115a714d9b7de209a0af691c1d22"/><file name="afs_query_parameter.php" hash="6552428d955d0a48c015e1f98ba62815"/><file name="afs_response_helper_base.php" hash="b087f7bdad35ed0526566042ef9afc8c"/><file name="afs_single_value_parameter.php" hash="65d002d7ac6b6e8dd6170309b4c84649"/></dir><dir name="AIF"><file name="Makefile" hash="2d232abf9913fcabb44033d5e5d1ebfd"/><dir name="TEST"><file name="Makefile" hash="24d3030d27e88732028d14fb1d81c203"/><file name="afsMultipartResponseTest.php" hash="70a64d0d599ea01806fac2126fb3680a"/><file name="authenticationTest.php" hash="2e476e9ab15ee221ddd63bb555262a28"/><file name="bowsInformationTest.php" hash="3bbfe71f431a35f0285afdca40906874"/><file name="documentManagerTest.php" hash="ad90a6146f5aeee383355bb05425b3dd"/><file name="documentTest.php" hash="59b204b10b90cd764b259ad4c2bc043a"/><file name="pafConnectorTest.php" hash="ac2928b501d9ea167af43dbf3adafa7d"/><file name="pafLiveTest.php" hash="92862c31d151c34b2caf44bff9d0fb80"/></dir><file name="afs_about_connector.php" hash="8972264a9b7cce237ad1a4b47852b529"/><file name="afs_authentication.php" hash="4285035550c9681a047b85abbca64936"/><file name="afs_bows_connector.php" hash="47a6bcafd5eba2361d2cea409f60d3f7"/><file name="afs_bows_connector_interface.php" hash="8fdf9749f0500a39741d696feb55af14"/><file name="afs_bows_exception.php" hash="1bd8657a37b8b4a9e08bfc4eb6b7e416"/><file name="afs_bows_information.php" hash="1f96a4cd84b2332f1186f9e0cea8542d"/><file name="afs_bows_information_cache.php" hash="1ae9a9243342c4e58a52e70473b68472"/><file name="afs_document.php" hash="c0003ec962a79b9d3f642b17bade0fff"/><file name="afs_document_manager.php" hash="8c5c0105d9337b7ae6a9f041f643ea88"/><file name="afs_multipart_response.php" hash="f2077c9eaf121fabdb2fc26c23b2e256"/><file name="afs_paf_connector.php" hash="96111b0536c83874b7c06ada5577106b"/><file name="afs_paf_live_connector.php" hash="9efeb2716f6d95e666f9c37726869fe7"/><file name="afs_paf_upload_reply.php" hash="0cb4905d1c894637d5e6acbd2cffc112"/><file name="afs_token_authentication.php" hash="1f003310f156f0a71db1d273375172d8"/><file name="afs_user_authentication.php" hash="03deeead93ee32753f2f7f80cfc011f4"/></dir><dir name="COMMON"><file name="Makefile" hash="7bb31592939024f74745d6b6cb7fec0b"/><dir name="TEST"><file name="Makefile" hash="d568cfe3683543f363312aa4b6d2bbad"/><file name="languageTest.php" hash="ad0f75b1c2f320c81eba32cade86191c"/><file name="toolsTest.php" hash="9276cb1a275d697f8e8365f2ac340cdf"/><file name="userSessionManagerTest.php" hash="b2b78d6fa156f1a61065f8ee5bfc6e0b"/></dir><file name="afs_connector_base.php" hash="b6b1f091ec71e5b92e4a1e5ca958255f"/><file name="afs_connector_interface.php" hash="68ad5e20a861b85dbf198f79cd2afd4c"/><file name="afs_exception.php" hash="b8eed4376088ae3003d0b77cc523e732"/><file name="afs_helper_base.php" hash="839cca78a663c3a22b4a8e35d1460129"/><file name="afs_helper_format.php" hash="30a3f6e945db7412ef95e83e7b0b5898"/><file name="afs_language.php" hash="277acb15b86089b37c812c47f2141d3c"/><file name="afs_service.php" hash="12c00c906e130860120552c40fa9dbc2"/><file name="afs_service_status.php" hash="1dee172850a76b46987534df89013878"/><file name="afs_tools.php" hash="26f6c01c5a61987925385e7a35260399"/><file name="afs_user_session_manager.php" hash="abd625f6b7b5cecf386dac9d82887764"/><file name="afs_versions.php" hash="556c912ff7f19f5083c4fb44d4d40ac6"/><dir name="lib"><dir name="JsonPath"><file name="JsonPath.php" hash="baa12e1baa9f8a20a095463042e96ad3"/><file name="JsonStore.php" hash="a9632aeb2126e98db9a49403a8f2ff77"/></dir></dir><dir name="php-SAI"><file name="README.md" hash="63ab581c83fe44918e6d074e20f08f95"/><dir name="lib"><dir name="Curl"><file name="Handle.php" hash="0fc7132737da7cee7df6b974447864ac"/></dir><file name="Curl.php" hash="358e4d3afca2035ee4d3f99f372ed15a"/><file name="CurlInterface.php" hash="714fa045dd4546d0c92cd022efb09422"/><file name="CurlStub.php" hash="fbdc0ece6321c5b5a1e27a65449f4a1f"/><dir name="rb_temp"><file name="HttpClient.php" hash="091b91c98acf9f1cd6c3d6d75cddfb88"/><file name="MultiCurl.php" hash="916e85d73bae6e136f889166ebc6db17"/><file name="SimpleCurl.php" hash="c296966a8bda96e03b464a1d3a9c8e06"/></dir></dir><dir name="tests"><file name="SAI_CurlStubTest.php" hash="bce69cbb17a40bd4eeba6bad1133216e"/></dir><file name=".gitignore" hash="09e625dea07b4d4098b19ec998d266f9"/></dir></dir><file name="COPYING" hash="b234ee4d69f5fce4486a80fdaf4a4263"/><file name="COPYING.LESSER" hash="4fbd65380cdd255951079008b364516c"/><file name="FAQ.md" hash="7d7c886674d70a0047303c5d93de6165"/><file name="Makefile" hash="225475a5a4a0204cecbb77621ff38bb2"/><file name="README.md" hash="7ecfd33825a0e6bc50cca099c1c0e50e"/><file name="afs_lib.doxygen" hash="8128d53d894cc57e08142377d13c72f4"/><file name="afs_lib.php" hash="946834742cd313e818f79bb96b6dfb52"/><file name="afs_version.php" hash="d2d295f9758c29cb26173f9095ff1400"/><file name="composer.json" hash="39190df70fafa99d7eb5ab566e8edf3f"/><dir name="doc"><file name="afs_filter_documentation.dox" hash="3bf4b96e25d95ce5953b822038c6f135"/><file name="afs_paf_upload.dox" hash="d36893db0234f171e6cfb43f6e13d47c"/><file name="afs_search.dox" hash="b1c5ab8728703822f910852cd17561f4"/><file name="afs_search_coder.dox" hash="77709e1bc691301017f0982e0348a9b9"/><file name="afs_search_query.dox" hash="21dcd1734a165a4cb3b4f62c42a6a0be"/><file name="afs_search_reply.dox" hash="cdb1d42447671f4352927b40b3f8f37d"/><dir name="data"><file name="acp_helper_example.php" hash="2815890e7afbae78e7eb4e6fc5c88f6f"/><file name="full_example.php" hash="e152a964d06e55de460c596070c714d8"/><file name="full_lightweight_example.php" hash="eac3bb2d251052f547a9f737e5cd0461"/><file name="raw_example.php" hash="703356b9284e7fe904cf1334abbe08c9"/><dir name="templates"><file name="error_template.html" hash="70f44bd0f45470d379a11d0a2fe507e4"/><file name="facet_template.html" hash="6836005a7dae45e9415273f1eb6b78e2"/><file name="facet_values_template.html" hash="9b41f2b55a1cecae5724b4fcd4a46cfb"/><file name="meta_template.html" hash="e664a3bb222d272ce2451fb10bf46de4"/><file name="pager_template.html" hash="2700ab5b60a1f9553b1c39374fda63d4"/><file name="result_template.html" hash="1572a4ef4e8dda0b3db1ea77bbed4a98"/><file name="spellcheck_template.html" hash="8042054a1f5a271b47c77f81436c4791"/></dir></dir><file name="detailled_integration_example_with_template.dox" hash="26ef377a6ef546b636a0e254d11d01f5"/><file name="lightweight_integration_example_with_template.dox" hash="5a388d2dbfad63ad6ec353407b79a6bb"/><file name="logo-antidot-long-200x41.png" hash="1ceac3fff767fb5e395bd767344a3d13"/><file name="main.dox" hash="ca3e97f95deead927fb3298ecafbad5e"/><file name="raw_integration_example.dox" hash="56a7126d008c2e49abdf9bf0b5ec9717"/><file name="template_prerequisites.dox" hash="baa24a943e19ff3654227850bd316abb"/><file name="templates_in_details.dox" hash="5e8db94382f1fbd6c4e0b424a9edc9a3"/></dir><file name="rules.mk" hash="ff48aa6a5c40e31b3f38aba1267e9a71"/><dir name="scripts"><file name="gen_doc.sh" hash="0f6fc60aca94da563397d3c710bd9d33"/><file name="increment_version.sh" hash="431db9c60d2f94d251be07957787fcb0"/><file name="print_version.sh" hash="a05ddc19cd27ff185721fe2bd0cffc25"/><file name="version_management.sh" hash="3d5ecd39f45ba081144b3033dbd14330"/></dir><file name=".gitignore" hash="0292f51c0906b2092255872c69603f29"/><file name=".travis.yml" hash="4330b9c449e9cd0e97829f679c2a2786"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><dir name="mdn"><dir name="antidot"><file name="CollapsibleLists.css" hash="c956d83facc41a97bf14726dcb953edb"/></dir></dir></dir><dir name="images"><dir name="mdn"><dir name="antidot"><file name="base.gif" hash="1f71b021e061a4948d69adc4ff10ccad"/><file name="button-closed.png" hash="563b78324e0712c0902cb4f77cb9eb86"/><file name="button-open.png" hash="c710849a0d2b61ad1f0fc36c0e59d131"/><file name="button.png" hash="97f3055c5046c851eea2dad7e5227508"/><file name="cd.gif" hash="f41037663522fab5c5c31530c7fa43d8"/><file name="empty.gif" hash="df22aff6e941ff1cc577333d1712b584"/><file name="folder.gif" hash="ea16980ab437fa6ba4aba3d480e83e9e"/><file name="folderopen.gif" hash="18aa3d75315bf95bf080357733437fcc"/><file name="globe.gif" hash="d6b48614cf8dc9553e077c19197637d2"/><file name="imgfolder.gif" hash="1d488d377762e65ab4e8b691ba01e5a4"/><file name="join.gif" hash="4d5d614e0da056df815a4306d6368692"/><file name="joinbottom.gif" hash="4b3daa7f2cc584f1aac0d142275d7cba"/><file name="line.gif" hash="63ab38a6203262f15ca46c631232ea2c"/><file name="list-item-contents.png" hash="00ae24d5bc76df9eedaea597859963e4"/><file name="list-item-last-open.png" hash="615ddd71f81b240e9ed7d4e383b2c01a"/><file name="list-item-last.png" hash="e2bfb790f46855c378e50f3c0a82ea01"/><file name="list-item-open.png" hash="732d1cc59f3a488c89c624eb434eac98"/><file name="list-item-root.png" hash="5529d21e7ec68e9cb750a4895ff0b480"/><file name="list-item.png" hash="e03ec1bf3d9e16bb3005ccf8d26eaa6c"/><file name="minus.gif" hash="d647fbbd0ec410b8f3bb3357b62eedcf"/><file name="minusbottom.gif" hash="b09d684cca7135ef728141aaf2464baa"/><file name="musicfolder.gif" hash="21ece951734f23adb2f75befe1f31fc1"/><file name="nolines_minus.gif" hash="eb2243a354ffcfac93ba0fe948f7167d"/><file name="nolines_plus.gif" hash="ec92b634b63608fb4b0dbf114e3b89e1"/><file name="page.gif" hash="c25b136c1cb3bb145495c25b35d93754"/><file name="plus.gif" hash="5c55d798909c553deca31d610bd18fac"/><file name="plusbottom.gif" hash="1924ce363c38a992f888a4df48c0b274"/><file name="question.gif" hash="ea0ca196ce0ebfd625cc1210abfdec6c"/><file name="trash.gif" hash="6cbfd3ed29531044aed9b4edb3cca9ad"/></dir></dir></dir></dir></dir></dir></target></contents>
23
  <compatible/>
24
  <dependencies><required><php><min>5.2.0</min><max>5.6.0</max></php><extension><name>curl</name><min/><max/></extension></required></dependencies>
25
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Antidot_Antidot</name>
4
+ <version>1.2.1</version>
5
  <stability>stable</stability>
6
  <license>LGPL</license>
7
  <channel>community</channel>
17
  Add cdata for variant name&amp;#xD;
18
  Add variant details for grouped products</notes>
19
  <authors><author><name>Antidot</name><user>antidot</user><email>contact@antidot.net</email></author><author><name>Antidot</name><user>antidot</user><email>contact@antidot.net</email></author></authors>
20
+ <date>2015-09-14</date>
21
+ <time>09:35:46</time>
22
+ <contents><target name="mage"><dir name="shell"><file name="antidotExport.php" hash="a4e184cdf1add5d42484e6997ea6f59c"/><file name="antidotExportCategory.php" hash="10de34988223fc8ca26e6f30c4070733"/><file name="antidotExportInc.php" hash="18f1b60b93245e2daf423c614dcd7efa"/><file name="antidotExportProduct.php" hash="9ddd7f0ba8e54b24665a32d26e5231b4"/></dir><dir name="i18n"><file name="de_DE" hash="f166a5ff29213a44fca77277b053897e"/><file name="en_US" hash="63c821044fda6f7c2a26dc84670b25bd"/><file name="es_ES" hash="f9319039054998955d63d51ed0930f3f"/><file name="fr_FR" hash="632367797f2fa9fef06e0b0c69377e01"/><file name="i18n.php" hash="0780b44563432f6e70de78f7a9d60f54"/></dir></target><target name="magecommunity"><dir name="MDN"><dir name="Antidot"><dir name="Block"><dir name="Catalog"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="2158b991ccdf394c8cd47cab00829e4d"/><file name="Boolean.php" hash="d17b08e1ec9047cf4050442ababd0808"/><file name="Category.php" hash="78cb53233ad74a2b5496d6f7857d8837"/><file name="Decimal.php" hash="75b31617bca2a8f20ee7fe113e3534f2"/><file name="Price.php" hash="244068a33e8ba64423c126baf883d2b5"/></dir><file name="View.php" hash="bbdd9bb31663415001ab3751c6737cde"/></dir></dir><dir name="Catalogsearch"><file name="Banner.php" hash="cfc866a6c1cfb2ee9cb690bed84781fe"/><file name="Category.php" hash="e9605415ba85929115a443b1b4f00ab0"/><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="2b274bf7d8f8dbd915bdf73f65e694fc"/></dir></dir><file name="Layer.php" hash="3ba32c0f20c4b7447229843f45b06d3f"/><file name="Result.php" hash="82e928664d7f1e0688f377cfbb5700bb"/></dir><dir name="Html"><file name="Select.php" hash="fc7fb19df1dd378d4e9e0860d2d47d07"/></dir><dir name="System"><dir name="Config"><dir name="Button"><file name="AfsStore.php" hash="4f00570d46d27d1cf89785e8db42a332"/><file name="Forward.php" hash="3917a1882c3d55837138782e60791167"/><file name="PushArticles.php" hash="a0cae65b4aba9b539421c0a6d06fb406"/><file name="PushCategories.php" hash="50e4b74388e1c5a65249c71dfae69400"/><file name="PushProducts.php" hash="bac543e1b17f91a558adef5da3012e28"/><file name="RestoreTemplate.php" hash="ffbbb0a73ff1ede611262a6a4da1a188"/><file name="ShowXml.php" hash="417ba0c9c62d8070b63f90397887dcc0"/></dir><dir name="Fieldset"><file name="Notice.php" hash="86e29b37d2c2390d5714ca99b45f4d6c"/></dir><dir name="Form"><dir name="Field"><dir name="Array"><file name="Additional.php" hash="d62316e3631c1c2b6a0119134c8002a8"/><file name="AdditionalFeed.php" hash="dcfb6d37d765a10e4a07465e70133dda"/><file name="ArticleAdditional.php" hash="38c62d610f585c460151841f7350348b"/><file name="ArticleIdentifier.php" hash="ec9479fd1ca087a1fe924795cc9ff5f6"/><file name="DefaultSort.php" hash="4989d99a73f57bed1fb994060cc38a72"/><file name="Facet.php" hash="7217f2296afaf11f514e4212a7a82cb9"/><file name="Identifier.php" hash="a9fa99227182bd72e59c9a315d580247"/><file name="ProductAdditionalFacet.php" hash="8d46e427d9efbac7e6ba04fdc88d4728"/><file name="ProductAdditionalField.php" hash="9c9f9c9c1c940963e1a24c039a392cc4"/><file name="ProductIdentifier.php" hash="d30809119cb35018697533075f7ee485"/><file name="Sort.php" hash="f986fbb048bf3f6aec813cdc1c70ec15"/></dir><file name="CategoryAttribute.php" hash="c119ca65f23950e7abb1f0d60e8b4755"/><file name="ProductAttribute.php" hash="6a61b98a9f6ac883a5e162e3edab300d"/></dir></dir><dir name="Html"><file name="Export.php" hash="f36beeca11c51e1a2e9678955d8cf1b8"/><file name="ShowXml.php" hash="7b70f39937aa9d24336edde6bdbdf97c"/><file name="Version.php" hash="34c624c382f3061cf322cfed52c416ac"/></dir></dir></dir></dir><dir name="Helper"><file name="Antidot.php" hash="7bbd2866c65a847e1415badb1ef0d015"/><dir name="CatalogSearch"><file name="Data.php" hash="81cc908609e68035d5714488f913e688"/></dir><file name="Compress.php" hash="12fa64a9c9f519a3f249954ab780e01c"/><file name="Data.php" hash="db586edb739ad7f7b0281a887e252a61"/><dir name="Enterprise"><dir name="Search"><file name="Data.php" hash="8bfe0146c64511f86cb796638b65112f"/></dir></dir><file name="LogExport.php" hash="6d6b262327bf1d920fc2b5b112edfef6"/><dir name="ManaFilters"><file name="Data.php" hash="f4f4e92c5e33c6142904cf27a75f6d23"/></dir><file name="Url.php" hash="1d2ee02a8e135bfc4b866f5219f62acd"/><file name="XmlWriter.php" hash="66cf65d950caddf895c823c5575a1912"/></dir><dir name="Model"><dir name="Catalog"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="3cd18414abccea60c5497931bc95e21e"/><file name="Boolean.php" hash="dd0414e0d96833bec6e32aac321c2763"/><file name="Category.php" hash="4dea470cb36708e0ae4b95bd0a24a85f"/><file name="Decimal.php" hash="b9b1e2cff1d0332fab77d101dca4c3d2"/><file name="Item.php" hash="c89bbca267af18a0447e0daf3e7cc8eb"/><file name="Price.php" hash="7529be0313a19896993f92eeb9dfc8a9"/></dir></dir><file name="Layer.php" hash="706000dd944a45f30826eccba2942862"/></dir><dir name="Catalogsearch"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="a83d6761a949c8196cba33948a48c8bf"/></dir></dir><file name="Layer.php" hash="b5aa8e2cc24f1b1362749049f1cdec32"/><dir name="Resource"><file name="Attribute.php" hash="80d2a34d746f307109b6bf910b0f2958"/></dir></dir><dir name="Export"><file name="Abstract.php" hash="b1c695f2ab0fb63a9c253ceb68883845"/><file name="Article.php" hash="790a58f2fa28c52302c996163b884393"/><file name="Category.php" hash="d3a82f9ace086bf0bec88e585e37578a"/><file name="Context.php" hash="d63d33f2dfa968e90ed11a6f76f41a34"/><dir name="Model"><dir name="Product"><file name="Link.php" hash="6f764a25fcde9b315d10f46189a428d1"/><dir name="Type"><file name="Configurable.php" hash="4bb627c1f5d1fbadd37a6b54e681406f"/><file name="Grouped.php" hash="8770d1ddf8228a2db136325da494de51"/></dir></dir><file name="Product.php" hash="fe1cbcf9257581f01bb1072db813355f"/></dir><file name="Product.php" hash="a3619bfbab7c81691775d5b747c57a47"/></dir><file name="Observer.php" hash="ac85f1a93b71df59fad86dbcd0579c53"/><dir name="Resource"><file name="Advanced.php" hash="989026021706cbcfb269451187002c19"/><dir name="Catalog"><dir name="Product"><file name="Collection.php" hash="1811ce81b3c42ec999541b5f493f0985"/></dir></dir><dir name="Engine"><file name="Abstract.php" hash="6fc0659e9f57633a707254680ad23e70"/><file name="Antidot.php" hash="6f038510c3eb9d6908443dec15d14232"/></dir><dir name="Export"><dir name="Product"><file name="Collection.php" hash="dfa31e927797fb1887aec5fcec2747d1"/><dir name="Link"><dir name="Product"><file name="Collection.php" hash="a50b67c39520422770b4b16d4ab51ba0"/></dir></dir><dir name="Type"><dir name="Configurable"><dir name="Product"><file name="Collection.php" hash="79d359ae0e176d3499225452d983c210"/></dir></dir></dir></dir><file name="Product.php" hash="f3e87d35ea55e911948f3909274e29b3"/></dir></dir><dir name="Search"><file name="Abstract.php" hash="fd71154b987b16f8d13bc3e10a3faeac"/><file name="Search.php" hash="4a70644bdcd6ade7519cfebe7bbe4a85"/><file name="Suggest.php" hash="6caac0bb7683b1d330049ed0d606f36f"/></dir><dir name="System"><dir name="Config"><file name="ArticleAttribute.php" hash="f3a9596d45f275299f16530a56845c96"/><dir name="Backend"><file name="Engine.php" hash="68c93651655a77c74fd79d1de6d19be3"/></dir><file name="CategoryAttribute.php" hash="9f19b99e16c99b0e8052b1e31d2a6317"/><file name="Dir.php" hash="c80d83280ebc5ab91fd45d246ec47ba3"/><file name="DisableEnable.php" hash="6d08f33a1580b2fd1d58d87248104166"/><file name="Facet.php" hash="8b771072a32f32e81a087581ace7fd72"/><file name="Number.php" hash="7985ea6c495a35173d68291389319f93"/><file name="Options.php" hash="06930da994dec4bb05ebc3f3e8c8abb8"/><file name="ProductAttribute.php" hash="c74ad00177c3a12b03c8684928d12c40"/><file name="PromoteRedirect.php" hash="c167973ea7a0ef09f0e5fa0fd0a08926"/><file name="Sort.php" hash="e0d2c1e72f56894b75baebcb6c4b8609"/><dir name="Source"><file name="Acpengine.php" hash="fdf8d5030d8823c325d707d8bb5b7208"/><file name="Engine.php" hash="0491592c4612779ffc7890456f6b946d"/></dir><dir name="Suggest"><file name="Type.php" hash="cef491efdb9fcef86d0df75030206a78"/></dir><file name="WSStatus.php" hash="ff4954e15d75dd3139290d96773d0abf"/></dir></dir><dir name="Transport"><file name="Abstract.php" hash="3272c44b08523a9836aa15c835e2ed25"/><file name="File.php" hash="0941fd452279605a2ea6a5d40f857000"/><file name="Ftp.php" hash="291dac423dbd826394b8028c6b00064b"/><file name="Http.php" hash="fb80d47a6d991b9f706418061a2cbd7e"/><file name="Interface.php" hash="32d1d3958e0cd726bc34cae482464ef8"/></dir><file name="Transport.php" hash="96c10d2ff359849de991d8a045cc9353"/></dir><dir name="Test"><dir name="Block"><dir name="Catalogsearch"><file name="Layer.php" hash="49725570e661d72db50daab46e0e18af"/></dir><dir name="System"><dir name="Config"><dir name="Button"><file name="AfsStore.php" hash="dcbfefb440b8512b1298b624a3582076"/></dir></dir></dir></dir><dir name="Helper"><dir name="CatalogSearch"><file name="Data.php" hash="a40c1e58b5000432763aa07dd49d4b5d"/></dir><file name="Data.php" hash="9c21bd8bfa43dab48d95a886812587e6"/></dir><dir name="Model"><dir name="Export"><dir name="Abstract"><dir name="fixtures"><file name="testGarbageCollection.yaml" hash="de6c8672be0c24a102ebfed004f2361b"/></dir></dir><file name="Abstract.php" hash="094d78a413adb76559ba3e0063f7eb03"/><file name="Article.php" hash="157dc12608521f1ad255142f0143ef18"/><dir name="Category"><dir name="fixtures"><file name="testEmptyFile.yaml" hash="9573e620466cfe8260f8a87e274c8261"/></dir></dir><file name="Category.php" hash="43c0813b3b00f68b1920b4e66cb3604d"/><dir name="Context"><dir name="fixtures"><file name="testContext.yaml" hash="d912a7bd71a209f591043a3644de3ceb"/></dir></dir><file name="Context.php" hash="1043f3b0b99d3d290d4f38e633864a25"/><dir name="Product"><dir name="fixtures"><file name="testInactiveParentCategory.yaml" hash="3ef9bcefae6399ccdc23e026746a1743"/><file name="testWriteImageUrl.yaml" hash="a4e08b8f1565eba67a16553cf57e1004"/><file name="testWritePricesFixedtax.yaml" hash="698da07581100c1eff5a1a85e2be6d3b"/><file name="testWriteProductNoVariant.yaml" hash="626a27b35977e5a52b02f85011c5e216"/><file name="testWriteProductNoVariantInStock.yaml" hash="9aa7736a422276842350ac73c6f4ba55"/><file name="testWriteProductUrl.yaml" hash="a4e08b8f1565eba67a16553cf57e1004"/><file name="testWriteProperties.yaml" hash="d434749b80908bbceefd5781e2d0e998"/><file name="testWriteXml.yaml" hash="774cbe1c5408ff8ad838f1693ec11d84"/></dir><dir name="providers"><file name="testWriteImageUrl.yaml" hash="666c33585c611bcc0b0ebe6e87dce1fc"/><file name="testWriteProductUrl.yaml" hash="18f511460efea04586fc888f5c85b3ea"/></dir></dir><file name="Product.php" hash="c3992e99a2752e8d8240de824faa4292"/></dir><dir name="Observer"><dir name="fixtures"><file name="testGetDefaultContext.yaml" hash="5b3998808a9667ba79e8138104e24b00"/></dir><dir name="providers"><file name="testGetOwnerForFilename.yaml" hash="c5c07e73f536f9ffacc0c3ff6b5a13d1"/></dir></dir><file name="Observer.php" hash="c69240a8fe5a637c3aa447c94550e268"/><dir name="Resource"><dir name="Catalog"><dir name="Product"><file name="Collection.php" hash="2ad006d8e096ade9043a9a370177782d"/></dir></dir><dir name="Engine"><dir name="Antidot"><dir name="fixtures"><file name="testFormatResult.yaml" hash="a1a684d4f08b4d3e3b7f3711e7563010"/></dir></dir><file name="Antidot.php" hash="46cbb6e95678c8fd55badb021a5a1a32"/></dir></dir><dir name="Search"><dir name="Suggest"><dir name="fixtures"><file name="testSuggest.yaml" hash="e845f0311d93608e3221fb0678f429cc"/></dir></dir><file name="Suggest.php" hash="d97172c8ec094146f953a9704f8e1936"/></dir><dir name="System"><dir name="Config"><dir name="Facet"><dir name="fixtures"><file name="testToOptionArray.yaml" hash="b76143bd57f68be024a31d905da9cabe"/></dir></dir><file name="Facet.php" hash="3e3ef7aa45b4226df9eaf177ed69326f"/><dir name="Sort"><dir name="expectations"><file name="testToOptionArray.yaml" hash="13fc5b4c17962fb267f443d03a2219b2"/></dir><dir name="fixtures"><file name="testToOptionArray1.yaml" hash="3160d541123737644dfea5c70db35f41"/><file name="testToOptionArray2.yaml" hash="74fd97f93892920908ab7eab0124eeb6"/><file name="testToOptionArray3.yaml" hash="fe9c8a5da75f3c0d66304a39c473a3bb"/></dir></dir><file name="Sort.php" hash="3435402ae9aa30d18c8265433d643d21"/><dir name="Source"><file name="Engine.php" hash="dcbee0d360773c28faa8a894cbed22ad"/></dir></dir></dir></dir><file name="PHPUnitUtil.php" hash="2a128a7c19f4c37cb9dd7fc60e679693"/></dir><dir name="controllers"><dir name="Admin"><file name="PushController.php" hash="3f7be8a53c7a01cfd11aa5a8a8fcfac6"/></dir><dir name="Front"><file name="SearchController.php" hash="d220bd4628830ea238775ed9788e0674"/></dir></dir><dir name="etc"><file name="config.xml" hash="ce5e9dd82d1077072064ec847d585434"/><file name="system.xml" hash="f1678909f76c86b3ce017b5d351a0bb9"/></dir><dir name="sql"><dir name="Antidot_setup"><file name="mysql4-install-0.9.php" hash="62672bc47ea92dbd46966fb76e4251e0"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="antidot.xml" hash="5124433ec044f619ae99afb074ed6efc"/></dir><dir name="template"><dir name="antidot"><dir name="catalog"><dir name="layer"><file name="category.phtml" hash="3ec81f7b3e3b947317da8664c8e15927"/><file name="filter.phtml" hash="2304baebff9b798e0ebd977fbc891346"/></dir></dir><dir name="catalogsearch"><dir name="result"><file name="banner.phtml" hash="4dc4b69ef2dd51aad9689dbfb2bf8f48"/><file name="category.phtml" hash="7413580b825508f2cfc08566d62369ae"/></dir><file name="result.phtml" hash="de6eecf5bd733d3440c843133afea8b6"/></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="MDN_Antidot.xml" hash="988c6b7e9da4e50f1727956833ab1696"/></dir></target><target name="magelocale"><dir name="de_AT"><file name="MDN_Antidot.csv" hash="6d55b32bb063457c70296109170f944c"/></dir><dir name="de_CH"><file name="MDN_Antidot.csv" hash="6d55b32bb063457c70296109170f944c"/></dir><dir name="de_DE"><file name="MDN_Antidot.csv" hash="6d55b32bb063457c70296109170f944c"/></dir><dir name="es_AR"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_CL"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_CO"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_CR"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_ES"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_MX"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_PA"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_PE"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="es_VE"><file name="MDN_Antidot.csv" hash="b7f7906a0af8c8a524033fe6565b8da1"/></dir><dir name="fr_CA"><file name="MDN_Antidot.csv" hash="cb32f785ce819fe925347b7863d8de36"/></dir><dir name="fr_FR"><file name="MDN_Antidot.csv" hash="cb32f785ce819fe925347b7863d8de36"/></dir></target><target name="mageweb"><dir name="js"><dir name="mdn"><dir name="antidot"><file name="CollapsibleLists.js" hash="86792ecde0c2759ba85e0d863dd147ce"/></dir></dir></dir></target><target name="magelib"><dir name="antidot"><dir name="AFS"><dir name="ACP"><file name="Makefile" hash="0f76232bfabc275a3dac973666fb5dae"/><dir name="TEST"><file name="Makefile" hash="ce56cc786e1df50148e1d3222c05e5f8"/><file name="acpConnectorTest.php" hash="25a8194f3dc8895640df4f4bba895d8e"/><file name="acpQueryTest.php" hash="74ad65a4af639a409ee72a75a2a043d6"/><file name="acpReplysetHelperTest.php" hash="4f0a0d471a06e139cd11c715b67ebe81"/><file name="acpResponseHelperTest.php" hash="6d30f99108db0d9956aef9ba5e1d88df"/><file name="acpTest.php" hash="d6119d150543e7943ba4e9907901ae5d"/></dir><file name="afs_acp.php" hash="78dbfbc92f68469c92898f1da4263e68"/><file name="afs_acp_configuration.php" hash="2d644cc6c5bf2cdaeca5780576c4bf0e"/><file name="afs_acp_connector.php" hash="b72439562b02024e0b9629c18394985d"/><file name="afs_acp_exception.php" hash="f610d2cc37a15d4b981d7b43939414ad"/><file name="afs_acp_query.php" hash="ced0629355f5d4fc1c219d1adb03297d"/><file name="afs_acp_query_manager.php" hash="b3348972a850c904fc664b4e27671439"/><file name="afs_acp_reply_helper.php" hash="b0259f24f10d2e92ed6e3b8cdaaacc44"/><file name="afs_acp_replyset_helper.php" hash="07e7fdb88a42a399c96261c47ffb0231"/><file name="afs_acp_response_helper.php" hash="33a66106fd3a94194514a0d8d39af1cd"/></dir><file name="Makefile" hash="7bb31592939024f74745d6b6cb7fec0b"/><dir name="SEARCH"><dir name="FILTER"><file name="Makefile" hash="d42338199c6857ded179af2117b9f571"/><dir name="TEST"><file name="Makefile" hash="ab37090c6c5e7af1b260376237737700"/><file name="filterBuilderTest.php" hash="161ff5c8e73914eef884d17456afa133"/><file name="filterCombinationTest.php" hash="2162288d5255d3b24fe94d75b939aa51"/><file name="filterTest.php" hash="1682c0a4d50158a8d2c9369d30e45a18"/><file name="groupFilterTest.php" hash="1ebe8ce7344ed64b93cf94632d3b0184"/></dir><file name="afs_combinable_filter.php" hash="336e6c6bc9ebae3f58602d23ef734182"/><file name="afs_combinator_filter.php" hash="e2fc560b9c0c31f20c73f2057a8b7b69"/><file name="afs_filter.php" hash="6dbfc8c668cd48510cc9a9243d1bf4c3"/><file name="afs_filter_exception.php" hash="ccce583c63a4a65f7f0a27fc4a487505"/><file name="afs_filter_wrapper.php" hash="30dec104456abc037019ad93922b5afd"/><file name="afs_group_filter.php" hash="b95fa3bc0e26bc39dfc53a6010bce32f"/><file name="afs_native_function_filter.php" hash="37176bdbc66cc3dca18149132921f0a5"/><file name="afs_operator_filter.php" hash="c7ea43c8d64eedbe33397f61737e0226"/><file name="afs_valued_filter.php" hash="483653071734f77972c9b9771e187d82"/></dir><file name="Makefile" hash="0f76232bfabc275a3dac973666fb5dae"/><dir name="TEST"><file name="Makefile" hash="ce56cc786e1df50148e1d3222c05e5f8"/><file name="clientDataHelperTest.php" hash="1556ab047e1df23447586d529768befd"/><file name="clusterHelperTest.php" hash="e112e7c756f63c8e8ceb554281b418c9"/><file name="conceptHelperTest.php" hash="b44e39b62d0537bf1f7b7feb23f8111f"/><file name="facetDefaultTest.php" hash="382e4ea35e1c7173371b4a84046a38e5"/><file name="facetHelperTest.php" hash="d51a714bc116e77f5f115c26e9640f10"/><file name="facetManagerTest.php" hash="bbef8e207c387dbe6a26142fd55264d5"/><file name="facetTest.php" hash="26123aa75cb2597a3ededfa9d778095d"/><file name="facetValuesSortOrderTest.php" hash="b650080bf9b2cce2ac42a245cb84c911"/><file name="feedCoderTest.php" hash="f2b5dfdd4fa3c4e5d14c790d15235146"/><file name="filterCoderTest.php" hash="46249fa13edccf1e5d5000daf2573b77"/><file name="headerHelperTest.php" hash="8eb9450972ce082c35d7b66be7735d79"/><file name="helperConfigurationTest.php" hash="be3f74e53e27744e8214f3c341172796"/><file name="intervalTest.php" hash="912389dad049853f6bf0b4eab2af5034"/><file name="metaHelperTest.php" hash="080f160b54636c4eee743544a6a12bee"/><file name="pagerHelperTest.php" hash="d96a9891523e453647493f3219e86357"/><file name="promoteBannerReplyHelper.php" hash="94c3c14517536437e9800eaa706fbe29"/><file name="promoteRedirectReplyHelper.php" hash="ed00c66be5127d8b374f6416abf328ef"/><file name="promoteReplyHelperTest.php" hash="7cbb68a7f50c2bd2ef11a085ac94deb2"/><file name="promoteReplysetHelperTest.php" hash="ac2f1e3073015143dc7b2b705711c845"/><file name="queryCoderTest.php" hash="03983a114c6697464f8bf016822ff4a3"/><file name="queryTest.php" hash="338264d8e6dbbc09e88bd9a8179e8be4"/><file name="replyHelperTest.php" hash="4d86f19ea7de2aece5d7fd9c143c3dbc"/><file name="replysetHelperTest.php" hash="897f074b8382c6853f51b06a5ee50b0a"/><file name="responseHelperTest.php" hash="ebb167e1c330af6aa0e6a2b917431040"/><file name="searchConnectorTest.php" hash="9201de573884b643041b6c32bc535e7e"/><file name="searchQueryManagerTest.php" hash="2188b262a1c11422bcc8133f68fa6dd9"/><file name="searchTest.php" hash="fa47a7819b5c7c71172d6b1f1e7a02f7"/><file name="spellcheckHelperTest.php" hash="49960fb90055dcf265ef41e491c11325"/><file name="spellcheckTextVisitorTest.php" hash="203f0d08f548a39135517a41f6e9e43a"/><file name="textVisitorTest.php" hash="b722845dd0f5f953574cb51284ad025b"/></dir><file name="afs_base_reply_helper.php" hash="57abe4828b7ed7126db963764faa718a"/><file name="afs_base_replyset_helper.php" hash="096b124a3ebdc6e8d6beb359bd8bb7c5"/><file name="afs_client_data_exception.php" hash="899957af974d04aa7eaca44903a7f86c"/><file name="afs_client_data_helper.php" hash="4700218e2400350014fde428bc86806b"/><file name="afs_cluster_exception.php" hash="86d97623db7aebaa28a20857ce2cf17f"/><file name="afs_cluster_helper.php" hash="60b7fbcc869a672929ef9fc6d840d2b2"/><file name="afs_cluster_parameter.php" hash="20ed527d3ed1a6cf2bc80e032ecd2c7e"/><file name="afs_coder_base.php" hash="fb87fbea43d12695154b3b6102e2a019"/><file name="afs_coder_interface.php" hash="3b179b2513e215751ee4edd190b2a719"/><file name="afs_concept_helper.php" hash="982cf3d2063c565cf19cc6136b049066"/><file name="afs_count.php" hash="9f83f3baa3cf4462c0db786f4eea479a"/><file name="afs_facet.php" hash="1b4d7d35ebe8ed4894fda4881d0b168f"/><file name="afs_facet_combination.php" hash="005e9742ee032194b86856195dd59f7d"/><file name="afs_facet_default.php" hash="cbcb5d28b7b00815ce5248017065e84b"/><file name="afs_facet_exception.php" hash="f1f0afdbf9a727b53c4731e5a40ac417"/><file name="afs_facet_helper.php" hash="fe1ca1e7242c319bac96488b1f5e2063"/><file name="afs_facet_helper_retriever.php" hash="5628cc41c50ab25fd3336df302d903f4"/><file name="afs_facet_layout.php" hash="c83f6fef1c13ba3cda667c611841ff87"/><file name="afs_facet_manager.php" hash="a3fabb34d56a9614d4a0a2917f6fea0c"/><file name="afs_facet_mode.php" hash="8dcac389a37f8267a367400377631dba"/><file name="afs_facet_sort.php" hash="0d7ba4059b10da9981b9c801355cb874"/><file name="afs_facet_type.php" hash="6df82cbfa627629f9523437994d1fbb1"/><file name="afs_facet_value_formatter.php" hash="d6580281f9ef5c0820615ac385aae863"/><file name="afs_facet_values_sort_mode.php" hash="17def98365132c810515f8cf3c6fb006"/><file name="afs_facet_values_sort_order.php" hash="f95f77cb5dd7015e4f2e6094ddba49a6"/><file name="afs_feed_coder.php" hash="ed7b40e872a7ed5aa30adbcffc05de56"/><file name="afs_filter_coder.php" hash="4edbdcf6760d80465e5d2533014ba307"/><file name="afs_filter_parameter.php" hash="2b03c2c83ffe2e2968aaf50ad4903921"/><file name="afs_fts_mode.php" hash="edbd9342cd9625183e1e01ed81b79fc3"/><file name="afs_header_helper.php" hash="3b30d839efe9128773c82d47cbd591b8"/><file name="afs_helper_configuration.php" hash="dbd0378574fbc5729babfbddfef0fd67"/><file name="afs_interval.php" hash="dbf9749881be0a2b063f8a33dff214f3"/><file name="afs_interval_exception.php" hash="40f223de231df03aae59596c1a493065"/><file name="afs_meta_helper.php" hash="8403689868c98db725ebd11748508c8b"/><file name="afs_pager_helper.php" hash="077052931e0cffb1e589c21b57156b38"/><file name="afs_producer.php" hash="7c8c515ccb8126523fa0d09a7f759dd5"/><file name="afs_promote_banner_reply_helper.php" hash="418702b3c053029b3aa8fcb2775c65bd"/><file name="afs_promote_redirect_reply_helper.php" hash="be17eda6f8b4552b9ec21183362171a2"/><file name="afs_promote_reply_helper.php" hash="0e2a4f67cd307f74e8b64cd3b158235c"/><file name="afs_promote_replyset_helper.php" hash="fdefc6f8a686addb31ea9b6c0a3fa5ad"/><file name="afs_query.php" hash="bd969a62cd4bbbcb5b9996eaa19353f7"/><file name="afs_query_coder.php" hash="ca0bfad66b8d8549ab3f33380d716732"/><file name="afs_query_coder_interface.php" hash="dd16f17b3606a7418c1c714475b19b51"/><file name="afs_query_object_interface.php" hash="a9af13e2c856e4136ccadfff60f72d36"/><file name="afs_raw_text_visitor.php" hash="fd574583c4c9110165c1cadc67b832de"/><file name="afs_reply_helper.php" hash="3919f9e83cba62be9bc67117b1087b03"/><file name="afs_reply_helper_factory.php" hash="f159f7d0ef7e5a209fb872a970d0d582"/><file name="afs_replyset_helper.php" hash="cb8f81391d9a59904dcb0c3d6ae31999"/><file name="afs_response_exception.php" hash="0a865bb92fb700ae555dcb5ae675f644"/><file name="afs_response_helper.php" hash="2fec8d101712087660dc6aba5119e3c2"/><file name="afs_search.php" hash="3f2e3ef447515a2fa05b270654ef2969"/><file name="afs_search_connector.php" hash="17242fb6536f4596b2c0198a16986310"/><file name="afs_search_query_manager.php" hash="77e30683ee4ba9e004e9c7c12d9c811d"/><file name="afs_sort_builtins.php" hash="0cc1617a62f1a834a28d7d2ac249b081"/><file name="afs_sort_coder.php" hash="1dfe2d32278383d8465df67535cb91dd"/><file name="afs_sort_order.php" hash="7755deb99386650c9974871474168cda"/><file name="afs_sort_parameter.php" hash="bfb8c59c1560ec8a3b597dc45aa8ecd5"/><file name="afs_spellcheck_helper.php" hash="bb5465848ada7a9df9875f2565fb9686"/><file name="afs_spellcheck_text_helper.php" hash="3ca5c3118660aa600aadb504ceff6c4c"/><file name="afs_spellcheck_text_visitor.php" hash="c44c23ae21f61b065e457911bbc45ed2"/><file name="afs_text_helper.php" hash="59c4ae24560948c3af0f4adbf6bd1803"/><file name="afs_text_visitor.php" hash="867b44a280403cd4567358ec6d59588a"/></dir><file name="afs_configuration_base.php" hash="f26dd9efda4923cc2c71057f21be97d9"/><file name="afs_connector.php" hash="aa04a21163b57ef338bf96bd55e95882"/><file name="afs_exception.php" hash="c1840fe279f9cb313cec151012ed4513"/><file name="afs_feed.php" hash="005305cace79a3aa7719a3c942df9da7"/><file name="afs_multiple_values_parameter.php" hash="96dc30f1fbf137cbfd73c2b195d9f9ef"/><file name="afs_origin.php" hash="a6b7e39a687210572c116afcbea0e7cb"/><file name="afs_query_base.php" hash="7209115a714d9b7de209a0af691c1d22"/><file name="afs_query_parameter.php" hash="6552428d955d0a48c015e1f98ba62815"/><file name="afs_response_helper_base.php" hash="b087f7bdad35ed0526566042ef9afc8c"/><file name="afs_single_value_parameter.php" hash="65d002d7ac6b6e8dd6170309b4c84649"/></dir><dir name="AIF"><file name="Makefile" hash="2d232abf9913fcabb44033d5e5d1ebfd"/><dir name="TEST"><file name="Makefile" hash="24d3030d27e88732028d14fb1d81c203"/><file name="afsMultipartResponseTest.php" hash="70a64d0d599ea01806fac2126fb3680a"/><file name="authenticationTest.php" hash="2e476e9ab15ee221ddd63bb555262a28"/><file name="bowsInformationTest.php" hash="3bbfe71f431a35f0285afdca40906874"/><file name="documentManagerTest.php" hash="ad90a6146f5aeee383355bb05425b3dd"/><file name="documentTest.php" hash="59b204b10b90cd764b259ad4c2bc043a"/><file name="pafConnectorTest.php" hash="ac2928b501d9ea167af43dbf3adafa7d"/><file name="pafLiveTest.php" hash="92862c31d151c34b2caf44bff9d0fb80"/></dir><file name="afs_about_connector.php" hash="8972264a9b7cce237ad1a4b47852b529"/><file name="afs_authentication.php" hash="4285035550c9681a047b85abbca64936"/><file name="afs_bows_connector.php" hash="47a6bcafd5eba2361d2cea409f60d3f7"/><file name="afs_bows_connector_interface.php" hash="8fdf9749f0500a39741d696feb55af14"/><file name="afs_bows_exception.php" hash="1bd8657a37b8b4a9e08bfc4eb6b7e416"/><file name="afs_bows_information.php" hash="1f96a4cd84b2332f1186f9e0cea8542d"/><file name="afs_bows_information_cache.php" hash="1ae9a9243342c4e58a52e70473b68472"/><file name="afs_document.php" hash="c0003ec962a79b9d3f642b17bade0fff"/><file name="afs_document_manager.php" hash="8c5c0105d9337b7ae6a9f041f643ea88"/><file name="afs_multipart_response.php" hash="f2077c9eaf121fabdb2fc26c23b2e256"/><file name="afs_paf_connector.php" hash="96111b0536c83874b7c06ada5577106b"/><file name="afs_paf_live_connector.php" hash="9efeb2716f6d95e666f9c37726869fe7"/><file name="afs_paf_upload_reply.php" hash="0cb4905d1c894637d5e6acbd2cffc112"/><file name="afs_token_authentication.php" hash="1f003310f156f0a71db1d273375172d8"/><file name="afs_user_authentication.php" hash="03deeead93ee32753f2f7f80cfc011f4"/></dir><dir name="COMMON"><file name="Makefile" hash="7bb31592939024f74745d6b6cb7fec0b"/><dir name="TEST"><file name="Makefile" hash="d568cfe3683543f363312aa4b6d2bbad"/><file name="languageTest.php" hash="ad0f75b1c2f320c81eba32cade86191c"/><file name="toolsTest.php" hash="9276cb1a275d697f8e8365f2ac340cdf"/><file name="userSessionManagerTest.php" hash="b2b78d6fa156f1a61065f8ee5bfc6e0b"/></dir><file name="afs_connector_base.php" hash="b6b1f091ec71e5b92e4a1e5ca958255f"/><file name="afs_connector_interface.php" hash="68ad5e20a861b85dbf198f79cd2afd4c"/><file name="afs_exception.php" hash="b8eed4376088ae3003d0b77cc523e732"/><file name="afs_helper_base.php" hash="839cca78a663c3a22b4a8e35d1460129"/><file name="afs_helper_format.php" hash="30a3f6e945db7412ef95e83e7b0b5898"/><file name="afs_language.php" hash="277acb15b86089b37c812c47f2141d3c"/><file name="afs_service.php" hash="12c00c906e130860120552c40fa9dbc2"/><file name="afs_service_status.php" hash="1dee172850a76b46987534df89013878"/><file name="afs_tools.php" hash="26f6c01c5a61987925385e7a35260399"/><file name="afs_user_session_manager.php" hash="abd625f6b7b5cecf386dac9d82887764"/><file name="afs_versions.php" hash="556c912ff7f19f5083c4fb44d4d40ac6"/><dir name="lib"><dir name="JsonPath"><file name="JsonPath.php" hash="baa12e1baa9f8a20a095463042e96ad3"/><file name="JsonStore.php" hash="a9632aeb2126e98db9a49403a8f2ff77"/></dir></dir><dir name="php-SAI"><file name="README.md" hash="63ab581c83fe44918e6d074e20f08f95"/><dir name="lib"><dir name="Curl"><file name="Handle.php" hash="0fc7132737da7cee7df6b974447864ac"/></dir><file name="Curl.php" hash="358e4d3afca2035ee4d3f99f372ed15a"/><file name="CurlInterface.php" hash="714fa045dd4546d0c92cd022efb09422"/><file name="CurlStub.php" hash="fbdc0ece6321c5b5a1e27a65449f4a1f"/><dir name="rb_temp"><file name="HttpClient.php" hash="091b91c98acf9f1cd6c3d6d75cddfb88"/><file name="MultiCurl.php" hash="916e85d73bae6e136f889166ebc6db17"/><file name="SimpleCurl.php" hash="c296966a8bda96e03b464a1d3a9c8e06"/></dir></dir><dir name="tests"><file name="SAI_CurlStubTest.php" hash="bce69cbb17a40bd4eeba6bad1133216e"/></dir><file name=".gitignore" hash="09e625dea07b4d4098b19ec998d266f9"/></dir></dir><file name="COPYING" hash="b234ee4d69f5fce4486a80fdaf4a4263"/><file name="COPYING.LESSER" hash="4fbd65380cdd255951079008b364516c"/><file name="FAQ.md" hash="7d7c886674d70a0047303c5d93de6165"/><file name="Makefile" hash="225475a5a4a0204cecbb77621ff38bb2"/><file name="README.md" hash="7ecfd33825a0e6bc50cca099c1c0e50e"/><file name="afs_lib.doxygen" hash="8128d53d894cc57e08142377d13c72f4"/><file name="afs_lib.php" hash="946834742cd313e818f79bb96b6dfb52"/><file name="afs_version.php" hash="d2d295f9758c29cb26173f9095ff1400"/><file name="composer.json" hash="39190df70fafa99d7eb5ab566e8edf3f"/><dir name="doc"><file name="afs_filter_documentation.dox" hash="3bf4b96e25d95ce5953b822038c6f135"/><file name="afs_paf_upload.dox" hash="d36893db0234f171e6cfb43f6e13d47c"/><file name="afs_search.dox" hash="b1c5ab8728703822f910852cd17561f4"/><file name="afs_search_coder.dox" hash="77709e1bc691301017f0982e0348a9b9"/><file name="afs_search_query.dox" hash="21dcd1734a165a4cb3b4f62c42a6a0be"/><file name="afs_search_reply.dox" hash="cdb1d42447671f4352927b40b3f8f37d"/><dir name="data"><file name="acp_helper_example.php" hash="2815890e7afbae78e7eb4e6fc5c88f6f"/><file name="full_example.php" hash="e152a964d06e55de460c596070c714d8"/><file name="full_lightweight_example.php" hash="eac3bb2d251052f547a9f737e5cd0461"/><file name="raw_example.php" hash="703356b9284e7fe904cf1334abbe08c9"/><dir name="templates"><file name="error_template.html" hash="70f44bd0f45470d379a11d0a2fe507e4"/><file name="facet_template.html" hash="6836005a7dae45e9415273f1eb6b78e2"/><file name="facet_values_template.html" hash="9b41f2b55a1cecae5724b4fcd4a46cfb"/><file name="meta_template.html" hash="e664a3bb222d272ce2451fb10bf46de4"/><file name="pager_template.html" hash="2700ab5b60a1f9553b1c39374fda63d4"/><file name="result_template.html" hash="1572a4ef4e8dda0b3db1ea77bbed4a98"/><file name="spellcheck_template.html" hash="8042054a1f5a271b47c77f81436c4791"/></dir></dir><file name="detailled_integration_example_with_template.dox" hash="26ef377a6ef546b636a0e254d11d01f5"/><file name="lightweight_integration_example_with_template.dox" hash="5a388d2dbfad63ad6ec353407b79a6bb"/><file name="logo-antidot-long-200x41.png" hash="1ceac3fff767fb5e395bd767344a3d13"/><file name="main.dox" hash="ca3e97f95deead927fb3298ecafbad5e"/><file name="raw_integration_example.dox" hash="56a7126d008c2e49abdf9bf0b5ec9717"/><file name="template_prerequisites.dox" hash="baa24a943e19ff3654227850bd316abb"/><file name="templates_in_details.dox" hash="5e8db94382f1fbd6c4e0b424a9edc9a3"/></dir><file name="rules.mk" hash="ff48aa6a5c40e31b3f38aba1267e9a71"/><dir name="scripts"><file name="gen_doc.sh" hash="0f6fc60aca94da563397d3c710bd9d33"/><file name="increment_version.sh" hash="431db9c60d2f94d251be07957787fcb0"/><file name="print_version.sh" hash="a05ddc19cd27ff185721fe2bd0cffc25"/><file name="version_management.sh" hash="3d5ecd39f45ba081144b3033dbd14330"/></dir><file name=".gitignore" hash="0292f51c0906b2092255872c69603f29"/><file name=".travis.yml" hash="4330b9c449e9cd0e97829f679c2a2786"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><dir name="mdn"><dir name="antidot"><file name="CollapsibleLists.css" hash="c956d83facc41a97bf14726dcb953edb"/></dir></dir></dir><dir name="images"><dir name="mdn"><dir name="antidot"><file name="base.gif" hash="1f71b021e061a4948d69adc4ff10ccad"/><file name="button-closed.png" hash="563b78324e0712c0902cb4f77cb9eb86"/><file name="button-open.png" hash="c710849a0d2b61ad1f0fc36c0e59d131"/><file name="button.png" hash="97f3055c5046c851eea2dad7e5227508"/><file name="cd.gif" hash="f41037663522fab5c5c31530c7fa43d8"/><file name="empty.gif" hash="df22aff6e941ff1cc577333d1712b584"/><file name="folder.gif" hash="ea16980ab437fa6ba4aba3d480e83e9e"/><file name="folderopen.gif" hash="18aa3d75315bf95bf080357733437fcc"/><file name="globe.gif" hash="d6b48614cf8dc9553e077c19197637d2"/><file name="imgfolder.gif" hash="1d488d377762e65ab4e8b691ba01e5a4"/><file name="join.gif" hash="4d5d614e0da056df815a4306d6368692"/><file name="joinbottom.gif" hash="4b3daa7f2cc584f1aac0d142275d7cba"/><file name="line.gif" hash="63ab38a6203262f15ca46c631232ea2c"/><file name="list-item-contents.png" hash="00ae24d5bc76df9eedaea597859963e4"/><file name="list-item-last-open.png" hash="615ddd71f81b240e9ed7d4e383b2c01a"/><file name="list-item-last.png" hash="e2bfb790f46855c378e50f3c0a82ea01"/><file name="list-item-open.png" hash="732d1cc59f3a488c89c624eb434eac98"/><file name="list-item-root.png" hash="5529d21e7ec68e9cb750a4895ff0b480"/><file name="list-item.png" hash="e03ec1bf3d9e16bb3005ccf8d26eaa6c"/><file name="minus.gif" hash="d647fbbd0ec410b8f3bb3357b62eedcf"/><file name="minusbottom.gif" hash="b09d684cca7135ef728141aaf2464baa"/><file name="musicfolder.gif" hash="21ece951734f23adb2f75befe1f31fc1"/><file name="nolines_minus.gif" hash="eb2243a354ffcfac93ba0fe948f7167d"/><file name="nolines_plus.gif" hash="ec92b634b63608fb4b0dbf114e3b89e1"/><file name="page.gif" hash="c25b136c1cb3bb145495c25b35d93754"/><file name="plus.gif" hash="5c55d798909c553deca31d610bd18fac"/><file name="plusbottom.gif" hash="1924ce363c38a992f888a4df48c0b274"/><file name="question.gif" hash="ea0ca196ce0ebfd625cc1210abfdec6c"/><file name="trash.gif" hash="6cbfd3ed29531044aed9b4edb3cca9ad"/></dir></dir></dir></dir></dir></dir></target></contents>
23
  <compatible/>
24
  <dependencies><required><php><min>5.2.0</min><max>5.6.0</max></php><extension><name>curl</name><min/><max/></extension></required></dependencies>
25
  </package>