/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Flat/Indexer.php
PHP | 1221 lines | 818 code | 111 blank | 292 comment | 116 complexity | 8cfb05dc444152094472c83b15cd77a8 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
- <?php
- /**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @category Mage
- * @package Mage_Catalog
- * @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
- */
- /**
- * Catalog Product Flat Indexer Resource Model
- *
- * @category Mage
- * @package Mage_Catalog
- * @author Magento Core Team <core@magentocommerce.com>
- */
- class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- extends Mage_Core_Model_Mysql4_Abstract
- {
- const XML_NODE_MAX_INDEX_COUNT = 'global/catalog/product/flat/max_index_count';
- const XML_NODE_ATTRIBUTE_NODES = 'global/catalog/product/flat/attribute_nodes';
- /**
- * Attribute codes for flat
- *
- * @var array
- */
- protected $_attributeCodes;
- /**
- * Attribute objects for flat cache
- *
- * @var array
- */
- protected $_attributes;
- /**
- * Required system attributes for preload
- *
- * @var array
- */
- protected $_systemAttributes = array('status', 'required_options', 'tax_class_id', 'weight');
- /**
- * Eav Catalog_Product Entity Type Id
- *
- * @var int
- */
- protected $_entityTypeId;
- /**
- * Flat table columns cache
- *
- * @var array
- */
- protected $_columns;
- /**
- * Flat table indexes cache
- *
- * @var array
- */
- protected $_indexes;
- /**
- * Product Type Instances cache
- *
- * @var array
- */
- protected $_productTypes;
- /**
- * Exists flat tables cache
- *
- * @var array
- */
- protected $_existsFlatTables = array();
- /**
- * Initialize connection
- *
- */
- protected function _construct()
- {
- $this->_init('catalog/product', 'entity_id');
- }
- /**
- * Rebuild Catalog Product Flat Data
- *
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function rebuild($store = null)
- {
- if (is_null($store)) {
- foreach (Mage::app()->getStores() as $store) {
- $this->rebuild($store->getId());
- }
- $flag = $this->getFlatHelper()->getFlag();
- $flag->setIsBuild(true)->save();
- return $this;
- }
- $this->prepareFlatTable($store);
- $this->cleanNonWebsiteProducts($store);
- $this->updateStaticAttributes($store);
- $this->updateEavAttributes($store);
- $this->updateEventAttributes($store);
- $this->updateRelationProducts($store);
- $this->cleanRelationProducts($store);
- return $this;
- }
- /**
- * Retrieve Catalog Product Flat helper
- *
- * @return Mage_Catalog_Helper_Product_Flat
- */
- public function getFlatHelper()
- {
- return Mage::helper('catalog/product_flat');
- }
- /**
- * Retrieve attribute codes using for flat
- *
- * @return array
- */
- public function getAttributeCodes()
- {
- if (is_null($this->_attributeCodes)) {
- $attributeNodes = Mage::getConfig()
- ->getNode(self::XML_NODE_ATTRIBUTE_NODES)
- ->children();
- foreach ($attributeNodes as $node) {
- $attributes = Mage::getConfig()->getNode((string)$node)->asArray();
- $attributes = array_keys($attributes);
- $this->_systemAttributes = array_unique(array_merge($attributes, $this->_systemAttributes));
- }
- $this->_attributeCodes = array();
- $whereCond = array(
- $this->_getReadAdapter()->quoteInto('main_table.backend_type=?', 'static'),
- $this->_getReadAdapter()->quoteInto('additional_table.used_in_product_listing=?', 1),
- $this->_getReadAdapter()->quoteInto('additional_table.used_for_sort_by=?', 1),
- $this->_getReadAdapter()->quoteInto('main_table.attribute_code IN(?)', $this->_systemAttributes)
- );
- if ($this->getFlatHelper()->isAddFilterableAttributes()) {
- $whereCond[] = $this->_getReadAdapter()->quoteInto('additional_table.is_filterable>?', 0);
- }
- $select = $this->_getReadAdapter()->select()
- ->from(array('main_table' => $this->getTable('eav/attribute')))
- ->join(
- array('additional_table' => $this->getTable('catalog/eav_attribute')),
- 'additional_table.attribute_id=main_table.attribute_id'
- )
- ->where('main_table.entity_type_id=?', $this->getEntityTypeId())
- ->where(join(' OR ', $whereCond));
- $attributesData = $this->_getReadAdapter()->fetchAll($select);
- Mage::getSingleton('eav/config')
- ->importAttributesData($this->getEntityType(), $attributesData);
- $this->_attributeCodes = array();
- foreach ($attributesData as $data) {
- $this->_attributeCodes[$data['attribute_id']] = $data['attribute_code'];
- }
- unset($attributesData);
- }
- return $this->_attributeCodes;
- }
- /**
- * Retrieve entity type
- *
- * @return string
- */
- public function getEntityType()
- {
- return 'catalog_product';
- }
- /**
- * Retrieve Catalog Entity Type Id
- *
- * @return int
- */
- public function getEntityTypeId()
- {
- if (is_null($this->_entityTypeId)) {
- $this->_entityTypeId = Mage::getResourceModel('catalog/config')
- ->getEntityTypeId();
- }
- return $this->_entityTypeId;
- }
- /**
- * Retrieve attribute objects for flat
- *
- * @param bool $cache
- * @return array
- */
- public function getAttributes()
- {
- if (is_null($this->_attributes)) {
- $attributeCodes = $this->getAttributeCodes(false);
- $entity = Mage::getSingleton('eav/config')
- ->getEntityType($this->getEntityType())
- ->getEntity();
- foreach ($attributeCodes as $attributeCode) {
- $attribute = Mage::getSingleton('eav/config')
- ->getAttribute($this->getEntityType(), $attributeCode)
- ->setEntity($entity);
- try {
- // check if exists source and backend model.
- // To prevent exception when some module was disabled
- $attribute->usesSource() && $attribute->getSource();
- $attribute->getBackend();
- $this->_attributes[$attributeCode] = $attribute;
- } catch (Exception $e) {
- Mage::logException($e);
- }
- }
- }
- return $this->_attributes;
- }
- /**
- * Retrieve loaded attribute by code
- *
- * @param string $attributeCode
- * @return Mage_Eav_Model_Entity_Attribute
- */
- public function getAttribute($attributeCode)
- {
- $attributes = $this->getAttributes();
- if (!isset($attributes[$attributeCode])) {
- $attribute = Mage::getModel('catalog/resource_eav_attribute')
- ->loadByCode($this->getEntityTypeId(), $attributeCode);
- if (!$attribute->getId()) {
- Mage::throwException(Mage::helper('catalog')->__('Invalid attribute %s.', $attributeCode));
- }
- $entity = Mage::getSingleton('eav/config')
- ->getEntityType($this->getEntityType())
- ->getEntity();
- $attribute->setEntity($entity);
- return $attribute;
- }
- return $attributes[$attributeCode];
- }
- /**
- * Retrieve Catalog Product Flat Table name
- *
- * @param int $store
- * @return string
- */
- public function getFlatTableName($store)
- {
- return $this->getTable('catalog/product_flat') . '_' . $store;
- }
- /**
- * Retrieve catalog product flat table columns array
- *
- * @return array
- */
- public function getFlatColumns()
- {
- if (is_null($this->_columns)) {
- $this->_columns = array();
- $this->_columns['entity_id'] = array(
- 'type' => 'int(10)',
- 'unsigned' => true,
- 'is_null' => false,
- 'default' => null,
- 'extra' => 'auto_increment'
- );
- if ($this->getFlatHelper()->isAddChildData()) {
- $this->_columns['child_id'] = array(
- 'type' => 'int(10)',
- 'unsigned' => true,
- 'is_null' => true,
- 'default' => null,
- 'extra' => null
- );
- $this->_columns['is_child'] = array(
- 'type' => 'tinyint(1)',
- 'unsigned' => true,
- 'is_null' => false,
- 'default' => 0,
- 'extra' => null
- );
- }
- $this->_columns['attribute_set_id'] = array(
- 'type' => 'smallint(5)',
- 'unsigned' => true,
- 'is_null' => false,
- 'default' => 0,
- 'extra' => null
- );
- $this->_columns['type_id'] = array(
- 'type' => 'varchar(32)',
- 'unsigned' => false,
- 'is_null' => false,
- 'default' => 'simple',
- 'extra' => null
- );
- foreach ($this->getAttributes() as $attribute) {
- /* @var $attribute Mage_Eav_Model_Entity_Attribute */
- $columns = $attribute
- ->setFlatAddFilterableAttributes($this->getFlatHelper()->isAddFilterableAttributes())
- ->setFlatAddChildData($this->getFlatHelper()->isAddChildData())
- ->getFlatColumns();
- if (is_null($columns)) {
- continue;
- }
- $this->_columns = array_merge($this->_columns, $columns);
- }
- $columnsObject = new Varien_Object();
- $columnsObject->setColumns($this->_columns);
- Mage::dispatchEvent('catalog_product_flat_prepare_columns', array(
- 'columns' => $columnsObject
- ));
- $this->_columns = $columnsObject->getColumns();
- }
- return $this->_columns;
- }
- /**
- * Retrieve catalog product flat table indexes array
- *
- * @return array
- */
- public function getFlatIndexes()
- {
- if (is_null($this->_indexes)) {
- $this->_indexes = array();
- if ($this->getFlatHelper()->isAddChildData()) {
- $this->_indexes['PRIMARY'] = array(
- 'type' => 'primary',
- 'fields' => array('entity_id', 'child_id')
- );
- $this->_indexes['IDX_CHILD'] = array(
- 'type' => 'index',
- 'fields' => array('child_id')
- );
- $this->_indexes['IDX_IS_CHILD'] = array(
- 'type' => 'index',
- 'fields' => array('entity_id', 'is_child')
- );
- }
- else {
- $this->_indexes['PRIMARY'] = array(
- 'type' => 'primary',
- 'fields' => array('entity_id')
- );
- }
- $this->_indexes['IDX_TYPE_ID'] = array(
- 'type' => 'index',
- 'fields' => array('type_id')
- );
- $this->_indexes['IDX_ATRRIBUTE_SET'] = array(
- 'type' => 'index',
- 'fields' => array('attribute_set_id')
- );
- foreach ($this->getAttributes() as $attribute) {
- /* @var $attribute Mage_Eav_Model_Entity_Attribute */
- $indexes = $attribute
- ->setFlatAddFilterableAttributes($this->getFlatHelper()->isAddFilterableAttributes())
- ->setFlatAddChildData($this->getFlatHelper()->isAddChildData())
- ->getFlatIndexes();
- if (is_null($indexes)) {
- continue;
- }
- $this->_indexes = array_merge($this->_indexes, $indexes);
- }
- $indexesObject = new Varien_Object();
- $indexesObject->setIndexes($this->_indexes);
- Mage::dispatchEvent('catalog_product_flat_prepare_indexes', array(
- 'indexes' => $indexesObject
- ));
- $this->_indexes = $indexesObject->getIndexes();
- }
- return $this->_indexes;
- }
- /**
- * Compare Flat style with Describe style columns
- *
- * If column a different - return false
- *
- * @param array $column
- * @param array $describe
- * @return bool
- */
- protected function _compareColumnProperties($column, $describe)
- {
- $type = $column['type'];
- $length = null;
- $precision = null;
- $scale = null;
- $matches = array();
- if (preg_match('/^((?:var)?char)\((\d+)\)/', $type, $matches)) {
- $type = $matches[1];
- $length = $matches[2];
- } else if (preg_match('/^decimal\((\d+),(\d+)\)/', $type, $matches)) {
- $type = 'decimal';
- $precision = $matches[1];
- $scale = $matches[2];
- } else if (preg_match('/^float\((\d+),(\d+)\)/', $type, $matches)) {
- $type = 'float';
- $precision = $matches[1];
- $scale = $matches[2];
- } else if (preg_match('/^((?:big|medium|small|tiny)?int)\((\d+)\)?/', $type, $matches)) {
- $type = $matches[1];
- }
- return ($describe['DATA_TYPE'] == $type)
- && ($describe['DEFAULT'] == $column['default'])
- && ((bool)$describe['NULLABLE'] == (bool)$column['is_null'])
- && ((bool)$describe['UNSIGNED'] == (bool)$column['unsigned'])
- && ($describe['LENGTH'] == $length)
- && ($describe['SCALE'] == $scale)
- && ($describe['PRECISION'] == $precision);
- }
- /**
- * Retrieve column definition fragment
- *
- * Example: `field_name` smallint(5) unsigned NOT NULL default '0'
- *
- * @param string $fieldName
- * @param array $fieldProp
- * @return string
- */
- protected function _sqlColunmDefinition($fieldName, $fieldProp)
- {
- $fieldNameQuote = $this->_getWriteAdapter()->quoteIdentifier($fieldName);
- /**
- * Process the case when 'is_null' prohibits null value, and 'default' proposed to be null
- * It just means that default value not specified
- */
- if (false === $fieldProp['is_null'] && null === $fieldProp['default']) {
- $defaultValue = '';
- } else {
- $defaultValue = $fieldProp['default'] === null ? ' DEFAULT NULL' : $this->_getReadAdapter()
- ->quoteInto(' DEFAULT ?', $fieldProp['default']);
- }
- return "{$fieldNameQuote} {$fieldProp['type']}"
- . ($fieldProp['unsigned'] ? ' UNSIGNED' : '')
- . ($fieldProp['extra'] ? ' ' . $fieldProp['extra'] : '')
- . ($fieldProp['is_null'] === false ? ' NOT NULL' : '')
- . $defaultValue;
- }
- /**
- * Retrieve index definition fragment
- *
- * Example: INDEX `IDX_NAME` (`field_id`)
- *
- * @param string $indexName
- * @param array $indexProp
- * @return string
- */
- protected function _sqlIndexDefinition($indexName, $indexProp)
- {
- $fields = $indexProp['fields'];
- if (is_array($fields)) {
- $fieldSql = array();
- foreach ($fields as $field) {
- $fieldSql[] = $this->_getReadAdapter()->quoteIdentifier($field);
- }
- $fieldSql = join(',', $fieldSql);
- }
- else {
- $fieldSql = $this->_getReadAdapter()->quoteIdentifier($fields);
- }
- $indexNameQuote = $this->_getReadAdapter()->quoteIdentifier($indexName);
- switch (strtolower($indexProp['type'])) {
- case 'primary':
- $condition = 'PRIMARY KEY';
- break;
- case 'unique':
- $condition = 'UNIQUE ' . $indexNameQuote;
- break;
- case 'fulltext':
- $condition = 'FULLTEXT ' . $indexNameQuote;
- break;
- default:
- $condition = 'INDEX ' . $indexNameQuote;
- break;
- }
- return sprintf('%s (%s)', $condition, $fieldSql);
- }
- /**
- * Prepare flat table for store
- *
- * @param int $store
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function prepareFlatTable($store)
- {
- $columns = $this->getFlatColumns();
- $indexes = $this->getFlatIndexes();
- $maxIndex = Mage::getConfig()->getNode(self::XML_NODE_MAX_INDEX_COUNT);
- if (count($indexes) > $maxIndex) {
- Mage::throwException(Mage::helper('catalog')->__("The Flat Catalog module has a limit of %2\$d filterable and/or sortable attributes. Currently there are %1\$d of them. Please reduce the number of filterable/sortable attributes in order to use this module.", count($indexes), $maxIndex));
- }
- $tableName = $this->getFlatTableName($store);
- $tableNameQuote = $this->_getWriteAdapter()->quoteIdentifier($tableName);
- if (!$this->_isFlatTableExists($store)) {
- $sql = "CREATE TABLE {$tableNameQuote} (\n";
- foreach ($columns as $field => $fieldProp) {
- $sql .= sprintf(" %s,\n",
- $this->_sqlColunmDefinition($field, $fieldProp));
- }
- foreach ($indexes as $indexName => $indexProp) {
- $sql .= sprintf(" %s,\n",
- $this->_sqlIndexDefinition($indexName, $indexProp));
- }
- $sql .= " CONSTRAINT `FK_CATALOG_PRODUCT_FLAT_{$store}_ENTITY` FOREIGN KEY (`entity_id`)"
- . " REFERENCES `{$this->getTable('catalog/product')}` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE";
- if ($this->getFlatHelper()->isAddChildData()) {
- $sql .= ",\n CONSTRAINT `FK_CATALOG_PRODUCT_FLAT_{$store}_CHILD` FOREIGN KEY (`child_id`)"
- . " REFERENCES `{$this->getTable('catalog/product')}` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE";
- }
- $sql .= "\n) ENGINE=InnoDB DEFAULT CHARSET=utf8";
- $this->_getWriteAdapter()->query($sql);
- $this->_existsFlatTables[$store] = true;
- }
- else {
- $this->_getWriteAdapter()->resetDdlCache($tableName);
- $describe = $this->_getWriteAdapter()->describeTable($tableName);
- $indexList = $this->_getWriteAdapter()->getIndexList($tableName);
- $addColumns = array_diff_key($columns, $describe);
- $dropColumns = array_diff_key($describe, $columns);
- $modifyColumns = array();
- $addIndexes = array_diff_key($indexes, $indexList);
- $dropIndexes = array_diff_key($indexList, $indexes);
- $addConstraints = array();
- if (!$this->getFlatHelper()->isAddChildData() && isset($describe['is_child'])) {
- $this->_getWriteAdapter()->delete($tableName, 'is_child=1');
- $this->_getWriteAdapter()->dropForeignKey($tableName, "FK_CATALOG_PRODUCT_FLAT_{$store}_CHILD");
- }
- if ($this->getFlatHelper()->isAddChildData() && !isset($describe['is_child'])) {
- $this->_getWriteAdapter()->truncate($tableName);
- $dropIndexes['PRIMARY'] = $indexList['PRIMARY'];
- $addIndexes['PRIMARY'] = $indexes['PRIMARY'];
- $addConstraints["FK_CATALOG_PRODUCT_FLAT_{$store}_CHILD"] = array(
- 'table_index' => 'child_id',
- 'ref_table' => $this->getTable('catalog/product'),
- 'ref_index' => 'entity_id',
- 'on_update' => 'CASCADE',
- 'on_delete' => 'CASCADE'
- );
- }
- foreach ($columns as $field => $fieldProp) {
- if (isset($describe[$field])
- && !$this->_compareColumnProperties($fieldProp, $describe[$field])) {
- $modifyColumns[$field] = $fieldProp;
- }
- }
- foreach ($indexList as $indexName => $indexProp) {
- if (isset($indexes[$indexName]) && ($indexes[$indexName]['type'] != $indexProp['type'])) {
- $dropIndexes[$indexName] = $indexProp;
- $addIndexes[$indexName] = $indexes[$indexName];
- }
- }
- if ($addColumns or $dropColumns or $modifyColumns or $addIndexes or $dropIndexes) {
- $sql = "ALTER TABLE {$tableNameQuote}";
- // drop columns
- foreach ($dropColumns as $columnName => $columnProp) {
- $columnNameQuote = $this->_getWriteAdapter()->quoteIdentifier($columnName);
- $sql .= " DROP COLUMN {$columnNameQuote},";
- }
- // drop indexes
- foreach ($dropIndexes as $indexName => $indexProp) {
- if ($indexName == 'PRIMARY') {
- $sql .= " DROP PRIMARY KEY,";
- }
- else {
- $indexNameQuote = $this->_getWriteAdapter()->quoteIdentifier($indexName);
- $sql .= " DROP INDEX {$indexNameQuote},";
- }
- }
- // modify colunm
- foreach ($modifyColumns as $columnName => $columnProp) {
- $sql .= sprintf(' MODIFY COLUMN %s,',
- $this->_sqlColunmDefinition($columnName, $columnProp));
- }
- // add columns
- foreach ($addColumns as $columnName => $columnProp) {
- $sql .= sprintf(' ADD COLUMN %s',
- $this->_sqlColunmDefinition($columnName, $columnProp));
- $afterColumn = $this->_arrayPrevKey($columns, $columnName);
- if ($afterColumn) {
- $sql .= ' AFTER ' . $this->_getWriteAdapter()->quoteIdentifier($afterColumn);
- }
- $sql .= ',';
- }
- // add indexes
- foreach ($addIndexes as $indexName => $indexProp) {
- $sql .= sprintf(' ADD %s,',
- $this->_sqlIndexDefinition($indexName, $indexProp));
- }
- $sql = rtrim($sql, ",");
- $this->_getWriteAdapter()->query($sql);
- }
- foreach ($addConstraints as $constraintName => $constraintProp) {
- $this->_getWriteAdapter()->addConstraint(
- $constraintName,
- $tableName,
- $constraintProp['table_index'],
- $constraintProp['ref_table'],
- $constraintProp['ref_index'],
- $constraintProp['on_delete'],
- $constraintProp['on_update']
- );
- }
- }
- return $this;
- }
- /**
- * Add or Update static attributes
- *
- * @param int $store
- * @param int|array $productIds update only product(s)
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function updateStaticAttributes($store, $productIds = null)
- {
- if (!$this->_isFlatTableExists($store)) {
- return $this;
- }
- $website = Mage::app()->getStore($store)->getWebsite()->getId();
- $status = $this->getAttribute('status');
- /* @var $status Mage_Eav_Model_Entity_Attribute */
- $fieldList = array('entity_id', 'type_id', 'attribute_set_id');
- $colsList = array('entity_id', 'type_id', 'attribute_set_id');
- if ($this->getFlatHelper()->isAddChildData()) {
- $fieldList = array_merge($fieldList, array('child_id', 'is_child'));
- $isChild = new Zend_Db_Expr('0');
- $colsList = array_merge($colsList, array('entity_id', $isChild));
- }
- $columns = $this->getFlatColumns();
- $select = $this->_getWriteAdapter()->select()
- ->from(
- array('e' => $this->getTable('catalog/product')),
- $colsList)
- ->join(
- array('wp' => $this->getTable('catalog/product_website')),
- "`e`.`entity_id`=`wp`.`product_id` AND `wp`.`website_id`={$website}",
- array())
- ->joinLeft(
- array('t1' => $status->getBackend()->getTable()),
- "`e`.`entity_id`=`t1`.`entity_id`",
- array())
- ->joinLeft(
- array('t2' => $status->getBackend()->getTable()),
- "t2.entity_id = t1.entity_id"
- . " AND t1.entity_type_id = t2.entity_type_id"
- . " AND t1.attribute_id = t2.attribute_id"
- . " AND t2.store_id = {$store}",
- array())
- ->where("t1.entity_type_id=?", $status->getEntityTypeId())
- ->where("t1.attribute_id=?", $status->getId())
- ->where("t1.store_id=?", 0)
- ->where("IF(`t2`.`value_id`>0, `t2`.`value`, `t1`.`value`)=?", Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
- foreach ($this->getAttributes() as $attributeCode => $attribute) {
- /* @var $attribute Mage_Eav_Model_Entity_Attribute */
- if ($attribute->getBackend()->getType() == 'static') {
- if (!isset($columns[$attributeCode])) {
- continue;
- }
- $fieldList[] = $attributeCode;
- $select->columns($attributeCode, 'e');
- }
- }
- if (!is_null($productIds)) {
- $select->where('e.entity_id IN(?)', $productIds);
- }
- $sql = $select->insertFromSelect($this->getFlatTableName($store), $fieldList);
- $this->_getWriteAdapter()->query($sql);
- return $this;
- }
- /**
- * Remove non website products
- *
- * @param int $store
- * @param int|array $productIds
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function cleanNonWebsiteProducts($store, $productIds = null)
- {
- $website = Mage::app()->getStore($store)->getWebsite()->getId();
- $joinCond = "`e`.`entity_id`=`wp`.`product_id` AND `wp`.`website_id`={$website}";
- if ($this->getFlatHelper()->isAddChildData()) {
- $joinCond .= " AND `e`.`child_id`=`wp`.`product_id`";
- }
- $select = $this->_getWriteAdapter()->select()
- ->from(
- array('e' => $this->getFlatTableName($store)),
- null)
- ->joinLeft(
- array('wp' => $this->getTable('catalog/product_website')),
- $joinCond,
- array());
- if (!is_null($productIds)) {
- $cond = array(
- $this->_getWriteAdapter()->quoteInto('e.entity_id IN(?)', $productIds)
- );
- if ($this->getFlatHelper()->isAddChildData()) {
- $cond[] = $this->_getWriteAdapter()->quoteInto('e.child_id IN(?)', $productIds);
- }
- $select->where(join(' OR ', $cond));
- }
- $sql = $select->deleteFromSelect('e');
- $this->_getWriteAdapter()->query($sql);
- return $this;
- }
- /**
- * Update attribute flat data
- *
- * @param Mage_Eav_Model_Entity_Attribute $attribute
- * @param int $store
- * @param int|array $productIds update only product(s)
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function updateAttribute($attribute, $store, $productIds = null)
- {
- if (!$this->_isFlatTableExists($store)) {
- return $this;
- }
- $describe = $this->_getWriteAdapter()->describeTable($this->getFlatTableName($store));
- if ($attribute->getBackend()->getType() == 'static') {
- if (!isset($describe[$attribute->getAttributeCode()])) {
- return $this;
- }
- $select = $this->_getWriteAdapter()->select()
- ->join(
- array('main_table' => $this->getTable('catalog/product')),
- 'main_table.entity_id=e.entity_id ',
- array($attribute->getAttributeCode() => 'main_table.' . $attribute->getAttributeCode())
- );
- if ($this->getFlatHelper()->isAddChildData()) {
- $select->where("e.is_child=?", 0);
- }
- if (!is_null($productIds)) {
- $select->where('main_table.entity_id IN(?)', $productIds);
- }
- $sql = $select->crossUpdateFromSelect(array('e' => $this->getFlatTableName($store)));
- $this->_getWriteAdapter()->query($sql);
- }
- else {
- $columns = $attribute->getFlatColumns();
- if (!$columns) {
- return $this;
- }
- foreach (array_keys($columns) as $columnName) {
- if (!isset($describe[$columnName])) {
- return $this;
- }
- }
- $select = $attribute->getFlatUpdateSelect($store);
- if ($select instanceof Varien_Db_Select) {
- if (!is_null($productIds)) {
- $select->where('e.entity_id IN(?)', $productIds);
- }
- $sql = $select->crossUpdateFromSelect(array('e' => $this->getFlatTableName($store)));
- $this->_getWriteAdapter()->query($sql);
- }
- }
- return $this;
- }
- /**
- * Update non static EAV attributes flat data
- *
- * @param int $store
- * @param int|array $productIds update only product(s)
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function updateEavAttributes($store, $productIds = null)
- {
- if (!$this->_isFlatTableExists($store)) {
- return $this;
- }
- foreach ($this->getAttributes() as $attribute) {
- /* @var $attribute Mage_Eav_Model_Entity_Attribute */
- if ($attribute->getBackend()->getType() != 'static') {
- $this->updateAttribute($attribute, $store, $productIds);
- }
- }
- return $this;
- }
- /**
- * Update events observer attributes
- *
- * @param int $store
- * @return Mage_Catalog_Model_Product_Flat_Indexer
- */
- public function updateEventAttributes($store = null)
- {
- Mage::dispatchEvent('catalog_product_flat_rebuild', array(
- 'store_id' => $store,
- 'table' => $this->getFlatTableName($store)
- ));
- }
- /**
- * Retrieve Product Type Instances
- * as key - type code, value - instance model
- *
- * @return array
- */
- public function getProductTypeInstances()
- {
- if (is_null($this->_productTypes)) {
- $this->_productTypes = array();
- $productEmulator = new Varien_Object();
- foreach (array_keys(Mage_Catalog_Model_Product_Type::getTypes()) as $typeId) {
- $productEmulator->setTypeId($typeId);
- $this->_productTypes[$typeId] = Mage::getSingleton('catalog/product_type')
- ->factory($productEmulator);
- }
- }
- return $this->_productTypes;
- }
- /**
- * Update relation products
- *
- * @param int $store
- * @param int|array $productIds Update child product(s) only
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function updateRelationProducts($store, $productIds = null)
- {
- if (!$this->getFlatHelper()->isAddChildData()) {
- return $this;
- }
- if (!$this->_isFlatTableExists($store)) {
- return $this;
- }
- foreach ($this->getProductTypeInstances() as $typeInstance) {
- if (!$typeInstance->isComposite()) {
- continue;
- }
- $relation = $typeInstance->getRelationInfo();
- if ($relation
- and $relation->getTable()
- and $relation->getParentFieldName()
- and $relation->getChildFieldName()
- ) {
- $columns = $this->getFlatColumns();
- $fieldList = array_keys($columns);
- unset($columns['entity_id']);
- unset($columns['child_id']);
- unset($columns['is_child']);
- $select = $this->_getWriteAdapter()->select()
- ->from(
- array('t' => $this->getTable($relation->getTable())),
- array($relation->getParentFieldName(), $relation->getChildFieldName(), new Zend_Db_Expr('1')))
- ->join(
- array('e' => $this->getFlatTableName($store)),
- "`e`.`entity_id`=`t`.`{$relation->getChildFieldName()}`",
- array_keys($columns)
- );
- if (!is_null($relation->getWhere())) {
- $select->where($relation->getWhere());
- }
- if (!is_null($productIds)) {
- $cond = array(
- $this->_getWriteAdapter()->quoteInto("{$relation->getChildFieldName()} IN(?)", $productIds),
- $this->_getWriteAdapter()->quoteInto("{$relation->getParentFieldName()} IN(?)", $productIds)
- );
- $select->where(join(' OR ', $cond));
- }
- $sql = $select->insertFromSelect($this->getFlatTableName($store), $fieldList);
- $this->_getWriteAdapter()->query($sql);
- }
- }
- return $this;
- }
- /**
- * Update children data from parent
- *
- * @param int $store
- * @param int|array $productIds
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function updateChildrenDataFromParent($store, $productIds = null)
- {
- if (!$this->getFlatHelper()->isAddChildData()) {
- return $this;
- }
- if (!$this->_isFlatTableExists($store)) {
- return $this;
- }
- $select = $this->_getWriteAdapter()->select();
- foreach (array_keys($this->getFlatColumns()) as $columnName) {
- if ($columnName == 'entity_id' || $columnName == 'child_id' || $columnName == 'is_child') {
- continue;
- }
- $select->columns(array($columnName => new Zend_Db_Expr('`t1`.`'. $columnName.'`')));
- }
- $select
- ->joinLeft(
- array('t1' => $this->getFlatTableName($store)),
- "`t2`.`child_id`=`t1`.`entity_id` AND `t1`.`is_child`=0",
- array())
- ->where('t2.is_child=1');
- if (!is_null($productIds)) {
- $select->where('t2.child_id IN(?)', $productIds);
- }
- $sql = $select->crossUpdateFromSelect(array('t2' => $this->getFlatTableName($store)));
- $this->_getWriteAdapter()->query($sql);
- return $this;
- }
- /**
- * Clean unused relation products
- *
- * @param int $store
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function cleanRelationProducts($store)
- {
- if (!$this->getFlatHelper()->isAddChildData()) {
- return $this;
- }
- foreach ($this->getProductTypeInstances() as $typeInstance) {
- if (!$typeInstance->isComposite()) {
- continue;
- }
- $relation = $typeInstance->getRelationInfo();
- if ($relation
- and $relation->getTable()
- and $relation->getParentFieldName()
- and $relation->getChildFieldName()
- ) {
- $select = $this->_getWriteAdapter()->select()
- ->distinct(true)
- ->from(
- $this->getTable($relation->getTable()),
- "{$relation->getParentFieldName()}"
- )
- ;
- $joinLeftCond = null;
- if (!is_null($relation->getWhere())) {
- $select->where($relation->getWhere());
- $joinLeftCond = ' AND ' . $relation->getWhere();
- }
- $entitySelect = new Zend_Db_Expr($select->__toString());
- $select = $this->_getWriteAdapter()->select()
- ->from(
- array('e' => $this->getFlatTableName($store)),
- null
- )
- ->joinLeft(
- array('t' => $this->getTable($relation->getTable())),
- "e.entity_id=t.{$relation->getParentFieldName()} AND e.child_id=t.{$relation->getChildFieldName()}"
- . $joinLeftCond,
- array())
- ->where("e.is_child=?", 1)
- ->where("e.entity_id IN(?)", $entitySelect)
- ->where("t.{$relation->getChildFieldName()} IS NULL");
- $sql = $select->deleteFromSelect('e');
- $this->_getWriteAdapter()->query($sql);
- }
- }
- return $this;
- }
- /**
- * Remove product data from flat
- *
- * @param int|array $productIds
- * @param int $store
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function removeProduct($productIds, $store)
- {
- if (!$this->_isFlatTableExists($store)) {
- return $this;
- }
- $cond = array(
- $this->_getWriteAdapter()->quoteInto('entity_id IN(?)', $productIds)
- );
- if ($this->getFlatHelper()->isAddChildData()) {
- $cond[] = $this->_getWriteAdapter()->quoteInto('child_id IN(?)', $productIds);
- }
- $cond = join(' OR ', $cond);
- $this->_getWriteAdapter()->delete($this->getFlatTableName($store), $cond);
- return $this;
- }
- /**
- * Remove children from parent product
- *
- * @param int|array $productIds
- * @param int $store
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function removeProductChildren($productIds, $store)
- {
- if (!$this->getFlatHelper()->isAddChildData()) {
- return $this;
- }
- $cond = array(
- $this->_getWriteAdapter()->quoteInto('entity_id IN(?)', $productIds),
- $this->_getWriteAdapter()->quoteInto('is_child=?', 1),
- );
- $this->_getWriteAdapter()->delete($this->getFlatTableName($store), $cond);
- return $this;
- }
- /**
- * Update flat data for product
- *
- * @param int|array $productIds
- * @param int $store
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function updateProduct($productIds, $store)
- {
- if (!$this->_isFlatTableExists($store)) {
- return $this;
- }
- $this->saveProduct($productIds, $store);
- Mage::dispatchEvent('catalog_product_flat_update_product', array(
- 'store_id' => $store,
- 'table' => $this->getFlatTableName($store),
- 'product_ids' => $productIds
- ));
- return $this;
- }
- /**
- * Save product(s) data for store
- *
- * @param int|array $productIds
- * @param int $store
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function saveProduct($productIds, $store)
- {
- if (!$this->_isFlatTableExists($store)) {
- return $this;
- }
- $this->updateStaticAttributes($store, $productIds);
- $this->updateEavAttributes($store, $productIds);
- return $this;
- }
- /**
- * Delete flat table process
- *
- * @param int $store
- * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer
- */
- public function deleteFlatTable($store)
- {
- if ($this->_isFlatTableExists($store)) {
- $tableName = $this->_getWriteAdapter()->quoteIdentifier($this->getFlatTableName($store));
- $sql = sprintf('DROP TABLE IF EXISTS %s', $tableName);
- $this->_getWriteAdapter()->query($sql);
- }
- return $this;
- }
- /**
- * Check is flat table for store exists
- *
- * @param int $store
- * @return bool
- */
- protected function _isFlatTableExists($store)
- {
- if (!isset($this->_existsFlatTables[$store])) {
- $tableName = $this->getFlatTableName($store);
- $tableExistsSql = $this->_getWriteAdapter()
- ->quoteInto("SHOW TABLE STATUS LIKE ?", $tableName);
- if ($this->_getWriteAdapter()->fetchRow($tableExistsSql)) {
- $this->_existsFlatTables[$store] = true;
- } else {
- $this->_existsFlatTables[$store] = false;
- }
- }
- return $this->_existsFlatTables[$store];
- }
- /**
- * Retrieve previous key from array by key
- *
- * @param array $array
- * @param mixed $key
- * @return mixed
- */
- protected function _arrayPrevKey(array $array, $key)
- {
- $prev = false;
- foreach (array_keys($array) as $k) {
- if ($k == $key) {
- return $prev;
- }
- $prev = $k;
- }
- return false;
- }
- /**
- * Retrieve next key from array by key
- *
- * @param array $array
- * @param mixed $key
- * @return mixed
- */
- protected function _arrayNextKey(array $array, $key)
- {
- $next = false;
- foreach (array_keys($array) as $k) {
- if ($next === true) {
- return $k;
- }
- if ($k == $key) {
- $next = true;
- }
- }
- return false;
- }
- }