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

/app/code/core/Mage/Dataflow/Model/Convert/Parser/Xml/Excel.php

https://github.com/FiveDigital/magento2
PHP | 493 lines | 321 code | 58 blank | 114 comment | 50 complexity | 4a043f34a6fd24a8ff7a9998f500fb80 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  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_Dataflow
  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. * Convert excel xml parser
  28. *
  29. * @category Mage
  30. * @package Mage_Dataflow
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Dataflow_Model_Convert_Parser_Xml_Excel extends Mage_Dataflow_Model_Convert_Parser_Abstract
  34. {
  35. /**
  36. * Simple Xml object
  37. *
  38. * @var SimpleXMLElement
  39. */
  40. protected $_xmlElement;
  41. /**
  42. * Field list
  43. *
  44. * @var array
  45. */
  46. protected $_parseFieldNames;
  47. public function parse()
  48. {
  49. $adapterName = $this->getVar('adapter', null);
  50. $adapterMethod = $this->getVar('method', 'saveRow');
  51. if (!$adapterName || !$adapterMethod) {
  52. $message = Mage::helper('Mage_Dataflow_Helper_Data')->__('Please declare "adapter" and "method" nodes first.');
  53. $this->addException($message, Mage_Dataflow_Model_Convert_Exception::FATAL);
  54. return $this;
  55. }
  56. try {
  57. $adapter = Mage::getModel($adapterName);
  58. }
  59. catch (Exception $e) {
  60. $message = Mage::helper('Mage_Dataflow_Helper_Data')->__('Declared adapter %s was not found.', $adapterName);
  61. $this->addException($message, Mage_Dataflow_Model_Convert_Exception::FATAL);
  62. return $this;
  63. }
  64. if (!method_exists($adapter, $adapterMethod)) {
  65. $message = Mage::helper('Mage_Dataflow_Helper_Data')->__('Method "%s" was not defined in adapter %s.', $adapterMethod, $adapterName);
  66. $this->addException($message, Mage_Dataflow_Model_Convert_Exception::FATAL);
  67. return $this;
  68. }
  69. $batchModel = $this->getBatchModel();
  70. $batchIoAdapter = $this->getBatchModel()->getIoAdapter();
  71. if (Mage::app()->getRequest()->getParam('files')) {
  72. $file = Mage::app()->getConfig()->getTempVarDir().'/import/'
  73. . urldecode(Mage::app()->getRequest()->getParam('files'));
  74. $this->_copy($file);
  75. }
  76. $batchIoAdapter->open(false);
  77. $isFieldNames = $this->getVar('fieldnames', '') == 'true' ? true : false;
  78. if (!$isFieldNames && is_array($this->getVar('map'))) {
  79. $this->_parseFieldNames = $this->getVar('map');
  80. }
  81. $worksheet = $this->getVar('single_sheet', '');
  82. $xmlString = $xmlRowString = '';
  83. $countRows = 0;
  84. $isWorksheet = $isRow = false;
  85. while (($xmlOriginalString = $batchIoAdapter->read()) !== false) {
  86. $xmlString .= $xmlOriginalString;
  87. if (!$isWorksheet) {
  88. $strposS = strpos($xmlString, '<Worksheet');
  89. $substrL = 10;
  90. //fix for OpenOffice
  91. if ($strposS === false) {
  92. $strposS = strpos($xmlString, '<ss:Worksheet');
  93. $substrL = 13;
  94. }
  95. if ($strposS === false) {
  96. $xmlString = substr($xmlString, -13);
  97. continue;
  98. }
  99. $xmlTmpString = substr($xmlString, $strposS);
  100. $strposF = strpos($xmlTmpString, '>');
  101. if ($strposF === false) {
  102. $xmlString = $xmlTmpString;
  103. continue;
  104. }
  105. if (!$worksheet) {
  106. $xmlString = substr($xmlTmpString, $strposF);
  107. $isWorksheet = true;
  108. continue;
  109. }
  110. else {
  111. if (preg_match('/ss:Name=\"'.preg_quote($worksheet).'\"/siU', substr($xmlTmpString, 0, $strposF))) {
  112. $xmlString = substr($xmlTmpString, $strposF);
  113. $isWorksheet = true;
  114. continue;
  115. }
  116. else {
  117. $xmlString = '';
  118. continue;
  119. }
  120. }
  121. }
  122. else {
  123. $xmlString = $this->_parseXmlRow($xmlString);
  124. $strposS = strpos($xmlString, '</Worksheet>');
  125. $substrL = 12;
  126. //fix for OpenOffice
  127. if ($strposS === false) {
  128. $strposS = strpos($xmlString, '</ss:Worksheet>');
  129. $substrL = 15;
  130. }
  131. if ($strposS !== false) {
  132. $xmlString = substr($xmlString, $strposS + $substrL);
  133. $isWorksheet = false;
  134. continue;
  135. }
  136. }
  137. }
  138. $this->addException(Mage::helper('Mage_Dataflow_Helper_Data')->__('Found %d rows.', $this->_countRows));
  139. $this->addException(Mage::helper('Mage_Dataflow_Helper_Data')->__('Starting %s :: %s', $adapterName, $adapterMethod));
  140. $batchModel->setParams($this->getVars())
  141. ->setAdapter($adapterName)
  142. ->save();
  143. // $adapter->$adapterMethod();
  144. return $this;
  145. $dom = new DOMDocument();
  146. // $dom->loadXML($this->getData());
  147. if (Mage::app()->getRequest()->getParam('files')) {
  148. $path = Mage::app()->getConfig()->getTempVarDir().'/import/';
  149. $file = $path.urldecode(Mage::app()->getRequest()->getParam('files'));
  150. if (file_exists($file)) {
  151. $dom->load($file);
  152. }
  153. } else {
  154. $this->validateDataString();
  155. $dom->loadXML($this->getData());
  156. }
  157. $worksheets = $dom->getElementsByTagName('Worksheet');
  158. if ($this->getVar('adapter') && $this->getVar('method')) {
  159. $adapter = Mage::getModel($this->getVar('adapter'));
  160. }
  161. foreach ($worksheets as $worksheet) {
  162. $wsName = $worksheet->getAttribute('ss:Name');
  163. $rows = $worksheet->getElementsByTagName('Row');
  164. $firstRow = true;
  165. $fieldNames = array();
  166. $wsData = array();
  167. $i = 0;
  168. foreach ($rows as $rowSet) {
  169. $index = 1;
  170. $cells = $rowSet->getElementsByTagName('Cell');
  171. $rowData = array();
  172. foreach ($cells as $cell) {
  173. $value = $cell->getElementsByTagName('Data')->item(0)->nodeValue;
  174. $ind = $cell->getAttribute('ss:Index');
  175. if (!is_null($ind) && $ind>0) {
  176. $index = $ind;
  177. }
  178. if ($firstRow && !$this->getVar('fieldnames')) {
  179. $fieldNames[$index] = 'column'.$index;
  180. }
  181. if ($firstRow && $this->getVar('fieldnames')) {
  182. $fieldNames[$index] = $value;
  183. } else {
  184. $rowData[$fieldNames[$index]] = $value;
  185. }
  186. $index++;
  187. }
  188. $row = $rowData;
  189. if ($row) {
  190. $loadMethod = $this->getVar('method');
  191. $adapter->$loadMethod(compact('i', 'row'));
  192. }
  193. $i++;
  194. $firstRow = false;
  195. if (!empty($rowData)) {
  196. $wsData[] = $rowData;
  197. }
  198. }
  199. $data[$wsName] = $wsData;
  200. $this->addException('Found worksheet "'.$wsName.'" with '.sizeof($wsData).' row(s)');
  201. }
  202. if ($wsName = $this->getVar('single_sheet')) {
  203. if (isset($data[$wsName])) {
  204. $data = $data[$wsName];
  205. } else {
  206. reset($data);
  207. $data = current($data);
  208. }
  209. }
  210. $this->setData($data);
  211. return $this;
  212. }
  213. /**
  214. * Parse MS Excel XML string
  215. *
  216. * @param string $xmlString
  217. * @return string
  218. */
  219. protected function _parseXmlRow($xmlString)
  220. {
  221. $found = true;
  222. while ($found === true) {
  223. $strposS = strpos($xmlString, '<Row');
  224. if ($strposS === false) {
  225. $found = false;
  226. continue;
  227. }
  228. $xmlTmpString = substr($xmlString, $strposS);
  229. $strposF = strpos($xmlTmpString, '</Row>');
  230. if ($strposF !== false) {
  231. $xmlRowString = substr($xmlTmpString, 0, $strposF + 6);
  232. $this->_saveParsedRow($xmlRowString);
  233. $xmlString = substr($xmlTmpString, $strposF + 6);
  234. }
  235. else {
  236. $found = false;
  237. continue;
  238. }
  239. }
  240. return $xmlString;
  241. }
  242. protected function _saveParsedRow($xmlString)
  243. {
  244. $xml = '<'.'?xml version="1.0"?'.'><'.'?mso-application progid="Excel.Sheet"?'
  245. .'><Workbook'
  246. .' xmlns="urn:schemas-microsoft-com:office:spreadsheet"'
  247. .' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
  248. .' xmlns:x="urn:schemas-microsoft-com:office:excel"'
  249. .' xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml"'
  250. .' xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"'
  251. .' xmlns:o="urn:schemas-microsoft-com:office:office"'
  252. .' xmlns:html="http://www.w3.org/TR/REC-html40"'
  253. .' xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet">'
  254. . $xmlString
  255. .'</Workbook>';
  256. try {
  257. $xmlElement = new SimpleXMLElement($xml);
  258. }
  259. catch (Exception $e) {
  260. $message = 'Invalid XML row';
  261. $this->addException($message, Mage_Dataflow_Model_Convert_Exception::ERROR);
  262. return $this;
  263. }
  264. $xmlData = array();
  265. $itemData = array();
  266. $cellIndex = 0;
  267. foreach ($xmlElement->Row->children() as $cell) {
  268. if (is_null($this->_parseFieldNames)) {
  269. $xmlData[(string)$cell->Data] = (string)$cell->Data;
  270. } else {
  271. $attributes = $cell->attributes('urn:schemas-microsoft-com:office:spreadsheet');
  272. if ($attributes && isset($attributes['Index'])) {
  273. $cellIndex = $attributes['Index'] - 1;
  274. }
  275. $xmlData[$cellIndex] = (string)$cell->Data;
  276. $cellIndex ++;
  277. }
  278. }
  279. if (is_null($this->_parseFieldNames)) {
  280. $this->_parseFieldNames = $xmlData;
  281. return $this;
  282. }
  283. $this->_countRows ++;
  284. $i = 0;
  285. foreach ($this->_parseFieldNames as $field) {
  286. $itemData[$field] = isset($xmlData[$i]) ? $xmlData[$i] : null;
  287. $i ++;
  288. }
  289. $batchImportModel = $this->getBatchImportModel()
  290. ->setId(null)
  291. ->setBatchId($this->getBatchModel()->getId())
  292. ->setBatchData($itemData)
  293. ->setStatus(1)
  294. ->save();
  295. return $this;
  296. }
  297. public function unparse()
  298. {
  299. $batchExport = $this->getBatchExportModel()
  300. ->setBatchId($this->getBatchModel()->getId());
  301. $fieldList = $this->getBatchModel()->getFieldList();
  302. $batchExportIds = $batchExport->getIdCollection();
  303. if (!is_array($batchExportIds)) {
  304. return $this;
  305. }
  306. $io = $this->getBatchModel()->getIoAdapter();
  307. $io->open();
  308. $xml = '<'.'?xml version="1.0"?'.'><'.'?mso-application progid="Excel.Sheet"?'
  309. .'><Workbook'
  310. .' xmlns="urn:schemas-microsoft-com:office:spreadsheet"'
  311. .' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
  312. .' xmlns:x="urn:schemas-microsoft-com:office:excel"'
  313. .' xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml"'
  314. .' xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"'
  315. .' xmlns:o="urn:schemas-microsoft-com:office:office"'
  316. .' xmlns:html="http://www.w3.org/TR/REC-html40"'
  317. .' xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet">'
  318. .'<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">'
  319. .'</OfficeDocumentSettings>'
  320. .'<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">'
  321. .'</ExcelWorkbook>';
  322. $io->write($xml);
  323. $wsName = htmlspecialchars($this->getVar('single_sheet'));
  324. $wsName = !empty($wsName) ? $wsName : Mage::helper('Mage_Dataflow_Helper_Data')->__('Sheet 1');
  325. $xml = '<Worksheet ss:Name="' . $wsName . '"><Table>';
  326. $io->write($xml);
  327. if ($this->getVar('fieldnames')) {
  328. $xml = $this->_getXmlString($fieldList);
  329. $io->write($xml);
  330. }
  331. foreach ($batchExportIds as $batchExportId) {
  332. $xmlData = array();
  333. $batchExport->load($batchExportId);
  334. $row = $batchExport->getBatchData();
  335. foreach ($fieldList as $field) {
  336. $xmlData[] = isset($row[$field]) ? $row[$field] : '';
  337. }
  338. $xmlData = $this->_getXmlString($xmlData);
  339. $io->write($xmlData);
  340. }
  341. $xml = '</Table></Worksheet></Workbook>';
  342. $io->write($xml);
  343. $io->close();
  344. return $this;
  345. // if ($wsName = $this->getVar('single_sheet')) {
  346. // $data = array($wsName => $this->getData());
  347. // } else {
  348. // $data = $this->getData();
  349. // }
  350. //
  351. // $this->validateDataGrid();
  352. //
  353. // $xml = '<'.'?xml version="1.0"?'.'><'.'?mso-application progid="Excel.Sheet"?'.'><Workbook'
  354. // .' xmlns="urn:schemas-microsoft-com:office:spreadsheet"'
  355. // .' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
  356. // .' xmlns:x="urn:schemas-microsoft-com:office:excel"'
  357. // .' xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml"'
  358. // .' xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"'
  359. // .' xmlns:o="urn:schemas-microsoft-com:office:office"'
  360. // .' xmlns:html="http://www.w3.org/TR/REC-html40"'
  361. // .' xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet">'
  362. // .'<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">'
  363. // .'</OfficeDocumentSettings>'
  364. // .'<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">'
  365. // .'</ExcelWorkbook>';
  366. //
  367. // if (is_array($data)) {
  368. // foreach ($data as $wsName=>$wsData) {
  369. // if (!is_array($wsData)) {
  370. // continue;
  371. // }
  372. // $fields = $this->getGridFields($wsData);
  373. //
  374. // $xml .= '<ss:Worksheet ss:Name="'.$wsName.'"><Table>';
  375. // if ($this->getVar('fieldnames')) {
  376. // $xml .= '<ss:Row>';
  377. // foreach ($fields as $fieldName) {
  378. // $xml .= '<ss:Cell><Data ss:Type="String">'.$fieldName.'</Data></ss:Cell>';
  379. // }
  380. // $xml .= '</ss:Row>';
  381. // }
  382. // foreach ($wsData as $i=>$row) {
  383. // if (!is_array($row)) {
  384. // continue;
  385. // }
  386. // $xml .= '<ss:Row>';
  387. // foreach ($fields as $fieldName) {
  388. // $data = isset($row[$fieldName]) ? $row[$fieldName] : '';
  389. // $xml .= '<ss:Cell><Data ss:Type="String">'.$data.'</Data></ss:Cell>';
  390. // }
  391. // $xml .= '</ss:Row>';
  392. // }
  393. // $xml .= '</Table></ss:Worksheet>';
  394. // }
  395. // }
  396. //
  397. // $xml .= '</Workbook>';
  398. //
  399. // $this->setData($xml);
  400. //
  401. // return $this;
  402. }
  403. /**
  404. * Prepare and return XML string for MS Excel XML from array
  405. *
  406. * @param array $fields
  407. * @return string
  408. */
  409. protected function _getXmlString(array $fields = array())
  410. {
  411. $xmlHeader = '<?xml version="1.0"?>' . "\n";
  412. $xmlRegexp = '/^<cell><row>(.*)?<\/row><\/cell>\s?$/ms';
  413. if (is_null($this->_xmlElement)) {
  414. $xmlString = $xmlHeader . '<cell><row></row></cell>';
  415. $this->_xmlElement = new SimpleXMLElement($xmlString, LIBXML_NOBLANKS);
  416. }
  417. $xmlData = array();
  418. $xmlData[] = '<Row>';
  419. foreach ($fields as $value) {
  420. $this->_xmlElement->row = htmlspecialchars($value);
  421. $value = str_replace($xmlHeader, '', $this->_xmlElement->asXML());
  422. $value = preg_replace($xmlRegexp, '\\1', $value);
  423. if (is_numeric($value)) {
  424. $value = trim($value);
  425. $dataType = 'Number';
  426. } else {
  427. $dataType = 'String';
  428. }
  429. $value = str_replace(array("\r\n", "\r", "\n"), '&#10;', $value);
  430. $xmlData[] = '<Cell><Data ss:Type="' . $dataType . '">' . $value . '</Data></Cell>';
  431. }
  432. $xmlData[] = '</Row>';
  433. return join('', $xmlData);
  434. }
  435. }