PageRenderTime 61ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/app/code/core/Mage/Eav/Model/Entity/Setup.php

https://bitbucket.org/andrewjleavitt/magestudy
PHP | 1206 lines | 749 code | 100 blank | 357 comment | 95 complexity | 5d4382045ff909895e627337adfadc88 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  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) 2010 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. * EAV Entity Setup Model
  28. *
  29. * @category Mage
  30. * @package Mage_Eav
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Eav_Model_Entity_Setup extends Mage_Core_Model_Resource_Setup
  34. {
  35. protected $_attributeTableFields;
  36. protected $_generalGroupName = 'General';
  37. public $defaultGroupIdAssociations = array('General'=>1);
  38. /**
  39. * Clean cache
  40. *
  41. * @return Mage_Eav_Model_Entity_Setup
  42. */
  43. public function cleanCache()
  44. {
  45. Mage::app()->cleanCache(array('eav'));
  46. return $this;
  47. }
  48. /**
  49. * Install Default Group Ids
  50. *
  51. * @return Mage_Eav_Model_Entity_Setup
  52. */
  53. public function installDefaultGroupIds()
  54. {
  55. $setIds = $this->getAllAttributeSetIds();
  56. foreach ($this->defaultGroupIdAssociations as $defaultGroupName=>$defaultGroupId) {
  57. foreach ($setIds as $set) {
  58. $groupId = $this->getTableRow('eav/attribute_group',
  59. 'attribute_group_name', $defaultGroupName, 'attribute_group_id', 'attribute_set_id', $set
  60. );
  61. if (!$groupId) {
  62. $groupId = $this->getTableRow('eav/attribute_group',
  63. 'attribute_set_id', $set, 'attribute_group_id'
  64. );
  65. }
  66. $this->updateTableRow('eav/attribute_group',
  67. 'attribute_group_id', $groupId,
  68. 'default_id', $defaultGroupId
  69. );
  70. }
  71. }
  72. return $this;
  73. }
  74. /******************* ENTITY TYPES *****************/
  75. /**
  76. * Add an entity type
  77. *
  78. * If already exists updates the entity type with params data
  79. *
  80. * @param string $code
  81. * @param array $params
  82. * @return Mage_Eav_Model_Entity_Setup
  83. */
  84. public function addEntityType($code, array $params)
  85. {
  86. $data = array(
  87. 'entity_type_code' => $code,
  88. 'entity_model' => $params['entity_model'],
  89. 'attribute_model' => isset($params['attribute_model']) ? $params['attribute_model'] : '',
  90. 'entity_table' => isset($params['table']) ? $params['table'] : 'eav/entity',
  91. 'increment_model' => isset($params['increment_model']) ? $params['increment_model'] : '',
  92. 'increment_per_store' => isset($params['increment_per_store']) ? $params['increment_per_store'] : 0,
  93. 'additional_attribute_table' => isset($params['additional_attribute_table']) ? $params['additional_attribute_table'] : '',
  94. 'entity_attribute_collection'=> isset($params['entity_attribute_collection']) ? $params['entity_attribute_collection'] : '',
  95. );
  96. if ($this->getEntityType($code, 'entity_type_id')) {
  97. $this->updateEntityType($code, $data);
  98. } else {
  99. $this->_conn->insert($this->getTable('eav/entity_type'), $data);
  100. }
  101. $this->addAttributeSet($code, 'Default');
  102. $this->addAttributeGroup($code, 'Default', $this->_generalGroupName);
  103. return $this;
  104. }
  105. /**
  106. * Update entity row
  107. *
  108. * @param string $code
  109. * @param string $field
  110. * @param string $value
  111. * @return Mage_Eav_Model_Entity_Setup
  112. */
  113. public function updateEntityType($code, $field, $value=null)
  114. {
  115. $this->updateTableRow('eav/entity_type',
  116. 'entity_type_id', $this->getEntityTypeId($code),
  117. $field, $value
  118. );
  119. return $this;
  120. }
  121. /**
  122. * Retrieve Entity Type Data
  123. *
  124. * @param int|string $id
  125. * @param string $field
  126. * @return mixed
  127. */
  128. public function getEntityType($id, $field=null)
  129. {
  130. return $this->getTableRow('eav/entity_type',
  131. is_numeric($id) ? 'entity_type_id' : 'entity_type_code', $id,
  132. $field
  133. );
  134. }
  135. /**
  136. * Retrieve Entity Type Id By Id or Code
  137. *
  138. * @param mixed $entityTypeId
  139. * @return int
  140. */
  141. public function getEntityTypeId($entityTypeId)
  142. {
  143. if (!is_numeric($entityTypeId)) {
  144. $entityTypeId = $this->getEntityType($entityTypeId, 'entity_type_id');
  145. }
  146. if (!is_numeric($entityTypeId)) {
  147. throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Wrong entity ID.'));
  148. }
  149. return $entityTypeId;
  150. }
  151. /**
  152. * Remove entity type by Id or Code
  153. *
  154. * @param mixed $id
  155. * @return Mage_Eav_Model_Entity_Setup
  156. */
  157. public function removeEntityType($id)
  158. {
  159. if (is_numeric($id)) {
  160. $this->deleteTableRow('eav/entity_type', 'entity_type_id', $id);
  161. }
  162. else {
  163. $this->deleteTableRow('eav/entity_type', 'entity_type_code', (string)$id);
  164. }
  165. return $this;
  166. }
  167. /******************* ATTRIBUTE SETS *****************/
  168. /**
  169. * Retrieve Attribute Set Sort order
  170. *
  171. * @param mixed $entityTypeId
  172. * @param int $sortOrder
  173. * @return int
  174. */
  175. public function getAttributeSetSortOrder($entityTypeId, $sortOrder=null)
  176. {
  177. if (!is_numeric($sortOrder)) {
  178. $sortOrder = $this->_conn->fetchOne("select max(sort_order)
  179. from ".$this->getTable('eav/attribute_set')."
  180. where entity_type_id=".$this->getEntityTypeId($entityTypeId)
  181. );
  182. $sortOrder++;
  183. }
  184. return $sortOrder;
  185. }
  186. /**
  187. * Add Attribute Set
  188. *
  189. * @param mixed $entityTypeId
  190. * @param string $name
  191. * @param int $sortOrder
  192. * @return Mage_Eav_Model_Entity_Setup
  193. */
  194. public function addAttributeSet($entityTypeId, $name, $sortOrder=null)
  195. {
  196. $data = array(
  197. 'entity_type_id'=>$this->getEntityTypeId($entityTypeId),
  198. 'attribute_set_name'=>$name,
  199. 'sort_order'=>$this->getAttributeSetSortOrder($entityTypeId, $sortOrder),
  200. );
  201. if ($id = $this->getAttributeSet($entityTypeId, $name, 'attribute_set_id')) {
  202. $this->updateAttributeSet($entityTypeId, $id, $data);
  203. } else {
  204. $this->_conn->insert($this->getTable('eav/attribute_set'), $data);
  205. $this->addAttributeGroup($entityTypeId, $name, $this->_generalGroupName);
  206. }
  207. return $this;
  208. }
  209. /**
  210. * Update attribute set data
  211. *
  212. * @param mixed $entityTypeId
  213. * @param int $id
  214. * @param string $field
  215. * @param mixed $value
  216. * @return Mage_Eav_Model_Entity_Setup
  217. */
  218. public function updateAttributeSet($entityTypeId, $id, $field, $value=null)
  219. {
  220. $this->updateTableRow('eav/attribute_set',
  221. 'attribute_set_id', $this->getAttributeSetId($entityTypeId, $id),
  222. $field, $value,
  223. 'entity_type_id', $this->getEntityTypeId($entityTypeId)
  224. );
  225. return $this;
  226. }
  227. /**
  228. * Retrieve Attribute set data by id or name
  229. *
  230. * @param mixed $entityTypeId
  231. * @param mixed $id
  232. * @param string $field
  233. * @return mixed
  234. */
  235. public function getAttributeSet($entityTypeId, $id, $field=null)
  236. {
  237. return $this->getTableRow('eav/attribute_set',
  238. is_numeric($id) ? 'attribute_set_id' : 'attribute_set_name', $id,
  239. $field,
  240. 'entity_type_id', $this->getEntityTypeId($entityTypeId)
  241. );
  242. }
  243. /**
  244. * Retrieve Attribute Set Id By Id or Name
  245. *
  246. * @throws Mage_Eav_Exception
  247. * @param mixed $entityTypeId
  248. * @param mixed $setId
  249. * @return int
  250. */
  251. public function getAttributeSetId($entityTypeId, $setId)
  252. {
  253. if (!is_numeric($setId)) {
  254. $setId = $this->getAttributeSet($entityTypeId, $setId, 'attribute_set_id');
  255. }
  256. if (!is_numeric($setId)) {
  257. throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Wrong attribute set ID.'));
  258. }
  259. return $setId;
  260. }
  261. /**
  262. * Remove Attribute Set
  263. *
  264. * @param mixed $entityTypeId
  265. * @param mixed $id
  266. * @return Mage_Eav_Model_Entity_Setup
  267. */
  268. public function removeAttributeSet($entityTypeId, $id)
  269. {
  270. $this->deleteTableRow('eav/attribute_set', 'attribute_set_id', $this->getAttributeSetId($entityTypeId, $id));
  271. return $this;
  272. }
  273. /**
  274. * Set Default Attribute Set to Entity Type
  275. *
  276. * @param mixed $entityType
  277. * @return Mage_Eav_Model_Entity_Setup
  278. */
  279. public function setDefaultSetToEntityType($entityType, $attributeSet = 'Default')
  280. {
  281. $entityTypeId = $this->getEntityTypeId($entityType);
  282. $setId = $this->getAttributeSetId($entityTypeId, $attributeSet);
  283. $this->updateEntityType($entityTypeId, 'default_attribute_set_id', $setId);
  284. return $this;
  285. }
  286. /**
  287. * Get identifiers of all attribute sets
  288. *
  289. * @return array
  290. */
  291. public function getAllAttributeSetIds($entityTypeId=null)
  292. {
  293. $where = '';
  294. if (!is_null($entityTypeId)) {
  295. $where = " WHERE `entity_type_id` = '" . $this->getEntityTypeId($entityTypeId) . "'";
  296. }
  297. $sql = "SELECT `attribute_set_id` FROM `{$this->getTable('eav/attribute_set')}`" . $where;
  298. return $this->_conn->fetchCol($sql);
  299. }
  300. /**
  301. * Retrieve Default Attribute Set for Entity Type
  302. *
  303. * @param string|int $entityType
  304. * @return int
  305. */
  306. public function getDefaultAttributeSetId($entityType)
  307. {
  308. $select = $this->getConnection()->select()
  309. ->from($this->getTable('eav/entity_type'), 'default_attribute_set_id')
  310. ->where(is_numeric($entityType) ? 'entity_type_id=?' : 'entity_type_code=?', $entityType);
  311. return $this->getConnection()->fetchOne($select);
  312. }
  313. /******************* ATTRIBUTE GROUPS *****************/
  314. /**
  315. * Retrieve Attribute Group Sort order
  316. *
  317. * @param mixed $entityTypeId
  318. * @param mixed $setId
  319. * @param int $sortOrder
  320. * @return int
  321. */
  322. public function getAttributeGroupSortOrder($entityTypeId, $setId, $sortOrder=null)
  323. {
  324. if (!is_numeric($sortOrder)) {
  325. $sortOrder = $this->_conn->fetchOne("select max(sort_order)
  326. from ".$this->getTable('eav/attribute_group')."
  327. where attribute_set_id=".$this->getAttributeSetId($entityTypeId, $setId)
  328. );
  329. $sortOrder++;
  330. }
  331. return $sortOrder;
  332. }
  333. /**
  334. * Add Attribute Group
  335. *
  336. * @param mixed $entityTypeId
  337. * @param mixed $setId
  338. * @param string $name
  339. * @param int $sortOrder
  340. * @return Mage_Eav_Model_Entity_Setup
  341. */
  342. public function addAttributeGroup($entityTypeId, $setId, $name, $sortOrder=null)
  343. {
  344. $setId = $this->getAttributeSetId($entityTypeId, $setId);
  345. $data = array(
  346. 'attribute_set_id'=>$setId,
  347. 'attribute_group_name'=>$name,
  348. );
  349. if (isset($this->defaultGroupIdAssociations[$name])) {
  350. $data['default_id'] = $this->defaultGroupIdAssociations[$name];
  351. }
  352. if (!is_null($sortOrder)) {
  353. $data['sort_order'] = $sortOrder;
  354. }
  355. if ($id = $this->getAttributeGroup($entityTypeId, $setId, $name, 'attribute_group_id')) {
  356. $this->updateAttributeGroup($entityTypeId, $setId, $id, $data);
  357. } else {
  358. if (is_null($sortOrder)) {
  359. $data['sort_order'] = $this->getAttributeGroupSortOrder($entityTypeId, $setId, $sortOrder);
  360. }
  361. $this->_conn->insert($this->getTable('eav/attribute_group'), $data);
  362. }
  363. return $this;
  364. }
  365. /**
  366. * Update Attribute Group Data
  367. *
  368. * @param mixed $entityTypeId
  369. * @param mixed $setId
  370. * @param mixed $id
  371. * @param string $field
  372. * @param mixed $value
  373. * @return Mage_Eav_Model_Entity_Setup
  374. */
  375. public function updateAttributeGroup($entityTypeId, $setId, $id, $field, $value=null)
  376. {
  377. $this->updateTableRow('eav/attribute_group',
  378. 'attribute_group_id', $this->getAttributeGroupId($entityTypeId, $setId, $id),
  379. $field, $value,
  380. 'attribute_set_id', $this->getAttributeSetId($entityTypeId, $setId)
  381. );
  382. return $this;
  383. }
  384. /**
  385. * Retrieve Attribute Group Data
  386. *
  387. * @param mixed $entityTypeId
  388. * @param mixed $setId
  389. * @param mixed $id
  390. * @param string $field
  391. * @return mixed
  392. */
  393. public function getAttributeGroup($entityTypeId, $setId, $id, $field=null)
  394. {
  395. $searchId = $id;
  396. if (is_numeric($id)) {
  397. $searchField = 'attribute_group_id';
  398. } else {
  399. if (isset($this->defaultGroupIdAssociations[$id])) {
  400. $searchField = 'default_id';
  401. $searchId = $this->defaultGroupIdAssociations[$id];
  402. } else {
  403. $searchField = 'attribute_group_name';
  404. }
  405. }
  406. return $this->getTableRow('eav/attribute_group',
  407. $searchField, $searchId, $field,
  408. 'attribute_set_id', $this->getAttributeSetId($entityTypeId, $setId)
  409. );
  410. }
  411. /**
  412. * Retrieve Attribute Group Id by Id or Name
  413. *
  414. * @param mixed $entityTypeId
  415. * @param mixed $setId
  416. * @param mixed $groupId
  417. * @return Mage_Eav_Model_Entity_Setup
  418. */
  419. public function getAttributeGroupId($entityTypeId, $setId, $groupId)
  420. {
  421. if (!is_numeric($groupId)) {
  422. $groupId = $this->getAttributeGroup($entityTypeId, $setId, $groupId, 'attribute_group_id');
  423. }
  424. if (!is_numeric($groupId)) {
  425. $groupId = $this->getDefaultAttributeGroupId($entityTypeId, $setId);
  426. }
  427. if (!is_numeric($groupId)) {
  428. throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Wrong attribute group ID.'));
  429. }
  430. return $groupId;
  431. }
  432. /**
  433. * Remove Attribute Group By Id or Name
  434. *
  435. * @param mixed $entityTypeId
  436. * @param mixed $setId
  437. * @param mixed $id
  438. * @return Mage_Eav_Model_Entity_Setup
  439. */
  440. public function removeAttributeGroup($entityTypeId, $setId, $id)
  441. {
  442. $this->deleteTableRow(
  443. 'eav/attribute_group',
  444. 'attribute_group_id',
  445. $this->getAttributeGroupId($entityTypeId, $setId, $id)
  446. );
  447. return $this;
  448. }
  449. /**
  450. * Retrieve Default Attribute Group Id By Entity Type and Attribute Set
  451. *
  452. * @param string|int $entityType
  453. * @param int $attributeSetId
  454. * @return int
  455. */
  456. public function getDefaultAttributeGroupId($entityType, $attributeSetId = null)
  457. {
  458. $entityType = $this->getEntityTypeId($entityType);
  459. if (!is_numeric($attributeSetId)) {
  460. $attributeSetId = $this->getDefaultAttributeSetId($entityType);
  461. }
  462. $select = $this->getConnection()->select()
  463. ->from($this->getTable('eav/attribute_group'), 'attribute_group_id')
  464. ->where('attribute_set_id=?', $attributeSetId)
  465. ->order('default_id DESC, sort_order')
  466. ->limit(1);
  467. return $this->getConnection()->fetchOne($select);
  468. }
  469. /******************* ATTRIBUTES *****************/
  470. /**
  471. * Retrieve value from array by key or return default value
  472. *
  473. * @param array $array
  474. * @param string $key
  475. * @param string $default
  476. * @return string
  477. */
  478. protected function _getValue($array, $key, $default = null)
  479. {
  480. return isset($array[$key]) ? $array[$key] : $default;
  481. }
  482. /**
  483. * Prepare attribute values to save
  484. *
  485. * @param array $attr
  486. * @return array
  487. */
  488. protected function _prepareValues($attr)
  489. {
  490. $data = array();
  491. $data = array(
  492. 'backend_model' => $this->_getValue($attr, 'backend', ''),
  493. 'backend_type' => $this->_getValue($attr, 'type', 'varchar'),
  494. 'backend_table' => $this->_getValue($attr, 'table', ''),
  495. 'frontend_model' => $this->_getValue($attr, 'frontend', ''),
  496. 'frontend_input' => $this->_getValue($attr, 'input', 'text'),
  497. 'frontend_label' => $this->_getValue($attr, 'label', ''),
  498. 'frontend_class' => $this->_getValue($attr, 'frontend_class', ''),
  499. 'source_model' => $this->_getValue($attr, 'source', ''),
  500. 'is_required' => $this->_getValue($attr, 'required', 1),
  501. 'is_user_defined' => $this->_getValue($attr, 'user_defined', 0),
  502. 'default_value' => $this->_getValue($attr, 'default', ''),
  503. 'is_unique' => $this->_getValue($attr, 'unique', 0),
  504. 'note' => $this->_getValue($attr, 'note', ''),
  505. );
  506. return $data;
  507. }
  508. /**
  509. * Add attribute to an entity type
  510. *
  511. * If attribute is system will add to all existing attribute sets
  512. *
  513. * @param string|integer $entityTypeId
  514. * @param string $code
  515. * @param array $attr
  516. * @return Mage_Eav_Model_Entity_Setup
  517. */
  518. public function addAttribute($entityTypeId, $code, array $attr)
  519. {
  520. $entityTypeId = $this->getEntityTypeId($entityTypeId);
  521. $data = array_merge(
  522. array(
  523. 'entity_type_id' => $entityTypeId,
  524. 'attribute_code' => $code
  525. ),
  526. $this->_prepareValues($attr)
  527. );
  528. $sortOrder = isset($attr['sort_order']) ? $attr['sort_order'] : null;
  529. if ($id = $this->getAttribute($entityTypeId, $code, 'attribute_id')) {
  530. $this->updateAttribute($entityTypeId, $id, $data, null, $sortOrder);
  531. } else {
  532. $this->_insertAttribute($data);
  533. }
  534. if (!empty($attr['group'])) {
  535. $sets = $this->_conn->fetchAll('select * from '.$this->getTable('eav/attribute_set').' where entity_type_id=?', $entityTypeId);
  536. foreach ($sets as $set) {
  537. $this->addAttributeGroup($entityTypeId, $set['attribute_set_id'], $attr['group']);
  538. $this->addAttributeToSet($entityTypeId, $set['attribute_set_id'], $attr['group'], $code, $sortOrder);
  539. }
  540. }
  541. if (empty($attr['user_defined'])) {
  542. $sets = $this->_conn->fetchAll('select * from '.$this->getTable('eav/attribute_set').' where entity_type_id=?', $entityTypeId);
  543. foreach ($sets as $set) {
  544. $this->addAttributeToSet($entityTypeId, $set['attribute_set_id'], $this->_generalGroupName, $code, $sortOrder);
  545. }
  546. }
  547. if (isset($attr['option']) && is_array($attr['option'])) {
  548. $option = $attr['option'];
  549. $option['attribute_id'] = $this->getAttributeId($entityTypeId, $code);
  550. $this->addAttributeOption($option);
  551. }
  552. return $this;
  553. }
  554. /**
  555. * Add Attribure Option
  556. *
  557. * @param array $option
  558. */
  559. public function addAttributeOption($option)
  560. {
  561. if (isset($option['value'])) {
  562. $optionTable = $this->getTable('eav/attribute_option');
  563. $optionValueTable = $this->getTable('eav/attribute_option_value');
  564. foreach ($option['value'] as $optionId => $values) {
  565. $intOptionId = (int) $optionId;
  566. if (!empty($option['delete'][$optionId])) {
  567. if ($intOptionId) {
  568. $condition = $this->_conn->quoteInto('option_id=?', $intOptionId);
  569. $this->_conn->delete($optionTable, $condition);
  570. }
  571. continue;
  572. }
  573. if (!$intOptionId) {
  574. $data = array(
  575. 'attribute_id' => $option['attribute_id'],
  576. 'sort_order' => isset($option['order'][$optionId]) ? $option['order'][$optionId] : 0,
  577. );
  578. $this->_conn->insert($optionTable, $data);
  579. $intOptionId = $this->_conn->lastInsertId();
  580. } else {
  581. $data = array(
  582. 'sort_order' => isset($option['order'][$optionId]) ? $option['order'][$optionId] : 0,
  583. );
  584. $this->_conn->update($optionTable, $data, $this->_conn->quoteInto('option_id=?', $intOptionId));
  585. }
  586. // Default value
  587. if (!isset($values[0])) {
  588. Mage::throwException(Mage::helper('eav')->__('Default option value is not defined.'));
  589. }
  590. $this->_conn->delete($optionValueTable, $this->_conn->quoteInto('option_id=?', $intOptionId));
  591. foreach ($values as $storeId => $value) {
  592. $data = array(
  593. 'option_id' => $intOptionId,
  594. 'store_id' => $storeId,
  595. 'value' => $value,
  596. );
  597. $this->_conn->insert($optionValueTable, $data);
  598. }
  599. }
  600. }
  601. }
  602. /**
  603. * Update Attribute data and Attribute additional data
  604. *
  605. * @param mixed $entityTypeId
  606. * @param mixed $id
  607. * @param string $field
  608. * @param mixed $value
  609. * @param int $sortOrder
  610. * @return Mage_Eav_Model_Entity_Setup
  611. */
  612. public function updateAttribute($entityTypeId, $id, $field, $value=null, $sortOrder=null)
  613. {
  614. $this->_updateAttribute($entityTypeId, $id, $field, $value, $sortOrder);
  615. $this->_updateAttributeAdditionalData($entityTypeId, $id, $field, $value);
  616. return $this;
  617. }
  618. /**
  619. * Update Attribute data
  620. *
  621. * @param mixed $entityTypeId
  622. * @param mixed $id
  623. * @param string $field
  624. * @param mixed $value
  625. * @param int $sortOrder
  626. * @return Mage_Eav_Model_Entity_Setup
  627. */
  628. protected function _updateAttribute($entityTypeId, $id, $field, $value=null, $sortOrder=null)
  629. {
  630. if (!is_null($sortOrder)) {
  631. $this->updateTableRow('eav/entity_attribute',
  632. 'attribute_id', $this->getAttributeId($entityTypeId, $id),
  633. 'sort_order', $sortOrder
  634. );
  635. }
  636. $attributeFields = $this->_getAttributeTableFields();
  637. if (is_array($field)) {
  638. $bind = array();
  639. foreach ($field as $k => $v) {
  640. if (isset($attributeFields[$k])) {
  641. $bind[$k] = $v;
  642. }
  643. }
  644. if (!$bind) {
  645. return $this;
  646. }
  647. $field = $bind;
  648. }
  649. else {
  650. if (!isset($attributeFields[$field])) {
  651. return $this;
  652. }
  653. }
  654. $this->updateTableRow('eav/attribute',
  655. 'attribute_id', $this->getAttributeId($entityTypeId, $id),
  656. $field, $value,
  657. 'entity_type_id', $this->getEntityTypeId($entityTypeId)
  658. );
  659. return $this;
  660. }
  661. /**
  662. * Update Attribute Additional data
  663. *
  664. * @param mixed $entityTypeId
  665. * @param mixed $id
  666. * @param string $field
  667. * @param mixed $value
  668. * @return Mage_Eav_Model_Entity_Setup
  669. */
  670. protected function _updateAttributeAdditionalData($entityTypeId, $id, $field, $value=null)
  671. {
  672. $additionalTable = $this->getEntityType($entityTypeId, 'additional_attribute_table');
  673. if (!$additionalTable) {
  674. return $this;
  675. }
  676. $additionalTableExists = $this->getConnection()->showTableStatus($this->getTable($additionalTable));
  677. if ($additionalTable && $additionalTableExists) {
  678. $attributeFields = $this->getConnection()->describeTable($this->getTable($additionalTable));
  679. if (is_array($field)) {
  680. $bind = array();
  681. foreach ($field as $k => $v) {
  682. if (isset($attributeFields[$k])) {
  683. $bind[$k] = $v;
  684. }
  685. }
  686. if (!$bind) {
  687. return $this;
  688. }
  689. $field = $bind;
  690. }
  691. else {
  692. if (!isset($attributeFields[$field])) {
  693. return $this;
  694. }
  695. }
  696. $this->updateTableRow($this->getTable($additionalTable),
  697. 'attribute_id', $this->getAttributeId($entityTypeId, $id),
  698. $field, $value
  699. );
  700. }
  701. return $this;
  702. }
  703. /**
  704. * Retrieve Attribute Data By Id or Code
  705. *
  706. * @param mixed $entityTypeId
  707. * @param mixed $id
  708. * @param string $field
  709. * @return mixed
  710. */
  711. public function getAttribute($entityTypeId, $id, $field = null)
  712. {
  713. $additionalTable = $this->getEntityType($entityTypeId, 'additional_attribute_table');
  714. $entityTypeId = $this->getEntityTypeId($entityTypeId);
  715. $idField = (is_numeric($id) ? 'attribute_id' : 'attribute_code');
  716. if (!$additionalTable) {
  717. return $this->getTableRow('eav/attribute', $idField, $id, $field, 'entity_type_id', $entityTypeId);
  718. }
  719. $mainTable = $this->getTable('eav/attribute');
  720. if (empty($this->_setupCache[$mainTable][$entityTypeId][$id])) {
  721. $additionalTable = $this->getTable($additionalTable);
  722. $select = $this->_conn->select()
  723. ->from(array('main' => $mainTable))
  724. ->join(
  725. array('additional' => $additionalTable),
  726. 'main.attribute_id=additional.attribute_id')
  727. ->where("main.{$idField}=?", $id)
  728. ->where("main.entity_type_id=?", $entityTypeId);
  729. $row = $this->_conn->fetchRow($select);
  730. if (!$row) {
  731. $this->_setupCache[$mainTable][$entityTypeId][$id] = false;
  732. } else {
  733. $this->_setupCache[$mainTable][$entityTypeId][$row['attribute_id']] = $row;
  734. $this->_setupCache[$mainTable][$entityTypeId][$row['attribute_code']] = $row;
  735. }
  736. }
  737. $row = $this->_setupCache[$mainTable][$entityTypeId][$id];
  738. if (!is_null($field)) {
  739. return isset($row[$field]) ? $row[$field] : false;
  740. }
  741. return $row;
  742. }
  743. /**
  744. * Retrieve Attribute Id Data By Id or Code
  745. *
  746. * @param mixed $entityTypeId
  747. * @param mixed $id
  748. * @return int
  749. */
  750. public function getAttributeId($entityTypeId, $id)
  751. {
  752. if (!is_numeric($id)) {
  753. $id = $this->getAttribute($entityTypeId, $id, 'attribute_id');
  754. }
  755. if (!is_numeric($id)) {
  756. //throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Wrong attribute ID.'));
  757. return false;
  758. }
  759. return $id;
  760. }
  761. /**
  762. * Return table name for eav attribute
  763. *
  764. * @param int|string $entityTypeId Entity Type id or Entity Type code
  765. * @param int|string $id Attribute id or Attribute code
  766. * @return string
  767. */
  768. public function getAttributeTable($entityTypeId, $id)
  769. {
  770. $entityKeyName = is_numeric($entityTypeId) ? 'entity_type_id' : 'entity_type_code';
  771. $attributeKeyName = is_numeric($id) ? 'attribute_id' : 'attribute_code';
  772. $select = $this->getConnection()->select()
  773. ->from(
  774. array('e' => $this->getTable('eav/entity_type')),
  775. array('entity_table'))
  776. ->join(
  777. array('a' => $this->getTable('eav/attribute')),
  778. 'a.entity_type_id=e.entity_type_id',
  779. array('backend_type'))
  780. ->where("e.{$entityKeyName}=?", $entityTypeId)
  781. ->where("a.{$attributeKeyName}=?", $id)
  782. ->limit(1);
  783. if ($result = $this->getConnection()->fetchRow($select)) {
  784. $table = $this->getTable($result['entity_table']);
  785. if ($result['backend_type'] != 'static') {
  786. $table .= '_' . $result['backend_type'];
  787. }
  788. return $table;
  789. }
  790. return false;
  791. }
  792. /**
  793. * Remove Attribute
  794. *
  795. * @param mixed $entityTypeId
  796. * @param mixed $code
  797. * @return Mage_Eav_Model_Entity_Setup
  798. */
  799. public function removeAttribute($entityTypeId, $code)
  800. {
  801. $mainTable = $this->getTable('eav/attribute');
  802. $attribute = $this->getAttribute($entityTypeId, $code);
  803. if ($attribute) {
  804. $this->deleteTableRow('eav/attribute', 'attribute_id', $attribute['attribute_id']);
  805. if (isset($this->_setupCache[$mainTable][$attribute['entity_type_id']][$attribute['attribute_code']])) {
  806. unset($this->_setupCache[$mainTable][$attribute['entity_type_id']][$attribute['attribute_code']]);
  807. }
  808. }
  809. return $this;
  810. }
  811. /**
  812. * Retrieve Attribute Sort Order
  813. *
  814. * @param mixed $entityTypeId
  815. * @param mixed $setId
  816. * @param mixed $groupId
  817. * @param int $sortOrder
  818. * @return Mage_Eav_Model_Entity_Setup
  819. */
  820. public function getAttributeSortOrder($entityTypeId, $setId, $groupId, $sortOrder=null)
  821. {
  822. if (!is_numeric($sortOrder)) {
  823. $sortOrder = $this->_conn->fetchOne("select max(sort_order)
  824. from ".$this->getTable('eav/entity_attribute')."
  825. where attribute_group_id=".$this->getAttributeGroupId($entityTypeId, $setId, $groupId)
  826. );
  827. $sortOrder++;
  828. }
  829. return $sortOrder;
  830. }
  831. /**
  832. * Add Attribute to All Groups on Attribute Set
  833. *
  834. * @param mixed $entityTypeId
  835. * @param mixed $setId
  836. * @param mixed $groupId
  837. * @param mixed $attributeId
  838. * @param int $sortOrder
  839. * @return Mage_Eav_Model_Entity_Setup
  840. */
  841. public function addAttributeToSet($entityTypeId, $setId, $groupId, $attributeId, $sortOrder=null)
  842. {
  843. $entityTypeId = $this->getEntityTypeId($entityTypeId);
  844. $setId = $this->getAttributeSetId($entityTypeId, $setId);
  845. $groupId = $this->getAttributeGroupId($entityTypeId, $setId, $groupId);
  846. $attributeId = $this->getAttributeId($entityTypeId, $attributeId);
  847. $generalGroupId = $this->getAttributeGroupId($entityTypeId, $setId, $this->_generalGroupName);
  848. $oldId = $this->_conn->fetchOne("select entity_attribute_id from ".$this->getTable('eav/entity_attribute')." where attribute_set_id=$setId and attribute_id=$attributeId");
  849. if ($oldId) {
  850. if ($groupId && $groupId != $generalGroupId) {
  851. $newGroupData = array('attribute_group_id'=>$groupId);
  852. $condition = $this->_conn->quoteInto('entity_attribute_id = ?', $oldId);
  853. $this->_conn->update($this->getTable('eav/entity_attribute'), $newGroupData, $condition);
  854. }
  855. return $this;
  856. }
  857. $this->_conn->insert($this->getTable('eav/entity_attribute'), array(
  858. 'entity_type_id' =>$entityTypeId,
  859. 'attribute_set_id' =>$setId,
  860. 'attribute_group_id'=>$groupId,
  861. 'attribute_id' =>$attributeId,
  862. 'sort_order' =>$this->getAttributeSortOrder($entityTypeId, $setId, $groupId, $sortOrder),
  863. ));
  864. return $this;
  865. }
  866. /**
  867. * Add or update attribute to group
  868. *
  869. * @param int|string $entityType
  870. * @param int|string $setId
  871. * @param int|string $groupId
  872. * @param int|string $attributeId
  873. * @param int $sortOrder
  874. * @return Mage_Eav_Model_Entity_Setup
  875. */
  876. public function addAttributeToGroup($entityType, $setId, $groupId, $attributeId, $sortOrder = null)
  877. {
  878. $entityType = $this->getEntityTypeId($entityType);
  879. $setId = $this->getAttributeSetId($entityType, $setId);
  880. $groupId = $this->getAttributeGroupId($entityType, $setId, $groupId);
  881. $attributeId = $this->getAttributeId($entityType, $attributeId);
  882. $bind = array(
  883. 'entity_type_id' => $entityType,
  884. 'attribute_set_id' => $setId,
  885. 'attribute_group_id' => $groupId,
  886. 'attribute_id' => $attributeId,
  887. );
  888. $select = $this->getConnection()->select()
  889. ->from($this->getTable('eav/entity_attribute'))
  890. ->where('entity_type_id=?', $entityType)
  891. ->where('attribute_set_id=?', $setId)
  892. ->where('attribute_id=?', $attributeId);
  893. $row = $this->getConnection()->fetchRow($select);
  894. if ($row) {
  895. // update
  896. if (!is_null($sortOrder)) {
  897. $bind['sort_order'] = $sortOrder;
  898. }
  899. $this->getConnection()->update(
  900. $this->getTable('eav/entity_attribute'),
  901. $bind,
  902. $this->getConnection()->quoteInto('entity_attribute_id=?', $row['entity_attribute_id'])
  903. );
  904. }
  905. else {
  906. if (is_null($sortOrder)) {
  907. $select = $this->getConnection()->select()
  908. ->from($this->getTable('eav/entity_attribute'), 'MAX(sort_order) + 10')
  909. ->where('entity_type_id=?', $entityType)
  910. ->where('attribute_set_id=?', $setId)
  911. ->where('attribute_group_id=?', $groupId);
  912. $sortOrder = $this->getConnection()->fetchOne($select);
  913. }
  914. $sortOrder = is_numeric($sortOrder) ? $sortOrder : 1;
  915. $bind['sort_order'] = $sortOrder;
  916. $this->getConnection()->insert($this->getTable('eav/entity_attribute'), $bind);
  917. }
  918. return $this;
  919. }
  920. /******************* BULK INSTALL *****************/
  921. /**
  922. * Install entities
  923. *
  924. * @param array $entities
  925. * @return Mage_Eav_Model_Entity_Setup
  926. */
  927. public function installEntities($entities=null)
  928. {
  929. $this->cleanCache();
  930. if (is_null($entities)) {
  931. $entities = $this->getDefaultEntities();
  932. }
  933. foreach ($entities as $entityName=>$entity) {
  934. $this->addEntityType($entityName, $entity);
  935. $frontendPrefix = isset($entity['frontend_prefix']) ? $entity['frontend_prefix'] : '';
  936. $backendPrefix = isset($entity['backend_prefix']) ? $entity['backend_prefix'] : '';
  937. $sourcePrefix = isset($entity['source_prefix']) ? $entity['source_prefix'] : '';
  938. foreach ($entity['attributes'] as $attrCode=>$attr) {
  939. if (!empty($attr['backend'])) {
  940. if ('_'===$attr['backend']) {
  941. $attr['backend'] = $backendPrefix;
  942. } elseif ('_'===$attr['backend']{0}) {
  943. $attr['backend'] = $backendPrefix.$attr['backend'];
  944. } else {
  945. $attr['backend'] = $attr['backend'];
  946. }
  947. }
  948. if (!empty($attr['frontend'])) {
  949. if ('_'===$attr['frontend']) {
  950. $attr['frontend'] = $frontendPrefix;
  951. } elseif ('_'===$attr['frontend']{0}) {
  952. $attr['frontend'] = $frontendPrefix.$attr['frontend'];
  953. } else {
  954. $attr['frontend'] = $attr['frontend'];
  955. }
  956. }
  957. if (!empty($attr['source'])) {
  958. if ('_'===$attr['source']) {
  959. $attr['source'] = $sourcePrefix;
  960. } elseif ('_'===$attr['source']{0}) {
  961. $attr['source'] = $sourcePrefix.$attr['source'];
  962. } else {
  963. $attr['source'] = $attr['source'];
  964. }
  965. }
  966. $this->addAttribute($entityName, $attrCode, $attr);
  967. }
  968. $this->setDefaultSetToEntityType($entityName);
  969. }
  970. return $this;
  971. }
  972. /****************************** CREATE ENTITY TABLES ***********************************/
  973. /**
  974. * Enter description here...
  975. *
  976. * @param unknown_type $baseName
  977. * @param array $options
  978. * - no-main
  979. * - no-default-types
  980. * - types
  981. * @return unknown
  982. */
  983. public function createEntityTables($baseName, array $options=array())
  984. {
  985. $sql = '';
  986. if (empty($options['no-main'])) {
  987. $sql = "
  988. DROP TABLE IF EXISTS `{$baseName}`;
  989. CREATE TABLE `{$baseName}` (
  990. `entity_id` int(10) unsigned NOT NULL auto_increment,
  991. `entity_type_id` smallint(8) unsigned NOT NULL default '0',
  992. `attribute_set_id` smallint(5) unsigned NOT NULL default '0',
  993. `increment_id` varchar(50) NOT NULL default '',
  994. `parent_id` int(10) unsigned NULL default '0',
  995. `store_id` smallint(5) unsigned NOT NULL default '0',
  996. `created_at` datetime NOT NULL default '0000-00-00 00:00:00',
  997. `updated_at` datetime NOT NULL default '0000-00-00 00:00:00',
  998. `is_active` tinyint(1) unsigned NOT NULL default '1',
  999. PRIMARY KEY (`entity_id`),
  1000. CONSTRAINT `FK_{$baseName}_type` FOREIGN KEY (`entity_type_id`) REFERENCES `eav_entity_type` (`entity_type_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  1001. CONSTRAINT `FK_{$baseName}_store` FOREIGN KEY (`store_id`) REFERENCES `core_store` (`store_id`) ON DELETE CASCADE ON UPDATE CASCADE
  1002. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
  1003. }
  1004. $types = array(
  1005. 'datetime'=>'datetime',
  1006. 'decimal'=>'decimal(12,4)',
  1007. 'int'=>'int',
  1008. 'text'=>'text',
  1009. 'varchar'=>'varchar(255)',
  1010. );
  1011. if (!empty($options['types']) && is_array($options['types'])) {
  1012. if ($options['no-default-types']) {
  1013. $types = array();
  1014. }
  1015. $types = array_merge($types, $options['types']);
  1016. }
  1017. foreach ($types as $type=>$fieldType) {
  1018. $sql .= "
  1019. DROP TABLE IF EXISTS `{$baseName}_{$type}`;
  1020. CREATE TABLE `{$baseName}_{$type}` (
  1021. `value_id` int(11) NOT NULL auto_increment,
  1022. `entity_type_id` smallint(8) unsigned NOT NULL default '0',
  1023. `attribute_id` smallint(5) unsigned NOT NULL default '0',
  1024. `store_id` smallint(5) unsigned NOT NULL default '0',
  1025. `entity_id` int(10) unsigned NOT NULL default '0',
  1026. `value` {$fieldType} NOT NULL,
  1027. PRIMARY KEY (`value_id`),
  1028. UNIQUE KEY `IDX_BASE` (`entity_type_id`,`entity_id`,`attribute_id`,`store_id`),
  1029. ".($type!=='text' ? "
  1030. KEY `value_by_attribute` (`attribute_id`,`value`),
  1031. KEY `value_by_entity_type` (`entity_type_id`,`value`),
  1032. " : "")."
  1033. CONSTRAINT `FK_{$baseName}_{$type}` FOREIGN KEY (`entity_id`) REFERENCES `{$baseName}` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  1034. CONSTRAINT `FK_{$baseName}_{$type}_attribute` FOREIGN KEY (`attribute_id`) REFERENCES `eav_attribute` (`attribute_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  1035. CONSTRAINT `FK_{$baseName}_{$type}_entity_type` FOREIGN KEY (`entity_type_id`) REFERENCES `eav_entity_type` (`entity_type_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  1036. CONSTRAINT `FK_{$baseName}_{$type}_store` FOREIGN KEY (`store_id`) REFERENCES `core_store` (`store_id`) ON DELETE CASCADE ON UPDATE CASCADE
  1037. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
  1038. }
  1039. try {
  1040. $this->_conn->multi_query($sql);
  1041. } catch (Exception $e) {
  1042. throw $e;
  1043. }
  1044. return $this;
  1045. }
  1046. /**
  1047. * Retrieve attribute table fields
  1048. *
  1049. * @return array
  1050. */
  1051. protected function _getAttributeTableFields() {
  1052. return $this->getConnection()->describeTable($this->getTable('eav/attribute'));
  1053. }
  1054. /**
  1055. * Insert attribute and filter data
  1056. *
  1057. * @return Mage_Eav_Model_Entity_Setup
  1058. */
  1059. protected function _insertAttribute(array $data) {
  1060. $bind = array();
  1061. $fields = $this->_getAttributeTableFields();
  1062. foreach ($data as $k => $v) {
  1063. if (isset($fields[$k])) {
  1064. $bind[$k] = $v;
  1065. }
  1066. }
  1067. if (!$bind) {
  1068. return $this;
  1069. }
  1070. $this->getConnection()->insert($this->getTable('eav/attribute'), $bind);
  1071. $attributeId = $this->getConnection()->lastInsertId();
  1072. $this->_insertAttributeAdditionalData(
  1073. $data['entity_type_id'],
  1074. array_merge(array('attribute_id' => $attributeId), $data)
  1075. );
  1076. return $this;
  1077. }
  1078. /**
  1079. * Insert attribute additional data
  1080. *
  1081. * @param array $data
  1082. * @return Mage_Eav_Model_Entity_Setup
  1083. */
  1084. protected function _insertAttributeAdditionalData($entityTypeId, array $data)
  1085. {
  1086. $additionalTable = $this->getEntityType($entityTypeId, 'additional_attribute_table');
  1087. if (!$additionalTable) {
  1088. return $this;
  1089. }
  1090. $additionalTableExists = $this->getConnection()->showTableStatus($this->getTable($additionalTable));
  1091. if ($additionalTable && $additionalTableExists) {
  1092. $bind = array();
  1093. $fields = $this->getConnection()->describeTable($this->getTable($additionalTable));
  1094. foreach ($data as $k => $v) {
  1095. if (isset($fields[$k])) {
  1096. $bind[$k] = $v;
  1097. }
  1098. }
  1099. if (!$bind) {
  1100. return $this;
  1101. }
  1102. $this->getConnection()->insert($this->getTable($additionalTable), $bind);
  1103. }
  1104. return $this;
  1105. }
  1106. }