PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Library/Kumbia/Report/Adapters/Text.php

http://kumbia-enterprise.googlecode.com/
PHP | 526 lines | 291 code | 40 blank | 195 comment | 37 complexity | d2b2b08096929e909136a51678b04ecb MD5 | raw file
  1. <?php
  2. /**
  3. * Kumbia Enterprise Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the New BSD License that is bundled
  8. * with this package in the file docs/LICENSE.txt.
  9. *
  10. * If you did not receive a copy of the license and are unable to
  11. * obtain it through the world-wide-web, please send an email
  12. * to license@loudertechnology.com so we can send you a copy immediately.
  13. *
  14. * @category Kumbia
  15. * @package Report
  16. * @subpackage Adapters
  17. * @copyright Copyright (c) 2008-2010 Louder Technology COL. (http://www.loudertechnology.com)
  18. * @license New BSD License
  19. * @version $Id: Html.php 122 2010-02-11 19:09:18Z gutierrezandresfelipe $
  20. */
  21. /**
  22. * TextReport
  23. *
  24. * Adaptador que permite generar reportes en Texto Plano
  25. *
  26. * @category Kumbia
  27. * @package Report
  28. * @subpackage Adapters
  29. * @copyright Copyright (c) 2008-2010 Louder Technology COL. (http://www.loudertechnology.com)
  30. * @license New BSD License
  31. * @abstract
  32. */
  33. class TextReport extends ReportAdapter implements ReportInterface {
  34. /**
  35. * Salida HTML
  36. *
  37. * @var string
  38. */
  39. private $_output;
  40. /**
  41. * Tamańo de texto predeterminado
  42. *
  43. * @var int
  44. * @static
  45. */
  46. private static $_defaultFontSize = 12;
  47. /**
  48. * Fuente de texto predeterminado
  49. *
  50. * @var int
  51. * @static
  52. */
  53. private static $_defaultFontFamily = "Lucida Console";
  54. /**
  55. * Alto de cada fila
  56. *
  57. * @var int
  58. */
  59. private $_rowHeight = 0;
  60. /**
  61. * Altura del encabezado
  62. *
  63. * @var int
  64. */
  65. private $_headerHeight = 0;
  66. /**
  67. * Numero total de paginas del reporte
  68. *
  69. * @var int
  70. */
  71. private $_totalPages = 0;
  72. /**
  73. * Totales de columnas
  74. *
  75. * @var array
  76. */
  77. protected $_totalizeValues = array();
  78. /**
  79. * Formatos de Columnas
  80. *
  81. * @var array
  82. */
  83. private $_columnFormats = array();
  84. /**
  85. * Número de columnas del reporte
  86. *
  87. * @var int
  88. */
  89. private $_numberColumns = null;
  90. /**
  91. * Indica si el reporte debe ser volcado a disco en cuanto se agregan los datos
  92. *
  93. * @var unknown_type
  94. */
  95. protected $_implicitFlush = false;
  96. /**
  97. * Handler al archivo temporal donde se volca el reporte
  98. *
  99. * @var handler
  100. */
  101. private $_tempFile;
  102. /**
  103. * Nombre del archivo temporal donde se volca el reporte
  104. *
  105. * @var string
  106. */
  107. private $_tempFileName;
  108. /**
  109. * Indica si el volcado del reporte ha sido iniciado
  110. *
  111. * @var boolean
  112. */
  113. private $_started = false;
  114. /**
  115. * Genera la salida del reporte
  116. *
  117. * @return string
  118. */
  119. public function getOutput(){
  120. $this->_prepareHead();
  121. $this->_renderPages();
  122. $this->_prepareFooter();
  123. return $this->_output;
  124. }
  125. /**
  126. * Inicia el reporte
  127. *
  128. * @param boolean $implicitFlush
  129. */
  130. protected function _start($implicitFlush=false){
  131. $this->_implicitFlush = $implicitFlush;
  132. if($this->_implicitFlush==true){
  133. $this->_tempFileName = 'public/temp/'.uniqid();
  134. $this->_tempFile = fopen($this->_tempFileName, 'w');
  135. $this->_prepareHead();
  136. $this->_renderHeader();
  137. $this->_appendToOutput("<p><table cellspacing='0' align='center'>\n");
  138. $this->_renderColumnHeaders();
  139. }
  140. $this->_started = true;
  141. }
  142. /**
  143. * Finalizar el reporte
  144. *
  145. */
  146. protected function _finish(){
  147. if($this->_implicitFlush==true){
  148. $this->_renderTotals();
  149. $this->_appendToOutput("</table></p>\n");
  150. $this->_prepareFooter();
  151. }
  152. }
  153. /**
  154. * Genera el encabezado del reporte
  155. *
  156. */
  157. private function _prepareHead(){
  158. if($this->_started==false){
  159. $output = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
  160. $output.= "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
  161. $output.= "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";
  162. $output.= "<head>\n";
  163. $output.= "<meta http-equiv='Content-type' content='text/plain; charset=".$this->getEncoding()."' />\n";
  164. $output.= "<meta http-equiv='Pragma' CONTENT='no-cache' />\n";
  165. $output.= "\t\t<meta http-equiv='Cache-Control' CONTENT='no-cache' />\n";
  166. $output.= "\t\t<title>".$this->getDocumentTitle()."</title>\n";
  167. $output.= "\t\t<style type='text/css'>\n";
  168. $output.= "\t\t\tbody, div, td, th { font-family: \"".self::$_defaultFontFamily."\"; font-size: ".self::$_defaultFontSize."px; }\n";
  169. $output.= "\t\t\ttable { border: none; }\n";
  170. $output.= "\t\t\tth, td { border: none; font-weight: normal; padding-left: 10px; }\n";
  171. $output.= "\t\t\tbody { margin: 0px; padding: 0px; }\n";
  172. $this->_appendToOutput($output);
  173. $this->_prepareCellHeaderStyle();
  174. $this->_prepareColumnStyles();
  175. $this->_prepareColumnFormats();
  176. $this->_prepareTotalizedColumns();
  177. $this->_appendToOutput("\t\t</style>\n");
  178. $this->_appendToOutput("\t</head>\n");
  179. $this->_appendToOutput("\t<body>\n");
  180. }
  181. }
  182. protected function _prepareFooter(){
  183. $this->_appendToOutput("\t</body>\n");
  184. $this->_appendToOutput("</html>\n");
  185. }
  186. /**
  187. * Agrega una cadena al reporte
  188. *
  189. * @param string $output
  190. */
  191. private function _appendToOutput($output){
  192. if($this->_implicitFlush==true){
  193. fwrite($this->_tempFile, $output);
  194. unset($output);
  195. } else {
  196. $this->_output.=$output;
  197. }
  198. }
  199. /**
  200. * Escribe los estilos de los encabezados del reporte
  201. *
  202. * @access protected
  203. */
  204. protected function _prepareCellHeaderStyle(){
  205. }
  206. /**
  207. * Obtiene los formatos asignados a las columnas del reporte
  208. *
  209. * @access protected
  210. */
  211. protected function _prepareColumnFormats(){
  212. $this->_columnFormats = $this->getColumnFormats();
  213. }
  214. /**
  215. * Obtiene los valores base de totales de las columnas
  216. *
  217. * @access protected
  218. */
  219. protected function _prepareTotalizedColumns(){
  220. $this->_totalizeValues = $this->getTotalizeValues();
  221. }
  222. /**
  223. * Escribe los estilos de las columnas del reporte
  224. *
  225. * @access protected
  226. */
  227. protected function _prepareColumnStyles(){
  228. $styles = $this->getColumnStyles();
  229. if(count($styles)){
  230. foreach($styles as $numberColumn => $style){
  231. $columnStyle = $style->getStyles();
  232. $preparedStyle = $this->_prepareStyle($columnStyle);
  233. $this->_appendToOutput("\t\t\t.c$numberColumn { ".join(";", $preparedStyle)."; }\n");
  234. }
  235. }
  236. }
  237. public function _prepareStyle($attributes){
  238. $style = array();
  239. foreach($attributes as $attributeName => $value){
  240. switch($attributeName){
  241. case 'textAlign':
  242. $style[] = 'text-align:'.$value;
  243. break;
  244. case 'paddingRight':
  245. $style[] = 'padding-right:'.$value;
  246. break;
  247. }
  248. }
  249. return $style;
  250. }
  251. /**
  252. * Renderiza el encabezado del documento
  253. *
  254. */
  255. protected function _renderHeader(){
  256. $header = $this->getHeader();
  257. if(is_array($header)){
  258. foreach($header as $item){
  259. $this->_renderItem($item);
  260. }
  261. } else {
  262. $this->_renderItem($item);
  263. }
  264. }
  265. /**
  266. * Renderiza un item
  267. *
  268. * @param mixed $item
  269. * @return array
  270. */
  271. protected function _renderItem($item){
  272. if(is_string($item)){
  273. $this->_appendToOutput($item);
  274. return;
  275. }
  276. if(is_object($item)==true){
  277. if(get_class($item)=="ReportText"){
  278. $html = "<div ";
  279. $itemStyle = $item->getAttributes();
  280. $style = $this->_prepareStyle($itemStyle);
  281. if(count($style)){
  282. $html.="style='".join(";", $style)."'";
  283. }
  284. $html.=">".$this->_prepareText($item->getText())."</div>\n";
  285. $this->_appendToOutput($html);
  286. return $itemStyle;
  287. }
  288. }
  289. }
  290. /**
  291. * Escribe los encabezados del reporte
  292. *
  293. */
  294. private function _renderColumnHeaders(){
  295. $output = "<thead>\n";
  296. foreach($this->getColumnHeaders() as $header){
  297. $output.="<th>$header</th>\n";
  298. }
  299. $output.="</thead>\n";
  300. $this->_appendToOutput($output);
  301. }
  302. /**
  303. * Crea un thumbnail
  304. *
  305. * @param int $pageNumber
  306. * @return string
  307. */
  308. private function _getPageThumbnail($pageNumber){
  309. $numColumns = count($this->getColumnHeaders());
  310. if($numColumns==0||$numColumns>6){
  311. $numColumns = 4;
  312. }
  313. $code = "<div class='thumbnail' align='center'>
  314. <a href='#$pageNumber'>
  315. <table cellspacing='0' cellpadding='0' width='50'><tr>";
  316. for($i=0;$i<$numColumns;++$i){
  317. $code.="<th></th>";
  318. }
  319. $code.="</tr>";
  320. for($j=0;$j<9;++$j){
  321. $code.="<tr>";
  322. for($i=0;$i<$numColumns;++$i){
  323. $code.="<td></td>";
  324. }
  325. $code.="</tr>";
  326. }
  327. $code.="</table>$pageNumber</a></div>";
  328. return $code;
  329. }
  330. /**
  331. * Escribe las páginas del reporte
  332. *
  333. * @param array $rows
  334. */
  335. private function _renderRows($rows){
  336. foreach($rows as $row){
  337. $this->_renderRow($row);
  338. }
  339. }
  340. /**
  341. * Agrega una fila al reporte en implicit flush
  342. *
  343. * @param array $row
  344. */
  345. protected function _addRow($row){
  346. $this->_renderRow($row);
  347. }
  348. /**
  349. * Escribe una fila del reporte
  350. *
  351. * @param array $row
  352. */
  353. private function _renderRow($row){
  354. $output = "<tr>\n";
  355. if($row['_type']=='normal'){
  356. unset($row['_type']);
  357. if($this->_numberColumns===null){
  358. $this->_numberColumns = count($row);
  359. }
  360. foreach($row as $numberColumn => $value){
  361. if(isset($this->_totalizeColumns[$numberColumn])){
  362. if(!isset($this->_totalizeValues[$numberColumn])){
  363. $this->_totalizeValues[$numberColumn] = 0;
  364. }
  365. $this->_totalizeValues[$numberColumn]+=$value;
  366. }
  367. if(isset($this->_columnFormats[$numberColumn])){
  368. $value = $this->_columnFormats[$numberColumn]->apply($value);
  369. }
  370. $output.="<td class='c$numberColumn'>$value</td>\n";
  371. }
  372. } else {
  373. if($row['_type']=='raw'){
  374. unset($row['_type']);
  375. foreach($row as $numberColumn => $rawColumn){
  376. $output.="<td colspan='".$rawColumn->getSpan()."'";
  377. $styles = $rawColumn->getStyle();
  378. if($styles){
  379. $style = $this->_prepareStyle($styles);
  380. $output.=" style='".join(';', $style)."' ";
  381. }
  382. $output.=">".$rawColumn->getValue()."</td>\n";
  383. unset($rawColumn);
  384. }
  385. }
  386. }
  387. $output.="</tr>\n";
  388. $this->_appendToOutput($output);
  389. }
  390. /**
  391. * Escribe las páginas del reporte
  392. *
  393. */
  394. private function _renderPages(){
  395. $output = '';
  396. $data = $this->getRows();
  397. if($this->getPagination()==true){
  398. $calculatedOffset = $this->getRowsPerPage();
  399. $renderRows = 0;
  400. $numberRows = count($data);
  401. if($calculatedOffset!=0){
  402. $rowsToRender = $calculatedOffset;
  403. } else {
  404. $calculatedOffset = -1;
  405. $rowsToRender = 0;
  406. }
  407. $pageNumber = 1;
  408. if($numberRows>0){
  409. while($renderRows<$numberRows){
  410. $this->_appendToOutput("<div align='center'><div class='page'><a name='$pageNumber'>\n");
  411. $this->_renderHeader();
  412. if($calculatedOffset==-1){
  413. $calculatedOffset = ceil(($this->_rowHeight*$numberRows+$this->_headerHeight+20)/700);
  414. $rowsToRender = floor($numberRows/$calculatedOffset);
  415. }
  416. $this->_appendToOutput("<p><table cellspacing='0'>\n");
  417. $this->_renderColumnHeaders();
  418. $this->_renderRows(array_slice($data, $renderRows, $rowsToRender));
  419. $this->_renderTotals();
  420. $this->_appendToOutput("</table></p>\n");
  421. $this->_appendToOutput("</div></div>\n");
  422. $renderRows+=$rowsToRender;
  423. ++$pageNumber;
  424. $this->_setPageNumber($pageNumber);
  425. }
  426. } else {
  427. $this->_appendToOutput("<div align='center'><div class='page'><a name='$pageNumber'>\n");
  428. $this->_renderHeader();
  429. $this->_appendToOutput("<p><table cellspacing='0'>\n");
  430. $this->_renderColumnHeaders();
  431. $this->_appendToOutput("</table></p>\n");
  432. $this->_appendToOutput("</div></div>\n");
  433. ++$pageNumber;
  434. $this->_setPageNumber($pageNumber);
  435. }
  436. $this->_totalPages = $pageNumber;
  437. } else {
  438. $this->_renderHeader();
  439. $this->_appendToOutput("<p><table cellspacing='0' align='center'>\n");
  440. $this->_renderColumnHeaders();
  441. $this->_renderRows($data);
  442. $this->_renderTotals();
  443. $this->_appendToOutput("</table></p>\n");
  444. }
  445. }
  446. /**
  447. * Renombra el archivo temporal del volcado al nombre dado por el usuario
  448. *
  449. * @param string $path
  450. * @return boolean
  451. */
  452. protected function _moveOutputTo($path){
  453. if(rename($this->_tempFileName, $path)){
  454. return basename('/'.$path);
  455. }
  456. }
  457. /**
  458. * Visualiza los totales del reporte
  459. *
  460. */
  461. private function _renderTotals(){
  462. if(count($this->_totalizeValues)>0){
  463. $output = '<tr>';
  464. for($i=0;$i<$this->_numberColumns;++$i){
  465. if(isset($this->_totalizeValues[$i])){
  466. if(isset($this->_columnFormats[$i])){
  467. $this->_totalizeValues[$i] = $this->_columnFormats[$i]->apply($this->_totalizeValues[$i]);
  468. }
  469. $output.='<td class="c'.$i.'">'.$this->_totalizeValues[$i].'</td>';
  470. } else {
  471. $output.='<td class="c'.$i.'"></td>';
  472. }
  473. }
  474. $output.='</tr>';
  475. $this->_appendToOutput($output);
  476. }
  477. }
  478. /**
  479. * Devuelve la extension del archivo recomendada
  480. *
  481. * @return string
  482. */
  483. protected function getFileExtension(){
  484. return 'html';
  485. }
  486. }