PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/dompdf/dompdf/include/table_frame_decorator.cls.php

https://gitlab.com/techniconline/kmc
PHP | 358 lines | 169 code | 65 blank | 124 comment | 24 complexity | e0c7be15de58f05b450b990b2c158ec1 MD5 | raw file
  1. <?php
  2. /**
  3. * @package dompdf
  4. * @link http://dompdf.github.com/
  5. * @author Benj Carson <benjcarson@digitaljunkies.ca>
  6. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  7. */
  8. /**
  9. * Decorates Frames for table layout
  10. *
  11. * @access private
  12. * @package dompdf
  13. */
  14. class Table_Frame_Decorator extends Frame_Decorator
  15. {
  16. static $VALID_CHILDREN = array("table-row-group",
  17. "table-row",
  18. "table-header-group",
  19. "table-footer-group",
  20. "table-column",
  21. "table-column-group",
  22. "table-caption",
  23. "table-cell");
  24. static $ROW_GROUPS = array('table-row-group',
  25. 'table-header-group',
  26. 'table-footer-group');
  27. /**
  28. * The Cellmap object for this table. The cellmap maps table cells
  29. * to rows and columns, and aids in calculating column widths.
  30. *
  31. * @var Cellmap
  32. */
  33. protected $_cellmap;
  34. /**
  35. * The minimum width of the table, in pt
  36. *
  37. * @var float
  38. */
  39. protected $_min_width;
  40. /**
  41. * The maximum width of the table, in pt
  42. *
  43. * @var float
  44. */
  45. protected $_max_width;
  46. /**
  47. * Table header rows. Each table header is duplicated when a table
  48. * spans pages.
  49. *
  50. * @var array
  51. */
  52. protected $_headers;
  53. /**
  54. * Table footer rows. Each table footer is duplicated when a table
  55. * spans pages.
  56. *
  57. * @var array
  58. */
  59. protected $_footers;
  60. /**
  61. * Class constructor
  62. *
  63. * @param Frame $frame the frame to decorate
  64. * @param DOMPDF $dompdf
  65. */
  66. function __construct(Frame $frame, DOMPDF $dompdf)
  67. {
  68. parent::__construct($frame, $dompdf);
  69. $this->_cellmap = new Cellmap($this);
  70. if ($frame->get_style()->table_layout === "fixed") {
  71. $this->_cellmap->set_layout_fixed(true);
  72. }
  73. $this->_min_width = null;
  74. $this->_max_width = null;
  75. $this->_headers = array();
  76. $this->_footers = array();
  77. }
  78. function reset()
  79. {
  80. parent::reset();
  81. $this->_cellmap->reset();
  82. $this->_min_width = null;
  83. $this->_max_width = null;
  84. $this->_headers = array();
  85. $this->_footers = array();
  86. $this->_reflower->reset();
  87. }
  88. //........................................................................
  89. /**
  90. * split the table at $row. $row and all subsequent rows will be
  91. * added to the clone. This method is overidden in order to remove
  92. * frames from the cellmap properly.
  93. *
  94. * @param Frame $child
  95. * @param bool $force_pagebreak
  96. *
  97. * @return void
  98. */
  99. function split(Frame $child = null, $force_pagebreak = false)
  100. {
  101. if (is_null($child)) {
  102. parent::split();
  103. return;
  104. }
  105. // If $child is a header or if it is the first non-header row, do
  106. // not duplicate headers, simply move the table to the next page.
  107. if (count($this->_headers) && !in_array($child, $this->_headers, true) &&
  108. !in_array($child->get_prev_sibling(), $this->_headers, true)
  109. ) {
  110. $first_header = null;
  111. // Insert copies of the table headers before $child
  112. foreach ($this->_headers as $header) {
  113. $new_header = $header->deep_copy();
  114. if (is_null($first_header))
  115. $first_header = $new_header;
  116. $this->insert_child_before($new_header, $child);
  117. }
  118. parent::split($first_header);
  119. } else if (in_array($child->get_style()->display, self::$ROW_GROUPS)) {
  120. // Individual rows should have already been handled
  121. parent::split($child);
  122. } else {
  123. $iter = $child;
  124. while ($iter) {
  125. $this->_cellmap->remove_row($iter);
  126. $iter = $iter->get_next_sibling();
  127. }
  128. parent::split($child);
  129. }
  130. }
  131. /**
  132. * Return a copy of this frame with $node as its node
  133. *
  134. * @param DOMNode $node
  135. * @return Frame
  136. */
  137. function copy(DOMNode $node)
  138. {
  139. $deco = parent::copy($node);
  140. // In order to keep columns' widths through pages
  141. $deco->_cellmap->set_columns($this->_cellmap->get_columns());
  142. $deco->_cellmap->lock_columns();
  143. return $deco;
  144. }
  145. /**
  146. * Static function to locate the parent table of a frame
  147. *
  148. * @param Frame $frame
  149. * @return Table_Frame_Decorator the table that is an ancestor of $frame
  150. */
  151. static function find_parent_table(Frame $frame)
  152. {
  153. while ($frame = $frame->get_parent())
  154. if ($frame->is_table())
  155. break;
  156. return $frame;
  157. }
  158. /**
  159. * Return this table's Cellmap
  160. *
  161. * @return Cellmap
  162. */
  163. function get_cellmap()
  164. {
  165. return $this->_cellmap;
  166. }
  167. /**
  168. * Return the minimum width of this table
  169. *
  170. * @return float
  171. */
  172. function get_min_width()
  173. {
  174. return $this->_min_width;
  175. }
  176. /**
  177. * Return the maximum width of this table
  178. *
  179. * @return float
  180. */
  181. function get_max_width()
  182. {
  183. return $this->_max_width;
  184. }
  185. /**
  186. * Set the minimum width of the table
  187. *
  188. * @param float $width the new minimum width
  189. */
  190. function set_min_width($width)
  191. {
  192. $this->_min_width = $width;
  193. }
  194. /**
  195. * Set the maximum width of the table
  196. *
  197. * @param float $width the new maximum width
  198. */
  199. function set_max_width($width)
  200. {
  201. $this->_max_width = $width;
  202. }
  203. /**
  204. * Restructure tree so that the table has the correct structure.
  205. * Invalid children (i.e. all non-table-rows) are moved below the
  206. * table.
  207. */
  208. function normalise()
  209. {
  210. // Store frames generated by invalid tags and move them outside the table
  211. $erroneous_frames = array();
  212. $anon_row = false;
  213. $iter = $this->get_first_child();
  214. while ($iter) {
  215. $child = $iter;
  216. $iter = $iter->get_next_sibling();
  217. $display = $child->get_style()->display;
  218. if ($anon_row) {
  219. if ($display === "table-row") {
  220. // Add the previous anonymous row
  221. $this->insert_child_before($table_row, $child);
  222. $table_row->normalise();
  223. $child->normalise();
  224. $anon_row = false;
  225. continue;
  226. }
  227. // add the child to the anonymous row
  228. $table_row->append_child($child);
  229. continue;
  230. } else {
  231. if ($display === "table-row") {
  232. $child->normalise();
  233. continue;
  234. }
  235. if ($display === "table-cell") {
  236. // Create an anonymous table row
  237. $tr = $this->get_node()->ownerDocument->createElement("tr");
  238. $frame = new Frame($tr);
  239. $css = $this->get_style()->get_stylesheet();
  240. $style = $css->create_style();
  241. $style->inherit($this->get_style());
  242. // Lookup styles for tr tags. If the user wants styles to work
  243. // better, they should make the tr explicit... I'm not going to
  244. // try to guess what they intended.
  245. if ($tr_style = $css->lookup("tr"))
  246. $style->merge($tr_style);
  247. // Okay, I have absolutely no idea why I need this clone here, but
  248. // if it's omitted, php (as of 2004-07-28) segfaults.
  249. $frame->set_style(clone $style);
  250. $table_row = Frame_Factory::decorate_frame($frame, $this->_dompdf, $this->_root);
  251. // Add the cell to the row
  252. $table_row->append_child($child);
  253. $anon_row = true;
  254. continue;
  255. }
  256. if (!in_array($display, self::$VALID_CHILDREN)) {
  257. $erroneous_frames[] = $child;
  258. continue;
  259. }
  260. // Normalise other table parts (i.e. row groups)
  261. foreach ($child->get_children() as $grandchild) {
  262. if ($grandchild->get_style()->display === "table-row") {
  263. $grandchild->normalise();
  264. }
  265. }
  266. // Add headers and footers
  267. if ($display === "table-header-group")
  268. $this->_headers[] = $child;
  269. else if ($display === "table-footer-group")
  270. $this->_footers[] = $child;
  271. }
  272. }
  273. if ($anon_row) {
  274. // Add the row to the table
  275. $this->_frame->append_child($table_row);
  276. $table_row->normalise();
  277. $this->_cellmap->add_row();
  278. }
  279. foreach ($erroneous_frames as $frame)
  280. $this->move_after($frame);
  281. }
  282. //........................................................................
  283. /**
  284. * Moves the specified frame and it's corresponding node outside of
  285. * the table.
  286. *
  287. * @param Frame $frame the frame to move
  288. */
  289. function move_after(Frame $frame)
  290. {
  291. $this->get_parent()->insert_child_after($frame, $this);
  292. }
  293. }