Overview

Packages

  • currencysymbol
  • MAbout
  • Mage
    • Admin
    • Adminhtml
    • AdminNotification
    • Api
    • Api2
    • Authorizenet
    • Backup
    • Bundle
    • Captcha
    • Catalog
    • CatalogIndex
    • CatalogInventory
    • CatalogRule
    • CatalogSearch
    • Centinel
    • Checkout
    • Cms
    • Compiler
    • Connect
    • Contacts
    • Core
    • Cron
    • CurrencySymbol
    • Customer
    • Dataflow
    • Directory
    • DirtectPost
    • Downloadable
    • Eav
    • GiftMessage
    • GoogleAnalytics
    • GoogleBase
    • GoogleCheckout
    • ImportExport
    • Index
    • Install
    • Log
    • Media
    • Newsletter
    • Oauth
    • Page
    • PageCache
    • Paygate
    • Payment
    • Paypal
    • PaypalUk
    • Persistent
    • Poll
    • ProductAlert
    • Rating
    • Reports
    • Review
    • Rss
    • Rule
    • Sales
    • SalesRule
    • Sedfriend
    • Sendfriend
    • Shipping
    • Sitemap
    • Tag
    • Tax
    • Usa
    • Weee
    • Widget
    • Wishlist
    • XmlConnect
  • None
  • Phoenix
    • Moneybookers
  • PHP
  • Zend
    • Date
    • Mime
    • XmlRpc

Classes

  • Mage_Catalog_Model_Entity_Product_Attribute_Design_Options_Container
  • Mage_Catalog_Model_Product_Attribute_Source_Inputtype
  • Mage_Eav_Block_Adminhtml_Attribute_Edit_Js
  • Mage_Eav_Block_Adminhtml_Attribute_Edit_Main_Abstract
  • Mage_Eav_Block_Adminhtml_Attribute_Edit_Options_Abstract
  • Mage_Eav_Helper_Data
  • Mage_Eav_Model_Adminhtml_System_Config_Source_Inputtype
  • Mage_Eav_Model_Adminhtml_System_Config_Source_Inputtype_Validator
  • Mage_Eav_Model_Attribute
  • Mage_Eav_Model_Attribute_Data
  • Mage_Eav_Model_Attribute_Data_Abstract
  • Mage_Eav_Model_Attribute_Data_Boolean
  • Mage_Eav_Model_Attribute_Data_Date
  • Mage_Eav_Model_Attribute_Data_File
  • Mage_Eav_Model_Attribute_Data_Hidden
  • Mage_Eav_Model_Attribute_Data_Image
  • Mage_Eav_Model_Attribute_Data_Multiline
  • Mage_Eav_Model_Attribute_Data_Multiselect
  • Mage_Eav_Model_Attribute_Data_Select
  • Mage_Eav_Model_Attribute_Data_Text
  • Mage_Eav_Model_Attribute_Data_Textarea
  • Mage_Eav_Model_Config
  • Mage_Eav_Model_Convert_Adapter_Entity
  • Mage_Eav_Model_Convert_Adapter_Grid
  • Mage_Eav_Model_Convert_Parser_Abstract
  • Mage_Eav_Model_Entity
  • Mage_Eav_Model_Entity_Abstract
  • Mage_Eav_Model_Entity_Attribute
  • Mage_Eav_Model_Entity_Attribute_Abstract
  • Mage_Eav_Model_Entity_Attribute_Backend_Abstract
  • Mage_Eav_Model_Entity_Attribute_Backend_Array
  • Mage_Eav_Model_Entity_Attribute_Backend_Datetime
  • Mage_Eav_Model_Entity_Attribute_Backend_Default
  • Mage_Eav_Model_Entity_Attribute_Backend_Increment
  • Mage_Eav_Model_Entity_Attribute_Backend_Serialized
  • Mage_Eav_Model_Entity_Attribute_Backend_Store
  • Mage_Eav_Model_Entity_Attribute_Backend_Time_Created
  • Mage_Eav_Model_Entity_Attribute_Backend_Time_Updated
  • Mage_Eav_Model_Entity_Attribute_Frontend_Abstract
  • Mage_Eav_Model_Entity_Attribute_Frontend_Datetime
  • Mage_Eav_Model_Entity_Attribute_Frontend_Default
  • Mage_Eav_Model_Entity_Attribute_Group
  • Mage_Eav_Model_Entity_Attribute_Option
  • Mage_Eav_Model_Entity_Attribute_Set
  • Mage_Eav_Model_Entity_Attribute_Source_Abstract
  • Mage_Eav_Model_Entity_Attribute_Source_Boolean
  • Mage_Eav_Model_Entity_Attribute_Source_Config
  • Mage_Eav_Model_Entity_Attribute_Source_Store
  • Mage_Eav_Model_Entity_Attribute_Source_Table
  • Mage_Eav_Model_Entity_Collection
  • Mage_Eav_Model_Entity_Collection_Abstract
  • Mage_Eav_Model_Entity_Increment_Abstract
  • Mage_Eav_Model_Entity_Increment_Alphanum
  • Mage_Eav_Model_Entity_Increment_Numeric
  • Mage_Eav_Model_Entity_Setup
  • Mage_Eav_Model_Entity_Store
  • Mage_Eav_Model_Entity_Type
  • Mage_Eav_Model_Form
  • Mage_Eav_Model_Form_Element
  • Mage_Eav_Model_Form_Fieldset
  • Mage_Eav_Model_Form_Type
  • Mage_Eav_Model_Mysql4_Config
  • Mage_Eav_Model_Mysql4_Entity_Attribute
  • Mage_Eav_Model_Mysql4_Entity_Attribute_Collection
  • Mage_Eav_Model_Mysql4_Entity_Attribute_Group
  • Mage_Eav_Model_Mysql4_Entity_Attribute_Group_Collection
  • Mage_Eav_Model_Mysql4_Entity_Attribute_Option
  • Mage_Eav_Model_Mysql4_Entity_Attribute_Option_Collection
  • Mage_Eav_Model_Mysql4_Entity_Attribute_Set
  • Mage_Eav_Model_Mysql4_Entity_Attribute_Set_Collection
  • Mage_Eav_Model_Mysql4_Entity_Store
  • Mage_Eav_Model_Mysql4_Entity_Type
  • Mage_Eav_Model_Mysql4_Entity_Type_Collection
  • Mage_Eav_Model_Mysql4_Form_Element
  • Mage_Eav_Model_Mysql4_Form_Element_Collection
  • Mage_Eav_Model_Mysql4_Form_Fieldset
  • Mage_Eav_Model_Mysql4_Form_Fieldset_Collection
  • Mage_Eav_Model_Mysql4_Form_Type
  • Mage_Eav_Model_Mysql4_Form_Type_Collection
  • Mage_Eav_Model_Resource_Attribute
  • Mage_Eav_Model_Resource_Attribute_Collection
  • Mage_Eav_Model_Resource_Config
  • Mage_Eav_Model_Resource_Entity_Attribute
  • Mage_Eav_Model_Resource_Entity_Attribute_Collection
  • Mage_Eav_Model_Resource_Entity_Attribute_Group
  • Mage_Eav_Model_Resource_Entity_Attribute_Group_Collection
  • Mage_Eav_Model_Resource_Entity_Attribute_Option
  • Mage_Eav_Model_Resource_Entity_Attribute_Option_Collection
  • Mage_Eav_Model_Resource_Entity_Attribute_Set
  • Mage_Eav_Model_Resource_Entity_Attribute_Set_Collection
  • Mage_Eav_Model_Resource_Entity_Store
  • Mage_Eav_Model_Resource_Entity_Type
  • Mage_Eav_Model_Resource_Entity_Type_Collection
  • Mage_Eav_Model_Resource_Form_Attribute
  • Mage_Eav_Model_Resource_Form_Attribute_Collection
  • Mage_Eav_Model_Resource_Form_Element
  • Mage_Eav_Model_Resource_Form_Element_Collection
  • Mage_Eav_Model_Resource_Form_Fieldset
  • Mage_Eav_Model_Resource_Form_Fieldset_Collection
  • Mage_Eav_Model_Resource_Form_Type
  • Mage_Eav_Model_Resource_Form_Type_Collection
  • Mage_Eav_Model_Resource_Helper_Mysql4

Interfaces

  • Mage_Eav_Model_Entity_Attribute_Backend_Interface
  • Mage_Eav_Model_Entity_Attribute_Frontend_Interface
  • Mage_Eav_Model_Entity_Attribute_Interface
  • Mage_Eav_Model_Entity_Attribute_Source_Interface
  • Mage_Eav_Model_Entity_Increment_Interface
  • Mage_Eav_Model_Entity_Interface

