PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/tine20/Tinebase/Export/Spreadsheet/Ods.php

https://gitlab.com/rsilveira1987/Expresso
PHP | 400 lines | 229 code | 56 blank | 115 comment | 15 complexity | d793c4f4ea1b08181a240f244324cc8a MD5 | raw file
  1. <?php
  2. /**
  3. * Tinebase Ods generation class
  4. *
  5. * @package Tinebase
  6. * @subpackage Export
  7. * @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
  8. * @author Philipp Schüle <p.schuele@metaways.de>
  9. * @copyright Copyright (c) 2009-2011 Metaways Infosystems GmbH (http://www.metaways.de)
  10. *
  11. * @todo add alternating row styles again?
  12. */
  13. /**
  14. * Tinebase Ods generation class
  15. *
  16. * @package Tinebase
  17. * @subpackage Export
  18. */
  19. class Tinebase_Export_Spreadsheet_Ods extends Tinebase_Export_Spreadsheet_Abstract implements Tinebase_Record_IteratableInterface
  20. {
  21. /**
  22. * user styles
  23. *
  24. * @var array
  25. */
  26. protected $_userStyles = array(
  27. '<number:date-style style:name="nShortDate" number:automatic-order="true"
  28. xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
  29. xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0">
  30. <number:day number:style="long"/>
  31. <number:text>.</number:text>
  32. <number:month number:style="long"/>
  33. <number:text>.</number:text>
  34. <number:year number:style="long"/>
  35. </number:date-style>',
  36. '<number:number-style style:name="N2"
  37. xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
  38. xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0">
  39. <number:number number:decimal-places="2" number:min-integer-digits="1"/>
  40. </number:number-style>',
  41. '<style:style style:name="ceHeader" style:family="table-cell"
  42. xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
  43. xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0">
  44. <style:table-cell-properties fo:background-color="#ccffff"/>
  45. <style:paragraph-properties fo:text-align="center" fo:margin-left="0cm"/>
  46. <style:text-properties fo:font-weight="bold"/>
  47. </style:style>',
  48. '<style:style style:name="ceBold" style:family="table-cell" style:data-style-name="N2"
  49. xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
  50. xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0">
  51. <style:text-properties fo:font-weight="bold"/>
  52. </style:style>',
  53. '<style:style style:name="ceAlternate" style:family="table-cell"
  54. xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
  55. xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0">
  56. <style:table-cell-properties fo:background-color="#ccccff"/>
  57. </style:style>',
  58. '<style:style style:name="ceAlternateCentered" style:family="table-cell"
  59. xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
  60. xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0">
  61. <style:table-cell-properties fo:background-color="#ccccff"/>
  62. <style:paragraph-properties fo:text-align="center" fo:margin-left="0cm"/>
  63. </style:style>',
  64. '<style:style style:name="ceShortDate" style:family="table-cell" style:data-style-name="nShortDate"
  65. xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
  66. xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0">
  67. <style:paragraph-properties fo:text-align="center" fo:margin-left="0cm"/>
  68. </style:style>',
  69. '<style:style style:name="numberStyle" style:family="table-cell" style:data-style-name="N2"
  70. xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
  71. xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0">
  72. <style:paragraph-properties fo:text-align="right"/>
  73. </style:style>',
  74. '<style:style style:name="numberStyleAlternate" style:family="table-cell" style:data-style-name="N2"
  75. xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
  76. xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0">
  77. <style:table-cell-properties fo:background-color="#ccccff"/>
  78. <style:paragraph-properties fo:text-align="right"/>
  79. </style:style>',
  80. );
  81. /**
  82. * fields with special treatment in addBody
  83. *
  84. * @var array
  85. */
  86. protected $_specialFields = array();
  87. /**
  88. * the opendocument object
  89. *
  90. * @var OpenDocument_Document
  91. */
  92. protected $_openDocumentObject = NULL;
  93. /**
  94. * the spreadsheet object
  95. *
  96. * @var OpenDocument_SpreadSheet
  97. */
  98. protected $_spreadSheetObject = NULL;
  99. /**
  100. * spreadsheet table
  101. *
  102. * @var OpenDocument_SpreadSheet_Table
  103. */
  104. protected $_activeTable = NULL;
  105. /**
  106. * holds style names for each column
  107. *
  108. * @var array
  109. */
  110. protected $_columnStyles = array();
  111. /**
  112. * generate export
  113. *
  114. * @return string filename
  115. */
  116. public function generate()
  117. {
  118. $this->_createDocument();
  119. // build export table (use current table if using template)
  120. Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Creating export for ' . $this->_modelName . ' . ' . $this->_getDataTableName());
  121. if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($this->_config->toArray(), TRUE));
  122. $this->_spreadSheetObject = $this->_openDocumentObject->getBody();
  123. if ($this->_spreadSheetObject->tableExists($this->_getDataTableName()) === true) {
  124. $this->_activeTable = $this->_spreadSheetObject->getTable($this->_getDataTableName());
  125. } else {
  126. $this->_activeTable = $this->_spreadSheetObject->appendTable($this->_getDataTableName());
  127. }
  128. $this->_setColumnStyles();
  129. // add header (disabled at the moment)
  130. if (isset($this->_config->header) && $this->_config->header) {
  131. $this->_addHead($this->_activeTable);
  132. }
  133. $this->_exportRecords();
  134. // create file
  135. $result = $this->_openDocumentObject->getDocument();
  136. return $result;
  137. }
  138. /**
  139. * get download content type
  140. *
  141. * @return string
  142. */
  143. public function getDownloadContentType()
  144. {
  145. return 'application/vnd.oasis.opendocument.spreadsheet';
  146. }
  147. /**
  148. * create new open document document
  149. *
  150. * @return void
  151. */
  152. protected function _createDocument()
  153. {
  154. // check for template file
  155. $templateFile = $this->_getTemplateFilename();
  156. $this->_openDocumentObject = new OpenDocument_Document(OpenDocument_Document::SPREADSHEET, $templateFile, Tinebase_Core::getTempDir(), $this->_userStyles);
  157. }
  158. /**
  159. * get open document object
  160. *
  161. * @return OpenDocument_Document
  162. */
  163. public function getDocument()
  164. {
  165. return $this->_openDocumentObject;
  166. }
  167. /**
  168. * defines column styles by the config xml
  169. */
  170. protected function _setColumnStyles()
  171. {
  172. $index = 1;
  173. $classPrefix = 'co';
  174. $defaultStyles = NULL;
  175. if ($this->_config->defaultColumnStyle) {
  176. $defaultStyles = array();
  177. foreach ($this->_config->defaultColumnStyle as $name => $style) {
  178. $defaultStyles[$name] = (string) $style;
  179. }
  180. $this->_addColumnStyle('co0', $defaultStyles);
  181. }
  182. foreach($this->_config->columns->column as $column) {
  183. if ($column->style) {
  184. if (! $defaultStyles) {
  185. $msg = 'If a column contains style, the "defaultColumnStyle" has to be defined!';
  186. Tinebase_Core::getLogger()->log(__METHOD__ . '::' . __LINE__ . ' ' . $msg . ' Definition Name: ' . (string) $this->_config->name);
  187. throw new Tinebase_Exception_UnexpectedValue($msg);
  188. }
  189. $columnStyles = array();
  190. foreach($column->style as $name => $style) {
  191. $columnStyles[$name] = (string) $style;
  192. }
  193. $this->_addColumnStyle($classPrefix . $index, $columnStyles);
  194. $this->_columnStyles[$index] = $classPrefix . $index;
  195. } else {
  196. $this->_columnStyles[$index] = 'co0';
  197. }
  198. $index++;
  199. }
  200. foreach($this->_columnStyles as $key => $style) {
  201. $this->_activeTable->appendColumn($style);
  202. }
  203. }
  204. /**
  205. * add ods head (headline, column styles)
  206. */
  207. protected function _addHead()
  208. {
  209. $i18n = $this->_translate->getAdapter();
  210. // add header (replace placeholders)
  211. if (isset($this->_config->headers)) {
  212. $row = $this->_activeTable->appendRow();
  213. $patterns = array(
  214. '/\{date\}/',
  215. '/\{user\}/',
  216. '/\{count\}/',
  217. );
  218. $c = $this->_controller;
  219. $count = $c::getInstance()->searchCount($this->_filter);
  220. $replacements = array(
  221. Zend_Date::now()->toString(Zend_Locale_Format::getDateFormat($this->_locale), $this->_locale),
  222. Tinebase_Core::getUser()->accountDisplayName,
  223. $i18n->translate('Total: ') . $count
  224. );
  225. foreach($this->_config->headers->header as $headerCell) {
  226. // replace data
  227. $value = preg_replace($patterns, $replacements, $headerCell);
  228. $cell = $row->appendCell($value, OpenDocument_SpreadSheet_Cell::TYPE_STRING);
  229. if ($this->_config->headerStyle) {
  230. $cell->setStyle((string) $this->_config->headerStyle);
  231. }
  232. }
  233. }
  234. $row = $this->_activeTable->appendRow();
  235. foreach($this->_config->columns->column as $field) {
  236. $headerValue = ($field->header) ? $i18n->translate($field->header) : $field->identifier;
  237. $cell = $row->appendCell($headerValue, OpenDocument_SpreadSheet_Cell::TYPE_STRING);
  238. if (isset($field->headerStyle)) {
  239. $cell->setStyle((string) $field->headerStyle);
  240. } else {
  241. $cell->setStyle('ceHeader');
  242. }
  243. }
  244. }
  245. /**
  246. * format strings
  247. *
  248. * @var string
  249. */
  250. protected $_format = 'ods';
  251. /**
  252. * add body rows
  253. *
  254. * @param Tinebase_Record_RecordSet $records
  255. */
  256. public function processIteration($_records)
  257. {
  258. $this->_resolveRecords($_records);
  259. // add record rows
  260. $i = 0;
  261. foreach ($_records as $record) {
  262. $this->processRecord($record, $i);
  263. $i++;
  264. }
  265. }
  266. /**
  267. * add single body row
  268. *
  269. * @param $record
  270. */
  271. public function processRecord($record, $idx)
  272. {
  273. $row = $this->_activeTable->appendRow();
  274. foreach ($this->_config->columns->column as $field) {
  275. // get type and value for cell
  276. $cellType = $this->_getCellType($field->type);
  277. $cellValue = $this->_getCellValue($field, $record, $cellType);
  278. // create cell with type and value and add style
  279. $cell = $row->appendCell($cellValue, $cellType);
  280. if ($field->columnStyle) {
  281. $cell->setStyle((string) $field->columnStyle);
  282. }
  283. // add formula
  284. if ($field->formula) {
  285. $cell->setFormula($field->formula);
  286. }
  287. }
  288. }
  289. /**
  290. * add style/width to column
  291. *
  292. * @param string $styleName
  293. * @param string $values
  294. */
  295. protected function _addColumnStyle($styleName, $values)
  296. {
  297. $xml = '<style:style style:name="' . $styleName . '" style:family="table-column" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"><style:table-column-properties';
  298. foreach($values as $attr => $value) {
  299. $xml .= ' style:' . $attr . '="' . $value . '"';
  300. }
  301. $xml .= ' /></style:style>';
  302. $this->_openDocumentObject->addStyle(array($xml));
  303. }
  304. /**
  305. * get name of data table
  306. *
  307. * @return string
  308. */
  309. protected function _getDataTableName()
  310. {
  311. return $this->_translate->_('Data');
  312. }
  313. /**
  314. * get cell type
  315. *
  316. * @param string $_fieldType
  317. * @return string
  318. */
  319. protected function _getCellType($_fieldType)
  320. {
  321. switch($_fieldType) {
  322. case 'date':
  323. case 'datetime':
  324. $result = OpenDocument_SpreadSheet_Cell::TYPE_DATE;
  325. break;
  326. case 'time':
  327. $result = OpenDocument_SpreadSheet_Cell::TYPE_TIME;
  328. break;
  329. case 'currency':
  330. $result = OpenDocument_SpreadSheet_Cell::TYPE_CURRENCY;
  331. break;
  332. case 'percentage':
  333. $result = OpenDocument_SpreadSheet_Cell::TYPE_PERCENTAGE;
  334. break;
  335. case 'float':
  336. case 'number':
  337. $result = OpenDocument_SpreadSheet_Cell::TYPE_FLOAT;
  338. break;
  339. default:
  340. $result = OpenDocument_SpreadSheet_Cell::TYPE_STRING;
  341. }
  342. return $result;
  343. }
  344. }