ElementBox   D
last analyzed

Complexity

Total Complexity 59

Size/Duplication

Total Lines 272
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 59
eloc 157
dl 0
loc 272
rs 4.08
c 3
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A spanAllRows() 0 8 2
B getBoxesByTagName() 0 17 8
D fixTables() 0 95 21
A setElement() 0 6 1
D buildTree() 0 90 26
A getElement() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like ElementBox often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ElementBox, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * ElementBox class.
6
 *
7
 * @package   YetiForcePDF\Layout
8
 *
9
 * @copyright YetiForce Sp. z o.o
10
 * @license   MIT
11
 * @author    Rafal Pospiech <[email protected]>
12
 */
13
14
namespace YetiForcePDF\Layout;
15
16
use YetiForcePDF\Html\Element;
17
18
/**
19
 * Class ElementBox.
20
 */
21
class ElementBox extends Box
22
{
23
	/**
24
	 * @var Element
25
	 */
26
	protected $element;
27
28
	/**
29
	 * Get element.
30
	 *
31
	 * @return Element
32
	 */
33
	public function getElement()
34
	{
35
		return $this->element;
36
	}
37
38
	/**
39
	 * Set element.
40
	 *
41
	 * @param Element $element
42
	 *
43
	 * @return $this
44
	 */
45
	public function setElement(Element $element)
46
	{
47
		$this->element = $element;
48
		$element->setBox($this);
49
50
		return $this;
51
	}
52
53
	/**
54
	 * Get boxes by tag name.
55
	 *
56
	 * @param string $tagName
57
	 *
58
	 * @return array
59
	 */
60
	public function getBoxesByTagName(string $tagName)
61
	{
62
		$boxes = [];
63
		$allChildren = [];
64
		$this->getAllChildren($allChildren);
65
		foreach ($allChildren as $child) {
66
			if ($child instanceof self && $child->getElement() && $child->getElement()->getDOMElement()) {
67
				if (isset($child->getElement()->getDOMElement()->tagName)) {
68
					$elementTagName = $child->getElement()->getDOMElement()->tagName;
69
					if ($elementTagName && strtolower($elementTagName) === strtolower($tagName)) {
70
						$boxes[] = $child;
71
					}
72
				}
73
			}
74
		}
75
76
		return $boxes;
77
	}
78
79
	/**
80
	 * Fix tables - iterate through cells and insert missing one.
81
	 *
82
	 * @return $this
83
	 */
84
	public function fixTables()
85
	{
86
		$tables = $this->getBoxesByType('TableWrapperBox');
87
		foreach ($tables as $tableWrapperBox) {
88
			$tableBox = $tableWrapperBox->getFirstChild();
89
			$rowGroups = $tableBox->getChildren();
90
			foreach ($rowGroups as $rowGroup) {
91
				// wrap rows with row groups
92
				if ($rowGroup instanceof TableRowBox) {
93
					if (!isset($wrapRowGroup)) {
94
						$wrapRowGroup = $tableBox->removeChild($tableBox->createRowGroupBox());
95
						$tableBox->insertBefore($wrapRowGroup, $rowGroup);
96
					}
97
					$wrapRowGroup->appendChild($tableBox->removeChild($rowGroup));
98
				}
99
			}
100
			unset($wrapRowGroup);
101
			$rowGroups = $tableBox->getChildren();
102
			if (empty($rowGroups)) {
103
				$rowGroup = $tableBox->createRowGroupBox();
104
				$row = $rowGroup->createRowBox();
105
				$column = $row->createColumnBox();
106
				$column->createCellBox();
107
			} else {
108
				$columnsCount = 0;
109
				foreach ($rowGroups as $rowGroup) {
110
					if (!$rowGroup->hasChildren()) {
111
						$row = $rowGroup->createRowBox();
112
						$column = $row->createColumnBox();
113
						$column->createCellBox();
114
					}
115
					foreach ($rowGroup->getChildren() as $rowIndex => $row) {
116
						$columns = $row->getChildren();
117
						$columnsCount = max($columnsCount, \count($columns));
118
						foreach ($columns as $columnIndex => $column) {
119
							if ($column->getRowSpan() > 1) {
120
								$rowSpans = $column->getRowSpan();
121
								for ($i = 1; $i < $rowSpans; ++$i) {
122
									$nextRow = $rowGroup->getChildren()[$rowIndex + $i];
123
									$rowChildren = $nextRow->getChildren();
124
									$insertColumn = $nextRow->removeChild($nextRow->createColumnBox());
125
									if (isset($rowChildren[$columnIndex])) {
126
										$before = $rowChildren[$columnIndex];
127
										$nextRow->insertBefore($insertColumn, $before);
128
									} else {
129
										$nextRow->appendChild($insertColumn);
130
									}
131
									$insertColumn->setStyle(clone $column->getStyle());
132
									$insertColumn->getStyle()->setBox($insertColumn);
133
									$insertCell = $insertColumn->createCellBox();
134
									$insertCell->setStyle(clone $column->getFirstChild()->getStyle());
135
									$insertCell->getStyle()->setBox($insertCell);
136
								}
137
							}
138
						}
139
					}
140
					foreach ($rowGroup->getChildren() as $row) {
141
						$columns = $row->getChildren();
142
						$missing = $columnsCount - \count($columns);
143
						for ($i = 0; $i < $missing; ++$i) {
144
							$column = $row->createColumnBox();
145
							$column->createCellBox();
146
						}
147
					}
148
					// fix row spans
149
					$rowSpans = [];
150
					$rowSpansUp = [];
151
					foreach ($rowGroup->getChildren() as $row) {
152
						foreach ($row->getChildren() as $columnIndex => $column) {
153
							if ($column->getRowSpan() > 1) {
154
								$rowSpans[$columnIndex] = $column->getRowSpan();
155
								$rowSpansUp[$columnIndex] = 0;
156
								$column->setRowSpanUp(0);
157
								$row->setRowSpanUp(max($row->getRowSpanUp(), 0));
158
								$row->setRowSpan(max($row->getRowSpan(), $column->getRowSpan()));
159
							} else {
160
								if (isset($rowSpans[$columnIndex]) && $rowSpans[$columnIndex] > 1) {
161
									if ($rowSpansUp[$columnIndex] < $rowSpans[$columnIndex]) {
162
										++$rowSpansUp[$columnIndex];
163
										$column->setRowSpanUp($rowSpansUp[$columnIndex]);
164
										$row->setRowSpanUp(max($row->getRowSpanUp(), $rowSpansUp[$columnIndex]));
165
										$row->setRowSpan(max($row->getRowSpan(), $column->getRowSpan()));
166
									} else {
167
										$rowSpansUp[$columnIndex] = 0;
168
										$rowSpans[$columnIndex] = 1;
169
									}
170
								}
171
							}
172
						}
173
					}
174
				}
175
			}
176
		}
177
178
		return $this;
179
	}
180
181
	/**
182
	 * Span all rows.
183
	 *
184
	 * @return $this
185
	 */
186
	public function spanAllRows()
187
	{
188
		$tablesBoxes = $this->getBoxesByType('TableBox');
189
		foreach ($tablesBoxes as $tableBox) {
190
			$tableBox->spanRows();
191
		}
192
193
		return $this;
194
	}
195
196
	/**
197
	 * Build tree.
198
	 *
199
	 * @param $parentBlock
200
	 *
201
	 * @return $this
202
	 */
203
	public function buildTree($parentBlock = null)
204
	{
205
		if ($this->getElement()) {
206
			$domElement = $this->getElement()->getDOMElement();
207
		} else {
208
			// tablebox doesn't have element so we can get it from table wrapper (parent box)
209
			$domElement = $this->getParent()->getElement()->getDOMElement();
0 ignored issues
show
Bug introduced by
The method getElement() does not exist on YetiForcePDF\Layout\Box. It seems like you code against a sub-type of YetiForcePDF\Layout\Box such as YetiForcePDF\Layout\ElementBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

209
			$domElement = $this->getParent()->/** @scrutinizer ignore-call */ getElement()->getDOMElement();
Loading history...
210
		}
211
		if ($domElement->hasChildNodes()) {
212
			foreach ($domElement->childNodes as $childDomElement) {
213
				if ($childDomElement instanceof \DOMComment) {
214
					continue;
215
				}
216
217
				$element = (new Element())
218
					->setDocument($this->document)
219
					->setDOMElement($childDomElement)
220
					->init();
221
				$style = (new \YetiForcePDF\Style\Style())
222
					->setDocument($this->document)
223
					->setElement($element);
224
				if ($childDomElement instanceof \DOMElement) {
225
					if ($childDomElement->hasAttribute('style')) {
226
						// for now only basic style is used - from current element only (with defaults)
227
						$style->setContent($childDomElement->getAttribute('style'));
228
					} elseif ('style' === $childDomElement->nodeName) {
229
						$style->parseCss($childDomElement->nodeValue);
230
					}
231
					$element->attachClasses();
232
				}
233
				$style = $style->parseInline();
234
				$display = $style->getRules('display');
235
				switch ($display) {
236
					case 'block':
237
						if ($childDomElement->hasAttribute('data-header')) {
238
							$this->appendHeaderBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendHeaderBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of YetiForcePDF\Layout\ElementBox such as YetiForcePDF\Layout\BlockBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

238
							$this->/** @scrutinizer ignore-call */ 
239
              appendHeaderBox($childDomElement, $element, $style, $parentBlock);
Loading history...
239
						} elseif ($childDomElement->hasAttribute('data-footer')) {
240
							$this->appendFooterBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendFooterBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of YetiForcePDF\Layout\ElementBox such as YetiForcePDF\Layout\BlockBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

240
							$this->/** @scrutinizer ignore-call */ 
241
              appendFooterBox($childDomElement, $element, $style, $parentBlock);
Loading history...
241
						} elseif ($childDomElement->hasAttribute('data-watermark')) {
242
							$this->appendWatermarkBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendWatermarkBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of YetiForcePDF\Layout\ElementBox such as YetiForcePDF\Layout\BlockBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

242
							$this->/** @scrutinizer ignore-call */ 
243
              appendWatermarkBox($childDomElement, $element, $style, $parentBlock);
Loading history...
243
						} elseif ($childDomElement->hasAttribute('data-font')) {
244
							$this->appendFontBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendFontBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of YetiForcePDF\Layout\ElementBox such as YetiForcePDF\Layout\BlockBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

244
							$this->/** @scrutinizer ignore-call */ 
245
              appendFontBox($childDomElement, $element, $style, $parentBlock);
Loading history...
245
						} elseif ($childDomElement->hasAttribute('data-barcode')) {
246
							$this->appendBarcodeBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendBarcodeBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of YetiForcePDF\Layout\ElementBox such as YetiForcePDF\Layout\BlockBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

246
							$this->/** @scrutinizer ignore-call */ 
247
              appendBarcodeBox($childDomElement, $element, $style, $parentBlock);
Loading history...
247
						} else {
248
							$this->appendBlockBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendBlockBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of said class. However, the method does not exist in YetiForcePDF\Layout\TextBox. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

248
							$this->/** @scrutinizer ignore-call */ 
249
              appendBlockBox($childDomElement, $element, $style, $parentBlock);
Loading history...
249
						}
250
251
						break;
252
					case 'table':
253
						$tableWrapper = $this->appendTableWrapperBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendTableWrapperBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of said class. However, the method does not exist in YetiForcePDF\Layout\TextBox. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

253
						/** @scrutinizer ignore-call */ 
254
      $tableWrapper = $this->appendTableWrapperBox($childDomElement, $element, $style, $parentBlock);
Loading history...
254
						$tableWrapper->appendTableBox($childDomElement, $element, $style, $parentBlock);
255
256
						break;
257
					case 'table-row-group':
258
					case 'table-header-group':
259
					case 'table-footer-group':
260
						$this->appendTableRowGroupBox($childDomElement, $element, $style, $parentBlock, $display);
0 ignored issues
show
Bug introduced by
The method appendTableRowGroupBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of YetiForcePDF\Layout\ElementBox such as YetiForcePDF\Layout\TableBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

260
						$this->/** @scrutinizer ignore-call */ 
261
             appendTableRowGroupBox($childDomElement, $element, $style, $parentBlock, $display);
Loading history...
261
262
						break;
263
					case 'table-row':
264
						$this->appendTableRowBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendTableRowBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of YetiForcePDF\Layout\ElementBox such as YetiForcePDF\Layout\TableBox or YetiForcePDF\Layout\TableRowGroupBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

264
						$this->/** @scrutinizer ignore-call */ 
265
             appendTableRowBox($childDomElement, $element, $style, $parentBlock);
Loading history...
265
266
						break;
267
					case 'table-cell':
268
						$this->appendTableCellBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendTableCellBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of YetiForcePDF\Layout\ElementBox such as YetiForcePDF\Layout\TableRowBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

268
						$this->/** @scrutinizer ignore-call */ 
269
             appendTableCellBox($childDomElement, $element, $style, $parentBlock);
Loading history...
269
270
						break;
271
					case 'inline':
272
						$inline = $this->appendInlineBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendInlineBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of said class. However, the method does not exist in YetiForcePDF\Layout\TextBox. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

272
						/** @scrutinizer ignore-call */ 
273
      $inline = $this->appendInlineBox($childDomElement, $element, $style, $parentBlock);
Loading history...
273
						if (isset($inline) && $childDomElement instanceof \DOMText) {
274
							$inline->setAnonymous(true)->appendText($childDomElement, null, null, $parentBlock);
275
						}
276
277
						break;
278
					case 'inline-block':
279
						$this->appendInlineBlockBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendInlineBlockBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of said class. However, the method does not exist in YetiForcePDF\Layout\TextBox. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

279
						$this->/** @scrutinizer ignore-call */ 
280
             appendInlineBlockBox($childDomElement, $element, $style, $parentBlock);
Loading history...
280
281
						break;
282
						case 'none':
283
							if ('style' === $childDomElement->nodeName) {
284
								$this->appendStyleBox($childDomElement, $element, $style, $parentBlock);
0 ignored issues
show
Bug introduced by
The method appendStyleBox() does not exist on YetiForcePDF\Layout\ElementBox. It seems like you code against a sub-type of YetiForcePDF\Layout\ElementBox such as YetiForcePDF\Layout\BlockBox. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

284
								$this->/** @scrutinizer ignore-call */ 
285
               appendStyleBox($childDomElement, $element, $style, $parentBlock);
Loading history...
285
							}
286
287
						break;
288
				}
289
			}
290
		}
291
292
		return $this;
293
	}
294
}
295