*/ abstract class Mage_Eav_Model_Entity_Collection_Abstract extends Varien_Data_Collection_Db { /** * Array of items with item id key * * @var array */ protected $_itemsById = array(); /** * Entity static fields * * @var array */ protected $_staticFields = array(); /** * Entity object to define collection's attributes * * @var Mage_Eav_Model_Entity_Abstract */ protected $_entity; /** * Entity types to be fetched for objects in collection * * @var array */ protected $_selectEntityTypes = array(); /** * Attributes to be fetched for objects in collection * * @var array */ protected $_selectAttributes = array(); /** * Attributes to be filtered order sorted by * * @var array */ protected $_filterAttributes = array(); /** * Joined entities * * @var array */ protected $_joinEntities = array(); /** * Joined attributes * * @var array */ protected $_joinAttributes = array(); /** * Joined fields data * * @var array */ protected $_joinFields = array(); /** * Use analytic function flag * If true - allows to prepare final select with analytic functions * * @var bool */ protected $_useAnalyticFunction = false; /** * Cast map for attribute order * * @var array */ protected $_castToIntMap = array( 'validate-digits' ); /** * Collection constructor * * @param Mage_Core_Model_Resource_Abstract $resource */ public function __construct($resource = null) { parent::__construct(); $this->_construct(); $this->setConnection($this->getEntity()->getReadConnection()); $this->_prepareStaticFields(); $this->_initSelect(); } /** * Initialize collection */ protected function _construct() { } /** * Retreive table name * * @param string $table * @return string */ public function getTable($table) { return $this->getResource()->getTable($table); } /** * Prepare static entity fields * * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _prepareStaticFields() { foreach ($this->getEntity()->getDefaultAttributes() as $field) { $this->_staticFields[$field] = $field; } return $this; } /** * Init select * * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _initSelect() { $this->getSelect()->from(array('e' => $this->getEntity()->getEntityTable())); if ($this->getEntity()->getTypeId()) { $this->addAttributeToFilter('entity_type_id', $this->getEntity()->getTypeId()); } return $this; } /** * Standard resource collection initalization * * @param string $model * @return Mage_Core_Model_Mysql4_Collection_Abstract */ protected function _init($model, $entityModel = null) { $this->setItemObjectClass(Mage::getConfig()->getModelClassName($model)); if ($entityModel === null) { $entityModel = $model; } $entity = Mage::getResourceSingleton($entityModel); $this->setEntity($entity); return $this; } /** * Set entity to use for attributes * * @param Mage_Eav_Model_Entity_Abstract $entity * @throws Mage_Eav_Exception * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function setEntity($entity) { if ($entity instanceof Mage_Eav_Model_Entity_Abstract) { $this->_entity = $entity; } elseif (is_string($entity) || $entity instanceof Mage_Core_Model_Config_Element) { $this->_entity = Mage::getModel('eav/entity')->setType($entity); } else { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid entity supplied: %s', print_r($entity, 1))); } return $this; } /** * Get collection's entity object * * @return Mage_Eav_Model_Entity_Abstract */ public function getEntity() { if (empty($this->_entity)) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Entity is not initialized')); } return $this->_entity; } /** * Get resource instance * * @return Mage_Core_Model_Mysql4_Abstract */ public function getResource() { return $this->getEntity(); } /** * Set template object for the collection * * @param Varien_Object $object * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function setObject($object=null) { if (is_object($object)) { $this->setItemObjectClass(get_class($object)); } else { $this->setItemObjectClass($object); } return $this; } /** * Add an object to the collection * * @param Varien_Object $object * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function addItem(Varien_Object $object) { if (get_class($object) !== $this->_itemObjectClass) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Attempt to add an invalid object')); } return parent::addItem($object); } /** * Retrieve entity attribute * * @param string $attributeCode * @return Mage_Eav_Model_Entity_Attribute_Abstract */ public function getAttribute($attributeCode) { if (isset($this->_joinAttributes[$attributeCode])) { return $this->_joinAttributes[$attributeCode]['attribute']; } return $this->getEntity()->getAttribute($attributeCode); } /** * Add attribute filter to collection * * If $attribute is an array will add OR condition with following format: * array( * array('attribute'=>'firstname', 'like'=>'test%'), * array('attribute'=>'lastname', 'like'=>'test%'), * ) * * @see self::_getConditionSql for $condition * @param Mage_Eav_Model_Entity_Attribute_Interface|integer|string|array $attribute * @param null|string|array $condition * @param string $operator * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function addAttributeToFilter($attribute, $condition = null, $joinType = 'inner') { if ($attribute === null) { $this->getSelect(); return $this; } if (is_numeric($attribute)) { $attribute = $this->getEntity()->getAttribute($attribute)->getAttributeCode(); } else if ($attribute instanceof Mage_Eav_Model_Entity_Attribute_Interface) { $attribute = $attribute->getAttributeCode(); } if (is_array($attribute)) { $sqlArr = array(); foreach ($attribute as $condition) { $sqlArr[] = $this->_getAttributeConditionSql($condition['attribute'], $condition, $joinType); } $conditionSql = '('.implode(') OR (', $sqlArr).')'; } else if (is_string($attribute)) { if ($condition === null) { $condition = ''; } $conditionSql = $this->_getAttributeConditionSql($attribute, $condition, $joinType); } if (!empty($conditionSql)) { $this->getSelect()->where($conditionSql, null, Varien_Db_Select::TYPE_CONDITION); } else { Mage::throwException('Invalid attribute identifier for filter ('.get_class($attribute).')'); } return $this; } /** * Wrapper for compatibility with Varien_Data_Collection_Db * * @param mixed $attribute * @param mixed $condition */ public function addFieldToFilter($attribute, $condition = null) { return $this->addAttributeToFilter($attribute, $condition); } /** * Add attribute to sort order * * @param string $attribute * @param string $dir * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function addAttributeToSort($attribute, $dir = self::SORT_ORDER_ASC) { if (isset($this->_joinFields[$attribute])) { $this->getSelect()->order($this->_getAttributeFieldName($attribute).' '.$dir); return $this; } if (isset($this->_staticFields[$attribute])) { $this->getSelect()->order("e.{$attribute} {$dir}"); return $this; } if (isset($this->_joinAttributes[$attribute])) { $attrInstance = $this->_joinAttributes[$attribute]['attribute']; $entityField = $this->_getAttributeTableAlias($attribute) . '.' . $attrInstance->getAttributeCode(); } else { $attrInstance = $this->getEntity()->getAttribute($attribute); $entityField = 'e.' . $attribute; } if ($attrInstance) { if ($attrInstance->getBackend()->isStatic()) { $orderExpr = $entityField; } else { $this->_addAttributeJoin($attribute, 'left'); if (isset($this->_joinAttributes[$attribute])||isset($this->_joinFields[$attribute])) { $orderExpr = $attribute; } else { $orderExpr = $this->_getAttributeTableAlias($attribute).'.value'; } } if (in_array($attrInstance->getFrontendClass(), $this->_castToIntMap)) { $orderExpr = Mage::getResourceHelper('eav')->getCastToIntExpression( $this->_prepareOrderExpression($orderExpr) ); } $orderExpr .= ' ' . $dir; $this->getSelect()->order($orderExpr); } return $this; } /** * Retrieve attribute expression by specified column * * @param string $field * @return string|Zend_Db_Expr */ protected function _prepareOrderExpression($field) { foreach ($this->getSelect()->getPart(Zend_Db_Select::COLUMNS) as $columnEntry) { if ($columnEntry[2] != $field) { continue; } if ($columnEntry[1] instanceof Zend_Db_Expr) { return $columnEntry[1]; } } return $field; } /** * Add attribute to entities in collection * * If $attribute=='*' select all attributes * * @param array|string|integer|Mage_Core_Model_Config_Element $attribute * @param false|string $joinType flag for joining attribute * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function addAttributeToSelect($attribute, $joinType = false) { if (is_array($attribute)) { Mage::getSingleton('eav/config')->loadCollectionAttributes($this->getEntity()->getType(), $attribute); foreach ($attribute as $a) { $this->addAttributeToSelect($a, $joinType); } return $this; } if ($joinType !== false && !$this->getEntity()->getAttribute($attribute)->isStatic()) { $this->_addAttributeJoin($attribute, $joinType); } elseif ('*' === $attribute) { $entity = clone $this->getEntity(); $attributes = $entity ->loadAllAttributes() ->getAttributesByCode(); foreach ($attributes as $attrCode=>$attr) { $this->_selectAttributes[$attrCode] = $attr->getId(); } } else { if (isset($this->_joinAttributes[$attribute])) { $attrInstance = $this->_joinAttributes[$attribute]['attribute']; } else { $attrInstance = Mage::getSingleton('eav/config') ->getCollectionAttribute($this->getEntity()->getType(), $attribute); } if (empty($attrInstance)) { throw Mage::exception( 'Mage_Eav', Mage::helper('eav')->__('Invalid attribute requested: %s', (string)$attribute) ); } $this->_selectAttributes[$attrInstance->getAttributeCode()] = $attrInstance->getId(); } return $this; } public function addEntityTypeToSelect($entityType, $prefix) { $this->_selectEntityTypes[$entityType] = array( 'prefix' => $prefix, ); return $this; } /** * Add field to static * * @param string $field * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function addStaticField($field) { if (!isset($this->_staticFields[$field])) { $this->_staticFields[$field] = $field; } return $this; } /** * Add attribute expression (SUM, COUNT, etc) * * Example: ('sub_total', 'SUM({{attribute}})', 'revenue') * Example: ('sub_total', 'SUM({{revenue}})', 'revenue') * * For some functions like SUM use groupByAttribute. * * @param string $alias * @param string $expression * @param string $attribute * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function addExpressionAttributeToSelect($alias, $expression, $attribute) { // validate alias if (isset($this->_joinFields[$alias])) { throw Mage::exception( 'Mage_Eav', Mage::helper('eav')->__('Joint field or attribute expression with this alias is already declared') ); } if (!is_array($attribute)) { $attribute = array($attribute); } $fullExpression = $expression; // Replacing multiple attributes foreach ($attribute as $attributeItem) { if (isset($this->_staticFields[$attributeItem])) { $attrField = sprintf('e.%s', $attributeItem); } else { $attributeInstance = $this->getAttribute($attributeItem); if ($attributeInstance->getBackend()->isStatic()) { $attrField = 'e.' . $attributeItem; } else { $this->_addAttributeJoin($attributeItem, 'left'); $attrField = $this->_getAttributeFieldName($attributeItem); } } $fullExpression = str_replace('{{attribute}}', $attrField, $fullExpression); $fullExpression = str_replace('{{' . $attributeItem . '}}', $attrField, $fullExpression); } $this->getSelect()->columns(array($alias => $fullExpression)); $this->_joinFields[$alias] = array( 'table' => false, 'field' => $fullExpression ); return $this; } /** * Groups results by specified attribute * * @param string|array $attribute */ public function groupByAttribute($attribute) { if (is_array($attribute)) { foreach ($attribute as $attributeItem) { $this->groupByAttribute($attributeItem); } } else { if (isset($this->_joinFields[$attribute])) { $this->getSelect()->group($this->_getAttributeFieldName($attribute)); return $this; } if (isset($this->_staticFields[$attribute])) { $this->getSelect()->group(sprintf('e.%s', $attribute)); return $this; } if (isset($this->_joinAttributes[$attribute])) { $attrInstance = $this->_joinAttributes[$attribute]['attribute']; $entityField = $this->_getAttributeTableAlias($attribute) . '.' . $attrInstance->getAttributeCode(); } else { $attrInstance = $this->getEntity()->getAttribute($attribute); $entityField = 'e.' . $attribute; } if ($attrInstance->getBackend()->isStatic()) { $this->getSelect()->group($entityField); } else { $this->_addAttributeJoin($attribute); $this->getSelect()->group($this->_getAttributeTableAlias($attribute).'.value'); } } return $this; } /** * Add attribute from joined entity to select * * Examples: * ('billing_firstname', 'customer_address/firstname', 'default_billing') * ('billing_lastname', 'customer_address/lastname', 'default_billing') * ('shipping_lastname', 'customer_address/lastname', 'default_billing') * ('shipping_postalcode', 'customer_address/postalcode', 'default_shipping') * ('shipping_city', $cityAttribute, 'default_shipping') * * Developer is encouraged to use existing instances of attributes and entities * After first use of string entity name it will be cached in the collection * * @todo connect between joined attributes of same entity * @param string $alias alias for the joined attribute * @param string|Mage_Eav_Model_Entity_Attribute_Abstract $attribute * @param string $bind attribute of the main entity to link with joined $filter * @param string $filter primary key for the joined entity (entity_id default) * @param string $joinType inner|left * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function joinAttribute($alias, $attribute, $bind, $filter=null, $joinType='inner', $storeId=null) { // validate alias if (isset($this->_joinAttributes[$alias])) { throw Mage::exception( 'Mage_Eav', Mage::helper('eav')->__('Invalid alias, already exists in joint attributes') ); } // validate bind attribute if (is_string($bind)) { $bindAttribute = $this->getAttribute($bind); } if (!$bindAttribute || (!$bindAttribute->isStatic() && !$bindAttribute->getId())) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid foreign key')); } // try to explode combined entity/attribute if supplied if (is_string($attribute)) { $attrArr = explode('/', $attribute); if (isset($attrArr[1])) { $entity = $attrArr[0]; $attribute = $attrArr[1]; } } // validate entity if (empty($entity) && $attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract) { $entity = $attribute->getEntity(); } elseif (is_string($entity)) { // retrieve cached entity if possible if (isset($this->_joinEntities[$entity])) { $entity = $this->_joinEntities[$entity]; } else { $entity = Mage::getModel('eav/entity')->setType($attrArr[0]); } } if (!$entity || !$entity->getTypeId()) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid entity type')); } // cache entity if (!isset($this->_joinEntities[$entity->getType()])) { $this->_joinEntities[$entity->getType()] = $entity; } // validate attribute if (is_string($attribute)) { $attribute = $entity->getAttribute($attribute); } if (!$attribute) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid attribute type')); } if (empty($filter)) { $filter = $entity->getEntityIdField(); } // add joined attribute $this->_joinAttributes[$alias] = array( 'bind' => $bind, 'bindAttribute' => $bindAttribute, 'attribute' => $attribute, 'filter' => $filter, 'store_id' => $storeId, ); $this->_addAttributeJoin($alias, $joinType); return $this; } /** * Join regular table field and use an attribute as fk * * Examples: * ('country_name', 'directory/country_name', 'name', 'country_id=shipping_country', * "{{table}}.language_code='en'", 'left') * * @param string $alias 'country_name' * @param string $table 'directory/country_name' * @param string $field 'name' * @param string $bind 'PK(country_id)=FK(shipping_country_id)' * @param string|array $cond "{{table}}.language_code='en'" OR array('language_code'=>'en') * @param string $joinType 'left' * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function joinField($alias, $table, $field, $bind, $cond=null, $joinType='inner') { // validate alias if (isset($this->_joinFields[$alias])) { throw Mage::exception( 'Mage_Eav', Mage::helper('eav')->__('Joined field with this alias is already declared') ); } // validate table if (strpos($table, '/')!==false) { $table = Mage::getSingleton('core/resource')->getTableName($table); } $tableAlias = $this->_getAttributeTableAlias($alias); // validate bind list($pk, $fk) = explode('=', $bind); $pk = $this->getSelect()->getAdapter()->quoteColumnAs(trim($pk), null); $bindCond = $tableAlias . '.' . trim($pk) . '=' . $this->_getAttributeFieldName(trim($fk)); // process join type switch ($joinType) { case 'left': $joinMethod = 'joinLeft'; break; default: $joinMethod = 'join'; } $condArr = array($bindCond); // add where condition if needed if ($cond !== null) { if (is_array($cond)) { foreach ($cond as $k=>$v) { $condArr[] = $this->_getConditionSql($tableAlias.'.'.$k, $v); } } else { $condArr[] = str_replace('{{table}}', $tableAlias, $cond); } } $cond = '(' . implode(') AND (', $condArr) . ')'; // join table $this->getSelect() ->$joinMethod(array($tableAlias => $table), $cond, ($field ? array($alias=>$field) : array())); // save joined attribute $this->_joinFields[$alias] = array( 'table' => $tableAlias, 'field' => $field, ); return $this; } /** * Join a table * * @param string|array $table * @param string $bind * @param string|array $fields * @param null|array $cond * @param string $joinType * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function joinTable($table, $bind, $fields = null, $cond = null, $joinType = 'inner') { $tableAlias = null; if (is_array($table)) { list($tableAlias, $tableName) = each($table); } else { $tableName = $table; } // validate table if (strpos($tableName, '/') !== false) { $tableName = Mage::getSingleton('core/resource')->getTableName($tableName); } if (empty($tableAlias)) { $tableAlias = $tableName; } // validate fields and aliases if (!$fields) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid joint fields')); } foreach ($fields as $alias=>$field) { if (isset($this->_joinFields[$alias])) { throw Mage::exception( 'Mage_Eav', Mage::helper('eav')->__('A joint field with this alias (%s) is already declared', $alias) ); } $this->_joinFields[$alias] = array( 'table' => $tableAlias, 'field' => $field, ); } // validate bind list($pk, $fk) = explode('=', $bind); $bindCond = $tableAlias . '.' . $pk . '=' . $this->_getAttributeFieldName($fk); // process join type switch ($joinType) { case 'left': $joinMethod = 'joinLeft'; break; default: $joinMethod = 'join'; } $condArr = array($bindCond); // add where condition if needed if ($cond !== null) { if (is_array($cond)) { foreach ($cond as $k => $v) { $condArr[] = $this->_getConditionSql($tableAlias.'.'.$k, $v); } } else { $condArr[] = str_replace('{{table}}', $tableAlias, $cond); } } $cond = '('.implode(') AND (', $condArr).')'; // join table $this->getSelect()->$joinMethod(array($tableAlias => $tableName), $cond, $fields); return $this; } /** * Remove an attribute from selection list * * @param string $attribute * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function removeAttributeToSelect($attribute = null) { if ($attribute === null) { $this->_selectAttributes = array(); } else { unset($this->_selectAttributes[$attribute]); } return $this; } /** * Set collection page start and records to show * * @param integer $pageNum * @param integer $pageSize * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function setPage($pageNum, $pageSize) { $this->setCurPage($pageNum) ->setPageSize($pageSize); return $this; } /** * Load collection data into object items * * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function load($printQuery = false, $logQuery = false) { if ($this->isLoaded()) { return $this; } Varien_Profiler::start('__EAV_COLLECTION_BEFORE_LOAD__'); Mage::dispatchEvent('eav_collection_abstract_load_before', array('collection' => $this)); $this->_beforeLoad(); Varien_Profiler::stop('__EAV_COLLECTION_BEFORE_LOAD__'); $this->_renderFilters(); $this->_renderOrders(); Varien_Profiler::start('__EAV_COLLECTION_LOAD_ENT__'); $this->_loadEntities($printQuery, $logQuery); Varien_Profiler::stop('__EAV_COLLECTION_LOAD_ENT__'); Varien_Profiler::start('__EAV_COLLECTION_LOAD_ATTR__'); $this->_loadAttributes($printQuery, $logQuery); Varien_Profiler::stop('__EAV_COLLECTION_LOAD_ATTR__'); Varien_Profiler::start('__EAV_COLLECTION_ORIG_DATA__'); foreach ($this->_items as $item) { $item->setOrigData(); } Varien_Profiler::stop('__EAV_COLLECTION_ORIG_DATA__'); $this->_setIsLoaded(); Varien_Profiler::start('__EAV_COLLECTION_AFTER_LOAD__'); $this->_afterLoad(); Varien_Profiler::stop('__EAV_COLLECTION_AFTER_LOAD__'); return $this; } /** * Clone and reset collection * * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _getAllIdsSelect($limit = null, $offset = null) { $idsSelect = clone $this->getSelect(); $idsSelect->reset(Zend_Db_Select::ORDER); $idsSelect->reset(Zend_Db_Select::LIMIT_COUNT); $idsSelect->reset(Zend_Db_Select::LIMIT_OFFSET); $idsSelect->reset(Zend_Db_Select::COLUMNS); $idsSelect->columns('e.' . $this->getEntity()->getIdFieldName()); $idsSelect->limit($limit, $offset); return $idsSelect; } /** * Retrive all ids for collection * * @return array */ public function getAllIds($limit = null, $offset = null) { return $this->getConnection()->fetchCol($this->_getAllIdsSelect($limit, $offset), $this->_bindParams); } /** * Retrive all ids sql * * @return array */ public function getAllIdsSql() { $idsSelect = clone $this->getSelect(); $idsSelect->reset(Zend_Db_Select::ORDER); $idsSelect->reset(Zend_Db_Select::LIMIT_COUNT); $idsSelect->reset(Zend_Db_Select::LIMIT_OFFSET); $idsSelect->reset(Zend_Db_Select::COLUMNS); $idsSelect->reset(Zend_Db_Select::GROUP); $idsSelect->columns('e.'.$this->getEntity()->getIdFieldName()); return $idsSelect; } /** * Save all the entities in the collection * * @todo make batch save directly from collection */ public function save() { foreach ($this->getItems() as $item) { $item->save(); } return $this; } /** * Delete all the entities in the collection * * @todo make batch delete directly from collection */ public function delete() { foreach ($this->getItems() as $k=>$item) { $this->getEntity()->delete($item); unset($this->_items[$k]); } return $this; } /** * Import 2D array into collection as objects * * If the imported items already exist, update the data for existing objects * * @param array $arr * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function importFromArray($arr) { $entityIdField = $this->getEntity()->getEntityIdField(); foreach ($arr as $row) { $entityId = $row[$entityIdField]; if (!isset($this->_items[$entityId])) { $this->_items[$entityId] = $this->getNewEmptyItem(); $this->_items[$entityId]->setData($row); } else { $this->_items[$entityId]->addData($row); } } return $this; } /** * Get collection data as a 2D array * * @return array */ public function exportToArray() { $result = array(); $entityIdField = $this->getEntity()->getEntityIdField(); foreach ($this->getItems() as $item) { $result[$item->getData($entityIdField)] = $item->getData(); } return $result; } /** * Retreive row id field name * * @return string */ public function getRowIdFieldName() { if ($this->_idFieldName === null) { $this->_setIdFieldName($this->getEntity()->getIdFieldName()); } return $this->getIdFieldName(); } /** * Set row id field name * @param string $fieldName * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function setRowIdFieldName($fieldName) { return $this->_setIdFieldName($fieldName); } /** * Load entities records into items * * @throws Exception * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function _loadEntities($printQuery = false, $logQuery = false) { if ($this->_pageSize) { $this->getSelect()->limitPage($this->getCurPage(), $this->_pageSize); } $this->printLogQuery($printQuery, $logQuery); try { /** * Prepare select query * @var string $query */ $query = $this->_prepareSelect($this->getSelect()); $rows = $this->_fetchAll($query); } catch (Exception $e) { Mage::printException($e, $query); $this->printLogQuery(true, true, $query); throw $e; } foreach ($rows as $v) { $object = $this->getNewEmptyItem() ->setData($v); $this->addItem($object); if (isset($this->_itemsById[$object->getId()])) { $this->_itemsById[$object->getId()][] = $object; } else { $this->_itemsById[$object->getId()] = array($object); } } return $this; } /** * Load attributes into loaded entities * * @throws Exception * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function _loadAttributes($printQuery = false, $logQuery = false) { if (empty($this->_items) || empty($this->_itemsById) || empty($this->_selectAttributes)) { return $this; } $entity = $this->getEntity(); $tableAttributes = array(); $attributeTypes = array(); foreach ($this->_selectAttributes as $attributeCode => $attributeId) { if (!$attributeId) { continue; } $attribute = Mage::getSingleton('eav/config')->getCollectionAttribute($entity->getType(), $attributeCode); if ($attribute && !$attribute->isStatic()) { $tableAttributes[$attribute->getBackendTable()][] = $attributeId; if (!isset($attributeTypes[$attribute->getBackendTable()])) { $attributeTypes[$attribute->getBackendTable()] = $attribute->getBackendType(); } } } $selects = array(); foreach ($tableAttributes as $table=>$attributes) { $select = $this->_getLoadAttributesSelect($table, $attributes); $selects[$attributeTypes[$table]][] = $this->_addLoadAttributesSelectValues( $select, $table, $attributeTypes[$table] ); } $selectGroups = Mage::getResourceHelper('eav')->getLoadAttributesSelectGroups($selects); foreach ($selectGroups as $selects) { if (!empty($selects)) { try { $select = implode(' UNION ALL ', $selects); $values = $this->getConnection()->fetchAll($select); } catch (Exception $e) { Mage::printException($e, $select); $this->printLogQuery(true, true, $select); throw $e; } foreach ($values as $value) { $this->_setItemAttributeValue($value); } } } return $this; } /** * Retrieve attributes load select * * @param string $table * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _getLoadAttributesSelect($table, $attributeIds = array()) { if (empty($attributeIds)) { $attributeIds = $this->_selectAttributes; } $helper = Mage::getResourceHelper('eav'); $entityIdField = $this->getEntity()->getEntityIdField(); $select = $this->getConnection()->select() ->from($table, array($entityIdField, 'attribute_id')) ->where('entity_type_id =?', $this->getEntity()->getTypeId()) ->where("$entityIdField IN (?)", array_keys($this->_itemsById)) ->where('attribute_id IN (?)', $attributeIds); return $select; } /** * @param Varien_Db_Select $select * @param string $table * @param string $type * @return Varien_Db_Select */ protected function _addLoadAttributesSelectValues($select, $table, $type) { $helper = Mage::getResourceHelper('eav'); $select->columns(array( 'value' => $helper->prepareEavAttributeValue($table. '.value', $type), )); return $select; } /** * Initialize entity ubject property value * * $valueInfo is _getLoadAttributesSelect fetch result row * * @param array $valueInfo * @throws Mage_Eav_Exception * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _setItemAttributeValue($valueInfo) { $entityIdField = $this->getEntity()->getEntityIdField(); $entityId = $valueInfo[$entityIdField]; if (!isset($this->_itemsById[$entityId])) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Data integrity: No header row found for attribute') ); } $attributeCode = array_search($valueInfo['attribute_id'], $this->_selectAttributes); if (!$attributeCode) { $attribute = Mage::getSingleton('eav/config')->getCollectionAttribute( $this->getEntity()->getType(), $valueInfo['attribute_id'] ); $attributeCode = $attribute->getAttributeCode(); } foreach ($this->_itemsById[$entityId] as $object) { $object->setData($attributeCode, $valueInfo['value']); } return $this; } /** * Get alias for attribute value table * * @param string $attributeCode * @return string */ protected function _getAttributeTableAlias($attributeCode) { return 'at_' . $attributeCode; } /** * Retreive attribute field name by attribute code * * @param string $attributeCode * @return string */ protected function _getAttributeFieldName($attributeCode) { $attributeCode = trim($attributeCode); if (isset($this->_joinAttributes[$attributeCode]['condition_alias'])) { return $this->_joinAttributes[$attributeCode]['condition_alias']; } if (isset($this->_staticFields[$attributeCode])) { return sprintf('e.%s', $attributeCode); } if (isset($this->_joinFields[$attributeCode])) { $attr = $this->_joinFields[$attributeCode]; return $attr['table'] ? $attr['table'] . '.' . $attr['field'] : $attr['field']; } $attribute = $this->getAttribute($attributeCode); if (!$attribute) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid attribute name: %s', $attributeCode)); } if ($attribute->isStatic()) { if (isset($this->_joinAttributes[$attributeCode])) { $fieldName = $this->_getAttributeTableAlias($attributeCode) . '.' . $attributeCode; } else { $fieldName = 'e.' . $attributeCode; } } else { $fieldName = $this->_getAttributeTableAlias($attributeCode) . '.value'; } return $fieldName; } /** * Add attribute value table to the join if it wasn't added previously * * @param string $attributeCode * @param string $joinType inner|left * @throws Mage_Eav_Exception * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _addAttributeJoin($attributeCode, $joinType = 'inner') { if (!empty($this->_filterAttributes[$attributeCode])) { return $this; } $adapter = $this->getConnection(); $attrTable = $this->_getAttributeTableAlias($attributeCode); if (isset($this->_joinAttributes[$attributeCode])) { $attribute = $this->_joinAttributes[$attributeCode]['attribute']; $entity = $attribute->getEntity(); $entityIdField = $entity->getEntityIdField(); $fkName = $this->_joinAttributes[$attributeCode]['bind']; $fkAttribute = $this->_joinAttributes[$attributeCode]['bindAttribute']; $fkTable = $this->_getAttributeTableAlias($fkName); if ($fkAttribute->getBackend()->isStatic()) { if (isset($this->_joinAttributes[$fkName])) { $fk = $fkTable . '.' . $fkAttribute->getAttributeCode(); } else { $fk = 'e.' . $fkAttribute->getAttributeCode(); } } else { $this->_addAttributeJoin($fkAttribute->getAttributeCode(), $joinType); $fk = $fkTable . '.value'; } $pk = $attrTable . '.' . $this->_joinAttributes[$attributeCode]['filter']; } else { $entity = $this->getEntity(); $entityIdField = $entity->getEntityIdField(); $attribute = $entity->getAttribute($attributeCode); $fk = 'e.' . $entityIdField; $pk = $attrTable . '.' . $entityIdField; } if (!$attribute) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid attribute name: %s', $attributeCode)); } if ($attribute->getBackend()->isStatic()) { $attrFieldName = $attrTable . '.' . $attribute->getAttributeCode(); } else { $attrFieldName = $attrTable . '.value'; } $fk = $adapter->quoteColumnAs($fk, null); $pk = $adapter->quoteColumnAs($pk, null); $condArr = array("$pk = $fk"); if (!$attribute->getBackend()->isStatic()) { $condArr[] = $this->getConnection()->quoteInto( $adapter->quoteColumnAs("$attrTable.attribute_id", null) . ' = ?', $attribute->getId()); } /** * process join type */ $joinMethod = ($joinType == 'left') ? 'joinLeft' : 'join'; $this->_joinAttributeToSelect($joinMethod, $attribute, $attrTable, $condArr, $attributeCode, $attrFieldName); $this->removeAttributeToSelect($attributeCode); $this->_filterAttributes[$attributeCode] = $attribute->getId(); /** * Fix double join for using same as filter */ $this->_joinFields[$attributeCode] = array( 'table' => '', 'field' => $attrFieldName, ); return $this; } /** * Adding join statement to collection select instance * * @param string $method * @param object $attribute * @param string $tableAlias * @param array $condition * @param string $fieldCode * @param string $fieldAlias * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _joinAttributeToSelect($method, $attribute, $tableAlias, $condition, $fieldCode, $fieldAlias) { $this->getSelect()->$method( array($tableAlias => $attribute->getBackend()->getTable()), '('.implode(') AND (', $condition).')', array($fieldCode => $fieldAlias) ); return $this; } /** * Get condition sql for the attribute * * @see self::_getConditionSql * @param string $attribute * @param mixed $condition * @param string $joinType * @return string */ protected function _getAttributeConditionSql($attribute, $condition, $joinType = 'inner') { if (isset($this->_joinFields[$attribute])) { return $this->_getConditionSql($this->_getAttributeFieldName($attribute), $condition); } if (isset($this->_staticFields[$attribute])) { return $this->_getConditionSql($this->getConnection()->quoteIdentifier('e.' . $attribute), $condition); } // process linked attribute if (isset($this->_joinAttributes[$attribute])) { $entity = $this->getAttribute($attribute)->getEntity(); $entityTable = $entity->getEntityTable(); } else { $entity = $this->getEntity(); $entityTable = 'e'; } if ($entity->isAttributeStatic($attribute)) { $conditionSql = $this->_getConditionSql( $this->getConnection()->quoteIdentifier('e.' . $attribute), $condition ); } else { $this->_addAttributeJoin($attribute, $joinType); if (isset($this->_joinAttributes[$attribute]['condition_alias'])) { $field = $this->_joinAttributes[$attribute]['condition_alias']; } else { $field = $this->_getAttributeTableAlias($attribute) . '.value'; } $conditionSql = $this->_getConditionSql($field, $condition); } return $conditionSql; } /** * Set sorting order * * $attribute can also be an array of attributes * * @param string|array $attribute * @param string $dir * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function setOrder($attribute, $dir = self::SORT_ORDER_ASC) { if (is_array($attribute)) { foreach ($attribute as $attr) { parent::setOrder($attr, $dir); } } return parent::setOrder($attribute, $dir); } /** * Retreive array of attributes * * @param array $arrAttributes * @return array */ public function toArray($arrAttributes = array()) { $arr = array(); foreach ($this->_items as $k => $item) { $arr[$k] = $item->toArray($arrAttributes); } return $arr; } /** * Treat "order by" items as attributes to sort * * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _renderOrders() { if (!$this->_isOrdersRendered) { foreach ($this->_orders as $attribute => $direction) { $this->addAttributeToSort($attribute, $direction); } $this->_isOrdersRendered = true; } return $this; } /** * After load method * * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _afterLoad() { return $this; } /** * Reset collection * * @return Mage_Eav_Model_Entity_Collection_Abstract */ protected function _reset() { parent::_reset(); $this->_selectEntityTypes = array(); $this->_selectAttributes = array(); $this->_filterAttributes = array(); $this->_joinEntities = array(); $this->_joinAttributes = array(); $this->_joinFields = array(); return $this; } /** * Returns already loaded element ids * * return array */ public function getLoadedIds() { return array_keys($this->_items); } /** * Prepare select for load * * @param Varien_Db_Select $select OPTIONAL * @return string */ public function _prepareSelect(Varien_Db_Select $select) { if ($this->_useAnalyticFunction) { $helper = Mage::getResourceHelper('core'); return $helper->getQueryUsingAnalyticFunction($select); } return (string)$select; } }