PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/app/code/core/Mage/ImportExport/Model/Export/Entity/Abstract.php

https://github.com/rgranadino/magento-mirror
PHP | 499 lines | 208 code | 55 blank | 236 comment | 39 complexity | 48b073e21d52ce75c2e8df27109aff4b MD5 | raw file
  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_ImportExport
  23. * @copyright Copyright (c) 2011 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. * Export entity abstract model
  28. *
  29. * @category Mage
  30. * @package Mage_ImportExport
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. abstract class Mage_ImportExport_Model_Export_Entity_Abstract
  34. {
  35. /**
  36. * Attribute code to its values. Only attributes with options and only default store values used.
  37. *
  38. * @var array
  39. */
  40. protected $_attributeValues = array();
  41. /**
  42. * Attribute code to its values. Only attributes with options and only default store values used.
  43. *
  44. * @var array
  45. */
  46. protected static $attrCodes = null;
  47. /**
  48. * DB connection.
  49. *
  50. * @var Varien_Db_Adapter_Pdo_Mysql
  51. */
  52. protected $_connection;
  53. /**
  54. * Array of attributes codes which are disabled for export.
  55. *
  56. * @var array
  57. */
  58. protected $_disabledAttrs = array();
  59. /**
  60. * Entity type id.
  61. *
  62. * @var int
  63. */
  64. protected $_entityTypeId;
  65. /**
  66. * Error codes with arrays of corresponding row numbers.
  67. *
  68. * @var array
  69. */
  70. protected $_errors = array();
  71. /**
  72. * Error counter.
  73. *
  74. * @var int
  75. */
  76. protected $_errorsCount = 0;
  77. /**
  78. * Limit of errors after which pre-processing will exit.
  79. *
  80. * @var int
  81. */
  82. protected $_errorsLimit = 100;
  83. /**
  84. * Export filter data.
  85. *
  86. * @var array
  87. */
  88. protected $_filter = array();
  89. /**
  90. * Attributes with index (not label) value.
  91. *
  92. * @var array
  93. */
  94. protected $_indexValueAttributes = array();
  95. /**
  96. * Validation failure message template definitions.
  97. *
  98. * @var array
  99. */
  100. protected $_messageTemplates = array();
  101. /**
  102. * Parameters.
  103. *
  104. * @var array
  105. */
  106. protected $_parameters = array();
  107. /**
  108. * Column names that holds values with particular meaning.
  109. *
  110. * @var array
  111. */
  112. protected $_particularAttributes = array();
  113. /**
  114. * Permanent entity columns.
  115. *
  116. * @var array
  117. */
  118. protected $_permanentAttributes = array();
  119. /**
  120. * Number of entities processed by validation.
  121. *
  122. * @var int
  123. */
  124. protected $_processedEntitiesCount = 0;
  125. /**
  126. * Number of rows processed by validation.
  127. *
  128. * @var int
  129. */
  130. protected $_processedRowsCount = 0;
  131. /**
  132. * Source model.
  133. *
  134. * @var Mage_ImportExport_Model_Export_Adapter_Abstract
  135. */
  136. protected $_writer;
  137. /**
  138. * Constructor.
  139. *
  140. * @return void
  141. */
  142. public function __construct()
  143. {
  144. $entityCode = $this->getEntityTypeCode();
  145. $this->_entityTypeId = Mage::getSingleton('eav/config')->getEntityType($entityCode)->getEntityTypeId();
  146. $this->_connection = Mage::getSingleton('core/resource')->getConnection('write');
  147. }
  148. /**
  149. * Initialize stores hash.
  150. *
  151. * @return Mage_ImportExport_Model_Export_Entity_Abstract
  152. */
  153. protected function _initStores()
  154. {
  155. foreach (Mage::app()->getStores(true) as $store) {
  156. $this->_storeIdToCode[$store->getId()] = $store->getCode();
  157. }
  158. ksort($this->_storeIdToCode); // to ensure that 'admin' store (ID is zero) goes first
  159. return $this;
  160. }
  161. /**
  162. * Get attributes codes which are appropriate for export.
  163. *
  164. * @return array
  165. */
  166. protected function _getExportAttrCodes()
  167. {
  168. if (null === self::$attrCodes) {
  169. if (!empty($this->_parameters[Mage_ImportExport_Model_Export::FILTER_ELEMENT_SKIP])
  170. && is_array($this->_parameters[Mage_ImportExport_Model_Export::FILTER_ELEMENT_SKIP])) {
  171. $skipAttr = array_flip($this->_parameters[Mage_ImportExport_Model_Export::FILTER_ELEMENT_SKIP]);
  172. } else {
  173. $skipAttr = array();
  174. }
  175. $attrCodes = array();
  176. foreach ($this->filterAttributeCollection($this->getAttributeCollection()) as $attribute) {
  177. if (!isset($skipAttr[$attribute->getAttributeId()])
  178. || in_array($attribute->getAttributeCode(), $this->_permanentAttributes)) {
  179. $attrCodes[] = $attribute->getAttributeCode();
  180. }
  181. }
  182. self::$attrCodes = $attrCodes;
  183. }
  184. return self::$attrCodes;
  185. }
  186. /**
  187. * Initialize attribute option values.
  188. *
  189. * @return Mage_ImportExport_Model_Export_Entity_Abstract
  190. */
  191. protected function _initAttrValues()
  192. {
  193. foreach ($this->getAttributeCollection() as $attribute) {
  194. $this->_attributeValues[$attribute->getAttributeCode()] = $this->getAttributeOptions($attribute);
  195. }
  196. return $this;
  197. }
  198. /**
  199. * Apply filter to collection and add not skipped attributes to select.
  200. *
  201. * @param Mage_Eav_Model_Entity_Collection_Abstract $collection
  202. * @return Mage_Eav_Model_Entity_Collection_Abstract
  203. */
  204. protected function _prepareEntityCollection(Mage_Eav_Model_Entity_Collection_Abstract $collection)
  205. {
  206. if (!isset($this->_parameters[Mage_ImportExport_Model_Export::FILTER_ELEMENT_GROUP])
  207. || !is_array($this->_parameters[Mage_ImportExport_Model_Export::FILTER_ELEMENT_GROUP])) {
  208. $exportFilter = array();
  209. } else {
  210. $exportFilter = $this->_parameters[Mage_ImportExport_Model_Export::FILTER_ELEMENT_GROUP];
  211. }
  212. $exportAttrCodes = $this->_getExportAttrCodes();
  213. foreach ($this->filterAttributeCollection($this->getAttributeCollection()) as $attribute) {
  214. $attrCode = $attribute->getAttributeCode();
  215. // filter applying
  216. if (isset($exportFilter[$attrCode])) {
  217. $attrFilterType = Mage_ImportExport_Model_Export::getAttributeFilterType($attribute);
  218. if (Mage_ImportExport_Model_Export::FILTER_TYPE_SELECT == $attrFilterType) {
  219. if (is_scalar($exportFilter[$attrCode]) && trim($exportFilter[$attrCode])) {
  220. $collection->addAttributeToFilter($attrCode, array('eq' => $exportFilter[$attrCode]));
  221. }
  222. } elseif (Mage_ImportExport_Model_Export::FILTER_TYPE_INPUT == $attrFilterType) {
  223. if (is_scalar($exportFilter[$attrCode]) && trim($exportFilter[$attrCode])) {
  224. $collection->addAttributeToFilter($attrCode, array('like' => "%{$exportFilter[$attrCode]}%"));
  225. }
  226. } elseif (Mage_ImportExport_Model_Export::FILTER_TYPE_DATE == $attrFilterType) {
  227. if (is_array($exportFilter[$attrCode]) && count($exportFilter[$attrCode]) == 2) {
  228. $from = array_shift($exportFilter[$attrCode]);
  229. $to = array_shift($exportFilter[$attrCode]);
  230. if (is_scalar($from) && strtotime($from)) {
  231. $collection->addAttributeToFilter($attrCode, array('from' => $from, 'date' => true));
  232. }
  233. if (is_scalar($to) && strtotime($to)) {
  234. $collection->addAttributeToFilter($attrCode, array('to' => $to, 'date' => true));
  235. }
  236. }
  237. } elseif (Mage_ImportExport_Model_Export::FILTER_TYPE_NUMBER == $attrFilterType) {
  238. if (is_array($exportFilter[$attrCode]) && count($exportFilter[$attrCode]) == 2) {
  239. $from = array_shift($exportFilter[$attrCode]);
  240. $to = array_shift($exportFilter[$attrCode]);
  241. if (is_numeric($from)) {
  242. $collection->addAttributeToFilter($attrCode, array('from' => $from));
  243. }
  244. if (is_numeric($to)) {
  245. $collection->addAttributeToFilter($attrCode, array('to' => $to));
  246. }
  247. }
  248. }
  249. }
  250. if (in_array($attrCode, $exportAttrCodes)) {
  251. $collection->addAttributeToSelect($attrCode);
  252. }
  253. }
  254. return $collection;
  255. }
  256. /**
  257. * Add error with corresponding current data source row number.
  258. *
  259. * @param string $errorCode Error code or simply column name
  260. * @param int $errorRowNum Row number.
  261. * @return Mage_ImportExport_Model_Import_Adapter_Abstract
  262. */
  263. public function addRowError($errorCode, $errorRowNum)
  264. {
  265. $this->_errors[$errorCode][] = $errorRowNum + 1; // one added for human readability
  266. $this->_invalidRows[$errorRowNum] = true;
  267. $this->_errorsCount ++;
  268. return $this;
  269. }
  270. /**
  271. * Add message template for specific error code from outside.
  272. *
  273. * @param string $errorCode Error code
  274. * @param string $message Message template
  275. * @return Mage_ImportExport_Model_Import_Entity_Abstract
  276. */
  277. public function addMessageTemplate($errorCode, $message)
  278. {
  279. $this->_messageTemplates[$errorCode] = $message;
  280. return $this;
  281. }
  282. /**
  283. * Export process.
  284. *
  285. * @return string
  286. */
  287. abstract public function export();
  288. /**
  289. * Clean up attribute collection.
  290. *
  291. * @param Mage_Eav_Model_Resource_Entity_Attribute_Collection $collection
  292. * @return Mage_Eav_Model_Resource_Entity_Attribute_Collection
  293. */
  294. public function filterAttributeCollection(Mage_Eav_Model_Resource_Entity_Attribute_Collection $collection)
  295. {
  296. $collection->load();
  297. foreach ($collection as $attribute) {
  298. if (in_array($attribute->getAttributeCode(), $this->_disabledAttrs)) {
  299. $collection->removeItemByKey($attribute->getId());
  300. }
  301. }
  302. return $collection;
  303. }
  304. /**
  305. * Entity attributes collection getter.
  306. *
  307. * @return Mage_Eav_Model_Resource_Entity_Attribute_Collection
  308. */
  309. abstract public function getAttributeCollection();
  310. /**
  311. * Returns attributes all values in label-value or value-value pairs form. Labels are lower-cased.
  312. *
  313. * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute
  314. * @return array
  315. */
  316. public function getAttributeOptions(Mage_Eav_Model_Entity_Attribute_Abstract $attribute)
  317. {
  318. $options = array();
  319. if ($attribute->usesSource()) {
  320. // should attribute has index (option value) instead of a label?
  321. $index = in_array($attribute->getAttributeCode(), $this->_indexValueAttributes) ? 'value' : 'label';
  322. // only default (admin) store values used
  323. $attribute->setStoreId(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID);
  324. try {
  325. foreach ($attribute->getSource()->getAllOptions(false) as $option) {
  326. foreach (is_array($option['value']) ? $option['value'] : array($option) as $innerOption) {
  327. if (strlen($innerOption['value'])) { // skip ' -- Please Select -- ' option
  328. $options[$innerOption['value']] = $innerOption[$index];
  329. }
  330. }
  331. }
  332. } catch (Exception $e) {
  333. // ignore exceptions connected with source models
  334. }
  335. }
  336. return $options;
  337. }
  338. /**
  339. * EAV entity type code getter.
  340. *
  341. * @abstract
  342. * @return string
  343. */
  344. abstract public function getEntityTypeCode();
  345. /**
  346. * Entity type ID getter.
  347. *
  348. * @return int
  349. */
  350. public function getEntityTypeId()
  351. {
  352. return $this->_entityTypeId;
  353. }
  354. /**
  355. * Returns error information.
  356. *
  357. * @return array
  358. */
  359. public function getErrorMessages()
  360. {
  361. $translator = Mage::helper('importexport');
  362. $messages = array();
  363. foreach ($this->_errors as $errorCode => $errorRows) {
  364. if (isset($this->_messageTemplates[$errorCode])) {
  365. $message = $translator->__($this->_messageTemplates[$errorCode]);
  366. } else {
  367. $message = $translator->__("Invalid value for '%s' column", $errorCode);
  368. }
  369. $messages[$message] = $errorRows;
  370. }
  371. return $messages;
  372. }
  373. /**
  374. * Returns error counter value.
  375. *
  376. * @return int
  377. */
  378. public function getErrorsCount()
  379. {
  380. return $this->_errorsCount;
  381. }
  382. /**
  383. * Returns invalid rows count.
  384. *
  385. * @return int
  386. */
  387. public function getInvalidRowsCount()
  388. {
  389. return count($this->_invalidRows);
  390. }
  391. /**
  392. * Returns number of checked entities.
  393. *
  394. * @return int
  395. */
  396. public function getProcessedEntitiesCount()
  397. {
  398. return $this->_processedEntitiesCount;
  399. }
  400. /**
  401. * Returns number of checked rows.
  402. *
  403. * @return int
  404. */
  405. public function getProcessedRowsCount()
  406. {
  407. return $this->_processedRowsCount;
  408. }
  409. /**
  410. * Inner writer object getter.
  411. *
  412. * @throws Exception
  413. * @return Mage_ImportExport_Model_Export_Adapter_Abstract
  414. */
  415. public function getWriter()
  416. {
  417. if (!$this->_writer) {
  418. Mage::throwException(Mage::helper('importexport')->__('No writer specified'));
  419. }
  420. return $this->_writer;
  421. }
  422. /**
  423. * Set parameters.
  424. *
  425. * @param array $parameters
  426. * @return Mage_ImportExport_Model_Export_Entity_Abstract
  427. */
  428. public function setParameters(array $parameters)
  429. {
  430. $this->_parameters = $parameters;
  431. return $this;
  432. }
  433. /**
  434. * Writer model setter.
  435. *
  436. * @param Mage_ImportExport_Model_Export_Adapter_Abstract $writer
  437. * @return Mage_ImportExport_Model_Export_Entity_Abstract
  438. */
  439. public function setWriter(Mage_ImportExport_Model_Export_Adapter_Abstract $writer)
  440. {
  441. $this->_writer = $writer;
  442. return $this;
  443. }
  444. }