BoxDimensions::getOuterHeight()   B
last analyzed

Complexity

Conditions 9
Paths 11

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 29
rs 8.0555
c 0
b 0
f 0
cc 9
nc 11
nop 0
1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * BoxDimensions class.
6
 *
7
 * @package   YetiForcePDF\Layout\Dimensions
8
 *
9
 * @copyright YetiForce Sp. z o.o
10
 * @license   MIT
11
 * @author    Rafal Pospiech <[email protected]>
12
 */
13
14
namespace YetiForcePDF\Layout\Dimensions;
15
16
use YetiForcePDF\Layout\Box;
17
use YetiForcePDF\Layout\LineBox;
18
use YetiForcePDF\Layout\TableWrapperBox;
19
use YetiForcePDF\Layout\TextBox;
20
use YetiForcePDF\Math;
21
22
/**
23
 * Class BoxDimensions.
24
 */
25
class BoxDimensions extends Dimensions
26
{
27
	/**
28
	 * @var Box
29
	 */
30
	protected $box;
31
32
	/**
33
	 * Set box.
34
	 *
35
	 * @param \YetiForcePDF\Layout\Box $box
36
	 *
37
	 * @return $this
38
	 */
39
	public function setBox(Box $box)
40
	{
41
		$this->box = $box;
42
		return $this;
43
	}
44
45
	/**
46
	 * Get box.
47
	 *
48
	 * @return \YetiForcePDF\Layout\Box
49
	 */
50
	public function getBox()
51
	{
52
		return $this->box;
53
	}
54
55
	/**
56
	 * Get raw width.
57
	 *
58
	 * @return string|null
59
	 */
60
	public function getRawWidth()
61
	{
62
		return $this->width;
63
	}
64
65
	/**
66
	 * Get raw height.
67
	 *
68
	 * @return string|null
69
	 */
70
	public function getRawHeight()
71
	{
72
		return $this->height;
73
	}
74
75
	/**
76
	 * {@inheritdoc}
77
	 */
78
	public function getWidth()
79
	{
80
		if (!$this->getBox()->isForMeasurement() && !$this->getBox()->getStyle()->haveSpacing()) {
81
			return '0';
82
		}
83
		if (!$this->getBox()->isDisplayable()) {
84
			return '0';
85
		}
86
		return parent::getWidth();
87
	}
88
89
	/**
90
	 * {@inheritdoc}
91
	 */
92
	public function getHeight()
93
	{
94
		if (!$this->getBox()->isForMeasurement() && !$this->getBox()->getStyle()->haveSpacing()) {
95
			return '0';
96
		}
97
		if (!$this->getBox()->isDisplayable()) {
98
			return '0';
99
		}
100
		return parent::getHeight();
101
	}
102
103
	/**
104
	 * Get innerWidth.
105
	 *
106
	 * @return string
107
	 */
108
	public function getInnerWidth(): string
109
	{
110
		$box = $this->getBox();
111
		if (!$box->isForMeasurement() && !$this->getBox()->getStyle()->haveSpacing()) {
112
			return '0';
113
		}
114
		if (!$this->getBox()->isDisplayable()) {
115
			return '0';
116
		}
117
		$style = $box->getStyle();
118
		$width = $this->getWidth();
119
		if (null === $width) {
0 ignored issues
show
introduced by
The condition null === $width is always false.
Loading history...
120
			return '0';
121
		}
122
		return Math::sub($width, $style->getHorizontalBordersWidth(), $style->getHorizontalPaddingsWidth());
123
	}
124
125
	/**
126
	 * Get innerHeight.
127
	 *
128
	 * @return string
129
	 */
130
	public function getInnerHeight(): string
131
	{
132
		$box = $this->getBox();
133
		if (!$box->isForMeasurement() && !$this->getBox()->getStyle()->haveSpacing()) {
134
			return '0';
135
		}
136
		if (!$this->getBox()->isDisplayable()) {
137
			return '0';
138
		}
139
		$style = $box->getStyle();
140
		$height = $this->getHeight();
141
		if (null === $height) {
142
			$height = '0';
143
			$element = $box->getElement();
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

143
			/** @scrutinizer ignore-call */ 
144
   $element = $box->getElement();
Loading history...
144
			if ($element && $element->getDOMElement() instanceof \DOMText) {
145
				$height = $style->getLineHeight();
146
			}
147
		}
148
		return Math::sub($height, $style->getVerticalBordersWidth(), $style->getVerticalPaddingsWidth());
149
	}
150
151
	/**
152
	 * Get width with margins.
153
	 *
154
	 * @return string
155
	 */
156
	public function getOuterWidth()
157
	{
158
		$box = $this->getBox();
159
		if (!$box->isForMeasurement() && !$this->getBox()->getStyle()->haveSpacing()) {
160
			return '0';
161
		}
162
		if (!$this->getBox()->isDisplayable()) {
163
			return '0';
164
		}
165
		if (!$box instanceof LineBox) {
166
			$style = $this->getBox()->getStyle();
167
			$childrenWidth = '0';
168
			// if some of the children overflows
169
			if ('inline' === $box->getStyle()->getRules('display')) {
170
				foreach ($box->getChildren() as $child) {
171
					if ($childWidth = $child->getDimensions()->getWidth()) {
172
						$childrenWidth = Math::add($childrenWidth, $childWidth);
173
					} else {
174
						$childrenWidth = Math::add($childrenWidth, $child->getDimensions()->getOuterWidth());
175
					}
176
				}
177
			} else {
178
				foreach ($box->getChildren() as $child) {
179
					if ($childWidth = $child->getDimensions()->getWidth()) {
180
						$childrenWidth = Math::max($childrenWidth, $childWidth);
181
					} else {
182
						$childrenWidth = Math::max($childrenWidth, $child->getDimensions()->getOuterWidth());
183
					}
184
				}
185
			}
186
			if (null !== $this->getWidth()) {
0 ignored issues
show
introduced by
The condition null !== $this->getWidth() is always true.
Loading history...
187
				$childrenWidth = Math::add($childrenWidth, $style->getHorizontalMarginsWidth(), $style->getHorizontalBordersWidth(), $style->getHorizontalPaddingsWidth());
188
				$width = Math::add($this->getWidth(), $style->getHorizontalMarginsWidth());
189
				return Math::max($width, $childrenWidth);
190
			}
191
			return Math::add($childrenWidth, $style->getHorizontalBordersWidth(), $style->getHorizontalPaddingsWidth());
192
		}
193
		return $this->getBox()->getChildrenWidth();
0 ignored issues
show
Bug introduced by
The method getChildrenWidth() does not exist on YetiForcePDF\Layout\Box. Did you maybe mean getChildren()? ( Ignorable by Annotation )

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

193
		return $this->getBox()->/** @scrutinizer ignore-call */ getChildrenWidth();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
194
	}
195
196
	/**
197
	 * Get height with margins.
198
	 *
199
	 * @return string
200
	 */
201
	public function getOuterHeight()
202
	{
203
		$box = $this->getBox();
204
		if (!$box->isForMeasurement() && !$this->getBox()->getStyle()->haveSpacing()) {
205
			return '0';
206
		}
207
		if (!$this->getBox()->isDisplayable()) {
208
			return '0';
209
		}
210
		$style = $this->getBox()->getStyle();
211
		if (!$box instanceof LineBox) {
212
			$childrenHeight = '0';
213
			// if some of the children overflows
214
			if ('inline' === $box->getStyle()->getRules('display')) {
215
				foreach ($box->getChildren() as $child) {
216
					$childrenHeight = Math::add($childrenHeight, $child->getDimensions()->getOuterHeight());
217
				}
218
			} else {
219
				foreach ($box->getChildren() as $child) {
220
					$childrenHeight = Math::max($childrenHeight, $child->getDimensions()->getOuterHeight());
221
				}
222
			}
223
			if (null !== $this->getHeight()) {
224
				$height = Math::add($this->getHeight(), $style->getVerticalMarginsWidth());
225
				return Math::max($height, $childrenHeight);
226
			}
227
			return Math::add($childrenHeight, $style->getVerticalBordersWidth(), $style->getVerticalPaddingsWidth());
228
		}
229
		return Math::add($this->getHeight(), $style->getHorizontalMarginsWidth());
0 ignored issues
show
Bug introduced by
It seems like $this->getHeight() can also be of type null; however, parameter $numbers of YetiForcePDF\Math::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

229
		return Math::add(/** @scrutinizer ignore-type */ $this->getHeight(), $style->getHorizontalMarginsWidth());
Loading history...
230
	}
231
232
	/**
233
	 * Reset width.
234
	 *
235
	 * @return $this
236
	 */
237
	public function resetWidth()
238
	{
239
		$this->setWidth();
240
		foreach ($this->getBox()->getChildren() as $child) {
241
			$child->getDimensions()->setWidth();
242
			$child->getDimensions()->resetWidth();
243
		}
244
		return $this;
245
	}
246
247
	/**
248
	 * Reset height.
249
	 *
250
	 * @return $this
251
	 */
252
	public function resetHeight()
253
	{
254
		$this->setHeight();
255
		foreach ($this->getBox()->getChildren() as $child) {
256
			$child->getDimensions()->setHeight();
257
			$child->getDimensions()->resetHeight();
258
		}
259
		return $this;
260
	}
261
262
	/**
263
	 * Get max width with margins.
264
	 *
265
	 * @return string
266
	 */
267
	public function getMaxWidth()
268
	{
269
		$box = $this->getBox();
270
		if (!$box->isForMeasurement()) {
271
			return '0';
272
		}
273
		if (!$box instanceof LineBox) {
274
			$style = $this->getBox()->getStyle();
275
			$childrenWidth = '0';
276
			// if some of the children overflows
277
			if ('inline' === $box->getStyle()->getRules('display')) {
278
				foreach ($box->getChildren() as $child) {
279
					$childrenWidth = Math::add($childrenWidth, $child->getDimensions()->getOuterWidth());
280
				}
281
			} elseif (\count($box->getSourceLines())) {
0 ignored issues
show
Bug introduced by
The method getSourceLines() does not exist on YetiForcePDF\Layout\Box. It seems like you code against a sub-type of YetiForcePDF\Layout\Box 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

281
			} elseif (\count($box->/** @scrutinizer ignore-call */ getSourceLines())) {
Loading history...
282
				foreach ($box->getSourceLines() as $line) {
283
					$childrenWidth = Math::max($childrenWidth, $line->getChildrenWidth());
284
				}
285
				foreach ($box->getChildren() as $child) {
286
					if (!$child instanceof LineBox) {
287
						$childrenWidth = Math::max($childrenWidth, $child->getDimensions()->getWidth() ?? '0'); // TODO: neither getOuterWidth or getWidth works here
288
					}
289
				}
290
			} else {
291
				// TODO: each block and inline-block should have source lines but for now i don't have time so this is just patch
292
				foreach ($box->getChildren() as $child) {
293
					$childrenWidth = Math::max($childrenWidth, $child->getDimensions()->getOuterWidth());
294
				}
295
			}
296
			if (null !== $this->getWidth()) {
0 ignored issues
show
introduced by
The condition null !== $this->getWidth() is always true.
Loading history...
297
				$childrenWidth = Math::add($childrenWidth, $style->getHorizontalMarginsWidth(), $style->getHorizontalBordersWidth(), $style->getHorizontalPaddingsWidth());
298
				$width = Math::add($this->getWidth(), $style->getHorizontalMarginsWidth());
299
				return Math::max($width, $childrenWidth);
300
			}
301
			return Math::add($childrenWidth, $style->getHorizontalBordersWidth(), $style->getHorizontalPaddingsWidth());
302
		}
303
		return $this->getBox()->getChildrenWidth();
304
	}
305
306
	/**
307
	 * Get minimum space that current box could have without overflow.
308
	 *
309
	 * @return string
310
	 */
311
	public function getMinWidth()
312
	{
313
		$box = $this->getBox();
314
		if (!$box->isForMeasurement()) {
315
			return '0';
316
		}
317
		if ($box instanceof TableWrapperBox) {
318
			return $box->getFirstChild()->getMinWidth();
0 ignored issues
show
Bug introduced by
The method getMinWidth() does not exist on YetiForcePDF\Layout\Box. It seems like you code against a sub-type of YetiForcePDF\Layout\Box 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

318
			return $box->getFirstChild()->/** @scrutinizer ignore-call */ getMinWidth();
Loading history...
319
		}
320
		if ($box instanceof TextBox) {
321
			return $this->getTextWidth($this->getBox()->getText());
0 ignored issues
show
Bug introduced by
The method getText() does not exist on YetiForcePDF\Layout\Box. Did you maybe mean getTextContent()? ( Ignorable by Annotation )

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

321
			return $this->getTextWidth($this->getBox()->/** @scrutinizer ignore-call */ getText());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
322
		}
323
		$maxTextWidth = '0';
324
		foreach ($box->getChildren() as $childBox) {
325
			if ($childBox instanceof TextBox) {
326
				$textWidth = $childBox->getDimensions()->getTextWidth($childBox->getText());
327
				$maxTextWidth = Math::max($maxTextWidth, $textWidth);
328
			} else {
329
				$minWidth = $childBox->getDimensions()->getMinWidth();
330
				$maxTextWidth = Math::max($maxTextWidth, $minWidth);
331
			}
332
		}
333
		$style = $this->getBox()->getStyle();
334
		return Math::add($maxTextWidth, $style->getHorizontalBordersWidth(), $style->getHorizontalPaddingsWidth(), $style->getHorizontalMarginsWidth());
335
	}
336
337
	/**
338
	 * Get text width.
339
	 *
340
	 * @param string $text
341
	 *
342
	 * @return string
343
	 */
344
	public function getTextWidth($text)
345
	{
346
		if (!$this->getBox()->isForMeasurement()) {
347
			return '0';
348
		}
349
		$font = $this->box->getStyle()->getFont();
350
		return $font->getTextWidth($text);
351
	}
352
353
	/**
354
	 * Get text height.
355
	 *
356
	 * @param string $text
357
	 *
358
	 * @return string
359
	 */
360
	public function getTextHeight($text)
361
	{
362
		if (!$this->getBox()->isForMeasurement()) {
363
			return '0';
364
		}
365
		$font = $this->box->getStyle()->getFont();
366
		return $font->getTextHeight($text);
367
	}
368
369
	/**
370
	 * Compute available space (basing on parent available space and parent border and padding).
371
	 *
372
	 * @return string
373
	 */
374
	public function computeAvailableSpace()
375
	{
376
		if (!$this->getBox()->isForMeasurement()) {
377
			return '0';
378
		}
379
		if ($parent = $this->getBox()->getParent()) {
380
			$parentStyle = $parent->getStyle();
381
			if (null === $parent->getDimensions()->getWidth()) {
0 ignored issues
show
introduced by
The condition null === $parent->getDimensions()->getWidth() is always false.
Loading history...
382
				return Math::sub($parent->getDimensions()->computeAvailableSpace(), $parentStyle->getHorizontalBordersWidth(), $parentStyle->getHorizontalPaddingsWidth());
383
			}
384
			return $this->getBox()->getParent()->getDimensions()->getInnerWidth();
385
		}
386
		return $this->document->getCurrentPage()->getDimensions()->getWidth();
387
	}
388
389
	/**
390
	 * Calculate width from style width:10%.
391
	 *
392
	 * @return mixed|string|null
393
	 */
394
	public function getStyleWidth()
395
	{
396
		if (!$this->getBox()->isForMeasurement() && !$this->getBox()) {
397
			return '0';
398
		}
399
		$width = $this->getBox()->getStyle()->getRules('width');
400
		if ('auto' === $width) {
401
			return null;
402
		}
403
		$percentPos = strpos($width, '%');
0 ignored issues
show
Bug introduced by
It seems like $width can also be of type array; however, parameter $haystack of strpos() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

403
		$percentPos = strpos(/** @scrutinizer ignore-type */ $width, '%');
Loading history...
404
		if (false !== $percentPos) {
405
			$widthInPercent = substr($width, 0, $percentPos);
0 ignored issues
show
Bug introduced by
It seems like $width can also be of type array; however, parameter $string of substr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

405
			$widthInPercent = substr(/** @scrutinizer ignore-type */ $width, 0, $percentPos);
Loading history...
406
			$closestBoxDimensions = $this->getBox()->getClosestBox()->getDimensions();
407
			if (null !== $closestBoxDimensions->getWidth()) {
0 ignored issues
show
introduced by
The condition null !== $closestBoxDimensions->getWidth() is always true.
Loading history...
408
				$parentWidth = $closestBoxDimensions->getInnerWidth();
409
				$style = $this->getBox()->getStyle();
410
				$parentWidth = Math::sub($parentWidth, $style->getHorizontalMarginsWidth());
411
				if ($parentWidth) {
412
					return Math::percent($widthInPercent, $parentWidth);
413
				}
414
			}
415
		} else {
416
			return $width;
417
		}
418
		return null;
419
	}
420
421
	/**
422
	 * Calculate height from style width:10%.
423
	 *
424
	 * @return mixed|string|null
425
	 */
426
	public function getStyleHeight()
427
	{
428
		if (!$this->getBox()->isForMeasurement()) {
429
			return '0';
430
		}
431
		$height = $this->getBox()->getStyle()->getRules('height');
432
		if ('auto' === $height) {
433
			return null;
434
		}
435
		$percentPos = strpos($height, '%');
0 ignored issues
show
Bug introduced by
It seems like $height can also be of type array; however, parameter $haystack of strpos() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

435
		$percentPos = strpos(/** @scrutinizer ignore-type */ $height, '%');
Loading history...
436
		if (false !== $percentPos) {
437
			$widthInPercent = substr($height, 0, $percentPos);
0 ignored issues
show
Bug introduced by
It seems like $height can also be of type array; however, parameter $string of substr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

437
			$widthInPercent = substr(/** @scrutinizer ignore-type */ $height, 0, $percentPos);
Loading history...
438
			$closestBoxDimensions = $this->getBox()->getClosestBox()->getDimensions();
439
			if (null !== $closestBoxDimensions->getHeight()) {
440
				$parentHeight = $closestBoxDimensions->getInnerHeight();
441
				if ($parentHeight) {
442
					return Math::percent($widthInPercent, $parentHeight);
443
				}
444
			}
445
		} else {
446
			return $height;
447
		}
448
		return null;
449
	}
450
}
451