Exceptions

  • Mage_Eav_Exception
  • Mage_Eav_Model_Entity_Attribute_Exception
  • Overview
  • Package
  • Class
  • Tree
   1: <?php
   2: /**
   3:  * Magento
   4:  *
   5:  * NOTICE OF LICENSE
   6:  *
   7:  * This source file is subject to the Open Software License (OSL 3.0)
   8:  * that is bundled with this package in the file LICENSE.txt.
   9:  * It is also available through the world-wide-web at this URL:
  10:  * http://opensource.org/licenses/osl-3.0.php
  11:  * If you did not receive a copy of the license and are unable to
  12:  * obtain it through the world-wide-web, please send an email
  13:  * to license@magentocommerce.com so we can send you a copy immediately.
  14:  *
  15:  * DISCLAIMER
  16:  *
  17:  * Do not edit or add to this file if you wish to upgrade Magento to newer
  18:  * versions in the future. If you wish to customize Magento for your
  19:  * needs please refer to http://www.magentocommerce.com for more information.
  20:  *
  21:  * @category    Mage
  22:  * @package     Mage_Eav
  23:  * @copyright   Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
  24:  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  25:  */
  26: 
  27: 
  28: /**
  29:  * Entity/Attribute/Model - entity abstract
  30:  *
  31:  * @category   Mage
  32:  * @package    Mage_Eav
  33:  * @author     Magento Core Team <core@magentocommerce.com>
  34:  */
  35: abstract class Mage_Eav_Model_Entity_Abstract extends Mage_Core_Model_Resource_Abstract
  36:     implements Mage_Eav_Model_Entity_Interface
  37: {
  38:     /**
  39:      * Read connection
  40:      *
  41:      * @var Varien_Db_Adapter_Pdo_Mysql
  42:      */
  43:     protected $_read;
  44: 
  45:     /**
  46:      * Write connection
  47:      *
  48:      * @var Varien_Db_Adapter_Pdo_Mysql
  49:      */
  50:     protected $_write;
  51: 
  52:     /**
  53:      * Entity type configuration
  54:      *
  55:      * @var Mage_Eav_Model_Entity_Type
  56:      */
  57:     protected $_type;
  58: 
  59:     /**
  60:      * Attributes array by attribute id
  61:      *
  62:      * @var array
  63:      */
  64:     protected $_attributesById              = array();
  65: 
  66:     /**
  67:      * Attributes array by attribute name
  68:      *
  69:      * @var unknown_type
  70:      */
  71:     protected $_attributesByCode            = array();
  72: 
  73:     /**
  74:      * 2-dimentional array by table name and attribute name
  75:      *
  76:      * @var array
  77:      */
  78:     protected $_attributesByTable           = array();
  79: 
  80:     /**
  81:      * Attributes that are static fields in entity table
  82:      *
  83:      * @var array
  84:      */
  85:     protected $_staticAttributes = array();
  86: 
  87:     /**
  88:      * Default Attributes that are static
  89:      *
  90:      * @var array
  91:      */
  92:     protected static $_defaultAttributes    = array();
  93: 
  94:     /**
  95:      * Entity table
  96:      *
  97:      * @var string
  98:      */
  99:     protected $_entityTable;
 100: 
 101:     /**
 102:      * Describe data for tables
 103:      *
 104:      * @var array
 105:      */
 106:     protected $_describeTable               = array();
 107: 
 108:     /**
 109:      * Entity table identification field name
 110:      *
 111:      * @var string
 112:      */
 113:     protected $_entityIdField;
 114: 
 115:     /**
 116:      * Entity values table identification field name
 117:      *
 118:      * @var string
 119:      */
 120:     protected $_valueEntityIdField;
 121: 
 122:     /**
 123:      * Entity value table prefix
 124:      *
 125:      * @var string
 126:      */
 127:     protected $_valueTablePrefix;
 128: 
 129:     /* Entity table string
 130:      *
 131:      * @var string
 132:      */
 133:     protected $_entityTablePrefix;
 134: 
 135:     /**
 136:      * Partial load flag
 137:      *
 138:      * @var boolean
 139:      */
 140:     protected $_isPartialLoad = false;
 141: 
 142:     /**
 143:      * Partial save flag
 144:      *
 145:      * @var boolean
 146:      */
 147:     protected $_isPartialSave = false;
 148: 
 149:     /**
 150:      * Attribute set id which used for get sorted attributes
 151:      *
 152:      * @var int
 153:      */
 154:     protected $_sortingSetId = null;
 155: 
 156:     /**
 157:      * Entity attribute values per backend table to delete
 158:      *
 159:      * @var array
 160:      */
 161:     protected $_attributeValuesToDelete = array();
 162: 
 163:     /**
 164:      * Entity attribute values per backend table to save
 165:      *
 166:      * @var array
 167:      */
 168:     protected $_attributeValuesToSave   = array();
 169: 
 170:     /**
 171:      * Array of describe attribute backend tables
 172:      * The table name as key
 173:      *
 174:      * @var array
 175:      */
 176:     protected static $_attributeBackendTables   = array();
 177: 
 178:     /**
 179:      * Set connections for entity operations
 180:      *
 181:      * @param Zend_Db_Adapter_Abstract|string $read
 182:      * @param Zend_Db_Adapter_Abstract|string|null $write
 183:      * @return Mage_Eav_Model_Entity_Abstract
 184:      */
 185:     public function setConnection($read, $write = null)
 186:     {
 187:         $this->_read  = $read;
 188:         $this->_write = $write ? $write : $read;
 189: 
 190:         return $this;
 191:     }
 192: 
 193:     /**
 194:      * Resource initialization
 195:      */
 196:     protected function _construct()
 197:     {}
 198: 
 199:     /**
 200:      * Retrieve connection for read data
 201:      *
 202:      * @return Varien_Db_Adapter_Interface
 203:      */
 204:     protected function _getReadAdapter()
 205:     {
 206:         if (is_string($this->_read)) {
 207:             $this->_read = Mage::getSingleton('core/resource')->getConnection($this->_read);
 208:         }
 209:         return $this->_read;
 210:     }
 211: 
 212:     /**
 213:      * Retrieve connection for write data
 214:      *
 215:      * @return Varien_Db_Adapter_Interface
 216:      */
 217:     protected function _getWriteAdapter()
 218:     {
 219:         if (is_string($this->_write)) {
 220:             $this->_write = Mage::getSingleton('core/resource')->getConnection($this->_write);
 221:         }
 222:         return $this->_write;
 223:     }
 224: 
 225:     /**
 226:      * Retrieve read DB connection
 227:      *
 228:      * @return Varien_Db_Adapter_Interface
 229:      */
 230:     public function getReadConnection()
 231:     {
 232:         return $this->_getReadAdapter();
 233:     }
 234: 
 235:     /**
 236:      * Retrieve write DB connection
 237:      *
 238:      * @return Varien_Db_Adapter_Interface
 239:      */
 240:     public function getWriteConnection()
 241:     {
 242:         return $this->_getWriteAdapter();
 243:     }
 244: 
 245:     /**
 246:      * For compatibility with Mage_Core_Model_Abstract
 247:      *
 248:      * @return string
 249:      */
 250:     public function getIdFieldName()
 251:     {
 252:         return $this->getEntityIdField();
 253:     }
 254: 
 255:     /**
 256:      * Retreive table name
 257:      *
 258:      * @param string $alias
 259:      * @return string
 260:      */
 261:     public function getTable($alias)
 262:     {
 263:         return Mage::getSingleton('core/resource')->getTableName($alias);
 264:     }
 265: 
 266:     /**
 267:      * Set configuration for the entity
 268:      *
 269:      * Accepts config node or name of entity type
 270:      *
 271:      * @param string|Mage_Eav_Model_Entity_Type $type
 272:      * @return Mage_Eav_Model_Entity_Abstract
 273:      */
 274:     public function setType($type)
 275:     {
 276:         $this->_type = Mage::getSingleton('eav/config')->getEntityType($type);
 277:         $this->_afterSetConfig();
 278:         return $this;
 279:     }
 280: 
 281:     /**
 282:      * Retrieve current entity config
 283:      *
 284:      * @return Mage_Eav_Model_Entity_Type
 285:      */
 286:     public function getEntityType()
 287:     {
 288:         if (empty($this->_type)) {
 289:             throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Entity is not initialized'));
 290:         }
 291:         return $this->_type;
 292:     }
 293: 
 294:     /**
 295:      * Get entity type name
 296:      *
 297:      * @return string
 298:      */
 299:     public function getType()
 300:     {
 301:         return $this->getEntityType()->getEntityTypeCode();
 302:     }
 303: 
 304:     /**
 305:      * Get entity type id
 306:      *
 307:      * @return int
 308:      */
 309:     public function getTypeId()
 310:     {
 311:         return (int)$this->getEntityType()->getEntityTypeId();
 312:     }
 313: 
 314:     /**
 315:      * Unset attributes
 316:      *
 317:      * If NULL or not supplied removes configuration of all attributes
 318:      * If string - removes only one, if array - all specified
 319:      *
 320:      * @param array|string|null $attributes
 321:      * @return Mage_Eav_Model_Entity_Abstract
 322:      */
 323:     public function unsetAttributes($attributes = null)
 324:     {
 325:         if ($attributes === null) {
 326:             $this->_attributesByCode    = array();
 327:             $this->_attributesById      = array();
 328:             $this->_attributesByTable   = array();
 329:             return $this;
 330:         }
 331: 
 332:         if (is_string($attributes)) {
 333:             $attributes = array($attributes);
 334:         }
 335: 
 336:         if (!is_array($attributes)) {
 337:             throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Unknown parameter'));
 338:         }
 339: 
 340:         foreach ($attributes as $attrCode) {
 341:             if (!isset($this->_attributesByCode[$attrCode])) {
 342:                 continue;
 343:             }
 344: 
 345:             $attr = $this->getAttribute($attrCode);
 346:             unset($this->_attributesById[$attr->getId()]);
 347:             unset($this->_attributesByTable[$attr->getBackend()->getTable()][$attrCode]);
 348:             unset($this->_attributesByCode[$attrCode]);
 349:         }
 350: 
 351:         return $this;
 352:     }
 353: 
 354:     /**
 355:      * Retrieve attribute instance by name, id or config node
 356:      *
 357:      * This will add the attribute configuration to entity's attributes cache
 358:      *
 359:      * If attribute is not found false is returned
 360:      *
 361:      * @param string|integer|Mage_Core_Model_Config_Element $attribute
 362:      * @return Mage_Eav_Model_Entity_Attribute_Abstract || false
 363:      */
 364:     public function getAttribute($attribute)
 365:     {
 366:         if (is_numeric($attribute)) {
 367:             $attributeId = $attribute;
 368: 
 369:             if (isset($this->_attributesById[$attributeId])) {
 370:                 return $this->_attributesById[$attributeId];
 371:             }
 372:             $attributeInstance = Mage::getSingleton('eav/config')->getAttribute($this->getEntityType(), $attributeId);
 373:             if ($attributeInstance) {
 374:                 $attributeCode = $attributeInstance->getAttributeCode();
 375:             }
 376: 
 377:         } else if (is_string($attribute)) {
 378:             $attributeCode = $attribute;
 379: 
 380:             if (isset($this->_attributesByCode[$attributeCode])) {
 381:                 return $this->_attributesByCode[$attributeCode];
 382:             }
 383:             $attributeInstance = Mage::getSingleton('eav/config')
 384:                 ->getAttribute($this->getEntityType(), $attributeCode);
 385:             if (!$attributeInstance->getAttributeCode() && in_array($attribute, $this->getDefaultAttributes())) {
 386:                 $attributeInstance
 387:                     ->setAttributeCode($attribute)
 388:                     ->setBackendType(Mage_Eav_Model_Entity_Attribute_Abstract::TYPE_STATIC)
 389:                     ->setIsGlobal(1)
 390:                     ->setEntity($this)
 391:                     ->setEntityType($this->getEntityType())
 392:                     ->setEntityTypeId($this->getEntityType()->getId());
 393:             }
 394:         } else if ($attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract) {
 395: 
 396:             $attributeInstance = $attribute;
 397:             $attributeCode = $attributeInstance->getAttributeCode();
 398:             if (isset($this->_attributesByCode[$attributeCode])) {
 399:                 return $this->_attributesByCode[$attributeCode];
 400:             }
 401:         }
 402: 
 403:         if (empty($attributeInstance)
 404:             || !($attributeInstance instanceof Mage_Eav_Model_Entity_Attribute_Abstract)
 405:             || (!$attributeInstance->getId()
 406:             && !in_array($attributeInstance->getAttributeCode(), $this->getDefaultAttributes()))
 407:         ) {
 408:             return false;
 409:         }
 410: 
 411:         $attribute = $attributeInstance;
 412: 
 413:         if (empty($attributeId)) {
 414:             $attributeId = $attribute->getAttributeId();
 415:         }
 416: 
 417:         if (!$attribute->getAttributeCode()) {
 418:             $attribute->setAttributeCode($attributeCode);
 419:         }
 420:         if (!$attribute->getAttributeModel()) {
 421:             $attribute->setAttributeModel($this->_getDefaultAttributeModel());
 422:         }
 423: 
 424:         $this->addAttribute($attribute);
 425: 
 426:         return $attribute;
 427:     }
 428: 
 429:     /**
 430:      * Return default static virtual attribute that doesn't exists in EAV attributes
 431:      *
 432:      * @param string $attributeCode
 433:      * @return Mage_Eav_Model_Entity_Attribute
 434:      */
 435:     protected function _getDefaultAttribute($attributeCode)
 436:     {
 437:         $entityTypeId = $this->getEntityType()->getId();
 438:         if (!isset(self::$_defaultAttributes[$entityTypeId][$attributeCode])) {
 439:             $attribute = Mage::getModel($this->getEntityType()->getAttributeModel())
 440:                 ->setAttributeCode($attributeCode)
 441:                 ->setBackendType(Mage_Eav_Model_Entity_Attribute_Abstract::TYPE_STATIC)
 442:                 ->setIsGlobal(1)
 443:                 ->setEntityType($this->getEntityType())
 444:                 ->setEntityTypeId($this->getEntityType()->getId());
 445:             self::$_defaultAttributes[$entityTypeId][$attributeCode] = $attribute;
 446:         }
 447: 
 448:         return self::$_defaultAttributes[$entityTypeId][$attributeCode];
 449:     }
 450: 
 451:     /**
 452:      * Adding attribute to entity
 453:      *
 454:      * @param   Mage_Eav_Model_Entity_Attribute_Abstract $attribute
 455:      * @return  Mage_Eav_Model_Entity_Abstract
 456:      */
 457:     public function addAttribute(Mage_Eav_Model_Entity_Attribute_Abstract $attribute)
 458:     {
 459:         $attribute->setEntity($this);
 460:         $attributeCode = $attribute->getAttributeCode();
 461: 
 462:         $this->_attributesByCode[$attributeCode] = $attribute;
 463: 
 464:         if ($attribute->isStatic()) {
 465:             $this->_staticAttributes[$attributeCode] = $attribute;
 466:         } else {
 467:             $this->_attributesById[$attribute->getId()] = $attribute;
 468:             $this->_attributesByTable[$attribute->getBackendTable()][$attributeCode] = $attribute;
 469:         }
 470: 
 471:         return $this;
 472:     }
 473: 
 474:     /**
 475:      * Retreive partial load flag
 476:      *
 477:      * @param boolean $flag
 478:      * @return boolean
 479:      */
 480:     public function isPartialLoad($flag = null)
 481:     {
 482:         $result = $this->_isPartialLoad;
 483:         if ($flag !== null) {
 484:             $this->_isPartialLoad = (bool)$flag;
 485:         }
 486:         return $result;
 487:     }
 488: 
 489:     /**
 490:      * Retreive partial save flag
 491:      *
 492:      * @param boolean $flag
 493:      * @return boolean
 494:      */
 495:     public function isPartialSave($flag = null)
 496:     {
 497:         $result = $this->_isPartialSave;
 498:         if ($flag !== null) {
 499:             $this->_isPartialSave = (bool)$flag;
 500:         }
 501:         return $result;
 502:     }
 503: 
 504:     /**
 505:      * Retrieve configuration for all attributes
 506:      *
 507:      * @return Mage_Eav_Model_Entity_Attribute_Abstract
 508:      */
 509:     public function loadAllAttributes($object=null)
 510:     {
 511:         $attributeCodes = Mage::getSingleton('eav/config')
 512:             ->getEntityAttributeCodes($this->getEntityType(), $object);
 513: 
 514:         /**
 515:          * Check and init default attributes
 516:          */
 517:         $defaultAttributes = $this->getDefaultAttributes();
 518:         foreach ($defaultAttributes as $attributeCode) {
 519:             $attributeIndex = array_search($attributeCode, $attributeCodes);
 520:             if ($attributeIndex !== false) {
 521:                 $this->getAttribute($attributeCodes[$attributeIndex]);
 522:                 unset($attributeCodes[$attributeIndex]);
 523:             } else {
 524:                 $this->addAttribute($this->_getDefaultAttribute($attributeCode));
 525:             }
 526:         }
 527: 
 528:         foreach ($attributeCodes as $code) {
 529:             $this->getAttribute($code);
 530:         }
 531: 
 532:         return $this;
 533:     }
 534: 
 535:     /**
 536:      * Retrieve sorted attributes
 537:      *
 538:      * @param int $setId
 539:      * @return array
 540:      */
 541:     public function getSortedAttributes($setId = null)
 542:     {
 543:         $attributes = $this->getAttributesByCode();
 544:         if ($setId === null) {
 545:             $setId = $this->getEntityType()->getDefaultAttributeSetId();
 546:         }
 547: 
 548:         // initialize set info
 549:         Mage::getSingleton('eav/entity_attribute_set')
 550:             ->addSetInfo($this->getEntityType(), $attributes, $setId);
 551: 
 552:         foreach ($attributes as $code => $attribute) {
 553:             /* @var $attribute Mage_Eav_Model_Entity_Attribute_Abstract */
 554:             if (!$attribute->isInSet($setId)) {
 555:                 unset($attributes[$code]);
 556:             }
 557:         }
 558: 
 559:         $this->_sortingSetId = $setId;
 560:         uasort($attributes, array($this, 'attributesCompare'));
 561:         return $attributes;
 562:     }
 563: 
 564:     /**
 565:      * Compare attributes
 566:      *
 567:      * @param Mage_Eav_Model_Entity_Attribute $attribute1
 568:      * @param Mage_Eav_Model_Entity_Attribute $attribute2
 569:      * @return int
 570:      */
 571:     public function attributesCompare($attribute1, $attribute2)
 572:     {
 573:         $sortPath      = sprintf('attribute_set_info/%s/sort', $this->_sortingSetId);
 574:         $groupSortPath = sprintf('attribute_set_info/%s/group_sort', $this->_sortingSetId);
 575: 
 576:         $sort1 =  ($attribute1->getData($groupSortPath) * 1000) + ($attribute1->getData($sortPath) * 0.0001);
 577:         $sort2 =  ($attribute2->getData($groupSortPath) * 1000) + ($attribute2->getData($sortPath) * 0.0001);
 578: 
 579:         if ($sort1 > $sort2) {
 580:             return 1;
 581:         } elseif ($sort1 < $sort2) {
 582:             return -1;
 583:         }
 584: 
 585:         return 0;
 586:     }
 587: 
 588:     /**
 589:      * Check whether the attribute is Applicable to the object
 590:      *
 591:      * @param   Varien_Object $object
 592:      * @param   Mage_Eav_Model_Entity_Attribute_Abstract $attribute
 593:      * @return  boolean
 594:      */
 595:     protected function _isApplicableAttribute($object, $attribute)
 596:     {
 597:         return true;
 598:     }
 599: 
 600:     /**
 601:      * Walk through the attributes and run method with optional arguments
 602:      *
 603:      * Returns array with results for each attribute
 604:      *
 605:      * if $method is in format "part/method" will run method on specified part
 606:      * for example: $this->walkAttributes('backend/validate');
 607:      *
 608:      * @param string $method
 609:      * @param array $args
 610:      * @param array $part attribute, backend, frontend, source
 611:      * @return array
 612:      */
 613:     public function walkAttributes($partMethod, array $args = array())
 614:     {
 615:         $methodArr = explode('/', $partMethod);
 616:         switch (sizeof($methodArr)) {
 617:             case 1:
 618:                 $part   = 'attribute';
 619:                 $method = $methodArr[0];
 620:                 break;
 621: 
 622:             case 2:
 623:                 $part   = $methodArr[0];
 624:                 $method = $methodArr[1];
 625:                 break;
 626:         }
 627:         $results = array();
 628:         foreach ($this->getAttributesByCode() as $attrCode => $attribute) {
 629: 
 630:             if (isset($args[0]) && is_object($args[0]) && !$this->_isApplicableAttribute($args[0], $attribute)) {
 631:                 continue;
 632:             }
 633: 
 634:             switch ($part) {
 635:                 case 'attribute':
 636:                     $instance = $attribute;
 637:                     break;
 638: 
 639:                 case 'backend':
 640:                     $instance = $attribute->getBackend();
 641:                     break;
 642: 
 643:                 case 'frontend':
 644:                     $instance = $attribute->getFrontend();
 645:                     break;
 646: 
 647:                 case 'source':
 648:                     $instance = $attribute->getSource();
 649:                     break;
 650:             }
 651: 
 652:             if (!$this->_isCallableAttributeInstance($instance, $method, $args)) {
 653:                 continue;
 654:             }
 655: 
 656:             try {
 657:                 $results[$attrCode] = call_user_func_array(array($instance, $method), $args);
 658:             } catch (Mage_Eav_Model_Entity_Attribute_Exception $e) {
 659:                 throw $e;
 660:             } catch (Exception $e) {
 661:                 $e = Mage::getModel('eav/entity_attribute_exception', $e->getMessage());
 662:                 $e->setAttributeCode($attrCode)->setPart($part);
 663:                 throw $e;
 664:             }
 665:         }
 666: 
 667:         return $results;
 668:     }
 669: 
 670:     /**
 671:      * Check whether attribute instance (attribute, backend, frontend or source) has method and applicable
 672:      *
 673:      * @param Mage_Eav_Model_Entity_Attribute_Abstract|Mage_Eav_Model_Entity_Attribute_Backend_Abstract|Mage_Eav_Model_Entity_Attribute_Frontend_Abstract|Mage_Eav_Model_Entity_Attribute_Source_Abstract $instance
 674:      * @param string $method
 675:      * @param array $args array of arguments
 676:      * @return boolean
 677:      */
 678:     protected function _isCallableAttributeInstance($instance, $method, $args)
 679:     {
 680:         if (!is_object($instance) || !method_exists($instance, $method)) {
 681:             return false;
 682:         }
 683: 
 684:         return true;
 685:     }
 686: 
 687:     /**
 688:      * Get attributes by name array
 689:      *
 690:      * @return array
 691:      */
 692:     public function getAttributesByCode()
 693:     {
 694:         return $this->_attributesByCode;
 695:     }
 696: 
 697:     /**
 698:      * Get attributes by id array
 699:      *
 700:      * @return array
 701:      */
 702:     public function getAttributesById()
 703:     {
 704:         return $this->_attributesById;
 705:     }
 706: 
 707:     /**
 708:      * Get attributes by table and name array
 709:      *
 710:      * @return array
 711:      */
 712:     public function getAttributesByTable()
 713:     {
 714:         return $this->_attributesByTable;
 715:     }
 716: 
 717:     /**
 718:      * Get entity table name
 719:      *
 720:      * @return string
 721:      */
 722:     public function getEntityTable()
 723:     {
 724:         if (!$this->_entityTable) {
 725:             $table = $this->getEntityType()->getEntityTable();
 726:             if (!$table) {
 727:                 $table = Mage_Eav_Model_Entity::DEFAULT_ENTITY_TABLE;
 728:             }
 729:             $this->_entityTable = Mage::getSingleton('core/resource')->getTableName($table);
 730:         }
 731: 
 732:         return $this->_entityTable;
 733:     }
 734: 
 735:     /**
 736:      * Get entity id field name in entity table
 737:      *
 738:      * @return string
 739:      */
 740:     public function getEntityIdField()
 741:     {
 742:         if (!$this->_entityIdField) {
 743:             $this->_entityIdField = $this->getEntityType()->getEntityIdField();
 744:             if (!$this->_entityIdField) {
 745:                 $this->_entityIdField = Mage_Eav_Model_Entity::DEFAULT_ENTITY_ID_FIELD;
 746:             }
 747:         }
 748: 
 749:         return $this->_entityIdField;
 750:     }
 751: 
 752:     /**
 753:      * Get default entity id field name in attribute values tables
 754:      *
 755:      * @return string
 756:      */
 757:     public function getValueEntityIdField()
 758:     {
 759:         return $this->getEntityIdField();
 760:     }
 761: 
 762:     /**
 763:      * Get prefix for value tables
 764:      *
 765:      * @return string
 766:      */
 767:     public function getValueTablePrefix()
 768:     {
 769:         if (!$this->_valueTablePrefix) {
 770:             $prefix = (string)$this->getEntityType()->getValueTablePrefix();
 771:             if (!empty($prefix)) {
 772:                 $this->_valueTablePrefix = $prefix;
 773:                 /**
 774:                  * entity type prefix include DB table name prefix
 775:                  */
 776:                 //Mage::getSingleton('core/resource')->getTableName($prefix);
 777:             } else {
 778:                 $this->_valueTablePrefix = $this->getEntityTable();
 779:             }
 780:         }
 781: 
 782:         return $this->_valueTablePrefix;
 783:     }
 784: 
 785:     /**
 786:      * Get entity table prefix for value
 787:      *
 788:      * @return string
 789:      */
 790:     public function getEntityTablePrefix()
 791:     {
 792:         if (empty($this->_entityTablePrefix)) {
 793:             $prefix = $this->getEntityType()->getEntityTablePrefix();
 794:             if (empty($prefix)) {
 795:                 $prefix = $this->getEntityType()->getEntityTable();
 796:                 if (empty($prefix)) {
 797:                     $prefix = Mage_Eav_Model_Entity::DEFAULT_ENTITY_TABLE;
 798:                 }
 799:             }
 800:             $this->_entityTablePrefix = $prefix;
 801:         }
 802: 
 803:         return $this->_entityTablePrefix;
 804:     }
 805: 
 806:     /**
 807:      * Check whether the attribute is a real field in entity table
 808:      *
 809:      * @see Mage_Eav_Model_Entity_Abstract::getAttribute for $attribute format
 810:      * @param integer|string|Mage_Eav_Model_Entity_Attribute_Abstract $attribute
 811:      * @return boolean
 812:      */
 813:     public function isAttributeStatic($attribute)
 814:     {
 815:         $attrInstance       = $this->getAttribute($attribute);
 816:         $attrBackendStatic  = $attrInstance->getBackend()->isStatic();
 817:         return $attrInstance && $attrBackendStatic;
 818:     }
 819: 
 820:     /**
 821:      * Validate all object's attributes against configuration
 822:      *
 823:      * @param Varien_Object $object
 824:      * @throws Mage_Eav_Model_Entity_Attribute_Exception
 825:      * @return bool|array
 826:      */
 827:     public function validate($object)
 828:     {
 829:         $this->loadAllAttributes($object);
 830:         $result = $this->walkAttributes('backend/validate', array($object));
 831:         $errors = array();
 832:         foreach ($result as $attributeCode => $error) {
 833:             if ($error === false) {
 834:                 $errors[$attributeCode] = true;
 835:             } elseif (is_string($error)) {
 836:                 $errors[$attributeCode] = $error;
 837:             }
 838:         }
 839:         if (!$errors) {
 840:             return true;
 841:         }
 842: 
 843:         return $errors;
 844:     }
 845: 
 846:     /**
 847:      * Set new increment id to object
 848:      *
 849:      * @param Varien_Object $object
 850:      * @return Mage_Eav_Model_Entity_Abstract
 851:      */
 852:     public function setNewIncrementId(Varien_Object $object)
 853:     {
 854:         if ($object->getIncrementId()) {
 855:             return $this;
 856:         }
 857: 
 858:         $incrementId = $this->getEntityType()->fetchNewIncrementId($object->getStoreId());
 859: 
 860:         if ($incrementId !== false) {
 861:             $object->setIncrementId($incrementId);
 862:         }
 863: 
 864:         return $this;
 865:     }
 866: 
 867:     /**
 868:      * Check attribute unique value
 869:      *
 870:      * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute
 871:      * @param Varien_Object $object
 872:      * @return boolean
 873:      */
 874:     public function checkAttributeUniqueValue(Mage_Eav_Model_Entity_Attribute_Abstract $attribute, $object)
 875:     {
 876:         $adapter = $this->_getReadAdapter();
 877:         $select = $adapter->select();
 878:         if ($attribute->getBackend()->getType() === 'static') {
 879:             $value = $object->getData($attribute->getAttributeCode());
 880:             $bind = array(
 881:                 'entity_type_id' => $this->getTypeId(),
 882:                 'attribute_code' => trim($value)
 883:             );
 884: 
 885:             $select
 886:                 ->from($this->getEntityTable(), $this->getEntityIdField())
 887:                 ->where('entity_type_id = :entity_type_id')
 888:                 ->where($attribute->getAttributeCode() . ' = :attribute_code');
 889:         } else {
 890:             $value = $object->getData($attribute->getAttributeCode());
 891:             if ($attribute->getBackend()->getType() == 'datetime') {
 892:                 $date  = new Zend_Date($value, Varien_Date::DATE_INTERNAL_FORMAT);
 893:                 $value = $date->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
 894:             }
 895:             $bind = array(
 896:                 'entity_type_id' => $this->getTypeId(),
 897:                 'attribute_id'   => $attribute->getId(),
 898:                 'value'          => trim($value)
 899:             );
 900:             $select
 901:                 ->from($attribute->getBackend()->getTable(), $attribute->getBackend()->getEntityIdField())
 902:                 ->where('entity_type_id = :entity_type_id')
 903:                 ->where('attribute_id = :attribute_id')
 904:                 ->where('value = :value');
 905:         }
 906:         $data = $adapter->fetchCol($select, $bind);
 907: 
 908:         if ($object->getId()) {
 909:             if (isset($data[0])) {
 910:                 return $data[0] == $object->getId();
 911:             }
 912:             return true;
 913:         }
 914: 
 915:         return !count($data);
 916:     }
 917: 
 918:     /**
 919:      * Retreive default source model
 920:      *
 921:      * @return string
 922:      */
 923:     public function getDefaultAttributeSourceModel()
 924:     {
 925:         return Mage_Eav_Model_Entity::DEFAULT_SOURCE_MODEL;
 926:     }
 927: 
 928:     /**
 929:      * Load entity's attributes into the object
 930:      *
 931:      * @param   Mage_Core_Model_Abstract $object
 932:      * @param   integer $entityId
 933:      * @param   array|null $attributes
 934:      * @return  Mage_Eav_Model_Entity_Abstract
 935:      */
 936:     public function load($object, $entityId, $attributes = array())
 937:     {
 938:         Varien_Profiler::start('__EAV_LOAD_MODEL__');
 939:         /**
 940:          * Load object base row data
 941:          */
 942:         $select  = $this->_getLoadRowSelect($object, $entityId);
 943:         $row     = $this->_getReadAdapter()->fetchRow($select);
 944: 
 945:         if (is_array($row)) {
 946:             $object->addData($row);
 947:         } else {
 948:             $object->isObjectNew(true);
 949:         }
 950: 
 951:         if (empty($attributes)) {
 952:             $this->loadAllAttributes($object);
 953:         } else {
 954:             foreach ($attributes as $attrCode) {
 955:                 $this->getAttribute($attrCode);
 956:             }
 957:         }
 958: 
 959:         $this->_loadModelAttributes($object);
 960: 
 961:         $object->setOrigData();
 962:         Varien_Profiler::start('__EAV_LOAD_MODEL_AFTER_LOAD__');
 963: 
 964:         $this->_afterLoad($object);
 965:         Varien_Profiler::stop('__EAV_LOAD_MODEL_AFTER_LOAD__');
 966: 
 967:         Varien_Profiler::stop('__EAV_LOAD_MODEL__');
 968:         return $this;
 969:     }
 970: 
 971:     /**
 972:      * Load model attributes data
 973:      *
 974:      * @param Mage_Core_Model_Abstract $object
 975:      * @return Mage_Eav_Model_Entity_Abstract
 976:      */
 977:     protected function _loadModelAttributes($object)
 978:     {
 979:         if (!$object->getId()) {
 980:             return $this;
 981:         }
 982: 
 983:         Varien_Profiler::start('__EAV_LOAD_MODEL_ATTRIBUTES__');
 984: 
 985:         $selects = array();
 986:         foreach (array_keys($this->getAttributesByTable()) as $table) {
 987:             $attribute = current($this->_attributesByTable[$table]);
 988:             $eavType = $attribute->getBackendType();
 989:             $select = $this->_getLoadAttributesSelect($object, $table);
 990:             $selects[$eavType][] = $this->_addLoadAttributesSelectFields($select, $table, $eavType);
 991:         }
 992:         $selectGroups = Mage::getResourceHelper('eav')->getLoadAttributesSelectGroups($selects);
 993:         foreach ($selectGroups as $selects) {
 994:             if (!empty($selects)) {
 995:                 $select = $this->_prepareLoadSelect($selects);
 996:                 $values = $this->_getReadAdapter()->fetchAll($select);
 997:                 foreach ($values as $valueRow) {
 998:                     $this->_setAttributeValue($object, $valueRow);
 999:                 }
1000:             }
1001:         }
1002: 
1003:         Varien_Profiler::stop('__EAV_LOAD_MODEL_ATTRIBUTES__');
1004: 
1005:         return $this;
1006:     }
1007: 
1008:     /**
1009:      * Prepare select object for loading entity attributes values
1010:      *
1011:      * @param  array $selects
1012:      * @return Zend_Db_Select
1013:      */
1014:     protected function _prepareLoadSelect(array $selects)
1015:     {
1016:         return $this->_getReadAdapter()->select()->union($selects, Zend_Db_Select::SQL_UNION_ALL);
1017:     }
1018: 
1019:     /**
1020:      * Retrieve select object for loading base entity row
1021:      *
1022:      * @param   Varien_Object $object
1023:      * @param   mixed $rowId
1024:      * @return  Zend_Db_Select
1025:      */
1026:     protected function _getLoadRowSelect($object, $rowId)
1027:     {
1028:         $select = $this->_getReadAdapter()->select()
1029:             ->from($this->getEntityTable())
1030:             ->where($this->getEntityIdField() . ' =?', $rowId);
1031: 
1032:         return $select;
1033:     }
1034: 
1035:     /**
1036:      * Retrieve select object for loading entity attributes values
1037:      *
1038:      * @param   Varien_Object $object
1039:      * @param   mixed $rowId
1040:      * @return  Zend_Db_Select
1041:      */
1042:     protected function _getLoadAttributesSelect($object, $table)
1043:     {
1044:         $select = $this->_getReadAdapter()->select()
1045:             ->from($table, array())
1046:             ->where($this->getEntityIdField() . ' =?', $object->getId());
1047: 
1048:         return $select;
1049:     }
1050: 
1051:     /**
1052:      * Adds Columns prepared for union
1053:      *
1054:      * @param Varien_Db_Select $select
1055:      * @param string $table
1056:      * @param string $type
1057:      * @return Varien_Db_Select
1058:      */
1059:     protected function _addLoadAttributesSelectFields($select, $table, $type)
1060:     {
1061:         $select->columns(
1062:             Mage::getResourceHelper('eav')->attributeSelectFields($table, $type)
1063:         );
1064:         return $select;
1065:     }
1066: 
1067:     /**
1068:      * Initialize attribute value for object
1069:      *
1070:      * @deprecated after 1.5.1.0 - mistake in method name
1071:      *
1072:      * @param   Varien_Object $object
1073:      * @param   array $valueRow
1074:      * @return  Mage_Eav_Model_Entity_Abstract
1075:      */
1076:     protected function _setAttribteValue($object, $valueRow)
1077:     {
1078:         return _setAttributeValue($object, $valueRow);
1079:     }
1080: 
1081:     /**
1082:      * Initialize attribute value for object
1083:      *
1084:      * @param   Varien_Object $object
1085:      * @param   array $valueRow
1086:      * @return  Mage_Eav_Model_Entity_Abstract
1087:      */
1088:     protected function _setAttributeValue($object, $valueRow)
1089:     {
1090:         $attribute = $this->getAttribute($valueRow['attribute_id']);
1091:         if ($attribute) {
1092:             $attributeCode = $attribute->getAttributeCode();
1093:             $object->setData($attributeCode, $valueRow['value']);
1094:             $attribute->getBackend()->setEntityValueId($object, $valueRow['value_id']);
1095:         }
1096: 
1097:         return $this;
1098:     }
1099: 
1100:     /**
1101:      * Save entity's attributes into the object's resource
1102:      *
1103:      * @param   Varien_Object $object
1104:      * @return  Mage_Eav_Model_Entity_Abstract
1105:      */
1106:     public function save(Varien_Object $object)
1107:     {
1108:         if ($object->isDeleted()) {
1109:             return $this->delete($object);
1110:         }
1111: 
1112:         if (!$this->isPartialSave()) {
1113:             $this->loadAllAttributes($object);
1114:         }
1115: 
1116:         if (!$object->getEntityTypeId()) {
1117:             $object->setEntityTypeId($this->getTypeId());
1118:         }
1119: 
1120:         $object->setParentId((int) $object->getParentId());
1121: 
1122:         $this->_beforeSave($object);
1123:         $this->_processSaveData($this->_collectSaveData($object));
1124:         $this->_afterSave($object);
1125: 
1126:         return $this;
1127:     }
1128: 
1129:     /**
1130:      * Retrieve Object instance with original data
1131:      *
1132:      * @param Varien_Object $object
1133:      * @return Varien_Object
1134:      */
1135:     protected function _getOrigObject($object)
1136:     {
1137:         $className  = get_class($object);
1138:         $origObject = new $className();
1139:         $origObject->setData(array());
1140:         $this->load($origObject, $object->getData($this->getEntityIdField()));
1141: 
1142:         return $origObject;
1143:     }
1144: 
1145:     /**
1146:      * Prepare entity object data for save
1147:      *
1148:      * result array structure:
1149:      * array (
1150:      *  'newObject', 'entityRow', 'insert', 'update', 'delete'
1151:      * )
1152:      *
1153:      * @param   Varien_Object $newObject
1154:      * @return  array
1155:      */
1156:     protected function _collectSaveData($newObject)
1157:     {
1158:         $newData   = $newObject->getData();
1159:         $entityId  = $newObject->getData($this->getEntityIdField());
1160: 
1161:         // define result data
1162:         $entityRow  = array();
1163:         $insert     = array();
1164:         $update     = array();
1165:         $delete     = array();
1166: 
1167:         if (!empty($entityId)) {
1168:             $origData = $newObject->getOrigData();
1169:             /**
1170:              * get current data in db for this entity if original data is empty
1171:              */
1172:             if (empty($origData)) {
1173:                 $origData = $this->_getOrigObject($newObject)->getOrigData();
1174:             }
1175: 
1176:             /**
1177:              * drop attributes that are unknown in new data
1178:              * not needed after introduction of partial entity loading
1179:              */
1180:             foreach ($origData as $k => $v) {
1181:                 if (!array_key_exists($k, $newData)) {
1182:                     unset($origData[$k]);
1183:                 }
1184:             }
1185:         } else {
1186:             $origData = array();
1187:         }
1188: 
1189:         $staticFields   = $this->_getWriteAdapter()->describeTable($this->getEntityTable());
1190:         $staticFields   = array_keys($staticFields);
1191:         $attributeCodes = array_keys($this->_attributesByCode);
1192: 
1193:         foreach ($newData as $k => $v) {
1194:             /**
1195:              * Check attribute information
1196:              */
1197:             if (is_numeric($k) || is_array($v)) {
1198:                 continue;
1199:             }
1200:             /**
1201:              * Check if data key is presented in static fields or attribute codes
1202:              */
1203:             if (!in_array($k, $staticFields) && !in_array($k, $attributeCodes)) {
1204:                 continue;
1205:             }
1206: 
1207:             $attribute = $this->getAttribute($k);
1208:             if (empty($attribute)) {
1209:                 continue;
1210:             }
1211: 
1212:             $attrId = $attribute->getAttributeId();
1213: 
1214:             /**
1215:              * if attribute is static add to entity row and continue
1216:              */
1217:             if ($this->isAttributeStatic($k)) {
1218:                 $entityRow[$k] = $this->_prepareStaticValue($k, $v);
1219:                 continue;
1220:             }
1221: 
1222:             /**
1223:              * Check comparability for attribute value
1224:              */
1225:             if ($this->_canUpdateAttribute($attribute, $v, $origData)) {
1226:                 if ($this->_isAttributeValueEmpty($attribute, $v)) {
1227:                     $delete[$attribute->getBackend()->getTable()][] = array(
1228:                         'attribute_id'  => $attrId,
1229:                         'value_id'      => $attribute->getBackend()->getEntityValueId($newObject)
1230:                     );
1231:                 } elseif ($v !== $origData[$k]) {
1232:                     $update[$attrId] = array(
1233:                         'value_id' => $attribute->getBackend()->getEntityValueId($newObject),
1234:                         'value'    => $v,
1235:                     );
1236:                 }
1237:             } else if (!$this->_isAttributeValueEmpty($attribute, $v)) {
1238:                 $insert[$attrId] = $v;
1239:             }
1240:         }
1241: 
1242:         $result = compact('newObject', 'entityRow', 'insert', 'update', 'delete');
1243:         return $result;
1244:     }
1245: 
1246:     /**
1247:      * Return if attribute exists in original data array.
1248:      *
1249:      * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute
1250:      * @param mixed $value New value of the attribute. Can be used in subclasses.
1251:      * @param array $origData
1252:      * @return bool
1253:      */
1254:     protected function _canUpdateAttribute(Mage_Eav_Model_Entity_Attribute_Abstract $attribute, $v, array &$origData)
1255:     {
1256:         return array_key_exists($attribute->getAttributeCode(), $origData);
1257:     }
1258: 
1259:     /**
1260:      * Retrieve static field properties
1261:      *
1262:      * @param string $field
1263:      * @return array
1264:      */
1265:     protected function _getStaticFieldProperties($field)
1266:     {
1267:         if (empty($this->_describeTable[$this->getEntityTable()])) {
1268:             $this->_describeTable[$this->getEntityTable()] = $this->_getWriteAdapter()
1269:                 ->describeTable($this->getEntityTable());
1270:         }
1271: 
1272:         if (isset($this->_describeTable[$this->getEntityTable()][$field])) {
1273:             return $this->_describeTable[$this->getEntityTable()][$field];
1274:         }
1275: 
1276:         return false;
1277:     }
1278: 
1279:     /**
1280:      * Prepare static value for save
1281:      *
1282:      * @param string $key
1283:      * @param mixed $value
1284:      * @return mixed
1285:      */
1286:     protected function _prepareStaticValue($key, $value)
1287:     {
1288:         $fieldProp = $this->_getStaticFieldProperties($key);
1289: 
1290:         if (!$fieldProp) {
1291:             return $value;
1292:         }
1293: 
1294:         if ($fieldProp['DATA_TYPE'] == 'decimal') {
1295:             $value = Mage::app()->getLocale()->getNumber($value);
1296:         }
1297: 
1298:         return $value;
1299:     }
1300: 
1301:     /**
1302:      * Save object collected data
1303:      *
1304:      * @param   array $saveData array('newObject', 'entityRow', 'insert', 'update', 'delete')
1305:      * @return  Mage_Eav_Model_Entity_Abstract
1306:      */
1307:     protected function _processSaveData($saveData)
1308:     {
1309:         extract($saveData);
1310:         /**
1311:          * Import variables into the current symbol table from save data array
1312:          *
1313:          * @see Mage_Eav_Model_Entity_Attribute_Abstract::_collectSaveData()
1314:          *
1315:          * @var array $entityRow
1316:          * @var Mage_Core_Model_Abstract $newObject
1317:          * @var array $insert
1318:          * @var array $update
1319:          * @var array $delete
1320:          */
1321:         $adapter        = $this->_getWriteAdapter();
1322:         $insertEntity   = true;
1323:         $entityTable    = $this->getEntityTable();
1324:         $entityIdField  = $this->getEntityIdField();
1325:         $entityId       = $newObject->getId();
1326: 
1327:         unset($entityRow[$entityIdField]);
1328:         if (!empty($entityId) && is_numeric($entityId)) {
1329:             $bind   = array('entity_id' => $entityId);
1330:             $select = $adapter->select()
1331:                 ->from($entityTable, $entityIdField)
1332:                 ->where("{$entityIdField} = :entity_id");
1333:             $result = $adapter->fetchOne($select, $bind);
1334:             if ($result) {
1335:                 $insertEntity = false;
1336:             }
1337:         } else {
1338:             $entityId = null;
1339:         }
1340: 
1341:         /**
1342:          * Process base row
1343:          */
1344:         $entityObject = new Varien_Object($entityRow);
1345:         $entityRow    = $this->_prepareDataForTable($entityObject, $entityTable);
1346:         if ($insertEntity) {
1347:             if (!empty($entityId)) {
1348:                 $entityRow[$entityIdField] = $entityId;
1349:                 $adapter->insertForce($entityTable, $entityRow);
1350:             } else {
1351:                 $adapter->insert($entityTable, $entityRow);
1352:                 $entityId = $adapter->lastInsertId($entityTable);
1353:             }
1354:             $newObject->setId($entityId);
1355:         } else {
1356:             $where = sprintf('%s=%d', $adapter->quoteIdentifier($entityIdField), $entityId);
1357:             $adapter->update($entityTable, $entityRow, $where);
1358:         }
1359: 
1360:         /**
1361:          * insert attribute values
1362:          */
1363:         if (!empty($insert)) {
1364:             foreach ($insert as $attributeId => $value) {
1365:                 $attribute = $this->getAttribute($attributeId);
1366:                 $this->_insertAttribute($newObject, $attribute, $value);
1367:             }
1368:         }
1369: 
1370:         /**
1371:          * update attribute values
1372:          */
1373:         if (!empty($update)) {
1374:             foreach ($update as $attributeId => $v) {
1375:                 $attribute = $this->getAttribute($attributeId);
1376:                 $this->_updateAttribute($newObject, $attribute, $v['value_id'], $v['value']);
1377:             }
1378:         }
1379: 
1380:         /**
1381:          * delete empty attribute values
1382:          */
1383:         if (!empty($delete)) {
1384:             foreach ($delete as $table => $values) {
1385:                 $this->_deleteAttributes($newObject, $table, $values);
1386:             }
1387:         }
1388: 
1389:         $this->_processAttributeValues();
1390: 
1391:         $newObject->isObjectNew(false);
1392: 
1393:         return $this;
1394:     }
1395: 
1396:     /**
1397:      * Insert entity attribute value
1398:      *
1399:      * @param   Varien_Object $object
1400:      * @param   Mage_Eav_Model_Entity_Attribute_Abstract $attribute
1401:      * @param   mixed $value
1402:      * @return  Mage_Eav_Model_Entity_Abstract
1403:      */
1404:     protected function _insertAttribute($object, $attribute, $value)
1405:     {
1406:         return $this->_saveAttribute($object, $attribute, $value);
1407:     }
1408: 
1409:     /**
1410:      * Update entity attribute value
1411:      *
1412:      * @param   Varien_Object $object
1413:      * @param   Mage_Eav_Model_Entity_Attribute_Abstract $attribute
1414:      * @param   mixed $valueId
1415:      * @param   mixed $value
1416:      * @return  Mage_Eav_Model_Entity_Abstract
1417:      */
1418:     protected function _updateAttribute($object, $attribute, $valueId, $value)
1419:     {
1420:         return $this->_saveAttribute($object, $attribute, $value);
1421:     }
1422: 
1423:     /**
1424:      * Save entity attribute value
1425:      *
1426:      * Collect for mass save
1427:      *
1428:      * @param Mage_Core_Model_Abstract $object
1429:      * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute
1430:      * @param mixed $value
1431:      * @return Mage_Eav_Model_Entity_Abstract
1432:      */
1433:     protected function _saveAttribute($object, $attribute, $value)
1434:     {
1435:         $table = $attribute->getBackend()->getTable();
1436:         if (!isset($this->_attributeValuesToSave[$table])) {
1437:             $this->_attributeValuesToSave[$table] = array();
1438:         }
1439: 
1440:         $entityIdField = $attribute->getBackend()->getEntityIdField();
1441: 
1442:         $data   = array(
1443:             'entity_type_id'    => $object->getEntityTypeId(),
1444:             $entityIdField      => $object->getId(),
1445:             'attribute_id'      => $attribute->getId(),
1446:             'value'             => $this->_prepareValueForSave($value, $attribute)
1447:         );
1448: 
1449:         $this->_attributeValuesToSave[$table][] = $data;
1450: 
1451:         return $this;
1452:     }
1453: 
1454:     /**
1455:      * Save and detele collected attribute values
1456:      *
1457:      * @return Mage_Eav_Model_Entity_Abstract
1458:      */
1459:     protected function _processAttributeValues()
1460:     {
1461:         $adapter = $this->_getWriteAdapter();
1462:         foreach ($this->_attributeValuesToSave as $table => $data) {
1463:             $adapter->insertOnDuplicate($table, $data, array('value'));
1464:         }
1465: 
1466:         foreach ($this->_attributeValuesToDelete as $table => $valueIds) {
1467:             $adapter->delete($table, array('value_id IN (?)' => $valueIds));
1468:         }
1469: 
1470:         // reset data arrays
1471:         $this->_attributeValuesToSave   = array();
1472:         $this->_attributeValuesToDelete = array();
1473: 
1474:         return $this;
1475:     }
1476: 
1477:     /**
1478:      * Prepare value for save
1479:      *
1480:      * @param mixed $value
1481:      * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute
1482:      * @return mixed
1483:      */
1484:     protected function _prepareValueForSave($value, Mage_Eav_Model_Entity_Attribute_Abstract $attribute)
1485:     {
1486:         if ($attribute->getBackendType() == 'decimal') {
1487:             return Mage::app()->getLocale()->getNumber($value);
1488:         }
1489: 
1490:         $backendTable = $attribute->getBackendTable();
1491:         if (!isset(self::$_attributeBackendTables[$backendTable])) {
1492:             self::$_attributeBackendTables[$backendTable] = $this->_getReadAdapter()->describeTable($backendTable);
1493:         }
1494:         $describe = self::$_attributeBackendTables[$backendTable];
1495:         return $this->_getReadAdapter()->prepareColumnValue($describe['value'], $value);
1496:     }
1497: 
1498:     /**
1499:      * Delete entity attribute values
1500:      *
1501:      * @param   Varien_Object $object
1502:      * @param   string $table
1503:      * @param   array $info
1504:      * @return  Varien_Object
1505:      */
1506:     protected function _deleteAttributes($object, $table, $info)
1507:     {
1508:         $valueIds = array();
1509:         foreach ($info as $itemData) {
1510:             $valueIds[] = $itemData['value_id'];
1511:         }
1512: 
1513:         if (empty($valueIds)) {
1514:             return $this;
1515:         }
1516: 
1517:         if (isset($this->_attributeValuesToDelete[$table])) {
1518:             $this->_attributeValuesToDelete[$table] = array_merge($this->_attributeValuesToDelete[$table], $valueIds);
1519:         } else {
1520:             $this->_attributeValuesToDelete[$table] = $valueIds;
1521:         }
1522: 
1523:         return $this;
1524:     }
1525: 
1526:     /**
1527:      * Save attribute
1528:      *
1529:      * @param Varien_Object $object
1530:      * @param string $attributeCode
1531:      * @return Mage_Eav_Model_Entity_Abstract
1532:      */
1533:     public function saveAttribute(Varien_Object $object, $attributeCode)
1534:     {
1535:         $attribute      = $this->getAttribute($attributeCode);
1536:         $backend        = $attribute->getBackend();
1537:         $table          = $backend->getTable();
1538:         $entity         = $attribute->getEntity();
1539:         $entityIdField  = $entity->getEntityIdField();
1540:         $adapter        = $this->_getWriteAdapter();
1541: 
1542:         $row = array(
1543:             'entity_type_id' => $entity->getTypeId(),
1544:             'attribute_id'   => $attribute->getId(),
1545:             $entityIdField   => $object->getData($entityIdField),
1546:         );
1547: 
1548:         $newValue = $object->getData($attributeCode);
1549:         if ($attribute->isValueEmpty($newValue)) {
1550:             $newValue = null;
1551:         }
1552: 
1553:         $whereArr = array();
1554:         foreach ($row as $field => $value) {
1555:             $whereArr[] = $adapter->quoteInto($field . '=?', $value);
1556:         }
1557:         $where = implode(' AND ', $whereArr);
1558: 
1559:         $adapter->beginTransaction();
1560: 
1561:         try {
1562:             $select = $adapter->select()
1563:                 ->from($table, 'value_id')
1564:                 ->where($where);
1565:             $origValueId = $adapter->fetchOne($select);
1566: 
1567:             if ($origValueId === false && ($newValue !== null)) {
1568:                 $this->_insertAttribute($object, $attribute, $newValue);
1569:             } elseif ($origValueId !== false && ($newValue !== null)) {
1570:                 $this->_updateAttribute($object, $attribute, $origValueId, $newValue);
1571:             } elseif ($origValueId !== false && ($newValue === null)) {
1572:                 $adapter->delete($table, $where);
1573:             }
1574:             $this->_processAttributeValues();
1575:             $adapter->commit();
1576:         } catch (Exception $e) {
1577:             $adapter->rollback();
1578:             throw $e;
1579:         }
1580: 
1581:         return $this;
1582:     }
1583: 
1584:     /**
1585:      * Delete entity using current object's data
1586:      *
1587:      * @return Mage_Eav_Model_Entity_Abstract
1588:      */
1589:     public function delete($object)
1590:     {
1591:         if (is_numeric($object)) {
1592:             $id = (int)$object;
1593:         } elseif ($object instanceof Varien_Object) {
1594:             $id = (int)$object->getId();
1595:         }
1596: 
1597:         $this->_beforeDelete($object);
1598: 
1599:         try {
1600:             $where = array(
1601:                 $this->getEntityIdField() . '=?' => $id
1602:             );
1603:             $this->_getWriteAdapter()->delete($this->getEntityTable(), $where);
1604:             $this->loadAllAttributes($object);
1605:             foreach ($this->getAttributesByTable() as $table => $attributes) {
1606:                 $this->_getWriteAdapter()->delete($table, $where);
1607:             }
1608:         } catch (Exception $e) {
1609:             throw $e;
1610:         }
1611: 
1612:         $this->_afterDelete($object);
1613:         return $this;
1614:     }
1615: 
1616:     /**
1617:      * After Load Entity process
1618:      *
1619:      * @param Varien_Object $object
1620:      * @return Mage_Eav_Model_Entity_Abstract
1621:      */
1622:     protected function _afterLoad(Varien_Object $object)
1623:     {
1624:         $this->walkAttributes('backend/afterLoad', array($object));
1625:         return $this;
1626:     }
1627: 
1628:     /**
1629:      * Before delete Entity process
1630:      *
1631:      * @param Varien_Object $object
1632:      * @return Mage_Eav_Model_Entity_Abstract
1633:      */
1634:     protected function _beforeSave(Varien_Object $object)
1635:     {
1636:         $this->walkAttributes('backend/beforeSave', array($object));
1637:         return $this;
1638:     }
1639: 
1640:     /**
1641:      * After Save Entity process
1642:      *
1643:      * @param Varien_Object $object
1644:      * @return Mage_Eav_Model_Entity_Abstract
1645:      */
1646:     protected function _afterSave(Varien_Object $object)
1647:     {
1648:         $this->walkAttributes('backend/afterSave', array($object));
1649:         return $this;
1650:     }
1651: 
1652:     /**
1653:      * Before Delete Entity process
1654:      *
1655:      * @param Varien_Object $object
1656:      * @return Mage_Eav_Model_Entity_Abstract
1657:      */
1658:     protected function _beforeDelete(Varien_Object $object)
1659:     {
1660:         $this->walkAttributes('backend/beforeDelete', array($object));
1661:         return $this;
1662:     }
1663: 
1664:     /**
1665:      * After delete entity process
1666:      *
1667:      * @param Varien_Object $object
1668:      * @return Mage_Eav_Model_Entity_Abstract
1669:      */
1670:     protected function _afterDelete(Varien_Object $object)
1671:     {
1672:         $this->walkAttributes('backend/afterDelete', array($object));
1673:         return $this;
1674:     }
1675: 
1676:     /**
1677:      * Retrieve Default attribute model
1678:      *
1679:      * @return string
1680:      */
1681:     protected function _getDefaultAttributeModel()
1682:     {
1683:         return Mage_Eav_Model_Entity::DEFAULT_ATTRIBUTE_MODEL;
1684:     }
1685: 
1686:     /**
1687:      * Retrieve default entity attributes
1688:      *
1689:      * @return array
1690:      */
1691:     protected function _getDefaultAttributes()
1692:     {
1693:         return array('entity_type_id', 'attribute_set_id', 'created_at', 'updated_at', 'parent_id', 'increment_id');
1694:     }
1695: 
1696:     /**
1697:      * Retrieve default entity static attributes
1698:      *
1699:      * @return array
1700:      */
1701:     public function getDefaultAttributes() {
1702:         return array_unique(array_merge($this->_getDefaultAttributes(), array($this->getEntityIdField())));
1703:     }
1704: 
1705:     /**
1706:      * After set config process
1707:      *
1708:      * @deprecated
1709:      * @return Mage_Eav_Model_Entity_Abstract
1710:      */
1711:     protected function _afterSetConfig()
1712:     {
1713:         return $this;
1714:     }
1715: 
1716:     /**
1717:      * Check is attribute value empty
1718:      *
1719:      * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute
1720:      * @param mixed $value
1721:      * @return bool
1722:      */
1723:     protected function _isAttributeValueEmpty(Mage_Eav_Model_Entity_Attribute_Abstract $attribute, $value)
1724:     {
1725:         return $attribute->isValueEmpty($value);
1726:     }
1727: }
1728: 
Magento 1.7.0.2 API documentation generated by ApiGen 2.8.0