Simtech_Searchanise - Version 2.0.2

Version Notes

[*] Full catalog import is now 2.5-3 times faster.
[*] For a group product, its child product descriptions are stored in a separate attribute (fixes the [:ATTR:] issue).
[!] The [:ATTR:] chunk could occur in the instant search widget. Fixed.
[!] Attribute weights tuned for more relevant search (e.g. description weight increased).

Download this release

Release Info

Developer Simbirsk Technologies, Ltd.
Extension Simtech_Searchanise
Version 2.0.2
Comparing to
See all releases


Code changes from version 2.0.1 to 2.0.2

app/code/community/Simtech/Searchanise/Helper/ApiXML.php CHANGED
@@ -32,9 +32,16 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
32
  // </if_isSearchable>
33
 
34
  // Tweaks
35
- const ADDITIONAL_CHECK_FOR_INCORRECT_PRODUCTS = true;
36
 
37
  protected static $flWithoutTags = false;
 
 
 
 
 
 
 
38
 
39
  public static function getStockItem($product, $store = null)
40
  {
@@ -86,6 +93,40 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
86
  return $tagCollection;
87
  }
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  /**
90
  * getProductImageLink
91
  *
@@ -93,69 +134,25 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
93
  * @param bool $flagKeepFrame
94
  * @param int $width
95
  * @param int $height
96
- * @return string
97
  */
98
  private static function getProductImageLink($product, $flagKeepFrame = true, $width = 70, $height = 70)
99
  {
100
- $imageLink = '';
101
 
102
  if ($product) {
103
- if (empty($imageLink)) {
104
- $smallImage = $product->getData('small_image');
105
-
106
- if (!empty($smallImage) && $smallImage != 'no_selection') {
107
- try {
108
- $imageLink = Mage::helper('catalog/image')
109
- ->init($product, 'small_image')
110
- ->constrainOnly(true) // Guarantee, that image picture will not be bigger, than it was.
111
- ->keepAspectRatio(true) // Guarantee, that image picture width/height will not be distorted.
112
- ->keepFrame($flagKeepFrame) // Guarantee, that image will have dimensions, set in $width/$height
113
- ->resize($width, $height);
114
- } catch (Exception $e) {
115
- // image not exists
116
- $imageLink = '';
117
- }
118
- }
119
  }
120
-
121
- if (empty($imageLink)) {
122
- $image = $product->getData('image');
123
-
124
- if (!empty($image) && $image != 'no_selection') {
125
- try {
126
- $imageLink = Mage::helper('catalog/image')
127
- ->init($product, 'image')
128
- ->constrainOnly(true) // Guarantee, that image picture will not be bigger, than it was.
129
- ->keepAspectRatio(true) // Guarantee, that image picture width/height will not be distorted.
130
- ->keepFrame($flagKeepFrame) // Guarantee, that image will have dimensions, set in $width/$height
131
- ->resize($width, $height);
132
- } catch (Exception $e) {
133
- // image not exists
134
- $imageLink = '';
135
- }
136
- }
137
  }
138
-
139
- if (empty($imageLink)) {
140
- $thumbnail = $product->getData('thumbnail');
141
-
142
- if (!empty($thumbnail) && $thumbnail != 'no_selection') {
143
- try {
144
- $imageLink = Mage::helper('catalog/image')
145
- ->init($product, 'thumbnail')
146
- ->constrainOnly(true) // Guarantee, that image picture will not be bigger, than it was.
147
- ->keepAspectRatio(true) // Guarantee, that image picture width/height will not be distorted.
148
- ->keepFrame($flagKeepFrame) // Guarantee, that image will have dimensions, set in $width/$height
149
- ->resize($width, $height);
150
- } catch (Exception $e) {
151
- // image not exists
152
- $imageLink = '';
153
- }
154
- }
155
  }
156
  }
157
 
158
- return $imageLink;
159
  }
160
 
161
  /**
@@ -229,12 +226,12 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
229
  *
230
  * @param Mage_Catalog_Model_Product $product
231
  * @param Mage_Core_Model_Store $store
232
- * @param bool $flagWithChildrenProducts
233
  * @param int $customerGroupId
234
  * @param float $groupPrice
235
  * @return float
236
  */
237
- private static function getProductMinimalPrice($product, $store, $flagWithChildrenProducts = true, $customerGroupId = null, $groupPrice = null)
238
  {
239
  $minimalPrice = false;
240
 
@@ -242,108 +239,121 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
242
  $product->setCustomerGroupId($customerGroupId);
243
  }
244
 
245
- if ($groupPrice != null) {
246
- $minimalPrice = $groupPrice;
247
- } else {
248
- $isCorrectProduct = true;
 
 
 
 
 
 
 
 
 
249
 
250
- // Additional check for incorrect configurable products.
251
- if (self::ADDITIONAL_CHECK_FOR_INCORRECT_PRODUCTS) {
252
- static $arrIncorrectProductIds = array();
 
 
 
 
 
253
 
254
- if (in_array($product->getId(), $arrIncorrectProductIds)) {
255
- $isCorrectProduct = false;
 
 
256
  }
 
 
 
 
 
 
 
257
 
258
- if ($isCorrectProduct && $product->isConfigurable()) {
259
- try {
260
- $attributes = $product->getTypeInstance(true)
261
- ->getConfigurableAttributes($product);
262
- foreach ($attributes as $attribute) {
263
- if (!$attribute->getProductAttribute()) {
264
- $isCorrectProduct = false;
265
- $arrIncorrectProductIds[] = $product->getId();
266
- Mage::helper('searchanise/ApiSe')->log('Incorrect configurable product ID = ' . $product->getId(), 'Warning');
267
- break;
 
 
 
 
 
 
 
 
 
268
  }
 
 
269
  }
 
 
 
 
 
 
 
270
  } catch (Exception $e) {
271
- Mage::helper('searchanise/ApiSe')->log($e->getMessage(), "Error: Script couldn't check for incorrect configurable product ID = " . $product->getId());
 
272
  }
273
  }
274
  }
275
- // end check
276
 
277
- if ($isCorrectProduct) {
278
- try {
279
- $minimalPrice = $product->getFinalPrice();
280
- } catch (Exception $e) {
281
- $minimalPrice = false;
282
- Mage::helper('searchanise/ApiSe')->log($e->getMessage(), "Error: Script couldn't get final price for product ID = " . $product->getId());
283
- }
284
  }
285
- }
286
 
287
- if ($minimalPrice === false) {
288
- $minimalPrice = $product->getPrice();
289
  }
290
 
291
- $minimalPrice = self::getProductShowPrice($product, $minimalPrice);
292
-
293
- if ($product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
294
- $_priceModel = $product->getPriceModel();
295
- if ($_priceModel) {
296
- // [1.5]
297
- if (version_compare(Mage::getVersion(), '1.6', '<')) {
298
- $minimalPrice = $_priceModel->getPrices($product, 'min');
299
- // [/1.5]
300
- // [v1.6] [v1.7] [v1.8]
301
- } else {
302
- $minimalPrice = $_priceModel->getTotalPrices($product, 'min', null, false);
303
- }
304
- // [/v1.6] [/v1.7] [/v1.8]
305
- $minimalPrice = self::getProductShowPrice($product, $minimalPrice);
306
- }
307
 
308
- } elseif ($flagWithChildrenProducts) {
309
- if ($product->isGrouped()) {
310
- // fixme in the future
311
- // maybe exist better solution get `minimalPrice` for `Grouped` product
312
- if ($typeInstance = $product->getTypeInstance()) {
313
- $requiredChildrenIds = $typeInstance->getChildrenIds($product->getId(), true);
314
- if ($requiredChildrenIds) {
315
- $childrenIds = array();
316
- $childrenProducts = null;
317
-
318
- foreach ($requiredChildrenIds as $groupedChildrenIds) {
319
- $childrenIds = array_merge($childrenIds, $groupedChildrenIds);
320
- }
321
 
322
- if ($childrenIds) {
323
- $childrenProducts = self::getProducts($childrenIds, $store, false, $customerGroupId);
324
- }
325
 
326
- if ($childrenProducts) {
327
- $minimalPrice = '';
 
 
 
 
 
 
 
328
 
329
- foreach ($childrenProducts as $childrenProductsKey => $childrenProduct) {
330
- if ($childrenProduct) {
331
- $minimalPriceChildren = self::getProductMinimalPrice($childrenProduct, $store, false, $customerGroupId);
 
332
 
333
- if (($minimalPriceChildren < $minimalPrice) ||
334
- ($minimalPrice == '')) {
335
- $minimalPrice = $minimalPriceChildren;
336
- }
337
- }
338
- }
339
- }
340
- }
341
  }
342
- // end fixme
 
 
343
  }
344
  }
345
 
346
- return $minimalPrice;
347
  }
348
 
