00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 class Mage_CatalogIndex_Model_Mysql4_Indexer extends Mage_Core_Model_Mysql4_Abstract
00034 {
00035 protected $_insertData = array();
00036 protected $_tableFields = array();
00037 protected $_attributeCache = array();
00038
00039 protected function _construct()
00040 {
00041 $this->_init('catalog/product', 'entity_id');
00042 }
00043
00044 protected function _loadAttribute($id)
00045 {
00046 if (!isset($this->_attributeCache[$id])) {
00047 $this->_attributeCache[$id] = Mage::getModel('eav/entity_attribute')->load($id);
00048 }
00049
00050 return $this->_attributeCache[$id];
00051 }
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 public function clear($eav = true, $price = true, $minimal = true, $finalPrice = true, $tierPrice = true, $products = null, $store = null)
00065 {
00066 $suffix = '';
00067 $priceSuffix = '';
00068 $tables = array('eav'=>'catalogindex/eav', 'price'=>'catalogindex/price');
00069 if (!is_null($products)) {
00070 if ($products instanceof Mage_Catalog_Model_Product) {
00071 $products = $products->getId();
00072 } elseif ($products instanceof Mage_Catalog_Model_Product_Condition_Interface) {
00073 $suffix = 'entity_id IN ('.$products->getIdsSelect($this->_getWriteAdapter())->__toString().')';
00074 }
00075 else if (!is_numeric($products) && !is_array($products)) {
00076 Mage::throwException('Invalid products supplied for indexing');
00077 }
00078 if (empty($suffix)) {
00079 $suffix = $this->_getWriteAdapter()->quoteInto('entity_id in (?)', $products);
00080 }
00081 }
00082 if (!is_null($store)) {
00083 $websiteIds = array();
00084
00085 if ($store instanceof Mage_Core_Model_Store) {
00086 $store = $store->getId();
00087 $websiteIds[] = Mage::app()->getStore($store)->getWebsiteId();
00088 } else if ($store instanceof Mage_Core_Model_Mysql4_Store_Collection) {
00089 $store = $store->getAllIds();
00090 foreach ($store as $one) {
00091 $websiteIds[] = Mage::app()->getStore($one)->getWebsiteId();
00092 }
00093 } else if (is_array($store)) {
00094 $resultStores = array();
00095 foreach ($store as $s) {
00096 if ($s instanceof Mage_Core_Model_Store) {
00097 $resultStores[] = $s->getId();
00098 $websiteIds[] = $s->getWebsiteId();
00099 } elseif (is_numeric($s)) {
00100 $websiteIds[] = Mage::app()->getStore($s)->getWebsiteId();
00101 $resultStores[] = $s;
00102 }
00103 }
00104 $store = $resultStores;
00105 }
00106
00107 if ($suffix) {
00108 $suffix .= ' AND ';
00109 }
00110
00111 $priceSuffix = $suffix . $this->_getWriteAdapter()->quoteInto('website_id in (?)', $websiteIds);
00112 $suffix .= $this->_getWriteAdapter()->quoteInto('store_id in (?)', $store);
00113
00114 }
00115
00116 if ($tierPrice) {
00117 $tables['tierPrice'] = 'catalogindex/price';
00118 $tierPrice = array(Mage::getSingleton('eav/entity_attribute')->getIdByCode('catalog_product', 'tier_price'));
00119 }
00120 if ($finalPrice) {
00121 $tables['finalPrice'] = 'catalogindex/price';
00122 $tierPrice = array(Mage::getSingleton('eav/entity_attribute')->getIdByCode('catalog_product', 'price'));
00123 }
00124 if ($minimal) {
00125 $tables['minimal'] = 'catalogindex/minimal_price';
00126 }
00127
00128
00129 foreach ($tables as $variable=>$table) {
00130 $variable = $$variable;
00131 $suffixToInsert = $suffix;
00132 if (in_array($table, $this->_getPriceTables())) {
00133 $suffixToInsert = $priceSuffix;
00134 }
00135
00136 if ($variable === true) {
00137 $query = "DELETE FROM {$this->getTable($table)} ";
00138 if ($suffixToInsert) {
00139 $query .= "WHERE {$suffixToInsert}";
00140 }
00141
00142 $this->_getWriteAdapter()->query($query);
00143 } else if (is_array($variable) && count($variable)) {
00144 $query = "DELETE FROM {$this->getTable($table)} WHERE ";
00145 $query .= $this->_getWriteAdapter()->quoteInto("attribute_id in (?)", $variable);
00146 if ($suffixToInsert) {
00147 $query .= " AND {$suffixToInsert}";
00148 }
00149
00150 $this->_getWriteAdapter()->query($query);
00151 }
00152 }
00153 }
00154
00155
00156
00157
00158
00159
00160 protected function _getPriceTables()
00161 {
00162 return array('catalogindex/price', 'catalogindex/minimal_price');
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 public function reindexTiers($products, $store, $forcedId = null)
00175 {
00176 $websiteId = $store->getWebsiteId();
00177 $attribute = Mage::getSingleton('eav/entity_attribute')->getIdByCode('catalog_product', 'tier_price');
00178 $this->_beginInsert(
00179 'catalogindex/price',
00180 array('entity_id', 'attribute_id', 'value', 'website_id', 'customer_group_id', 'qty')
00181 );
00182
00183
00184
00185
00186
00187
00188
00189 $products = Mage::getSingleton('catalogindex/retreiver')->assignProductTypes($products);
00190 if (is_null($forcedId)) {
00191 foreach ($products as $type=>$typeIds) {
00192 $retreiver = Mage::getSingleton('catalogindex/retreiver')->getRetreiver($type);
00193 if ($retreiver->areChildrenIndexable(Mage_CatalogIndex_Model_Retreiver::CHILDREN_FOR_TIERS)) {
00194 foreach ($typeIds as $id) {
00195 $children = $retreiver->getChildProductIds($store, $id);
00196 if ($children) {
00197 $this->reindexTiers($children, $store, $id);
00198 }
00199 }
00200 }
00201 }
00202 }
00203
00204 $attributeIndex = $this->getTierData($products, $store);
00205 foreach ($attributeIndex as $index) {
00206 $type = $index['type_id'];
00207 $id = (is_null($forcedId) ? $index['entity_id'] : $forcedId);
00208 if ($id && $index['value']) {
00209 if ($index['all_groups'] == 1) {
00210 foreach (Mage::getSingleton('catalogindex/retreiver')->getCustomerGroups() as $group) {
00211 $this->_insert('catalogindex/price', array(
00212 $id,
00213 $attribute,
00214 $index['value'],
00215 $websiteId,
00216 (int) $group->getId(),
00217 (int) $index['qty']
00218 ));
00219 }
00220 } else {
00221 $this->_insert('catalogindex/price', array(
00222 $id,
00223 $attribute,
00224 $index['value'],
00225 $websiteId,
00226 (int) $index['customer_group_id'],
00227 (int) $index['qty']
00228 ));
00229 }
00230 }
00231 }
00232 $this->_commitInsert('catalogindex/price');
00233 return $this;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 public function reindexPrices($products, $attributeIds, $store)
00245 {
00246 $this->reindexAttributes($products, $attributeIds, $store, null, 'catalogindex/price', true);
00247 return $this;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 public function reindexFinalPrices($products, $store, $forcedId = null)
00260 {
00261 $priceAttribute = Mage::getSingleton('eav/entity_attribute')->getIdByCode('catalog_product', 'price');
00262 $this->_beginInsert('catalogindex/price', array(
00263 'entity_id',
00264 'website_id',
00265 'customer_group_id',
00266 'value',
00267 'attribute_id',
00268 'tax_class_id'
00269 ));
00270
00271 $productTypes = Mage::getSingleton('catalogindex/retreiver')->assignProductTypes($products);
00272 foreach ($productTypes as $type=>$products) {
00273 $retreiver = Mage::getSingleton('catalogindex/retreiver')->getRetreiver($type);
00274 foreach ($products as $product) {
00275 if (is_null($forcedId)) {
00276 if ($retreiver->areChildrenIndexable(Mage_CatalogIndex_Model_Retreiver::CHILDREN_FOR_PRICES)) {
00277 $children = $retreiver->getChildProductIds($store, $product);
00278 if ($children) {
00279 $this->reindexFinalPrices($children, $store, $product);
00280 }
00281 }
00282 }
00283 foreach (Mage::getSingleton('catalogindex/retreiver')->getCustomerGroups() as $group) {
00284 $finalPrice = $retreiver->getFinalPrice($product, $store, $group);
00285 $taxClassId = $retreiver->getTaxClassId($product, $store);
00286 $id = $product;
00287 if (!is_null($forcedId)) {
00288 $id = $forcedId;
00289 }
00290
00291 if (false !== $finalPrice && false !== $id && false !== $priceAttribute) {
00292 $this->_insert('catalogindex/price', array(
00293 $id,
00294 $store->getWebsiteId(),
00295 $group->getId(),
00296 $finalPrice,
00297 $priceAttribute,
00298 $taxClassId
00299 ));
00300 }
00301 }
00302 }
00303 }
00304 $this->_commitInsert('catalogindex/price');
00305 return $this;
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 public function reindexMinimalPrices($products, $store)
00317 {
00318 $this->_beginInsert('catalogindex/minimal_price', array(
00319 'website_id',
00320 'entity_id',
00321 'customer_group_id',
00322 'value',
00323 'tax_class_id'
00324 ));
00325 $this->clear(false, false, true, false, false, $products, $store);
00326 $products = Mage::getSingleton('catalogindex/retreiver')->assignProductTypes($products);
00327
00328 foreach ($products as $type=>$typeIds) {
00329 $retreiver = Mage::getSingleton('catalogindex/retreiver')->getRetreiver($type);
00330
00331 foreach ($typeIds as $id) {
00332 $minimal = array();
00333 if ($retreiver->areChildrenIndexable(Mage_CatalogIndex_Model_Retreiver::CHILDREN_FOR_PRICES)) {
00334 $children = $retreiver->getChildProductIds($store, $id);
00335 if ($children) {
00336 $minimal = $this->getMinimalPrice(array($type=>$children), $store);
00337 }
00338 } else {
00339 $minimal = $this->getMinimalPrice(array($type=>array($id)), $store);
00340 }
00341
00342 if (is_array($minimal)) {
00343 foreach ($minimal as $price) {
00344 if (!isset($price['tax_class_id'])) {
00345 $price['tax_class_id'] = 0;
00346 }
00347 $this->_insert('catalogindex/minimal_price', array(
00348 $store->getWebsiteId(),
00349 $id,
00350 $price['customer_group_id'],
00351 $price['minimal_value'],
00352 $price['tax_class_id']
00353 ));
00354 }
00355 }
00356 }
00357 }
00358
00359 $this->_commitInsert('catalogindex/minimal_price');
00360 return $this;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 public function reindexAttributes($products, $attributeIds, $store, $forcedId = null, $table = 'catalogindex/eav', $storeIsWebsite = false)
00375 {
00376 $storeField = 'store_id';
00377 $websiteId = null;
00378 if ($storeIsWebsite) {
00379 $storeField = 'website_id';
00380 if ($store instanceof Mage_Core_Model_Store) {
00381 $websiteId = $store->getWebsiteId();
00382 } else {
00383 $websiteId = Mage::app()->getStore($store)->getWebsiteId();
00384 }
00385 }
00386
00387 $this->_beginInsert($table, array('entity_id', 'attribute_id', 'value', $storeField));
00388
00389 $products = Mage::getSingleton('catalogindex/retreiver')->assignProductTypes($products);
00390
00391 if (is_null($forcedId)) {
00392 foreach ($products as $type=>$typeIds) {
00393 $retreiver = Mage::getSingleton('catalogindex/retreiver')->getRetreiver($type);
00394 if ($retreiver->areChildrenIndexable(Mage_CatalogIndex_Model_Retreiver::CHILDREN_FOR_ATTRIBUTES)) {
00395 foreach ($typeIds as $id) {
00396 $children = $retreiver->getChildProductIds($store, $id);
00397 if ($children) {
00398 $this->reindexAttributes($children, $attributeIds, $store, $id, $table, $storeIsWebsite);
00399 }
00400 }
00401 }
00402 }
00403 }
00404
00405 $attributeIndex = $this->getProductData($products, $attributeIds, $store);
00406 foreach ($attributeIndex as $index) {
00407 $type = $index['type_id'];
00408 $id = (is_null($forcedId) ? $index['entity_id'] : $forcedId);
00409
00410 if ($id && $index['attribute_id'] && isset($index['value'])) {
00411 $attribute = $this->_loadAttribute($index['attribute_id']);
00412 if ($attribute->getFrontendInput() == 'multiselect') {
00413 $index['value'] = explode(',', $index['value']);
00414 }
00415
00416 if (is_array($index['value'])) {
00417 foreach ($index['value'] as $value) {
00418 $this->_insert($table, array(
00419 $id,
00420 $index['attribute_id'],
00421 $value,
00422 (is_null($websiteId) ? $store->getId() : $websiteId)
00423 ));
00424 }
00425 } else {
00426 $this->_insert($table, array(
00427 $id,
00428 $index['attribute_id'],
00429 $index['value'],
00430 (is_null($websiteId) ? $store->getId() : $websiteId)
00431 ));
00432 }
00433 }
00434 }
00435
00436 $this->_commitInsert($table);
00437 return $this;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447 public function getTierData($products, $store){
00448 $result = array();
00449 foreach ($products as $type=>$typeIds) {
00450 $retreiver = Mage::getSingleton('catalogindex/retreiver')->getRetreiver($type);
00451 $byType = $retreiver->getTierPrices($typeIds, $store);
00452 if ($byType) {
00453 $result = array_merge($result, $byType);
00454 }
00455 }
00456 return $result;
00457 }
00458
00459
00460
00461
00462
00463
00464
00465
00466 public function getMinimalPrice($products, $store)
00467 {
00468 $result = array();
00469 foreach ($products as $type=>$typeIds) {
00470 $retreiver = Mage::getSingleton('catalogindex/retreiver')->getRetreiver($type);
00471 $byType = $retreiver->getMinimalPrice($typeIds, $store);
00472 if ($byType) {
00473 $result = array_merge($result, $byType);
00474 }
00475 }
00476 return $result;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 public function getProductData($products, $attributeIds, $store){
00488 $result = array();
00489 foreach ($products as $type=>$typeIds) {
00490 $retreiver = Mage::getSingleton('catalogindex/retreiver')->getRetreiver($type);
00491 $byType = $retreiver->getAttributeData($typeIds, $attributeIds, $store);
00492 if ($byType) {
00493 $result = array_merge($result, $byType);
00494 }
00495 }
00496 return $result;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506 protected function _beginInsert($table, $fields){
00507 $this->_tableFields[$table] = $fields;
00508 return $this;
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518 protected function _commitInsert($table, $forced = true){
00519 if (isset($this->_insertData[$table]) && count($this->_insertData[$table]) && ($forced || count($this->_insertData[$table]) >= 100)) {
00520 $query = 'REPLACE INTO ' . $this->getTable($table) . ' (' . implode(', ', $this->_tableFields[$table]) . ') VALUES ';
00521 $separator = '';
00522 foreach ($this->_insertData[$table] as $row) {
00523 $rowString = $this->_getWriteAdapter()->quoteInto('(?)', $row);
00524 $query .= $separator . $rowString;
00525 $separator = ', ';
00526 }
00527 $this->_getWriteAdapter()->query($query);
00528 $this->_insertData[$table] = array();
00529 }
00530 return $this;
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540 protected function _insert($table, $data) {
00541 $this->_insertData[$table][] = $data;
00542 $this->_commitInsert($table, false);
00543 return $this;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552 public function prepareCatalogProductFlatColumns(Varien_Object $object)
00553 {
00554 $columns = $object->getColumns();
00555
00556 foreach (Mage::getSingleton('catalogindex/retreiver')->getCustomerGroups() as $group) {
00557 $columnName = 'display_price_group_' . $group->getId();
00558 $columns[$columnName] = array(
00559 'type' => 'decimal(12,4)',
00560 'unsigned' => false,
00561 'is_null' => true,
00562 'default' => null,
00563 'extra' => null
00564 );
00565 }
00566
00567 $object->setColumns($columns);
00568
00569 return $this;
00570 }
00571
00572
00573
00574
00575
00576
00577
00578 public function prepareCatalogProductFlatIndexes(Varien_Object $object)
00579 {
00580 $indexes = $object->getIndexes();
00581
00582 foreach (Mage::getSingleton('catalogindex/retreiver')->getCustomerGroups() as $group) {
00583 $columnName = 'display_price_group_' . $group->getId();
00584 $indexName = 'IDX_DISPLAY_PRICE_GROUP_' . $group->getId();
00585 $indexes[$indexName] = array(
00586 'type' => 'index',
00587 'fields' => array($columnName)
00588 );
00589 }
00590
00591 $object->setIndexes($indexes);
00592
00593 return $this;
00594 }
00595
00596
00597
00598
00599
00600
00601
00602
00603 public function updateCatalogProductFlat($storeId, $productIds = null, $tableName = null)
00604 {
00605 if (is_null($tableName)) {
00606 $tableName = $this->getTable('catalog/product_flat') . '_' . $storeId;
00607 }
00608 $addChildData = Mage::helper('catalog/product_flat')->isAddChildData();
00609
00610 $priceAttribute = Mage::getSingleton('eav/entity_attribute')
00611 ->getIdByCode('catalog_product', 'price');
00612 $websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
00613
00614 foreach (Mage::getSingleton('catalogindex/retreiver')->getCustomerGroups() as $group) {
00615 $columnName = 'display_price_group_' . $group->getId();
00616
00617
00618
00619
00620 $select = $this->_getWriteAdapter()->select()
00621 ->join(
00622 array('p' => $this->getTable('catalogindex/price')),
00623 "`e`.`entity_id`=`p`.`entity_id`"
00624 . " AND `p`.`attribute_id`={$priceAttribute}"
00625 . " AND `p`.`customer_group_id`={$group->getId()}"
00626 . " AND `p`.`website_id`={$websiteId}",
00627 array($columnName => 'value'));
00628 if ($addChildData) {
00629 $select->where('e.is_child=?', 0);
00630 }
00631
00632 if ($productIds instanceof Mage_Catalog_Model_Product_Condition_Interface) {
00633 $select->where('e.entity_id IN ('.$productIds->getIdsSelect($this->_getWriteAdapter())->__toString().')');
00634 } elseif (!is_null($productIds)) {
00635 $select->where("e.entity_id IN(?)", $productIds);
00636 }
00637
00638 $sql = $select->crossUpdateFromSelect(array('e' => $tableName));
00639 $this->_getWriteAdapter()->query($sql);
00640
00641 if ($addChildData) {
00642
00643
00644
00645 $select = $this->_getWriteAdapter()->select()
00646 ->join(
00647 array('p' => $this->getTable('catalogindex/price')),
00648 "`e`.`child_id`=`p`.`entity_id`"
00649 . " AND `p`.`attribute_id`={$priceAttribute}"
00650 . " AND `p`.`customer_group_id`={$group->getId()}"
00651 . " AND `p`.`website_id`={$websiteId}",
00652 array($columnName => 'value'))
00653 ->where('e.is_child=?', 1);
00654
00655 if ($productIds instanceof Mage_Catalog_Model_Product_Condition_Interface) {
00656 $select->where('e.child_id IN ('.$productIds->getIdsSelect($this->_getWriteAdapter())->__toString().')');
00657 } elseif (!is_null($productIds)) {
00658 $select->where("e.child_id IN(?)", $productIds);
00659 }
00660
00661 $sql = $select->crossUpdateFromSelect(array('e' => $tableName));
00662 $this->_getWriteAdapter()->query($sql);
00663 }
00664
00665 }
00666
00667 return $this;
00668 }
00669 }