Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.45% covered (success)
95.45%
63 / 66
85.71% covered (success)
85.71%
6 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Wrap
95.45% covered (success)
95.45%
63 / 66
85.71% covered (success)
85.71%
6 / 7
32
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 createLeft
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createRight
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setBox
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
6
 setBoxCoordinates
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getBox
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStrings
93.48% covered (success)
93.48%
43 / 46
0.00% covered (danger)
0.00%
0 / 1
20.11
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Pdf\Document\Page\Text;
15
16use Pop\Pdf\Document\Page;
17use Pop\Pdf\Document\Font;
18use InvalidArgumentException;
19
20/**
21 * Pdf page text wrap class
22 *
23 * @category   Pop
24 * @package    Pop\Pdf
25 * @author     Nick Sagona, III <dev@nolainteractive.com>
26 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
27 * @license    http://www.popphp.org/license     New BSD License
28 * @version    5.0.0
29 */
30class Wrap extends AbstractAlignment
31{
32
33   /**
34     * Wrap box boundary
35     * @var array
36     */
37    protected array $box = [
38        'left'   => 0,
39        'right'  => 0,
40        'top'    => 0,
41        'bottom' => 0
42    ];
43
44    /**
45     * Constructor
46     *
47     * Instantiate a PDF text wrap object.
48     *
49     * @param string $alignment
50     * @param int    $leftX
51     * @param int    $rightX
52     * @param array  $box
53     * @param int    $leading
54     */
55    public function __construct(string $alignment = self::LEFT, int $leftX = 0, int $rightX = 0, array $box = [], int $leading = 0)
56    {
57        parent::__construct($alignment, $leftX, $rightX, $leading);
58        if (!empty($box)) {
59            $this->setBox($box);
60        }
61    }
62
63    /**
64     * Create LEFT alignment object
65     *
66     * @param int    $leftX
67     * @param int    $rightX
68     * @param array  $box
69     * @param int    $leading
70     * @return Wrap
71     */
72    public static function createLeft(int $leftX = 0, int $rightX = 0, array $box = [], int $leading = 0): Wrap
73    {
74        return new self(self::LEFT, $leftX, $rightX, $box, $leading);
75    }
76
77    /**
78     * Create RIGHT alignment object
79     *
80     * @param int    $leftX
81     * @param int    $rightX
82     * @param array  $box
83     * @param int    $leading
84     * @return Wrap
85     */
86    public static function createRight(int $leftX = 0, int $rightX = 0, array $box = [], int $leading = 0): Wrap
87    {
88        return new self(self::RIGHT, $leftX, $rightX, $box, $leading);
89    }
90
91    /**
92     * Set the wrap box boundary
93     *
94     * @param  array $box
95     * @throws InvalidArgumentException
96     * @return Wrap
97     */
98    public function setBox(array $box): Wrap
99    {
100        if ((count($box) != 4) || !isset($box['left']) || !isset($box['right']) || !isset($box['top']) || !isset($box['bottom'])) {
101            throw new InvalidArgumentException(
102                "Error: The box array must contain the four coordinates 'left', 'right', 'top' and 'bottom'."
103            );
104        }
105
106        $this->box['left']   = $box['left'];
107        $this->box['right']  = $box['right'];
108        $this->box['top']    = $box['top'];
109        $this->box['bottom'] = $box['bottom'];
110
111        return $this;
112    }
113
114    /**
115     * Set the wrap box boundary by coordinates
116     *
117     * @param  int $left
118     * @param  int $right
119     * @param  int $top
120     * @param  int $bottom
121     * @return Wrap
122     */
123    public function setBoxCoordinates(int $left, int $right, int $top, int $bottom): Wrap
124    {
125        $this->box['left']   = $left;
126        $this->box['right']  = $right;
127        $this->box['top']    = $top;
128        $this->box['bottom'] = $bottom;
129
130        return $this;
131    }
132
133    /**
134     * Get the wrap box boundary
135     *
136     * @return array
137     */
138    public function getBox(): array
139    {
140        return $this->box;
141    }
142
143    /**
144     * Get strings
145     *
146     * @param  Page\Text $text
147     * @param  Font      $font
148     * @param  int       $startY
149     * @return array
150     */
151    public function getStrings(Page\Text $text, Font $font, int $startY): array
152    {
153        $stringAry = ($text->hasStrings()) ? $text->getStrings() : [$text->getString()];
154        $strings   = [];
155        $append    = false;
156
157        foreach ($stringAry as $key => $string) {
158            $stringValue = ($string instanceof Page\Text) ? $string->getString() : $string;
159            if (($append) && !empty($curString)) {
160                $stringValue = $curString . ' ' . $stringValue;
161                $append      = false;
162            }
163            $curString  = '';
164            $words      = explode(' ', $stringValue);
165            $startX     = $this->leftX;
166
167            if ($this->leading == 0) {
168                $this->leading = $text->getSize();
169            }
170
171            foreach ($words as $word) {
172                if ($this->isRight()) {
173                    if (($startY <= $this->box['top']) && ($startY >= $this->box['bottom'])) {
174                        $wrapLength = abs($this->rightX - $this->box['right']);
175                        $x          = $this->box['right'];
176                    } else {
177                        $wrapLength = abs($this->rightX - $this->leftX);
178                        $x          = $startX;
179                    }
180                } else {
181                    $x          = $startX;
182                    $wrapLength = (($startY <= $this->box['top']) && ($startY >= $this->box['bottom'])) ?
183                        abs($this->box['left'] - $this->leftX) : abs($this->rightX - $this->leftX);
184                }
185
186                $newString = ($curString != '') ? $curString . ' ' . $word : $word;
187                if ($font->getStringWidth($newString, $text->getSize()) <= $wrapLength) {
188                    $curString = $newString;
189                } else {
190                    $strings[] = [
191                        'string' => $curString,
192                        'x'      => $x,
193                        'y'      => $startY
194                    ];
195                    $curString = $word;
196                    $startY   -= $this->leading;
197                }
198            }
199
200            if (!empty($curString)) {
201                if ($key == (count($stringAry) - 1)) {
202                    if ($this->isRight()) {
203                        $x = (($startY <= $this->box['top']) && ($startY >= $this->box['bottom'])) ?
204                            $this->box['right'] : $startX;
205                    } else {
206                        $x = $startX;
207                    }
208
209                    $strings[] = [
210                        'string' => $curString,
211                        'x'      => $x,
212                        'y'      => $startY
213                    ];
214                } else {
215                    $append = true;
216                }
217            }
218        }
219
220        return $strings;
221    }
222
223}