349
  /**
@@ -370,7 +380,7 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
370
  }
371
 
372
  if ($childrenIds) {
373
- $childrenProducts = self::getProducts($childrenIds, $store);
374
  }
375
  }
376
  }
@@ -407,33 +417,39 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
407
  return $strIdValues;
408
  }
409
 
410
- private static function addArrTextAttributeValues($product, $attributeCode, &$arrTextValues)
411
  {
412
  $textValues = $product->getResource()->getAttribute($attributeCode)->getFrontend()->getValue($product);
 
413
  if ($textValues != '') {
414
- $arrValues = explode(',', $textValues);
415
- if (!empty($arrValues)) {
416
- foreach ($arrValues as $v) {
417
- if ($v != '') {
418
- $trimValue = trim($v);
419
- if ($trimValue != '' && !in_array($trimValue, $arrTextValues)) {
420
- $arrTextValues[] .= $trimValue;
421
- }
 
 
422
  }
423
  }
 
 
 
424
  }
425
  }
426
 
427
  return true;
428
  }
429
 
430
- private static function getTextAttributesValuesXML($products, $attributeCode)
431
  {
432
  $strTextValues = '';
433
  $arrTextValues = array();
434
 
435
  foreach ($products as $p) {
436
- self::addArrTextAttributeValues($p, $attributeCode, $arrTextValues);
437
  }
438
  if ($arrTextValues) {
439
  foreach ($arrTextValues as $textValue) {
@@ -444,6 +460,244 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
444
  return $strTextValues;
445
  }
446
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  public static function generateProductXML($product, $store = null, $checkData = true)
448
  {
449
  $entry = '';
@@ -463,7 +717,7 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
463
  $unitedProducts[] = $childrenProduct;
464
  }
465
  }
466
- $useFullFeed = Mage::helper('searchanise/ApiSe')->getUseFullFeed();
467
  $entry .= '<entry>' . self::XML_END_LINE;
468
  $entry .= '<id>' . $product->getId() . '</id>' . self::XML_END_LINE;
469
 
@@ -481,30 +735,7 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
481
  $entry .= '<link href="' . $productUrl . '" />' . self::XML_END_LINE;
482
  $entry .= '<cs:product_code><![CDATA[' . $product->getSku() . ']]></cs:product_code>' . self::XML_END_LINE;
483
 
484
- // <prices>
485
- {
486
- $customerGroups = Mage::getModel('customer/group')->getCollection()->load();
487
-
488
- foreach ($customerGroups as $keyCustomerGroup => $customerGroup) {
489
- // It is needed because the 'setCustomerGroupId' function works only once.
490
- $productCurrentGroup = clone $product;
491
- $customerGroupId = $customerGroup->getId();
492
-
493
- $price = self::getProductMinimalPrice($productCurrentGroup, $store, true, $customerGroupId);
494
- if ($price != '') {
495
- $price = round($price, Mage::helper('searchanise/ApiSe')->getFloatPrecision());
496
- }
497
-
498
- if ($customerGroupId == Mage_Customer_Model_Group::NOT_LOGGED_IN_ID) {
499
- $entry .= '<cs:price>' . $price . '</cs:price>'. self::XML_END_LINE;
500
- $defaultPrice = $price; // default price get for not logged user
501
- }
502
- $label_ = Mage::helper('searchanise/ApiSe')->getLabelForPricesUsergroup() . $customerGroup->getId();
503
- $entry .= '<cs:attribute name="' . $label_ . '" type="float">' . $price . '</cs:attribute>' . self::XML_END_LINE;
504
- unset($productCurrentGroup);
505
- }
506
- }
507
- // </prices>
508
 
509
  // <quantity>
510
  {
@@ -548,222 +779,8 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
548
  }
549
  // </attributes_position>
550
 
551
- // <attributes>
552
- {
553
- //~ $product->getAttributes();
554
- $attributes = Mage::getResourceModel('catalog/product_attribute_collection');
555
- $attributes
556
- ->setItemObjectClass('catalog/resource_eav_attribute')
557
- // ->setOrder('position', 'ASC') // not need, because It will slow with "order"
558
- ->load();
559
-
560
- if (!empty($attributes)) {
561
- foreach ($attributes as $attribute) {
562
- $attributeCode = $attribute->getAttributeCode();
563
- $value = $product->getData($attributeCode);
564
-
565
- // unitedValues - main value + childrens values
566
- $unitedValues = array();
567
- {
568
- if ($value == '') {
569
- // nothing
570
- } elseif (is_array($value) && empty($value)) {
571
- // nothing
572
- } else {
573
- $unitedValues[] = $value;
574
- }
575
- if ($childrenProducts) {
576
- foreach ($childrenProducts as $childrenProductsKey => $childrenProduct) {
577
- $childValue = $childrenProduct->getData($attributeCode);
578
- if ($childValue == '') {
579
- // Nothing.
580
- } elseif (is_array($childValue) && empty($childValue)) {
581
- // Nothing.
582
- } else {
583
- if (!in_array($childValue, $unitedValues)) {
584
- $unitedValues[] = $childValue;
585
- }
586
- }
587
- }
588
- }
589
- }
590
- $inputType = $attribute->getData('frontend_input');
591
- $isSearchable = $attribute->getIsSearchable();
592
- $isVisibleInAdvancedSearch = $attribute->getIsVisibleInAdvancedSearch();
593
- $usedForSortBy = $attribute->getUsedForSortBy();
594
- $attributeName = 'attribute_' . $attribute->getId();
595
- $attributeWeight = 0;
596
- $isRequireAttribute = $useFullFeed || $isSearchable || $isVisibleInAdvancedSearch || $usedForSortBy;
597
-
598
- if (empty($unitedValues)) {
599
- // nothing
600
-
601
- // <system_attributes>
602
- } elseif ($attributeCode == 'price') {
603
- // already defined in the '<cs:price>' field
604
-
605
- } elseif ($attributeCode == 'status' || $attributeCode == 'visibility') {
606
- $entry .= '<cs:attribute name="' . $attributeCode . '" type="text" text_search="N">';
607
- $entry .= $value;
608
- $entry .= '</cs:attribute>' . self::XML_END_LINE;
609
-
610
- } elseif ($attributeCode == 'weight') {
611
- $strTextValues = self::getTextAttributesValuesXML($unitedProducts, $attributeCode);
612
- if ($strTextValues != '') {
613
- $entry .= '<cs:attribute name="' . $attributeCode . '" type="float" text_search="N">';
614
- // fixme in the future
615
- // need for fixed bug of Server
616
- $entry .= ' ';
617
- // end fixme
618
- $entry .= $strTextValues;
619
- $entry .= '</cs:attribute>' . self::XML_END_LINE;
620
- }
621
-
622
- // <dates>
623
- } elseif ($attributeCode == 'created_at' || $attributeCode == 'updated_at') {
624
- $dateTimestamp = Mage::getModel('core/date')->timestamp(strtotime($value));
625
- $entry .= '<cs:attribute name="' . $attributeCode .'" type="int" text_search="N">';
626
- $entry .= $dateTimestamp;
627
- $entry .= '</cs:attribute>' . self::XML_END_LINE;
628
- // </dates>
629
-
630
- } elseif ($attributeCode == 'has_options') {
631
- } elseif ($attributeCode == 'required_options') {
632
- } elseif ($attributeCode == 'custom_layout_update') {
633
- } elseif ($attributeCode == 'tier_price') { // quantity discount
634
- } elseif ($attributeCode == 'image_label') {
635
- } elseif ($attributeCode == 'small_image_label') {
636
- } elseif ($attributeCode == 'thumbnail_label') {
637
- } elseif ($attributeCode == 'url_key') { // seo name
638
- // <system_attributes>
639
-
640
- } elseif ($attributeCode == 'group_price') {
641
- // nothing
642
- // fixme in the future if need
643
-
644
- } elseif (
645
- $attributeCode == 'short_description' ||
646
- $attributeCode == 'description' ||
647
- $attributeCode == 'meta_title' ||
648
- $attributeCode == 'meta_description' ||
649
- $attributeCode == 'meta_keyword') {
650
-
651
- if ($isRequireAttribute) {
652
- if ($isSearchable) {
653
- // <descriptions>
654
- if ($inputType == 'short_description') {
655
- $attributeWeight = self::WEIGHT_SHORT_DESCRIPTION;
656
- } elseif ($inputType == 'description') {
657
- $attributeWeight = self::WEIGHT_DESCRIPTION;
658
- // </descriptions>
659
-
660
- // <meta_information>
661
- } elseif ($inputType == 'meta_title') {
662
- $attributeWeight = self::WEIGHT_META_TITLE;
663
- } elseif ($inputType == 'meta_description') {
664
- $attributeWeight = self::WEIGHT_META_DESCRIPTION;
665
- } elseif ($inputType == 'meta_keyword') {
666
- $attributeWeight = self::WEIGHT_META_KEYWORDS;
667
- // </meta_information>
668
- } else {
669
- // Nothing.
670
- }
671
- }
672
-
673
- $strTextValues = self::getTextAttributesValuesXML($unitedProducts, $attributeCode);
674
- if ($strTextValues != '') {
675
- $entry .= '<cs:attribute name="' . $attributeCode .'" type="text" text_search="Y" weight="' . $attributeWeight . '">';
676
- // fixme in the future
677
- // need for fixed bug of Server
678
- $entry .= ' ';
679
- // end fixme
680
- $entry .= $strTextValues;
681
- $entry .= '</cs:attribute>' . self::XML_END_LINE;
682
- }
683
- }
684
-
685
- } elseif ($inputType == 'price') {
686
- // Other attributes with type 'price'.
687
- $entry .= '<cs:attribute name="' . $attributeName .'" type="float">';
688
- $entry .= $value;
689
- $entry .= '</cs:attribute>' . self::XML_END_LINE;
690
-
691
- } elseif ($inputType == 'select' || $inputType == 'multiselect') {
692
- // <id_values>
693
- if ($strIdValues = self::getIdAttributesValuesXML($unitedValues)) {
694
- $entry .= '<cs:attribute name="' . $attributeName .'" type="text">';
695
- // fixme in the future
696
- // need for fixed bug of Server
697
- $entry .= ' ';
698
- // end fixme
699
-
700
- $entry .= $strIdValues;
701
- $entry .= '</cs:attribute>' . self::XML_END_LINE;
702
- }
703
- // </id_values>
704
 
705
- // <text_values>
706
- if ($isRequireAttribute) {
707
- $strTextValues = self::getTextAttributesValuesXML($unitedProducts, $attributeCode);
708
-
709
- if ($strTextValues != '') {
710
- if ($isSearchable) {
711
- $attributeWeight = self::WEIGHT_SELECT_ATTRIBUTES;
712
- }
713
-
714
- $entry .= '<cs:attribute name="' . $attributeCode .'" type="text" text_search="Y" weight="' . $attributeWeight . '">';
715
- // fixme in the future
716
- // need for fixed bug of Server
717
- $entry .= ' ';
718
- // end fixme
719
- $entry .= $strTextValues;
720
- $entry .= '</cs:attribute>' . self::XML_END_LINE;
721
- }
722
- }
723
- // </text_values>
724
-
725
- } elseif ($inputType == 'text' || $inputType == 'textarea') {
726
- if ($isRequireAttribute) {
727
- $strTextValues = self::getTextAttributesValuesXML($unitedProducts, $attributeCode);
728
-
729
- if ($strTextValues != '') {
730
- if ($isSearchable) {
731
- if ($inputType == 'text') {
732
- $attributeWeight = self::WEIGHT_TEXT_ATTRIBUTES;
733
- } elseif ($inputType == 'textarea') {
734
- $attributeWeight = self::WEIGHT_TEXT_AREA_ATTRIBUTES;
735
- } else {
736
- // Nothing.
737
- }
738
- }
739
- $entry .= '<cs:attribute name="' . $attributeName .'" type="text" text_search="Y" weight="' . $attributeWeight . '">';
740
- // fixme in the future
741
- // need for fixed bug of Server
742
- $entry .= ' ';
743
- // end fixme
744
- $entry .= $strTextValues;
745
- $entry .= '</cs:attribute>' . self::XML_END_LINE;
746
- }
747
- }
748
- } elseif ($inputType == 'date') {
749
- if ($isRequireAttribute) {
750
- $dateTimestamp = Mage::getModel('core/date')->timestamp(strtotime($value));
751
- $entry .= '<cs:attribute name="' . $attributeCode .'" type="int" text_search="N">';
752
- $entry .= $dateTimestamp;
753
- $entry .= '</cs:attribute>' . self::XML_END_LINE;
754
- }
755
- } elseif ($inputType == 'media_image') {
756
- // Nothing.
757
- } elseif ($inputType == 'gallery') {
758
- // Nothing.
759
- } else {
760
- // Attribute not will use.
761
- }
762
- }
763
- }
764
- }
765
- // </attributes>
766
-
767
  // <categories>
768
  {
769
  $entry .= '<cs:attribute name="category_ids" type="text">';
@@ -963,16 +980,8 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
963
  return $validProductIds;
964
  }
965
 
966
- // public static function getProductsByItems($productIds, $store = null, $flagAddMinimalPrice = false, $customerGroupId = null)
967
- public static function getProducts($productIds, $store = null, $flagAddMinimalPrice = false, $customerGroupId = null)
968
  {
969
- // Need for generate correct url and get right products.
970
- if ($store) {
971
- Mage::app()->setCurrentStore($store->getId());
972
- } else {
973
- Mage::app()->setCurrentStore(0);
974
- }
975
-
976
  $products = array();
977
  $productIds = self::validateProductIds($productIds, $store);
978
 
@@ -998,13 +1007,6 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
998
  }
999
 
1000
  if ($product) {
1001
- if ($store) {
1002
- $product->setWebsiteId($store->getWebsiteId());
1003
- }
1004
- if ($customerGroupId != null) {
1005
- $product->setCustomerGroupId($customerGroupId);
1006
- }
1007
-
1008
  $products[] = $product;
1009
  }
1010
  }
@@ -1013,37 +1015,35 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
1013
  return $products;
1014
  }
1015
 
1016
- public static function getProductsOld($productIds = null, $store = null, $flagAddMinimalPrice = false, $customerGroupId = null)
1017
  {
1018
- // Need for generate correct url and get right data.
 
 
 
 
 
1019
  if ($store) {
1020
  Mage::app()->setCurrentStore($store->getId());
1021
  } else {
1022
  Mage::app()->setCurrentStore(0);
1023
  }
1024
 
1025
- $productId = 0;
1026
-
1027
- if (!empty($productIds)) {
1028
- if (!is_array($productIds)) {
1029
- $productId = $productIds;
1030
- } elseif (is_array($productIds) && count($productIds) == 1){
1031
- $flGetOneProduct = true;
1032
- $productId = reset($productIds);
1033
- }
1034
- }
1035
-
1036
- if (!empty($productId)) {
1037
- $products = array();
1038
- $product = Mage::getModel('catalog/product')->load($productId);
1039
 
1040
- if ($customerGroupId != null) {
1041
- $product->setCustomerGroupId($customerGroupId);
 
 
 
1042
  }
1043
 
1044
- $products[] = $product;
1045
-
1046
- } else {
1047
  $products = Mage::getModel('catalog/product')
1048
  ->getCollection()
1049
  ->addAttributeToSelect('*')
@@ -1057,72 +1057,53 @@ class Simtech_Searchanise_Helper_ApiXML extends Mage_Core_Helper_Data
1057
  }
1058
  }
1059
 
1060
- if (!empty($store)) {
1061
  $products
1062
  ->setStoreId($store)
1063
  ->addStoreFilter($store);
1064
- } else {
1065
- // nothing
1066
  }
1067
 
1068
- if (!empty($productIds)) {
1069
  // Already exist automatic definition 'one value' or 'array'.
1070
  $products->addIdFilter($productIds);
1071
- }
1072
-
1073
- if ($flagAddMinimalPrice == true) {
1074
- $products->addMinimalPrice();
1075
- }
1076
 
1077
  $products->load();
1078
- }
1079
 
1080
- return $products;
1081
- }
1082
-
1083
- // Main functions //
1084
- public static function generateProductsXML($productIds = null, $store = null, $flagAddMinimalPrice = false, $checkData = true)
1085
- {
1086
- $ret = '';
1087
 
1088
- $products = self::getProducts($productIds, $store, $flagAddMinimalPrice);
1089
 
1090
- // fixme, need delete
1091
- // additional check for products without minimal price
1092
- // deprecated, because use only $flagAddMinimalPrice = false in current module
1093
- if ($flagAddMinimalPrice === true) {
1094
- if (!$products) {
1095
- return self::generateProductsXML($productIds, $store, false);
1096
- }
1097
- $products2 = self::getProducts($productIds, $store, false);
1098
- $arrProduct2 = $products2->toArray();
1099
- if (count($products2) > count($products)) {
1100
- $additionalProductsIds = array();
1101
- foreach ($products2 as $productId => $product) {
1102
- // fixme array_key_exists
1103
- if (!array_key_exists($productId, $products)) {
1104
- $additionalProductsIds[] = $productId;
1105
  }
1106
- }
1107
- if (!empty($additionalProductsIds)) {
1108
- $additionalProducts = self::getProducts($additionalProductsIds, $store, false);
1109
- $arrAdditionalProducts = $additionalProducts->toArray();
1110
- if ((!empty($arrAdditionalProducts)) && (count($arrAdditionalProducts) != 0)) {
1111
- foreach ($additionalProducts as $product) {
1112
- $ret .= self::generateProductXML($product, $store, $checkData);
1113
- }
1114
  }
1115
  }
1116
  }
1117
  }
1118
- // end fixme
 
 
 
 
 
 
 
 
 
1119
 
1120
  if ($products) {
1121
  foreach ($products as $product) {
1122
  $ret .= self::generateProductXML($product, $store, $checkData);
1123
  }
1124
  }
1125
-
1126
  return $ret;
1127
  }
1128
 
32
  // </if_isSearchable>
33
 
34
  // Tweaks
35
+ const ADDITIONAL_CHECK_FOR_INCORRECT_PRODUCTS = false;
36
 
37
  protected static $flWithoutTags = false;
38
+
39
+ public static $isGetProductsByItems = false;
40
+
41
+ public static function setIsGetProductsByItems($value = false)
42
+ {
43
+ self::$isGetProductsByItems = $value;
44
+ }
45
 
46
  public static function getStockItem($product, $store = null)
47
  {
93
  return $tagCollection;
94
  }
95
 
96
+ /**
97
+ * generateProductImage
98
+ *
99
+ * @param Mage_Catalog_Model_Product $product
100
+ * @param bool $flagKeepFrame
101
+ * @param int $width
102
+ * @param int $height
103
+ * @return Mage_Catalog_Model_Product_Image $image
104
+ */
105
+ private static function generateProductImage($product, $imageType = 'small_image', $flagKeepFrame = true, $width = 70, $height = 70)
106
+ {
107
+ $image = '';
108
+ $productImage = $product->getData($imageType);
109
+
110
+ if (!empty($productImage) && $productImage != 'no_selection') {
111
+ try {
112
+ $image = Mage::helper('catalog/image')
113
+ ->init($product, $imageType)
114
+ ->constrainOnly(true) // Guarantee, that image picture will not be bigger, than it was.
115
+ ->keepAspectRatio(true) // Guarantee, that image picture width/height will not be distorted.
116
+ ->keepFrame($flagKeepFrame); // Guarantee, that image will have dimensions, set in $width/$height
117
+
118
+ if ($width || $height) {
119
+ $image->resize($width, $height);
120
+ }
121
+ } catch (Exception $e) {
122
+ // image not exists
123
+ $image = '';
124
+ }
125
+ }
126
+
127
+ return $image;
128
+ }
129
+
130
  /**
131
  * getProductImageLink
132
  *
134
  * @param bool $flagKeepFrame
135
  * @param int $width
136
  * @param int $height
137
+ * @return Mage_Catalog_Model_Product_Image $image
138
  */
