Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.77% covered (success)
96.77%
120 / 124
95.83% covered (success)
95.83%
46 / 48
CRAP
0.00% covered (danger)
0.00%
0 / 1
RichText
96.77% covered (success)
96.77%
120 / 124
95.83% covered (success)
95.83%
46 / 48
65
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 __clone
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getActiveParagraphIndex
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActiveParagraph
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setActiveParagraph
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getParagraph
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 createParagraph
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
5
 addText
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 createText
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createBreak
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createTextRun
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPlainText
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParagraphs
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setParagraphs
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getWrap
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setWrap
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getAutoFit
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFontScale
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLineSpaceReduction
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setAutoFit
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getHorizontalOverflow
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setHorizontalOverflow
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getVerticalOverflow
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setVerticalOverflow
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isUpright
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setUpright
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isVertical
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setVertical
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setVerticalAlignCenter
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 getVerticalAlignCenter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getColumns
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setColumns
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getInsetBottom
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setInsetBottom
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getInsetLeft
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setInsetLeft
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getInsetRight
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setInsetRight
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getInsetTop
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setInsetTop
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setAutoShrinkHorizontal
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 hasAutoShrinkHorizontal
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setAutoShrinkVertical
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 hasAutoShrinkVertical
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getColumnSpacing
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setColumnSpacing
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getHashCode
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2/**
3 * This file is part of PHPPresentation - A pure PHP library for reading and writing
4 * presentations documents.
5 *
6 * PHPPresentation is free software distributed under the terms of the GNU Lesser
7 * General Public License version 3 as published by the Free Software Foundation.
8 *
9 * For the full copyright and license information, please read the LICENSE
10 * file that was distributed with this source code. For the full list of
11 * contributors, visit https://github.com/PHPOffice/PHPPresentation/contributors.
12 *
13 * @see        https://github.com/PHPOffice/PHPPresentation
14 *
15 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16 */
17
18declare(strict_types=1);
19
20namespace PhpOffice\PhpPresentation\Shape;
21
22use PhpOffice\PhpPresentation\AbstractShape;
23use PhpOffice\PhpPresentation\ComparableInterface;
24use PhpOffice\PhpPresentation\Exception\NotAllowedValueException;
25use PhpOffice\PhpPresentation\Exception\OutOfBoundsException;
26use PhpOffice\PhpPresentation\Shape\RichText\Paragraph;
27use PhpOffice\PhpPresentation\Shape\RichText\TextElementInterface;
28
29/**
30 * \PhpOffice\PhpPresentation\Shape\RichText.
31 */
32class RichText extends AbstractShape implements ComparableInterface
33{
34    /** Wrapping */
35    public const WRAP_NONE = 'none';
36    public const WRAP_SQUARE = 'square';
37
38    /** Autofit */
39    public const AUTOFIT_DEFAULT = 'spAutoFit';
40    public const AUTOFIT_SHAPE = 'spAutoFit';
41    public const AUTOFIT_NOAUTOFIT = 'noAutofit';
42    public const AUTOFIT_NORMAL = 'normAutofit';
43
44    /** Overflow */
45    public const OVERFLOW_CLIP = 'clip';
46    public const OVERFLOW_OVERFLOW = 'overflow';
47
48    /** Vertical alignment center */
49    public const VALIGN_CENTER = 1;
50    public const VALIGN_NOTCENTER = 0;
51
52    /**
53     * Rich text paragraphs.
54     *
55     * @var array<Paragraph>
56     */
57    private $richTextParagraphs = [];
58
59    /**
60     * Active paragraph.
61     *
62     * @var int
63     */
64    private $activeParagraph = 0;
65
66    /**
67     * Text wrapping.
68     *
69     * @var string
70     */
71    private $wrap = self::WRAP_SQUARE;
72
73    /**
74     * Autofit.
75     *
76     * @var string
77     */
78    private $autoFit = self::AUTOFIT_DEFAULT;
79
80    /**
81     * Horizontal overflow.
82     *
83     * @var string
84     */
85    private $horizontalOverflow = self::OVERFLOW_OVERFLOW;
86
87    /**
88     * Vertical overflow.
89     *
90     * @var string
91     */
92    private $verticalOverflow = self::OVERFLOW_OVERFLOW;
93
94    /**
95     * Text upright?
96     *
97     * @var bool
98     */
99    private $upright = false;
100
101    /**
102     * Vertical text?
103     *
104     * @var bool
105     */
106    private $vertical = false;
107
108    /**
109     * Number of columns (1 - 16).
110     *
111     * @var int
112     */
113    private $columns = 1;
114
115    /**
116     * The spacing between columns.
117     *
118     * @var int
119     */
120    private $columnSpacing = 0;
121
122    /**
123     * Bottom inset (in pixels).
124     *
125     * @var float
126     */
127    private $bottomInset = 4.8;
128
129    /**
130     * Left inset (in pixels).
131     *
132     * @var float
133     */
134    private $leftInset = 9.6;
135
136    /**
137     * Right inset (in pixels).
138     *
139     * @var float
140     */
141    private $rightInset = 9.6;
142
143    /**
144     * Top inset (in pixels).
145     *
146     * @var float
147     */
148    private $topInset = 4.8;
149
150    /**
151     * Horizontal Auto Shrink.
152     *
153     * @var null|bool
154     */
155    private $autoShrinkHorizontal;
156
157    /**
158     * Vertical Auto Shrink.
159     *
160     * @var null|bool
161     */
162    private $autoShrinkVertical;
163
164    /**
165     * The percentage of the original font size to which the text is scaled.
166     *
167     * @var null|float
168     */
169    private $fontScale;
170
171    /**
172     * The percentage of the reduction of the line spacing.
173     *
174     * @var null|float
175     */
176    private $lnSpcReduction;
177
178    /**
179     * Define vertical text center position into shape (center,not center).
180     *
181     * @var int
182     */
183    private $verticalAlignCenter = self::VALIGN_NOTCENTER;
184
185    /**
186     * Create a new \PhpOffice\PhpPresentation\Shape\RichText instance.
187     */
188    public function __construct()
189    {
190        // Initialise variables
191        $this->richTextParagraphs = [
192            new Paragraph(),
193        ];
194
195        // Initialize parent
196        parent::__construct();
197    }
198
199    /**
200     * Magic Method : clone.
201     */
202    public function __clone()
203    {
204        // Call perent clonage for heritage
205        parent::__clone();
206        // Clone each paragraph
207        foreach ($this->richTextParagraphs as &$paragraph) {
208            $paragraph = clone $paragraph;
209        }
210    }
211
212    /**
213     * Get active paragraph index.
214     */
215    public function getActiveParagraphIndex(): int
216    {
217        return $this->activeParagraph;
218    }
219
220    public function getActiveParagraph(): Paragraph
221    {
222        return $this->richTextParagraphs[$this->activeParagraph];
223    }
224
225    /**
226     * Set active paragraph.
227     */
228    public function setActiveParagraph(int $index = 0): Paragraph
229    {
230        if ($index >= count($this->richTextParagraphs)) {
231            throw new OutOfBoundsException(0, count($this->richTextParagraphs), $index);
232        }
233
234        $this->activeParagraph = $index;
235
236        return $this->getActiveParagraph();
237    }
238
239    /**
240     * Get paragraph.
241     */
242    public function getParagraph(int $index = 0): Paragraph
243    {
244        if ($index >= count($this->richTextParagraphs)) {
245            throw new OutOfBoundsException(0, count($this->richTextParagraphs), $index);
246        }
247
248        return $this->richTextParagraphs[$index];
249    }
250
251    /**
252     * Create paragraph.
253     */
254    public function createParagraph(): Paragraph
255    {
256        $numParagraphs = count($this->richTextParagraphs);
257        if ($numParagraphs > 0) {
258            $alignment = clone $this->getActiveParagraph()->getAlignment();
259            $font = clone $this->getActiveParagraph()->getFont();
260            $bulletStyle = clone $this->getActiveParagraph()->getBulletStyle();
261        }
262
263        $this->richTextParagraphs[] = new Paragraph();
264        $this->activeParagraph = count($this->richTextParagraphs) - 1;
265
266        if (isset($alignment)) {
267            $this->getActiveParagraph()->setAlignment($alignment);
268        }
269        if (isset($font)) {
270            $this->getActiveParagraph()->setFont($font);
271        }
272        if (isset($bulletStyle)) {
273            $this->getActiveParagraph()->setBulletStyle($bulletStyle);
274        }
275
276        return $this->getActiveParagraph();
277    }
278
279    /**
280     * Add text.
281     *
282     * @param null|TextElementInterface $pText Rich text element
283     */
284    public function addText(?TextElementInterface $pText = null): self
285    {
286        $this->richTextParagraphs[$this->activeParagraph]->addText($pText);
287
288        return $this;
289    }
290
291    /**
292     * Create text (can not be formatted !).
293     *
294     * @param string $pText Text
295     */
296    public function createText(string $pText = ''): RichText\TextElement
297    {
298        return $this->richTextParagraphs[$this->activeParagraph]->createText($pText);
299    }
300
301    /**
302     * Create break.
303     */
304    public function createBreak(): RichText\BreakElement
305    {
306        return $this->richTextParagraphs[$this->activeParagraph]->createBreak();
307    }
308
309    /**
310     * Create text run (can be formatted).
311     *
312     * @param string $pText Text
313     */
314    public function createTextRun(string $pText = ''): RichText\Run
315    {
316        return $this->richTextParagraphs[$this->activeParagraph]->createTextRun($pText);
317    }
318
319    /**
320     * Get plain text.
321     */
322    public function getPlainText(): string
323    {
324        // Return value
325        $returnValue = '';
326
327        // Loop trough all Paragraph
328        foreach ($this->richTextParagraphs as $p) {
329            $returnValue .= $p->getPlainText();
330        }
331
332        // Return
333        return $returnValue;
334    }
335
336    /**
337     * Convert to string.
338     *
339     * @return string
340     */
341    public function __toString()
342    {
343        return $this->getPlainText();
344    }
345
346    /**
347     * @return array<Paragraph>
348     */
349    public function getParagraphs(): array
350    {
351        return $this->richTextParagraphs;
352    }
353
354    /**
355     * Set paragraphs.
356     *
357     * @param array<Paragraph> $paragraphs Array of paragraphs
358     */
359    public function setParagraphs(array $paragraphs = []): self
360    {
361        $this->richTextParagraphs = $paragraphs;
362        $this->activeParagraph = count($this->richTextParagraphs) - 1;
363
364        return $this;
365    }
366
367    /**
368     * Get text wrapping.
369     */
370    public function getWrap(): string
371    {
372        return $this->wrap;
373    }
374
375    /**
376     * Set text wrapping.
377     */
378    public function setWrap(string $value = self::WRAP_SQUARE): self
379    {
380        $this->wrap = $value;
381
382        return $this;
383    }
384
385    /**
386     * Get autofit.
387     */
388    public function getAutoFit(): string
389    {
390        return $this->autoFit;
391    }
392
393    /**
394     * Get pourcentage of fontScale.
395     */
396    public function getFontScale(): ?float
397    {
398        return $this->fontScale;
399    }
400
401    /**
402     * Get pourcentage of the line space reduction.
403     */
404    public function getLineSpaceReduction(): ?float
405    {
406        return $this->lnSpcReduction;
407    }
408
409    /**
410     * Set autofit.
411     */
412    public function setAutoFit(string $value = self::AUTOFIT_DEFAULT, ?float $fontScale = null, ?float $lnSpcReduction = null): self
413    {
414        $this->autoFit = $value;
415
416        if (null !== $fontScale) {
417            $this->fontScale = $fontScale;
418        }
419
420        if (null !== $lnSpcReduction) {
421            $this->lnSpcReduction = $lnSpcReduction;
422        }
423
424        return $this;
425    }
426
427    /**
428     * Get horizontal overflow.
429     */
430    public function getHorizontalOverflow(): string
431    {
432        return $this->horizontalOverflow;
433    }
434
435    /**
436     * Set horizontal overflow.
437     */
438    public function setHorizontalOverflow(string $value = self::OVERFLOW_OVERFLOW): self
439    {
440        $this->horizontalOverflow = $value;
441
442        return $this;
443    }
444
445    /**
446     * Get vertical overflow.
447     */
448    public function getVerticalOverflow(): string
449    {
450        return $this->verticalOverflow;
451    }
452
453    /**
454     * Set vertical overflow.
455     */
456    public function setVerticalOverflow(string $value = self::OVERFLOW_OVERFLOW): self
457    {
458        $this->verticalOverflow = $value;
459
460        return $this;
461    }
462
463    /**
464     * Get upright.
465     */
466    public function isUpright(): bool
467    {
468        return $this->upright;
469    }
470
471    /**
472     * Set vertical.
473     */
474    public function setUpright(bool $value = false): self
475    {
476        $this->upright = $value;
477
478        return $this;
479    }
480
481    /**
482     * Get vertical.
483     */
484    public function isVertical(): bool
485    {
486        return $this->vertical;
487    }
488
489    /**
490     * Set vertical.
491     */
492    public function setVertical(bool $value = false): self
493    {
494        $this->vertical = $value;
495
496        return $this;
497    }
498
499    /**
500     * Define the vertical alignment if centered or not.
501     *
502     * @param int $value 1=center 0=not
503     *
504     * @see self::VALIGN_CENTER, self::VALIGN_NOTCENTER
505     */
506    public function setVerticalAlignCenter(int $value): self
507    {
508        if (!in_array(
509            $value,
510            [self::VALIGN_CENTER, self::VALIGN_NOTCENTER]
511        )) {
512            throw new NotAllowedValueException((string) $value, [(string) self::VALIGN_CENTER, (string) self::VALIGN_NOTCENTER]);
513        }
514
515        $this->verticalAlignCenter = $value;
516
517        return $this;
518    }
519
520    /**
521     * Get the vertical alignment center.
522     */
523    public function getVerticalAlignCenter(): int
524    {
525        return $this->verticalAlignCenter;
526    }
527
528    /**
529     * Get columns.
530     */
531    public function getColumns(): int
532    {
533        return $this->columns;
534    }
535
536    /**
537     * Set columns.
538     */
539    public function setColumns(int $value = 1): self
540    {
541        if ($value > 16 || $value < 1) {
542            throw new OutOfBoundsException(1, 16, $value);
543        }
544
545        $this->columns = $value;
546
547        return $this;
548    }
549
550    /**
551     * Get bottom inset.
552     */
553    public function getInsetBottom(): float
554    {
555        return $this->bottomInset;
556    }
557
558    /**
559     * Set bottom inset.
560     */
561    public function setInsetBottom(float $value = 4.8): self
562    {
563        $this->bottomInset = $value;
564
565        return $this;
566    }
567
568    /**
569     * Get left inset.
570     */
571    public function getInsetLeft(): float
572    {
573        return $this->leftInset;
574    }
575
576    /**
577     * Set left inset.
578     */
579    public function setInsetLeft(float $value = 9.6): self
580    {
581        $this->leftInset = $value;
582
583        return $this;
584    }
585
586    /**
587     * Get right inset.
588     */
589    public function getInsetRight(): float
590    {
591        return $this->rightInset;
592    }
593
594    /**
595     * Set left inset.
596     */
597    public function setInsetRight(float $value = 9.6): self
598    {
599        $this->rightInset = $value;
600
601        return $this;
602    }
603
604    /**
605     * Get top inset.
606     */
607    public function getInsetTop(): float
608    {
609        return $this->topInset;
610    }
611
612    /**
613     * Set top inset.
614     */
615    public function setInsetTop(float $value = 4.8): self
616    {
617        $this->topInset = $value;
618
619        return $this;
620    }
621
622    public function setAutoShrinkHorizontal(?bool $value = null): self
623    {
624        $this->autoShrinkHorizontal = $value;
625
626        return $this;
627    }
628
629    public function hasAutoShrinkHorizontal(): ?bool
630    {
631        return $this->autoShrinkHorizontal;
632    }
633
634    /**
635     * Set vertical auto shrink.
636     */
637    public function setAutoShrinkVertical(?bool $value = null): self
638    {
639        $this->autoShrinkVertical = $value;
640
641        return $this;
642    }
643
644    /**
645     * Set vertical auto shrink.
646     */
647    public function hasAutoShrinkVertical(): ?bool
648    {
649        return $this->autoShrinkVertical;
650    }
651
652    /**
653     * Get spacing between columns.
654     */
655    public function getColumnSpacing(): int
656    {
657        return $this->columnSpacing;
658    }
659
660    /**
661     * Set spacing between columns.
662     */
663    public function setColumnSpacing(int $value = 0): self
664    {
665        if ($value >= 0) {
666            $this->columnSpacing = $value;
667        }
668
669        return $this;
670    }
671
672    /**
673     * Get hash code.
674     *
675     * @return string Hash code
676     */
677    public function getHashCode(): string
678    {
679        $hashElements = '';
680        foreach ($this->richTextParagraphs as $element) {
681            $hashElements .= $element->getHashCode();
682        }
683
684        return md5(
685            $hashElements
686            . $this->wrap
687            . $this->autoFit
688            . $this->horizontalOverflow
689            . $this->verticalOverflow
690            . ($this->upright ? '1' : '0')
691            . ($this->vertical ? '1' : '0')
692            . $this->columns
693            . $this->columnSpacing
694            . $this->bottomInset
695            . $this->leftInset
696            . $this->rightInset
697            . $this->topInset
698            . $this->verticalAlignCenter
699            . parent::getHashCode()
700            . __CLASS__
701        );
702    }
703}