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