139
  private static function getProductImageLink($product, $flagKeepFrame = true, $width = 70, $height = 70)
140
  {
141
+ $image = '';
142
 
143
  if ($product) {
144
+ if (empty($image)) {
145
+ $image = self::generateProductImage($product, 'small_image', $flagKeepFrame, $width, $height);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  }
147
+ if (empty($image)) {
148
+ $image = self::generateProductImage($product, 'image', $flagKeepFrame, $width, $height);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  }
150
+ if (empty($image)) {
151
+ $image = self::generateProductImage($product, 'thumbnail', $flagKeepFrame, $width, $height);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  }
153
  }
154
 
155
+ return $image;
156
  }
157
 
158
  /**
226
  *
227
  * @param Mage_Catalog_Model_Product $product
228
  * @param Mage_Core_Model_Store $store
229
+ * @param Mage_Catalog_Model_Resource_Product_Collection $childrenProducts
230
  * @param int $customerGroupId
231
  * @param float $groupPrice
232
  * @return float
233
  */
234
+ private static function getProductMinimalPrice($product, $store, $childrenProducts = null, $customerGroupId = null, $groupPrice = null)
235
  {
236
  $minimalPrice = false;
237
 
239
  $product->setCustomerGroupId($customerGroupId);
240
  }
241
 
