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

/tine20/Tinebase/Export/Csv.php

https://gitlab.com/israel.correa/Expresso
PHP | 294 lines | 152 code | 33 blank | 109 comment | 38 complexity | 3d9878d5612c80e24830dc6e536f1bb2 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-3.0, LGPL-2.1, LGPL-3.0, JSON, Apache-2.0
  1. <?php
  2. /**
  3. * Tinebase Csv Export 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) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
  10. *
  11. * @todo use export definitions
  12. */
  13. /**
  14. * Tinebase Csv Export class
  15. *
  16. * @package Tinebase
  17. * @subpackage Export
  18. */
  19. class Tinebase_Export_Csv extends Tinebase_Export_Abstract implements Tinebase_Record_IteratableInterface
  20. {
  21. /**
  22. * relation types
  23. *
  24. * @var array
  25. */
  26. protected $_relationsTypes = array();
  27. /**
  28. * relation subfields
  29. *
  30. * @var array
  31. */
  32. protected $_relationFields = array();
  33. /**
  34. * special fields
  35. *
  36. * @var array
  37. */
  38. protected $_specialFields = array();
  39. /**
  40. * fields to skip
  41. *
  42. * @var array
  43. */
  44. protected $_skipFields = array(
  45. 'id' ,
  46. 'created_by' ,
  47. 'creation_time' ,
  48. 'last_modified_by' ,
  49. 'last_modified_time' ,
  50. 'is_deleted' ,
  51. 'deleted_time' ,
  52. 'deleted_by' ,
  53. );
  54. /**
  55. * write export to stdout?
  56. *
  57. * @var boolean
  58. */
  59. protected $_toStdout = FALSE;
  60. /**
  61. * format strings
  62. *
  63. * @var string
  64. */
  65. protected $_format = 'csv';
  66. /**
  67. * csv filehandle resource
  68. *
  69. * @var resource
  70. */
  71. protected $_filehandle = NULL;
  72. /**
  73. * fields
  74. *
  75. * @var array
  76. */
  77. protected $_fields = NULL;
  78. /**
  79. * the constructor
  80. *
  81. * @param Tinebase_Model_Filter_FilterGroup $_filter
  82. * @param Tinebase_Controller_Record_Interface $_controller (optional)
  83. * @param array $_additionalOptions (optional) additional options
  84. */
  85. public function __construct(Tinebase_Model_Filter_FilterGroup $_filter, Tinebase_Controller_Record_Interface $_controller = NULL, $_additionalOptions = array())
  86. {
  87. parent::__construct($_filter, $_controller, $_additionalOptions);
  88. if (isset($_additionalOptions['toStdout'])) {
  89. $this->_toStdout = $_additionalOptions['toStdout'];
  90. }
  91. }
  92. /**
  93. * The php build in fputcsv function is buggy, so we need an own one :-(
  94. *
  95. * @param resource $filePointer
  96. * @param array $dataArray
  97. * @param char $delimiter
  98. * @param char $enclosure
  99. * @param char $escapeEnclosure
  100. */
  101. public static function fputcsv($filePointer, $dataArray, $delimiter = ',', $enclosure = '"', $escapeEnclosure = '"')
  102. {
  103. $string = "";
  104. $writeDelimiter = false;
  105. foreach($dataArray as $dataElement) {
  106. if ($writeDelimiter) {
  107. $string .= $delimiter;
  108. }
  109. $escapedDataElement = (! is_array($dataElement)) ? preg_replace("/$enclosure/", $escapeEnclosure . $enclosure , $dataElement) : '';
  110. $string .= $enclosure . $escapedDataElement . $enclosure;
  111. $writeDelimiter = true;
  112. }
  113. $string .= "\n";
  114. fwrite($filePointer, $string);
  115. }
  116. /**
  117. * generate export
  118. *
  119. * @return string|boolean filename
  120. */
  121. public function generate()
  122. {
  123. if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Generating new csv export of ' . $this->_modelName);
  124. $filename = $this->_getFilename();
  125. $this->_filehandle = ($this->_toStdout) ? STDOUT : fopen($filename, 'w');
  126. $fields = $this->_getFields();
  127. self::fputcsv($this->_filehandle, $fields);
  128. $this->_exportRecords();
  129. if (!$this->_toStdout) {
  130. fclose($this->_filehandle);
  131. }
  132. return $filename;
  133. }
  134. /**
  135. * get record / export fields
  136. *
  137. * @return array
  138. */
  139. protected function _getFields()
  140. {
  141. if ($this->_fields === NULL) {
  142. $record = new $this->_modelName(array(), TRUE);
  143. $fields = array();
  144. foreach ($record->getFields() as $key) {
  145. if ($key === 'customfields') {
  146. foreach ($this->_getCustomFieldNames() as $cfName) {
  147. $fields[] = $cfName;
  148. }
  149. } else {
  150. $fields[] = $key;
  151. if (in_array($key, array_keys($this->_specialFields))) {
  152. $fields[] = $this->_specialFields[$key];
  153. }
  154. }
  155. }
  156. if ($record->has('tags')) {
  157. $fields[] = 'tags';
  158. }
  159. $fields = array_diff($fields, $this->_skipFields);
  160. $fields = array_merge($fields, $this->_getRelationFields());
  161. $this->_fields = $fields;
  162. if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' fields to export: ' . implode(', ', $fields));
  163. }
  164. return $this->_fields;
  165. }
  166. /**
  167. * get relation fields
  168. *
  169. * @return array
  170. */
  171. protected function _getRelationFields()
  172. {
  173. $result = array();
  174. foreach ($this->_relationsTypes as $relationType) {
  175. if (isset($this->_relationFields[$relationType])) {
  176. foreach ($this->_relationFields[$relationType] as $relationField) {
  177. $result[] = $relationType . '-' . $relationField;
  178. }
  179. } else {
  180. $result[] = $relationType;
  181. }
  182. }
  183. return $result;
  184. }
  185. /**
  186. * add rows to csv body
  187. *
  188. * @param Tinebase_Record_RecordSet $_records
  189. */
  190. public function processIteration($_records)
  191. {
  192. if (count($_records) === 0) {
  193. return;
  194. }
  195. if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Exporting ' . count($_records) . ' records ...');
  196. $this->_resolveRecords($_records);
  197. if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_records->toArray(), TRUE));
  198. foreach ($_records as $record) {
  199. $csvArray = array();
  200. foreach ($this->_getFields() as $fieldName) {
  201. if (in_array($fieldName, $this->_relationsTypes)
  202. || (! empty($this->_relationsTypes) && preg_match('/^' . implode('|', $this->_relationsTypes) . '-/', $fieldName))
  203. ) {
  204. if (strpos($fieldName, '-') !== FALSE) {
  205. list($relationType, $recordField) = explode('-', $fieldName);
  206. } else {
  207. $relationType = $fieldName;
  208. $recordField = NULL;
  209. }
  210. $csvArray[] = $this->_addRelations($record, $relationType, $recordField, TRUE);
  211. } else if (in_array($fieldName, $this->_specialFields)) {
  212. $arrayFlipped = array_flip($this->_specialFields);
  213. $csvArray[] = $this->_addSpecialValue($record, $arrayFlipped[$fieldName]);
  214. } else if ($fieldName == 'tags') {
  215. $csvArray[] = $this->_getTags($record);
  216. } else if ($fieldName == 'notes') {
  217. $csvArray[] = $this->_addNotes($record);
  218. } else if ($fieldName == 'container_id') {
  219. $csvArray[] = $this->_getContainer($record, 'id');
  220. } else if (in_array($fieldName, $this->_getCustomFieldNames())) {
  221. if (is_array($record->customfields) && (isset($record->customfields[$fieldName]) || array_key_exists($fieldName, $record->customfields))) {
  222. $csvArray[] = $record->customfields[$fieldName];
  223. } else {
  224. $csvArray[] = '';
  225. }
  226. } else {
  227. $csvArray[] = $record->{$fieldName};
  228. }
  229. }
  230. self::fputcsv($this->_filehandle, $csvArray);
  231. }
  232. }
  233. /**
  234. * get export filename
  235. *
  236. * @return string filename
  237. */
  238. public function _getFilename()
  239. {
  240. return ($this->_toStdout) ? 'STDOUT' : Tinebase_Core::getTempDir() . DIRECTORY_SEPARATOR . md5(uniqid(rand(), true)) . '.csv';
  241. }
  242. /**
  243. * get export config / csv export does not use export definitions atm
  244. *
  245. * @param array $_additionalOptions additional options
  246. * @return Zend_Config_Xml
  247. */
  248. protected function _getExportConfig($_additionalOptions = array())
  249. {
  250. return new Zend_Config($_additionalOptions);
  251. }
  252. /**
  253. * get download content type
  254. *
  255. * @return string
  256. */
  257. public function getDownloadContentType()
  258. {
  259. return 'text/csv';
  260. }
  261. }