diff --git a/views_pdf_plugin_style_table.inc b/views_pdf_plugin_style_table.inc index 678f985..8fce8f4 100644 --- a/views_pdf_plugin_style_table.inc +++ b/views_pdf_plugin_style_table.inc @@ -14,15 +14,27 @@ class views_pdf_plugin_style_table extends views_plugin_style { /** - * Render the style + * Render the PDF table document. + * + * Unlike the HTML style renderers, the PDF table is a side-effect of + * this function, not the result; it assumes that the view has a pdf property + * initialized with a PdfTemplate instance, and adds to that. + * + * @return + * An empty string. */ function render() { - $output = ''; - - $this->view->numberOfRecords = count($this->view->result); - $this->view->pdf->drawTable($this->view, $this->options); - - return $output; + $this->view->numberOfRecords = count($this->view->result); + $this->view->pdf->finalizeColumns($this->view, $this->options); + // Group the rows according to the grouping field, if specified. + $sets = $this->render_grouping($this->view->result, $this->options['grouping']); + foreach ($sets as $title => $rows) { + if (!empty($title)) { + $this->view->numberOfRecords += 2; + } + $this->view->pdf->drawTable($this->view, $title, $rows, $this->options); + } + return ''; } diff --git a/views_pdf_template.php b/views_pdf_template.php index 1faa138..1f61557 100644 --- a/views_pdf_template.php +++ b/views_pdf_template.php @@ -44,7 +44,12 @@ class PdfTemplate extends FPDI protected $headerFooterOptions = array(); protected $lastWritingPage = 1; protected $lastWritingPositions; - + protected $defaultColumnWidth = 0; + protected $rowX = 0; + protected $rowY = 0; + protected $rowHeight = 0; + protected $rowWidth = 0; + protected $groupHeadOptions = NULL; protected static $defaultFontList = array( @@ -202,22 +207,18 @@ class PdfTemplate extends FPDI } /** - * This method draws a field on the PDF. + * Initialize context settings in the format PdfTemplate::renderRow uses. + * + * @param $optionRoot + * The array to which to add the settings. */ - public function drawContent($row, $options, &$view = NULL, $key = NULL, $printLabels = TRUE) { - - if (!is_array($options)) { - $options = array(); - } - - // Set defaults: - $options += array( + protected function initializeOptions(&$optionRoot) { + $optionRoot += array( 'position' => array(), 'text' => array(), 'render' => array(), - ); - - $options['position'] += array( + ); + $optionRoot['position'] += array( 'corner' => 'top_left', 'x' => 0, 'y' => 0, @@ -225,18 +226,27 @@ class PdfTemplate extends FPDI 'width' => 0, 'height' => 0, ); - - $options['text'] += array( + $optionRoot['text'] += array( 'font_family' => 'default', 'font_style' => '', ); - - $options['render'] += array( + $optionRoot['render'] += array( 'eval_before' => '', 'eval_after' => '', ); + } + + /** + * This method draws a field on the PDF. + */ + public function drawContent($row, $options, &$view = NULL, $key = NULL, $printLabels = TRUE) { + + if (!is_array($options)) { + $options = array(); + } - + // Set defaults: + $this->initializeOptions($options); // Get the page dimensions $pageDim = $this->getPageDimensions(); @@ -513,215 +523,187 @@ class PdfTemplate extends FPDI } /** - * This method draws a table on the PDF. + * Subdivide unallocated space evenly between widthless columns. + * + * @param $cols + * The view fields represented as columns. + * @param $options + * Options array appropriate for a PDF table style plugin. */ - public function drawTable(&$view, $options) { - - $rows = $view->result; - $columns = $view->field; - $pageDim = $this->getPageDimensions(); - - // Set draw point to the indicated position: - if (empty($options['position']['x'])) { - $options['position']['x'] = 0; + protected function subdivideWidth($cols, &$options) { + $sumWidth = 0; + $nWidthless = 0; + foreach ($cols as $id => $columnName) { + if (isset($options['info'][$id]['position']['width']) && !empty($options['info'][$id]['position']['width'])){ + $sumWidth += $options['info'][$id]['position']['width']; + } + else { + $nWidthless++; + } } - - if (empty($options['position']['y'])) { - $options['position']['y'] = 0; + if ($nWidthless > 0 && $sumWidth < $this->rowWidth) { + $this->defaultColumnWidth = ($this->rowWidth - $sumWidth) / $nWidthless; + } + else { + $this->defaultColumnWidth = 0; + } + } + + /** + * Extend the options with table cell rendering settings. + * + * @param $id + * The view field key string. + * @param $stylekey + * A string to identify the type of table cell. + * @param $objpos + * Position string. + * @param $options + * Options array appropriate for a PDF table style plugin. + */ + protected function addTableCellOptions($id, $stylekey, $objpos, &$options) { + if (!isset($options['info'][$id])) { + $options['info'][$id] += array($stylekey => array()); + $styleopt = &$options['info'][$id][$stylekey]; + $this->initializeOptions($styleopt); + } + else { + $styleopt = &$options['info'][$id][$stylekey]; } + $styleopt['position']['object'] = $objpos; + $styleopt['position']['width'] = ((isset($options['info'][$id]['position']['width']) && !empty($options['info'][$id]['position']['width'])) + ? $options['info'][$id]['position']['width'] + : $this->defaultColumnWidth); + } + + /** + * Finalize column definitions in preparation for drawing tables. + * + * @param $view + * The view to be displayed as tables. + * @param $options + * Options array appropriate for a PDF table style plugin. + */ + public function finalizeColumns(&$view, &$options) { + // Set draw point to the indicated position: + $inx = (empty($options['position']['x'])) ? 0 : $options['position']['x']; + $iny = (empty($options['position']['y'])) ? 0 : $options['position']['y']; if (isset($options['position']['last_writing_position']) && $options['position']['last_writing_position']) { - $y = $options['position']['y'] + $this->y; - $x = $options['position']['x'] + $this->x; + $this->rowY = $iny + $this->y; + $this->rowX = $inx + $this->x; } else { - $y = $options['position']['y']; - $x = $options['position']['x']; + $this->rowY = $iny; + $this->rowX = $inx; } - if (isset($options['position']['width']) && !empty($options['position']['width'])) { - $width = $options['position']['width']; + if (isset($options['position']['row_height']) && !empty($options['position']['row_height'])) { + $this->rowHeight = $options['position']['row_height']; } else { - $width = $pageDim['wk'] - $this->rMargin - $x; + $this->rowHeight = 0; } - $sumWidth = 0; - $numberOfColumnsWithoutWidth = 0; - - // Set the definitiv width of a column - foreach ($columns as $id => $columnName) { - if (isset($options['info'][$id]['position']['width']) && !empty($options['info'][$id]['position']['width'])){ - $sumWidth += $options['info'][$id]['position']['width']; - } - else { - $numberOfColumnsWithoutWidth++; + if (isset($options['position']['width']) && !empty($options['position']['width'])) { + $this->rowWidth = $options['position']['width']; + } + else { + $pageDim = $this->getPageDimensions(); + $this->rowWidth = $pageDim['wk'] - $this->rMargin - $x; + } + $this->subdivideWidth($view->field, $options); + $this->groupHeadOptions = array(); + $this->initializeOptions($this->groupHeadOptions); + $this->groupHeadOptions['position']['width'] = $this->rowWidth; + $this->groupHeadOptions['text']['align'] = 'C'; + foreach ($view->field as $id => $column) { + if (empty($column->options['exclude'])) { + $this->addTableCellOptions($id, 'header_style', 'last_position_without_reset', $options); + $this->addTableCellOptions($id, 'body_style', 'last_position', $options); } } - if ($numberOfColumnsWithoutWidth > 0) { - $defaultColumnWidth = ($width - $sumWidth) / $numberOfColumnsWithoutWidth; + } + + /** + * Set the row position, allowing for page breaks. + * + * @param $x + * Local horizontal position. + * @param $y + * Local vertical position. + */ + protected function positionRow(&$x, &$y) { + $pageDim = $this->getPageDimensions(); + if (($this->rowY + $this->bMargin + $this->rowHeight) > $pageDim['hk']) { + $this->rowY = $this->tMargin; + $this->addPage(); } - else { - $defaultColumnWidth = 0; + if ($this->lastWritingPage != $this->getPage()) { + $this->rowY = $this->y; // $rowY - $pageDim['hk'] } - - // Print header: - $rowX = $x; - $page = $this->getPage(); - if ($page == 0) { + $x = $this->rowX; + $y = $this->rowY; + } + + /** + * This method draws a table on the PDF. + */ + public function drawTable(&$view, $group_heading, $rows, &$options) { + $x = $this->rowX; + $y = $this->rowY; + $columns = $view->field; + if ($this->getPage() == 0) { $this->addPage(); - $page = $this->getPage(); } - - if (!isset($options['position']['row_height']) || empty($options['position']['row_height'])) { - $options['position']['row_height'] = 0; - } - + if (!empty($group_heading)) { + $this->rowY += $this->rowHeight; + $this->positionRow($x, $y); + $this->renderRow($x, $y, $group_heading, $this->groupHeadOptions); + $this->rowY = $this->y; + } + $this->positionRow($x, $y); foreach ($columns as $id => $column) { - if (!empty($column->options['exclude'])) { continue; } - - $options['info'][$id] += array( - 'header_style' => array(), - 'body_style' => array(), - ); - - $options['info'][$id]['header_style'] += array( - 'position' => array(), - 'text' => array(), - 'render' => array(), - ); - - $options['info'][$id]['header_style']['position'] += array( - 'corner' => 'top_left', - 'x' => NULL, - 'y' => NULL, - 'object' => '', - 'width' => NULL, - 'height' => NULL, - ); - - $options['info'][$id]['header_style']['text'] += array( - 'font_family' => 'default', - 'font_style' => '', - ); - - $options['info'][$id]['header_style']['text'] += array( - 'eval_before' => '', - 'eval_after' => '', - ); - - $options['info'][$id]['body_style'] += array( - 'position' => array(), - 'text' => array(), - 'render' => array(), - ); - - $options['info'][$id]['body_style']['position'] += array( - 'corner' => 'top_left', - 'x' => NULL, - 'y' => NULL, - 'object' => '', - 'width' => NULL, - 'height' => NULL, - ); - - $options['info'][$id]['body_style']['text'] += array( - 'font_family' => 'default', - 'font_style' => '', - ); - - $options['info'][$id]['body_style']['text'] += array( - 'eval_before' => '', - 'eval_after' => '', - ); - - $headerOptions = $options['info'][$id]['header_style']; - - if (isset($options['info'][$id]['position']['width']) && !empty($options['info'][$id]['position']['width'])){ - $headerOptions['position']['width'] = $options['info'][$id]['position']['width']; - } - else { - $headerOptions['position']['width'] = $defaultColumnWidth; - } - $headerOptions['position']['object'] = 'last_position_without_reset'; - $this->SetY($y); $this->SetX($x); - $this->setPage($page); - + $headerOptions = $options['info'][$id]['header_style']; $this->renderRow($x, $y, $column->options['label'], $headerOptions); $x += $headerOptions['position']['width']; } - $rowY = $this->y; - - if (!isset($options['position']['row_height']) || empty($options['position']['row_height'])) { - $options['position']['row_height'] = 0; - } - + $this->rowY = $this->y; foreach ($rows as $row) { - $x = $rowX; - - // Get the page dimensions - $pageDim = $this->getPageDimensions(); - - if (($rowY + $this->bMargin + $options['position']['row_height']) > $pageDim['hk']) { - $rowY = $this->tMargin; - $this->addPage(); - } - - if ($this->lastWritingPage != $this->getPage()) { - $rowY = $this->y; // $rowY - $pageDim['hk'] - } - - $y = $rowY; - $page = $this->getPage(); + $this->positionRow($x, $y); foreach ($columns as $id => $column) { - if (!empty($column->options['exclude']) && is_object($view->field[$id])) { // Render the element, but dont print the output. This // is required to allow the use of tokens in other fields. $view->field[$id]->theme($row); continue; } - - $bodyOptions = $options['info'][$id]['body_style']; - - if (isset($options['info'][$id]['position']['width']) && !empty($options['info'][$id]['position']['width'])){ - $bodyOptions['position']['width'] = $options['info'][$id]['position']['width']; - } - else { - $bodyOptions['position']['width'] = $defaultColumnWidth; - } - $bodyOptions['position']['object'] = 'last_position'; - - $this->setPage($page); $this->SetY($y); $this->SetX($x); - - $bodyOptions['position']['height'] = 0; - - $this->renderRow($x, $y, $row, $bodyOptions, $view, $id); - + $bodyOptions = $options['info'][$id]['body_style']; + $this->renderRow($x, $y, $row, $bodyOptions, $view, $id, FALSE); $x += $bodyOptions['position']['width']; // If the cell is writting over the row, we need to adjust the // row y position. - if (($rowY + $options['position']['row_height']) < $this->y) { - $rowY = $this->y - $options['position']['row_height']; + if (($this->rowY + $this->rowHeight) < $this->y) { + $this->rowY = $this->y - $this->rowHeight; } } - $rowY += $options['position']['row_height']; + $this->rowY += $this->rowHeight; } - $this->SetY($rowY + $options['position']['row_height']); + $this->SetY($this->rowY + $this->rowHeight); }