242
+ $_priceModel = $product->getPriceModel();
243
+
244
+ if ($_priceModel && $product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
245
+ // [1.5]
246
+ if (version_compare(Mage::getVersion(), '1.6', '<')) {
247
+ $minimalPrice = $_priceModel->getPrices($product, 'min');
248
+ // [/1.5]
249
+ // [v1.6] [v1.7] [v1.8]
250
+ } else {
251
+ $minimalPrice = $_priceModel->getTotalPrices($product, 'min', null, false);
252
+ }
253
+ // [/v1.6] [/v1.7] [/v1.8]
254
+ $minimalPrice = self::getProductShowPrice($product, $minimalPrice);
255
 
256
+ } elseif ($product->isGrouped() && $childrenProducts) {
257
+ // fixme in the future
258
+ // maybe exist better solution get `minimalPrice` for `Grouped` product
259
+ $minimalPrice = '';
260
+
261
+ foreach ($childrenProducts as $childrenProductsKey => $childrenProduct) {
262
+ if ($childrenProduct) {
263
+ $minimalPriceChildren = self::getProductMinimalPrice($childrenProduct, $store, null, $customerGroupId);
264
 
265
+ if (($minimalPriceChildren < $minimalPrice) ||
266
+ ($minimalPrice == '')) {
267
+ $minimalPrice = $minimalPriceChildren;
268
+ }
269
  }
270
+ }
271
+ // end fixme
272
+ } else {
273
+ if ($groupPrice != null) {
274
+ $minimalPrice = $groupPrice;
275
+ } else {
276
+ $isCorrectProduct = true;
277
 
278
+ // Additional check for incorrect configurable products.
279
+ if (self::ADDITIONAL_CHECK_FOR_INCORRECT_PRODUCTS) {
280
+ static $arrIncorrectProductIds = array();
281
+
282
+ if (in_array($product->getId(), $arrIncorrectProductIds)) {
283
+ $isCorrectProduct = false;
284
+ }
285
+
286
+ if ($isCorrectProduct && $product->isConfigurable()) {
287
+ try {
288
+ $attributes = $product->getTypeInstance(true)
289
+ ->getConfigurableAttributes($product);
290
+ foreach ($attributes as $attribute) {
291
+ if (!$attribute->getProductAttribute()) {
292
+ $isCorrectProduct = false;
293
+ $arrIncorrectProductIds[] = $product->getId();
294
+ Mage::helper('searchanise/ApiSe')->log('Incorrect configurable product ID = ' . $product->getId(), 'Warning');
295
+ break;
296
+ }
297
  }
298
+ } catch (Exception $e) {
299
+ Mage::helper('searchanise/ApiSe')->log($e->getMessage(), "Error: Script couldn't check for incorrect configurable product ID = " . $product->getId());
300
  }
301
+ }
302
+ }
303
+ // end check
304
+
305
+ if ($isCorrectProduct) {
306
+ try {
307
+ // $minimalPrice = $product->getFinalPrice();
308
  } catch (Exception $e) {
309
+ $minimalPrice = false;
310
+ Mage::helper('searchanise/ApiSe')->log($e->getMessage(), "Error: Script couldn't get final price for product ID = " . $product->getId());
311
  }
312
  }
313
  }
 
314
 
315
+ if ($minimalPrice === false) {
316
+ $minimalPrice = $product->getPrice();
 
 
 
 
 
317
  }
 
318
 
319
+ $minimalPrice = self::getProductShowPrice($product, $minimalPrice);
 
320
  }
321
 
322
+ return $minimalPrice;
323
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
 
325
+ private static function _generateProductPricesXML($product, $childrenProducts = null, $store = null)
326
+ {
327
+ $result = '';
 
 
 
 
 
 
 
 
 
 
328
 
329
+ static $customerGroups;
 
 
330
 
331
+ if (!isset($customerGroups)) {
332
+ $customerGroups = Mage::getModel('customer/group')->getCollection()->load();
333
+ }
334
+
335
+ if ($customerGroups) {
336
+ foreach ($customerGroups as $keyCustomerGroup => $customerGroup) {
337
+ // It is needed because the 'setCustomerGroupId' function works only once.
338
+ $productCurrentGroup = clone $product;
339
+ $customerGroupId = $customerGroup->getId();
340
 
341
+ $price = self::getProductMinimalPrice($productCurrentGroup, $store, $childrenProducts, $customerGroupId);
342
+ if ($price != '') {
343
+ $price = round($price, Mage::helper('searchanise/ApiSe')->getFloatPrecision());
344
+ }
345
 
346
+ if ($customerGroupId == Mage_Customer_Model_Group::NOT_LOGGED_IN_ID) {
347
+ $result .= '<cs:price>' . $price . '</cs:price>'. self::XML_END_LINE;
348
+ $defaultPrice = $price; // default price get for not logged user
 
 
 
 
 
349
  }
350
+ $label_ = Mage::helper('searchanise/ApiSe')->getLabelForPricesUsergroup() . $customerGroup->getId();
351
+ $result .= '<cs:attribute name="' . $label_ . '" type="float">' . $price . '</cs:attribute>' . self::XML_END_LINE;
352
+ unset($productCurrentGroup);
353
  }
354
  }
355
 
356
+ return $result;
357
  }
358
 
359
  /**
380
  }
381
 
382
  if ($childrenIds) {
383
+ $childrenProducts = self::getProducts($childrenIds, $store, null);
384
  }
385
  }
386
  }
417
  return $strIdValues;
418
  }
419
 
420
+ private static function addArrTextAttributeValues($product, $attributeCode, $inputType, &$arrTextValues)
421
  {
422
  $textValues = $product->getResource()->getAttribute($attributeCode)->getFrontend()->getValue($product);
423
+
424
  if ($textValues != '') {
425
+ if ($inputType == 'multiselect') {
426
+ $arrValues = explode(',', $textValues);
427
+ if (!empty($arrValues)) {
428
+ foreach ($arrValues as $v) {
429
+ if ($v != '') {
430
+ $trimValue = trim($v);
431
+ if ($trimValue != '' && !in_array($trimValue, $arrTextValues)) {
432
+ $arrTextValues[] .= $trimValue;
433
+ }
434
+ }
435
  }
436
  }
437
+ } else {
438
+ $trimValue = trim($textValues);
439
+ $arrTextValues[] .= $trimValue;
440
  }
441
  }
442
 
443
  return true;
444
  }
445
 
446
+ private static function getTextAttributesValuesXML($products, $attributeCode, $inputType)
447
  {
448
  $strTextValues = '';
449
  $arrTextValues = array();
450
 
451
  foreach ($products as $p) {
452
+ self::addArrTextAttributeValues($p, $attributeCode, $inputType, $arrTextValues);
453
  }
454
  if ($arrTextValues) {
455
  foreach ($arrTextValues as $textValue) {
460
  return $strTextValues;
461
  }
462
 
463
+ private static function _generateProductAttributesXML($product, $childrenProducts = null, $unitedProducts = null, $store = null)
464
+ {
465
+ $result = '';
466
+
467
+ static $attributes;
468
+
469
+ if (!isset($attributes)) {
470
+ $attributes = Mage::getResourceModel('catalog/product_attribute_collection');
471
+ $attributes
472
+ ->setItemObjectClass('catalog/resource_eav_attribute')
473
+ // ->setOrder('position', 'ASC') // not need, because It will slow with "order"
474
+ ->load();
475
+ }
476
+
477
+ if ($attributes) {
478
+ $useFullFeed = Mage::helper('searchanise/ApiSe')->getUseFullFeed();
479
+ foreach ($attributes as $attribute) {
480
+ $attributeCode = $attribute->getAttributeCode();
481
+ $value = $product->getData($attributeCode);
482
+
483
+ // unitedValues - main value + childrens values
484
+ $unitedValues = array();
485
+ {
486
+ if ($value == '') {
487
+ // nothing
488
+ } elseif (is_array($value) && empty($value)) {
489
+ // nothing
490
+ } else {
491
+ $unitedValues[] = $value;
492
+ }
493
+ if ($childrenProducts) {
494
+ foreach ($childrenProducts as $childrenProductsKey => $childrenProduct) {
495
+ $childValue = $childrenProduct->getData($attributeCode);
496
+ if ($childValue == '') {
497
+ // Nothing.
498
+ } elseif (is_array($childValue) && empty($childValue)) {
499
+ // Nothing.
500
+ } else {
501
+ if (!in_array($childValue, $unitedValues)) {
502
+ $unitedValues[] = $childValue;
503
+ }
504
+ }
505
+ }
506
+ }
507
+ }
508
+ $inputType = $attribute->getData('frontend_input');
509
+ $isSearchable = $attribute->getIsSearchable();
510
+ $isVisibleInAdvancedSearch = $attribute->getIsVisibleInAdvancedSearch();
511
+ $usedForSortBy = $attribute->getUsedForSortBy();
512
+ $attributeName = 'attribute_' . $attribute->getId();
513
+ $attributeWeight = 0;
514
+ $isRequireAttribute = $useFullFeed || $isSearchable || $isVisibleInAdvancedSearch || $usedForSortBy;
515
+
516
+ if (empty($unitedValues)) {
517
+ // nothing
518
+
519
+ // <system_attributes>
520
+ } elseif ($attributeCode == 'price') {
521
+ // already defined in the '<cs:price>' field
522
+
523
+ } elseif ($attributeCode == 'status' || $attributeCode == 'visibility') {
524
+ $result .= '<cs:attribute name="' . $attributeCode . '" type="text" text_search="N">';
525
+ $result .= $value;
526
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
527
+
528
+ } elseif ($attributeCode == 'weight') {
529
+ $strTextValues = self::getTextAttributesValuesXML($unitedProducts, $attributeCode, $inputType);
530
+ if ($strTextValues != '') {
531
+ $result .= '<cs:attribute name="' . $attributeCode . '" type="float" text_search="N">';
532
+ // fixme in the future
533
+ // need for fixed bug of Server
534
+ $result .= ' ';
535
+ // end fixme
536
+ $result .= $strTextValues;
537
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
538
+ }
539
+
540
+ // <dates>
541
+ } elseif ($attributeCode == 'created_at' || $attributeCode == 'updated_at') {
542
+ $dateTimestamp = Mage::getModel('core/date')->timestamp(strtotime($value));
543
+ $result .= '<cs:attribute name="' . $attributeCode .'" type="int" text_search="N">';
544
+ $result .= $dateTimestamp;
545
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
546
+ // </dates>
547
+
548
+ } elseif ($attributeCode == 'has_options') {
549
+ } elseif ($attributeCode == 'required_options') {
550
+ } elseif ($attributeCode == 'custom_layout_update') {
551
+ } elseif ($attributeCode == 'tier_price') { // quantity discount
552
+ } elseif ($attributeCode == 'image_label') {
553
+ } elseif ($attributeCode == 'small_image_label') {
554
+ } elseif ($attributeCode == 'thumbnail_label') {
555
+ } elseif ($attributeCode == 'url_key') { // seo name
556
+ // <system_attributes>
557
+
558
+ } elseif ($attributeCode == 'group_price') {
559
+ // nothing
560
+ // fixme in the future if need
561
+
562
+ } elseif (
563
+ $attributeCode == 'short_description' ||
564
+ $attributeCode == 'description' ||
565
+ $attributeCode == 'meta_title' ||
566
+ $attributeCode == 'meta_description' ||
567
+ $attributeCode == 'meta_keyword') {
568
+
569
+ if ($isRequireAttribute) {
570
+ if ($isSearchable) {
571
+ if ($attributeCode == 'short_description') {
572
+ $attributeWeight = self::WEIGHT_SHORT_DESCRIPTION;
573
+ } elseif ($attributeCode == 'description') {
574
+ $attributeWeight = self::WEIGHT_DESCRIPTION;
575
+ } elseif ($attributeCode == 'meta_title') {
576
+ $attributeWeight = self::WEIGHT_META_TITLE;
577
+ } elseif ($attributeCode == 'meta_description') {
578
+ $attributeWeight = self::WEIGHT_META_DESCRIPTION;
579
+ } elseif ($attributeCode == 'meta_keyword') {
580
+ $attributeWeight = self::WEIGHT_META_KEYWORDS;
581
+ } else {
582
+ // Nothing.
583
+ }
584
+ }
585
+
586
+ $strTextValues = self::getTextAttributesValuesXML($unitedProducts, $attributeCode, $inputType);
587
+ if ($strTextValues != '') {
588
+ if ($attributeCode == 'description') {
589
+ if ($value != '') {
590
+ $result .= '<cs:attribute name="' . $attributeCode .'" type="text" text_search="Y" weight="' . $attributeWeight . '">';
591
+ $result .= '<![CDATA[' . $value . ']]>';
592
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
593
+ }
594
+
595
+ $result .= '<cs:attribute name="se_grouped_' . $attributeCode .'" type="text" text_search="Y" weight="' . $attributeWeight . '">';
596
+ } else {
597
+ $result .= '<cs:attribute name="' . $attributeCode .'" type="text" text_search="Y" weight="' . $attributeWeight . '">';
598
+ }
599
+ // fixme in the future
600
+ // need for fixed bug of Server
601
+ $result .= ' ';
602
+ // end fixme
603
+ $result .= $strTextValues;
604
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
605
+ }
606
+ }
607
+
608
+ } elseif ($inputType == 'price') {
609
+ // Other attributes with type 'price'.
610
+ $result .= '<cs:attribute name="' . $attributeName .'" type="float">';
611
+ $result .= $value;
612
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
613
+
614
+ } elseif ($inputType == 'select' || $inputType == 'multiselect') {
615
+ // <id_values>
616
+ if ($strIdValues = self::getIdAttributesValuesXML($unitedValues)) {
617
+ $result .= '<cs:attribute name="' . $attributeName .'" type="text">';
618
+ // fixme in the future
619
+ // need for fixed bug of Server
620
+ $result .= ' ';
621
+ // end fixme
622
+
623
+ $result .= $strIdValues;
624
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
625
+ }
626
+ // </id_values>
627
+
628
+ // <text_values>
629
+ if ($isRequireAttribute) {
630
+ $strTextValues = self::getTextAttributesValuesXML($unitedProducts, $attributeCode, $inputType);
631
+
632
+ if ($strTextValues != '') {
633
+ if ($isSearchable) {
634
+ $attributeWeight = self::WEIGHT_SELECT_ATTRIBUTES;
635
+ }
636
+
637
+ $result .= '<cs:attribute name="' . $attributeCode .'" type="text" text_search="Y" weight="' . $attributeWeight . '">';
638
+ // fixme in the future
639
+ // need for fixed bug of Server
640
+ $result .= ' ';
641
+ // end fixme
642
+ $result .= $strTextValues;
643
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
644
+ }
645
+ }
646
+ // </text_values>
647
+
648
+ } elseif ($inputType == 'text' || $inputType == 'textarea') {
649
+ if ($isRequireAttribute) {
650
+ $strTextValues = self::getTextAttributesValuesXML($unitedProducts, $attributeCode, $inputType);
651
+
652
+ if ($strTextValues != '') {
653
+ if ($isSearchable) {
654
+ if ($inputType == 'text') {
655
+ $attributeWeight = self::WEIGHT_TEXT_ATTRIBUTES;
656
+ } elseif ($inputType == 'textarea') {
657
+ $attributeWeight = self::WEIGHT_TEXT_AREA_ATTRIBUTES;
658
+ } else {
659
+ // Nothing.
660
+ }
661
+ }
662
+ $result .= '<cs:attribute name="' . $attributeName .'" type="text" text_search="Y" weight="' . $attributeWeight . '">';
663
+ // fixme in the future
664
+ // need for fixed bug of Server
665
+ $result .= ' ';
666
+ // end fixme
667
+ $result .= $strTextValues;
668
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
669
+ }
670
+ }
671
+ } elseif ($inputType == 'date') {
672
+ if ($isRequireAttribute) {
673
+ $dateTimestamp = Mage::getModel('core/date')->timestamp(strtotime($value));
674
+ $result .= '<cs:attribute name="' . $attributeCode .'" type="int" text_search="N">';
675
+ $result .= $dateTimestamp;
676
+ $result .= '</cs:attribute>' . self::XML_END_LINE;
677
+ }
678
+ } elseif ($inputType == 'media_image') {
679
+ if ($isRequireAttribute) {
680
+ $image = self::generateProductImage($product, $attributeCode, true, 0, 0);
681
+ if (!empty($image)) {
682
+ $imageLink = '' . $image;
683
+ if (!empty($imageLink)) {
684
+ $result .= '<cs:attribute name="' . $attributeCode .'" type="text" text_search="N" weight="0"><![CDATA[';
685
+ $result .= $imageLink;
686
+ $result .= ']]></cs:attribute>' . self::XML_END_LINE;
687
+ }
688
+ }
689
+ }
690
+ } elseif ($inputType == 'gallery') {
691
+ // Nothing.
692
+ } else {
693
+ // Attribute not will use.
694
+ }
695
+ }
696
+ }
697
+
698
+ return $result;
699
+ }
700
+
701
  public static function generateProductXML($product, $store = null, $checkData = true)
702
  {
703
  $entry = '';
717
  $unitedProducts[] = $childrenProduct;
718
  }
719
  }
720
+
721
  $entry .= '<entry>' . self::XML_END_LINE;
722
  $entry .= '<id>' . $product->getId() . '</id>' . self::XML_END_LINE;
723
 
735
  $entry .= '<link href="' . $productUrl . '" />' . self::XML_END_LINE;
736
  $entry .= '<cs:product_code><![CDATA[' . $product->getSku() . ']]></cs:product_code>' . self::XML_END_LINE;
737
 
738
+ $entry .= self::_generateProductPricesXML($product, $childrenProducts, $store);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
739
 
740
  // <quantity>
741
  {
779
  }
780
  // </attributes_position>
781
 
782
+ $entry .= self::_generateProductAttributesXML($product, $childrenProducts, $unitedProducts, $store);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
783
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
784
  // <categories>
785
  {
786
  $entry .= '<cs:attribute name="category_ids" type="text">';
980
  return $validProductIds;
981
  }
982
 
983
+ private static function _getProductsByItems($productIds, $store = null)
 
984
  {
 
 
 
 
 
 
 
985
  $products = array();
986
  $productIds = self::validateProductIds($productIds, $store);
987
 
1007
  }
1008
 
1009
  if ($product) {
 
 
 
 
 
 
 
1010
  $products[] = $product;
1011
  }
1012
  }
1015
  return $products;
1016
  }
1017
 
1018
+ public static function getProducts($productIds = null, $store = null, $customerGroupId = null)
1019
  {
1020
+ $resultProducts = array();
1021
+ if (empty($productIds)) {
1022
+ return $resultProducts;
1023
+ }
1024
+
1025
+ // Need for generate correct url and get right products.
1026
  if ($store) {
1027
  Mage::app()->setCurrentStore($store->getId());
1028
  } else {
1029
  Mage::app()->setCurrentStore(0);
1030
  }
1031
 
1032
+ static $arrProducts = array();
1033
+ $keyProductIds = implode('_', $productIds) . ':' . ($store ? $store->getId() : '0') . ':' . $customerGroupId . ':' . (self::$isGetProductsByItems ? '1' : '0');
1034
+
1035
+ if (isset($arrProducts[$keyProductIds])) {
1036
+ // Nothing.
1037
+ } else {
1038
+ $products = null;
 
 
 
 
 
 
 
1039
 
1040
+ // Need for generate correct url and get right data.
1041
+ if ($store) {
1042
+ Mage::app()->setCurrentStore($store->getId());
1043
+ } else {
1044
+ Mage::app()->setCurrentStore(0);
1045
  }
1046
 
 
 
 
1047
  $products = Mage::getModel('catalog/product')
1048
  ->getCollection()
1049
  ->addAttributeToSelect('*')
1057
  }
1058
  }
1059
 
1060
+ if ($store) {
1061
  $products
1062
  ->setStoreId($store)
1063
  ->addStoreFilter($store);
 
 
1064
  }
1065
 
1066
+ // if (!empty($productIds)) {
1067
  // Already exist automatic definition 'one value' or 'array'.
1068
  $products->addIdFilter($productIds);
1069
+ // }
 
 
 
 
1070
 
1071
  $products->load();
 
1072
 
1073
+ $arrProducts[$keyProductIds] = $products;
1074
+ }
 
 
 
 
 
1075
 
1076
+ $resultProducts = $arrProducts[$keyProductIds];
1077
 
1078
+ if ($resultProducts && ($store || $customerGroupId != null)) {
1079
+ foreach ($resultProducts as $key => &$product) {
1080
+ if ($product) {
1081
+ if ($store) {
1082
+ $product->setWebsiteId($store->getWebsiteId());
 
 
 
 
 
 
 
 
 
 
1083
  }
1084
+ if ($customerGroupId != null) {
1085
+ $product->setCustomerGroupId($customerGroupId);
 
 
 
 
 
 
1086
  }
1087
  }
1088
  }
1089
  }
1090
+
1091
+ return $resultProducts;
1092
+ }
1093
+
1094
+ // Main functions //
1095
+ public static function generateProductsXML($productIds = null, $store = null, $checkData = true)
1096
+ {
1097
+ $ret = '';
1098
+
1099
+ $products = self::getProducts($productIds, $store, null);
1100
 
1101
  if ($products) {
1102
  foreach ($products as $product) {
1103
  $ret .= self::generateProductXML($product, $store, $checkData);
1104
  }
1105
  }
1106
+
1107
  return $ret;
1108
  }
1109
 
app/code/community/Simtech/Searchanise/controllers/InfoController.php CHANGED
@@ -22,6 +22,7 @@ class Simtech_Searchanise_InfoController extends Mage_Core_Controller_Front_Acti
22
  const DISPLAY_ERRORS = 'display_errors';
23
  const PRODUCT_ID = 'product_id';
24
  const PRODUCT_IDS = 'product_ids';
 
25
  const PARENT_PRIVATE_KEY = 'parent_private_key';
26
 
27
  /**
@@ -66,13 +67,17 @@ class Simtech_Searchanise_InfoController extends Mage_Core_Controller_Front_Acti
66
  echo Mage::helper('core')->jsonEncode($options);
67
  }
68
  } else {
69
- $resync = $this->getRequest()->getParam(self::RESYNC);
70
- $profiler = $this->getRequest()->getParam(self::PROFILER);
71
- $storeId = $this->getRequest()->getParam(self::STORE_ID);
72
- $checkData = $this->getRequest()->getParam(self::CHECK_DATA);
73
- $displayErrors = $this->getRequest()->getParam(self::DISPLAY_ERRORS);
74
- $productId = $this->getRequest()->getParam(self::PRODUCT_ID);
75
- $productIds = $this->getRequest()->getParam(self::PRODUCT_IDS);
 
 
 
 
76
 
77
  if ($displayErrors) {
78
  @error_reporting(E_ALL);
@@ -94,8 +99,7 @@ class Simtech_Searchanise_InfoController extends Mage_Core_Controller_Front_Acti
94
  }
95
 
96
  if ($profiler) {
97
- $numberIterations = 100;
98
- $old = $this->getRequest()->getParam('old');
99
 
100
  if (empty($productIds)) {
101
  Mage::app()->setCurrentStore(0);
@@ -103,7 +107,7 @@ class Simtech_Searchanise_InfoController extends Mage_Core_Controller_Front_Acti
103
 
104
  $productIds = array();
105
  foreach ($allProductIds as $key => $value) {
106
- $productIds [] = $value['entity_id'];
107
  if (count($productIds) > $numberIterations) {
108
  break;
109
  }
@@ -112,24 +116,23 @@ class Simtech_Searchanise_InfoController extends Mage_Core_Controller_Front_Acti
112
  }
113
 
114
  $n = 0;
 
115
  while ($n < $numberIterations) {
116
- if ($old == 'Y') {
117
- $productFeeds = Mage::helper('searchanise/ApiXML')->generateProductsXML($productIds, $store);
118
- // $products = Mage::helper('searchanise/ApiXML')->getProductsOld($productIds, $store);
119
- } else {
120
- $productFeeds = Mage::helper('searchanise/ApiXML')->generateProductsXML($productIds, $store);
121
- // $products = Mage::helper('searchanise/ApiXML')->getProducts($productIds, $store);
122
- }
123
-
124
  $n++;
125
  }
126
 
127
  echo $this->_profiler();
 
 
 
 
 
128
  } elseif ($resync) {
129
  Mage::helper('searchanise/ApiSe')->queueImport($store);
130
 
131
  } elseif (!empty($productIds)) {
132
- $productFeeds = Mage::helper('searchanise/ApiXML')->generateProductsXML($productIds, $store, false, $checkData);
133
  if ($productFeeds) {
134
  $xmlHeader = Mage::helper('searchanise/ApiXML')->getXMLHeader($store);
135
  $xmlFooter = Mage::helper('searchanise/ApiXML')->getXMLFooter($store);
22
  const DISPLAY_ERRORS = 'display_errors';
23
  const PRODUCT_ID = 'product_id';
24
  const PRODUCT_IDS = 'product_ids';
25
+ const BY_ITEMS = 'by_items';
26
  const PARENT_PRIVATE_KEY = 'parent_private_key';
27
 
28
  /**
67
  echo Mage::helper('core')->jsonEncode($options);
68
  }
69
  } else {
70
+ $resync = $this->getRequest()->getParam(self::RESYNC);
71
+ $profiler = $this->getRequest()->getParam(self::PROFILER);
72
+ $storeId = $this->getRequest()->getParam(self::STORE_ID);
73
+ $checkData = $this->getRequest()->getParam(self::CHECK_DATA);
74
+ $displayErrors = $this->getRequest()->getParam(self::DISPLAY_ERRORS);
75
+ $productId = $this->getRequest()->getParam(self::PRODUCT_ID);
76
+ $productIds = $this->getRequest()->getParam(self::PRODUCT_IDS);
77
+ $byItems = $this->getRequest()->getParam(self::BY_ITEMS);
78
+ if ($byItems == 'Y') {
79
+ Mage::helper('searchanise/ApiXML')->setIsGetProductsByItems(true);
80
+ }
81
 
82
  if ($displayErrors) {
83
  @error_reporting(E_ALL);
99
  }
100
 
101
  if ($profiler) {
102
+ $numberIterations = 1000;
 
103
 
104
  if (empty($productIds)) {
105
  Mage::app()->setCurrentStore(0);
107
 
108
  $productIds = array();
109
  foreach ($allProductIds as $key => $value) {
110
+ $productIds[] = $value['entity_id'];
111
  if (count($productIds) > $numberIterations) {
112
  break;
113
  }
116
  }
117
 
118
  $n = 0;
119
+ $productFeeds = '';
120
  while ($n < $numberIterations) {
121
+ $productFeeds = Mage::helper('searchanise/ApiXML')->generateProductsXML($productIds, $store, true);
 
 
 
 
 
 
 
122
  $n++;
123
  }
124
 
125
  echo $this->_profiler();
126
+ if ($visual) {
127
+ Mage::helper('searchanise/ApiSe')->printR($productFeeds);
128
+ } else {
129
+ echo Mage::helper('core')->jsonEncode($productFeeds);
130
+ }
131
  } elseif ($resync) {
132
  Mage::helper('searchanise/ApiSe')->queueImport($store);
133
 
134
  } elseif (!empty($productIds)) {
135
+ $productFeeds = Mage::helper('searchanise/ApiXML')->generateProductsXML($productIds, $store, $checkData);
136
  if ($productFeeds) {
137
  $xmlHeader = Mage::helper('searchanise/ApiXML')->getXMLHeader($store);
138
  $xmlFooter = Mage::helper('searchanise/ApiXML')->getXMLFooter($store);
app/code/community/Simtech/Searchanise/etc/config.xml CHANGED
@@ -15,7 +15,7 @@
15
  <config>
16
  <modules>
17
  <Simtech_Searchanise>
18
- <version>2.0.1</version>
19
  </Simtech_Searchanise>
20
  </modules>
21
  <frontend>
@@ -568,7 +568,7 @@
568
  <search_timeout>3</search_timeout>
569
  <request_timeout>10</request_timeout>
570
  <ajax_async_timeout>1</ajax_async_timeout>
571
- <products_per_pass>50</products_per_pass>
572
  <max_error_count>25</max_error_count>
573
  <max_processing_thread>3</max_processing_thread>
574
  <max_processing_time>720</max_processing_time>
15
  <config>
16
  <modules>
17
  <Simtech_Searchanise>
18
+ <version>2.0.2</version>
19
  </Simtech_Searchanise>
20
  </modules>
21
  <frontend>
568
  <search_timeout>3</search_timeout>
569
  <request_timeout>10</request_timeout>
570
  <ajax_async_timeout>1</ajax_async_timeout>
571
+ <products_per_pass>100</products_per_pass>
572
  <max_error_count>25</max_error_count>
573
  <max_processing_thread>3</max_processing_thread>
574
  <max_processing_time>720</max_processing_time>
app/code/community/Simtech/Searchanise/etc/config_without_search.xml CHANGED
@@ -15,7 +15,7 @@
15
  <config>
16
  <modules>
17
  <Simtech_Searchanise>
18
- <version>2.0.1</version>
19
  </Simtech_Searchanise>
20
  </modules>
21
  <frontend>
@@ -568,7 +568,7 @@
568
  <search_timeout>3</search_timeout>
569
  <request_timeout>10</request_timeout>
570
  <ajax_async_timeout>1</ajax_async_timeout>
571
- <products_per_pass>50</products_per_pass>
572
  <max_error_count>25</max_error_count>
573
  <max_processing_thread>3</max_processing_thread>
574
  <max_processing_time>720</max_processing_time>
15
  <config>
16
  <modules>
17
  <Simtech_Searchanise>
18
+ <version>2.0.2</version>
19
  </Simtech_Searchanise>
20
  </modules>
21
  <frontend>
568
  <search_timeout>3</search_timeout>
569
  <request_timeout>10</request_timeout>
570
  <ajax_async_timeout>1</ajax_async_timeout>
571
+ <products_per_pass>100</products_per_pass>
572
  <max_error_count>25</max_error_count>
573
  <max_processing_thread>3</max_processing_thread>
574
  <max_processing_time>720</max_processing_time>
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Simtech_Searchanise</name>
4
- <version>2.0.1</version>
5
  <stability>stable</stability>
6
  <license uri="http://docs.searchanise.com/connector_addon/license_agreement.html">Commercial license: http://docs.searchanise.com/connector_addon/license_agreement.html</license>
7
  <channel>community</channel>
@@ -10,14 +10,14 @@
10
  <description>Searchanise is a free SaaS solution providing fast and smart search for online stores. It provides rapid search results and instant search suggestions presented in a fancy and customizable widget.&#xD;
11
  &#xD;
12
  With the help of Searchanise Connector Add-on you will be able to connect your store to the service and start using the search widget in no time. Power up your store right now!</description>
13
- <notes>[+] More product attributes can be collected for better deal-aggregator export (e.g. Google Shopping).&lt;br /&gt;&#xD;
14
- [*] Catalog data submitting speed improved.&lt;br /&gt;&#xD;
15
- [!] Fixed an issue with currencies containing the "'" character, which could break the instant search widget and Searchanise admin panel.&lt;br /&gt;&#xD;
16
- [*] Configured products support improved: extra data validation added.</notes>
17
  <authors><author><name>Simbirsk Technologies, Ltd.</name><user>searchanise</user><email>sales@searchanise.com</email></author></authors>
18
- <date>2014-01-20</date>
19
- <time>08:08:00</time>
20
- <contents><target name="magecommunity"><dir name="Simtech"><dir name="Searchanise"><dir name="Block"><file name="Async.php" hash="bc97c98da15f5abbc1d8922ca477dc6d"/><file name="Autocomplete.php" hash="efc89ac3f897be3bc307fba6a36778f0"/><file name="Jsinit.php" hash="3cb0a3bd02858a6ce81d14dbc7b6042f"/><dir name="Product"><dir name="List"><file name="Toolbar.php" hash="759854378cb8c35c37a8a7f44076194f"/></dir><file name="Result.php" hash="4e767e273ee21a38332ac226af878291"/></dir><file name="Result.php" hash="dec7b27ab9511c956680eb60eba9b95e"/></dir><dir name="Helper"><file name="ApiSe.php" hash="5f68ea5c944463c2bb7aac69c51f75cc"/><file name="ApiXML.php" hash="9f35543cb1edf6c8e13adae021abaf2e"/><file name="Data.php" hash="7c600b973ddaf87cd6a3d507bc6691c5"/></dir><dir name="Model"><file name="Advanced.php" hash="2a22ebcf7ac75b54681ef8a27bad2e47"/><dir name="Config"><file name="Data.php" hash="ddc558d22208f0ebc1e4378c9d050022"/></dir><file name="Config.php" hash="00ca3c7955f3ff2283c636a2074b6f03"/><dir name="Import"><dir name="Entity"><file name="Product.php" hash="4997af528b36f0f576d1c01402e14b03"/></dir></dir><dir name="Layer"><dir name="Filter"><file name="Category.php" hash="e290ab29f2d50e1acbbbb37496150ea4"/><file name="Price.php" hash="743887b32bf012274ad8a371fff96411"/></dir></dir><file name="Layer.php" hash="3e8c975d649ae6e20fcc69d35779c97c"/><file name="LayerCatalogSearch.php" hash="42058e0552719902f3f40f91e816b460"/><dir name="Mysql4"><dir name="Advanced"><file name="Collection.php" hash="dd8c6f3cbb0621a5a7320f3104e68da6"/></dir><dir name="Config"><file name="Collection.php" hash="470218c1eb3f1cc1ca0e6d0e93e1b097"/></dir><file name="Config.php" hash="c95dc8ecd7ab4f955b6eaf4710ab960e"/><dir name="Fulltext"><file name="Collection.php" hash="5646955503a90020f87cfd861ac07e73"/></dir><dir name="Product"><file name="Collection.php" hash="28b478eb328502ce03e389404d9f54b5"/><file name="CollectionTag.php" hash="ea06ec75ee4d083f2b4232c5fe298f00"/></dir><dir name="Queue"><file name="Collection.php" hash="30ca0f8640bdc443deb94cd2e71010c8"/></dir><file name="Queue.php" hash="286351623e8f011a21519f8d9c3e3151"/><file name="Store.php" hash="0126a4291d7dad6641bf59abb0f64cc4"/></dir><file name="Observer.php" hash="5db27768e7d77ed7ddc63ae9f4c4308c"/><file name="Queue.php" hash="831f5ea7e57810f9c78d09659424e9a7"/><file name="Request.php" hash="4bcc67cae33aa9d173e9c414a0367488"/><dir name="Resource"><dir name="Advanced"><file name="Collection.php" hash="6744555254ba1c57f482504b5f16012a"/></dir><dir name="Eav"><dir name="Mysql4"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="05320757b9289edac4f15230cd06c0e1"/><file name="Price.php" hash="ed4e21a18c552e3a92b21ff6e8bc5d61"/></dir></dir><dir name="Product"><file name="Action.php" hash="006e3c8c775cf31a8b9c66fb934c9d2d"/></dir></dir></dir><dir name="Fulltext"><file name="Collection.php" hash="273467b2e39649fcd0a8eede59c5ab98"/></dir><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="643a513735ac2a2ac9fba08ff1fa79a0"/><file name="Price.php" hash="15d7ab510b37655a148e077dcece13df"/></dir></dir><dir name="Product"><file name="Collection.php" hash="b7c9a1c2fc24ecf78a32fd0d9d46b120"/><file name="CollectionTag.php" hash="60f12d27d78426a8e04e01d2cbdadb48"/></dir><file name="Store.php" hash="dee8bb23b7fe48dc55e46e93f583699a"/></dir><file name="Searchanise.php" hash="0a03a35854470a310f075298c9a1abf2"/><dir name="System"><dir name="Config"><dir name="Source"><dir name="Searchanise"><file name="TypeAsync.php" hash="11d1aa481094ccbeab365b1fed33440d"/></dir></dir></dir></dir><dir name="Tag"><file name="Relation.php" hash="598f81fd8b2ac77baf24211c2ed03e55"/></dir></dir><dir name="controllers"><file name="AdvancedController.php" hash="5ea4f7fb3362d720462dc0a8e1f1497b"/><file name="AsyncController.php" hash="e1a7dd9debd00fb7df09804d99e56e9e"/><file name="CategoryController.php" hash="06eac1ad4730d42379f6bc6aae097427"/><file name="IndexController.php" hash="e3234ca51a7669741e29ff7c38789989"/><file name="InfoController.php" hash="ab8556ae00d6b807994565acc237553b"/><file name="OptionsController.php" hash="46b8e49dd1026a5e07410b51d101d498"/><file name="ProductController.php" hash="4cf4e991446a36ea34b7c1d350971e1a"/><file name="ResultController.php" hash="2c1d838a2897ffcbb8bc61743254e934"/><file name="ResyncController.php" hash="0612f929d375427326821dfc12186be8"/><file name="SignupController.php" hash="80f87a63d6272f98a068dde35f1d140e"/></dir><dir name="etc"><file name="config.xml" hash="fcae27310305390a96f7fd2f7882091b"/><file name="config_without_search.xml" hash="48706176e1080dfab63f8a6102e70edf"/><file name="system.xml" hash="a006341e693571d11efaa9d289ebf7fa"/></dir><dir name="sql"><dir name="searchanise_setup"><file name="mysql4-install-0.1.0.php" hash="754324c8783e9cc24de86396e1587e73"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="searchanise"><file name="dashboard.phtml" hash="0ec8814b915e8594b019062c071cc485"/></dir></dir><dir name="layout"><file name="searchanise.xml" hash="68baa611d05db05f8816ea2a8260e961"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="searchanise.xml" hash="5e904fee02cbd42324a297d513b9f582"/></dir></dir></dir><dir name="default"><dir name="default"><dir name="template"><dir name="catalogsearch"><file name="form.mini.phtml" hash="fcf8e06e66801a36c96f20ca5d187123"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Simtech_Searchanise.xml" hash="04148681a6648bd370ab62140cbf2ad9"/></dir></target><target name="magelocale"><dir name="en_US"><file name="Simtech_Searchanise.csv" hash="1bdb7fddc596dac1460bc3054c425187"/></dir></target></contents>
21
  <compatible/>
22
  <dependencies><required><php><min>5.2.13</min><max>6.0.0</max></php></required></dependencies>
23
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Simtech_Searchanise</name>
4
+ <version>2.0.2</version>
5
  <stability>stable</stability>
6
  <license uri="http://docs.searchanise.com/connector_addon/license_agreement.html">Commercial license: http://docs.searchanise.com/connector_addon/license_agreement.html</license>
7
  <channel>community</channel>
10
  <description>Searchanise is a free SaaS solution providing fast and smart search for online stores. It provides rapid search results and instant search suggestions presented in a fancy and customizable widget.&#xD;
11
  &#xD;
12
  With the help of Searchanise Connector Add-on you will be able to connect your store to the service and start using the search widget in no time. Power up your store right now!</description>
13
+ <notes>[*] Full catalog import is now 2.5-3 times faster.&#xD;
14
+ [*] For a group product, its child product descriptions are stored in a separate attribute (fixes the [:ATTR:] issue).&#xD;
15
+ [!] The [:ATTR:] chunk could occur in the instant search widget. Fixed.&#xD;
16
+ [!] Attribute weights tuned for more relevant search (e.g. description weight increased).</notes>
17
  <authors><author><name>Simbirsk Technologies, Ltd.</name><user>searchanise</user><email>sales@searchanise.com</email></author></authors>
18
+ <date>2014-01-28</date>
19
+ <time>07:42:45</time>
20
+ <contents><target name="magecommunity"><dir name="Simtech"><dir name="Searchanise"><dir name="Block"><file name="Async.php" hash="bc97c98da15f5abbc1d8922ca477dc6d"/><file name="Autocomplete.php" hash="efc89ac3f897be3bc307fba6a36778f0"/><file name="Jsinit.php" hash="3cb0a3bd02858a6ce81d14dbc7b6042f"/><dir name="Product"><dir name="List"><file name="Toolbar.php" hash="759854378cb8c35c37a8a7f44076194f"/></dir><file name="Result.php" hash="4e767e273ee21a38332ac226af878291"/></dir><file name="Result.php" hash="dec7b27ab9511c956680eb60eba9b95e"/></dir><dir name="Helper"><file name="ApiSe.php" hash="5f68ea5c944463c2bb7aac69c51f75cc"/><file name="ApiXML.php" hash="718b40e3039d701196ca8da9b3a5933e"/><file name="Data.php" hash="7c600b973ddaf87cd6a3d507bc6691c5"/></dir><dir name="Model"><file name="Advanced.php" hash="2a22ebcf7ac75b54681ef8a27bad2e47"/><dir name="Config"><file name="Data.php" hash="ddc558d22208f0ebc1e4378c9d050022"/></dir><file name="Config.php" hash="00ca3c7955f3ff2283c636a2074b6f03"/><dir name="Import"><dir name="Entity"><file name="Product.php" hash="4997af528b36f0f576d1c01402e14b03"/></dir></dir><dir name="Layer"><dir name="Filter"><file name="Category.php" hash="e290ab29f2d50e1acbbbb37496150ea4"/><file name="Price.php" hash="743887b32bf012274ad8a371fff96411"/></dir></dir><file name="Layer.php" hash="3e8c975d649ae6e20fcc69d35779c97c"/><file name="LayerCatalogSearch.php" hash="42058e0552719902f3f40f91e816b460"/><dir name="Mysql4"><dir name="Advanced"><file name="Collection.php" hash="dd8c6f3cbb0621a5a7320f3104e68da6"/></dir><dir name="Config"><file name="Collection.php" hash="470218c1eb3f1cc1ca0e6d0e93e1b097"/></dir><file name="Config.php" hash="c95dc8ecd7ab4f955b6eaf4710ab960e"/><dir name="Fulltext"><file name="Collection.php" hash="5646955503a90020f87cfd861ac07e73"/></dir><dir name="Product"><file name="Collection.php" hash="28b478eb328502ce03e389404d9f54b5"/><file name="CollectionTag.php" hash="ea06ec75ee4d083f2b4232c5fe298f00"/></dir><dir name="Queue"><file name="Collection.php" hash="30ca0f8640bdc443deb94cd2e71010c8"/></dir><file name="Queue.php" hash="286351623e8f011a21519f8d9c3e3151"/><file name="Store.php" hash="0126a4291d7dad6641bf59abb0f64cc4"/></dir><file name="Observer.php" hash="5db27768e7d77ed7ddc63ae9f4c4308c"/><file name="Queue.php" hash="831f5ea7e57810f9c78d09659424e9a7"/><file name="Request.php" hash="4bcc67cae33aa9d173e9c414a0367488"/><dir name="Resource"><dir name="Advanced"><file name="Collection.php" hash="6744555254ba1c57f482504b5f16012a"/></dir><dir name="Eav"><dir name="Mysql4"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="05320757b9289edac4f15230cd06c0e1"/><file name="Price.php" hash="ed4e21a18c552e3a92b21ff6e8bc5d61"/></dir></dir><dir name="Product"><file name="Action.php" hash="006e3c8c775cf31a8b9c66fb934c9d2d"/></dir></dir></dir><dir name="Fulltext"><file name="Collection.php" hash="273467b2e39649fcd0a8eede59c5ab98"/></dir><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="643a513735ac2a2ac9fba08ff1fa79a0"/><file name="Price.php" hash="15d7ab510b37655a148e077dcece13df"/></dir></dir><dir name="Product"><file name="Collection.php" hash="b7c9a1c2fc24ecf78a32fd0d9d46b120"/><file name="CollectionTag.php" hash="60f12d27d78426a8e04e01d2cbdadb48"/></dir><file name="Store.php" hash="dee8bb23b7fe48dc55e46e93f583699a"/></dir><file name="Searchanise.php" hash="0a03a35854470a310f075298c9a1abf2"/><dir name="System"><dir name="Config"><dir name="Source"><dir name="Searchanise"><file name="TypeAsync.php" hash="11d1aa481094ccbeab365b1fed33440d"/></dir></dir></dir></dir><dir name="Tag"><file name="Relation.php" hash="598f81fd8b2ac77baf24211c2ed03e55"/></dir></dir><dir name="controllers"><file name="AdvancedController.php" hash="5ea4f7fb3362d720462dc0a8e1f1497b"/><file name="AsyncController.php" hash="e1a7dd9debd00fb7df09804d99e56e9e"/><file name="CategoryController.php" hash="06eac1ad4730d42379f6bc6aae097427"/><file name="IndexController.php" hash="e3234ca51a7669741e29ff7c38789989"/><file name="InfoController.php" hash="ad7268c1ccba3323bd2c20341a14f880"/><file name="OptionsController.php" hash="46b8e49dd1026a5e07410b51d101d498"/><file name="ProductController.php" hash="4cf4e991446a36ea34b7c1d350971e1a"/><file name="ResultController.php" hash="2c1d838a2897ffcbb8bc61743254e934"/><file name="ResyncController.php" hash="0612f929d375427326821dfc12186be8"/><file name="SignupController.php" hash="80f87a63d6272f98a068dde35f1d140e"/></dir><dir name="etc"><file name="config.xml" hash="528aaa445dbe31d08b63a818063035c5"/><file name="config_without_search.xml" hash="a7b9f3676b3aeed285145c26ed34c39b"/><file name="system.xml" hash="a006341e693571d11efaa9d289ebf7fa"/></dir><dir name="sql"><dir name="searchanise_setup"><file name="mysql4-install-0.1.0.php" hash="754324c8783e9cc24de86396e1587e73"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="searchanise"><file name="dashboard.phtml" hash="0ec8814b915e8594b019062c071cc485"/></dir></dir><dir name="layout"><file name="searchanise.xml" hash="68baa611d05db05f8816ea2a8260e961"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="searchanise.xml" hash="5e904fee02cbd42324a297d513b9f582"/></dir></dir></dir><dir name="default"><dir name="default"><dir name="template"><dir name="catalogsearch"><file name="form.mini.phtml" hash="fcf8e06e66801a36c96f20ca5d187123"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Simtech_Searchanise.xml" hash="04148681a6648bd370ab62140cbf2ad9"/></dir></target><target name="magelocale"><dir name="en_US"><file name="Simtech_Searchanise.csv" hash="1bdb7fddc596dac1460bc3054c425187"/></dir></target></contents>
21
  <compatible/>
22
  <dependencies><required><php><min>5.2.13</min><max>6.0.0</max></php></required></dependencies>
23
  </package>