• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PHPOffice / PHPWord / 25414441731

06 May 2026 03:12AM UTC coverage: 94.696% (-2.1%) from 96.757%
25414441731

Pull #2874

github

web-flow
Merge 3fa85d6e3 into 0ab0b4940
Pull Request #2874: Addresses issue #12

135 of 420 new or added lines in 30 files covered. (32.14%)

1 existing line in 1 file now uncovered.

12588 of 13293 relevant lines covered (94.7%)

34.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.95
/src/PhpWord/Style/Table.php
1
<?php
2

3
/**
4
 * This file is part of PHPWord - A pure PHP library for reading and writing
5
 * word processing documents.
6
 *
7
 * PHPWord is free software distributed under the terms of the GNU Lesser
8
 * General Public License version 3 as published by the Free Software Foundation.
9
 *
10
 * For the full copyright and license information, please read the LICENSE
11
 * file that was distributed with this source code. For the full list of
12
 * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
13
 *
14
 * @see         https://github.com/PHPOffice/PHPWord
15
 *
16
 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
17
 */
18

19
namespace PhpOffice\PhpWord\Style;
20

21
use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType;
22
use PhpOffice\PhpWord\Settings;
23
use PhpOffice\PhpWord\SimpleType\Jc;
24
use PhpOffice\PhpWord\SimpleType\JcTable;
25
use PhpOffice\PhpWord\SimpleType\TblWidth;
26

27
class Table extends Border
28
{
29
    //values for http://www.datypic.com/sc/ooxml/t-w_ST_TblLayoutType.html
30
    /**
31
     * AutoFit Table Layout.
32
     *
33
     * @var string
34
     */
35
    const LAYOUT_AUTO = 'autofit';
36
    /**
37
     * Fixed Width Table Layout.
38
     *
39
     * @var string
40
     */
41
    const LAYOUT_FIXED = 'fixed';
42

43
    /**
44
     * Is this a first row style?
45
     *
46
     * @var bool
47
     */
48
    private $isFirstRow = false;
49

50
    /**
51
     * Style for first row.
52
     *
53
     * @var Table
54
     */
55
    private $firstRowStyle;
56

57
    /**
58
     * Cell margin top.
59
     *
60
     * @var int
61
     */
62
    private $cellMarginTop;
63

64
    /**
65
     * Cell margin left.
66
     *
67
     * @var int
68
     */
69
    private $cellMarginLeft;
70

71
    /**
72
     * Cell margin right.
73
     *
74
     * @var int
75
     */
76
    private $cellMarginRight;
77

78
    /**
79
     * Cell margin bottom.
80
     *
81
     * @var int
82
     */
83
    private $cellMarginBottom;
84

85
    /**
86
     * Border size inside horizontal.
87
     *
88
     * @var int
89
     */
90
    private $borderInsideHSize;
91

92
    /**
93
     * Border color inside horizontal.
94
     *
95
     * @var string
96
     */
97
    private $borderInsideHColor;
98

99
    /**
100
     * Border size inside vertical.
101
     *
102
     * @var int
103
     */
104
    private $borderInsideVSize;
105

106
    /**
107
     * Border color inside vertical.
108
     *
109
     * @var string
110
     */
111
    private $borderInsideVColor;
112

113
    /**
114
     * Shading.
115
     *
116
     * @var Shading
117
     */
118
    private $shading;
119

120
    /**
121
     * @var string
122
     */
123
    private $alignment = '';
124

125
    /**
126
     * @var float|int Width value
127
     */
128
    private $width = 0;
129

130
    /**
131
     * @var string Width unit
132
     */
133
    private $unit = TblWidth::AUTO;
134

135
    /**
136
     * @var null|float|int cell spacing value
137
     */
138
    private $cellSpacing;
139

140
    /**
141
     * @var string Table Layout
142
     */
143
    private $layout = self::LAYOUT_AUTO;
144

145
    /**
146
     * Position.
147
     *
148
     * @var ?TablePosition
149
     */
150
    private $position;
151

152
    /** @var null|TblWidthComplexType */
153
    private $indent;
154

155
    /**
156
     * The width of each column, computed based on the max cell width of each column.
157
     *
158
     * @var int[]
159
     */
160
    private $columnWidths;
161

162
    /**
163
     * Visually Right to Left Table.
164
     *
165
     * @see  http://www.datypic.com/sc/ooxml/e-w_bidiVisual-1.html
166
     *
167
     * @var ?bool
168
     */
169
    private $bidiVisual;
170

171
    /**
172
     * @var string tblCaption value
173
     *
174
     * This is also the title of the alt text field
175
     */
176
    private $tblCaption = '';
177

178
    /**
179
     * @var string tblDescription value
180
     *
181
     * This is also the content of the alt text field
182
     */
183
    private $tblDescription = '';
184

185
    /**
186
     * Create new table style.
187
     */
188
    public function __construct(?array $tableStyle = null, ?array $firstRowStyle = null)
189
    {
190
        // Clone first row from table style, but with certain properties disabled
191
        if ($firstRowStyle !== null) {
90✔
192
            $this->firstRowStyle = clone $this;
2✔
193
            $this->firstRowStyle->isFirstRow = true;
2✔
194
            unset(
2✔
195
                $this->firstRowStyle->firstRowStyle,
2✔
196
                $this->firstRowStyle->borderInsideHSize,
2✔
197
                $this->firstRowStyle->borderInsideHColor,
2✔
198
                $this->firstRowStyle->borderInsideVSize,
2✔
199
                $this->firstRowStyle->borderInsideVColor,
2✔
200
                $this->firstRowStyle->cellMarginTop,
2✔
201
                $this->firstRowStyle->cellMarginLeft,
2✔
202
                $this->firstRowStyle->cellMarginRight,
2✔
203
                $this->firstRowStyle->cellMarginBottom,
2✔
204
                $this->firstRowStyle->cellSpacing,
2✔
205
                $this->firstRowStyle->tblCaption,
2✔
206
                $this->firstRowStyle->tblDescription
2✔
207
            );
2✔
208
            $this->firstRowStyle->setStyleByArray($firstRowStyle);
2✔
209
        }
210

211
        if ($tableStyle !== null) {
90✔
212
            $this->setStyleByArray($tableStyle);
16✔
213
        }
214
    }
215

216
    /**
217
     * @param null|float|int $cellSpacing
218
     */
219
    public function setCellSpacing($cellSpacing = null): self
220
    {
221
        $this->cellSpacing = $cellSpacing;
4✔
222

223
        return $this;
4✔
224
    }
225

226
    /**
227
     * @return null|float|int
228
     */
229
    public function getCellSpacing()
230
    {
231
        return $this->cellSpacing;
30✔
232
    }
233

234
    /**
235
     * Set first row.
236
     *
237
     * @return Table
238
     */
239
    public function getFirstRow()
240
    {
241
        return $this->firstRowStyle;
29✔
242
    }
243

244
    /**
245
     * Get background.
246
     *
247
     * @return ?string
248
     */
249
    public function getBgColor()
250
    {
251
        if ($this->shading !== null) {
3✔
252
            return $this->shading->getFill();
2✔
253
        }
254

255
        return null;
1✔
256
    }
257

258
    /**
259
     * Set background.
260
     *
261
     * @param string $value
262
     *
263
     * @return self
264
     */
265
    public function setBgColor($value = null)
266
    {
267
        $this->setShading(['fill' => $value]);
6✔
268

269
        return $this;
6✔
270
    }
271

272
    /**
273
     * Get TLRBHV Border Size.
274
     *
275
     * @return int[]
276
     */
277
    public function getBorderSize()
278
    {
279
        return [
30✔
280
            $this->getBorderTopSize(),
30✔
281
            $this->getBorderLeftSize(),
30✔
282
            $this->getBorderRightSize(),
30✔
283
            $this->getBorderBottomSize(),
30✔
284
            $this->getBorderInsideHSize(),
30✔
285
            $this->getBorderInsideVSize(),
30✔
286
        ];
30✔
287
    }
288

289
    /**
290
     * Set TLRBHV Border Size.
291
     *
292
     * @param int $value Border size in eighths of a point (1/8 point)
293
     *
294
     * @return self
295
     */
296
    public function setBorderSize($value = null)
297
    {
298
        $this->setBorderTopSize($value);
10✔
299
        $this->setBorderLeftSize($value);
10✔
300
        $this->setBorderRightSize($value);
10✔
301
        $this->setBorderBottomSize($value);
10✔
302
        $this->setBorderInsideHSize($value);
10✔
303
        $this->setBorderInsideVSize($value);
10✔
304

305
        return $this;
10✔
306
    }
307

308
    /**
309
     * Get TLRBHV Border Color.
310
     *
311
     * @return string[]
312
     */
313
    public function getBorderColor()
314
    {
315
        return [
8✔
316
            $this->getBorderTopColor(),
8✔
317
            $this->getBorderLeftColor(),
8✔
318
            $this->getBorderRightColor(),
8✔
319
            $this->getBorderBottomColor(),
8✔
320
            $this->getBorderInsideHColor(),
8✔
321
            $this->getBorderInsideVColor(),
8✔
322
        ];
8✔
323
    }
324

325
    /**
326
     * Set TLRBHV Border Color.
327
     *
328
     * @param string $value
329
     *
330
     * @return self
331
     */
332
    public function setBorderColor($value = null)
333
    {
334
        $this->setBorderTopColor($value);
8✔
335
        $this->setBorderLeftColor($value);
8✔
336
        $this->setBorderRightColor($value);
8✔
337
        $this->setBorderBottomColor($value);
8✔
338
        $this->setBorderInsideHColor($value);
8✔
339
        $this->setBorderInsideVColor($value);
8✔
340

341
        return $this;
8✔
342
    }
343

344
    /**
345
     * Get border size inside horizontal.
346
     *
347
     * @return int
348
     */
349
    public function getBorderInsideHSize()
350
    {
351
        return $this->getTableOnlyProperty('borderInsideHSize');
31✔
352
    }
353

354
    /**
355
     * Set border size inside horizontal.
356
     *
357
     * @param int $value
358
     *
359
     * @return self
360
     */
361
    public function setBorderInsideHSize($value = null)
362
    {
363
        return $this->setTableOnlyProperty('borderInsideHSize', $value);
13✔
364
    }
365

366
    /**
367
     * Get border color inside horizontal.
368
     *
369
     * @return string
370
     */
371
    public function getBorderInsideHColor()
372
    {
373
        return $this->getTableOnlyProperty('borderInsideHColor');
9✔
374
    }
375

376
    /**
377
     * Set border color inside horizontal.
378
     *
379
     * @param string $value
380
     *
381
     * @return self
382
     */
383
    public function setBorderInsideHColor($value = null)
384
    {
385
        return $this->setTableOnlyProperty('borderInsideHColor', $value, false);
11✔
386
    }
387

388
    /**
389
     * Get border size inside vertical.
390
     *
391
     * @return int
392
     */
393
    public function getBorderInsideVSize()
394
    {
395
        return $this->getTableOnlyProperty('borderInsideVSize');
31✔
396
    }
397

398
    /**
399
     * Set border size inside vertical.
400
     *
401
     * @param int $value
402
     *
403
     * @return self
404
     */
405
    public function setBorderInsideVSize($value = null)
406
    {
407
        return $this->setTableOnlyProperty('borderInsideVSize', $value);
13✔
408
    }
409

410
    /**
411
     * Get border color inside vertical.
412
     *
413
     * @return string
414
     */
415
    public function getBorderInsideVColor()
416
    {
417
        return $this->getTableOnlyProperty('borderInsideVColor');
9✔
418
    }
419

420
    /**
421
     * Set border color inside vertical.
422
     *
423
     * @param string $value
424
     *
425
     * @return self
426
     */
427
    public function setBorderInsideVColor($value = null)
428
    {
429
        return $this->setTableOnlyProperty('borderInsideVColor', $value, false);
11✔
430
    }
431

432
    /**
433
     * Get cell margin top.
434
     *
435
     * @return int
436
     */
437
    public function getCellMarginTop()
438
    {
439
        return $this->getTableOnlyProperty('cellMarginTop');
2✔
440
    }
441

442
    /**
443
     * Set cell margin top.
444
     *
445
     * @param int $value
446
     *
447
     * @return self
448
     */
449
    public function setCellMarginTop($value = null)
450
    {
451
        return $this->setTableOnlyProperty('cellMarginTop', $value);
13✔
452
    }
453

454
    /**
455
     * Get cell margin left.
456
     *
457
     * @return int
458
     */
459
    public function getCellMarginLeft()
460
    {
461
        return $this->getTableOnlyProperty('cellMarginLeft');
2✔
462
    }
463

464
    /**
465
     * Set cell margin left.
466
     *
467
     * @param int $value
468
     *
469
     * @return self
470
     */
471
    public function setCellMarginLeft($value = null)
472
    {
473
        return $this->setTableOnlyProperty('cellMarginLeft', $value);
13✔
474
    }
475

476
    /**
477
     * Get cell margin right.
478
     *
479
     * @return int
480
     */
481
    public function getCellMarginRight()
482
    {
483
        return $this->getTableOnlyProperty('cellMarginRight');
2✔
484
    }
485

486
    /**
487
     * Set cell margin right.
488
     *
489
     * @param int $value
490
     *
491
     * @return self
492
     */
493
    public function setCellMarginRight($value = null)
494
    {
495
        return $this->setTableOnlyProperty('cellMarginRight', $value);
13✔
496
    }
497

498
    /**
499
     * Get cell margin bottom.
500
     *
501
     * @return int
502
     */
503
    public function getCellMarginBottom()
504
    {
505
        return $this->getTableOnlyProperty('cellMarginBottom');
2✔
506
    }
507

508
    /**
509
     * Set cell margin bottom.
510
     *
511
     * @param int $value
512
     *
513
     * @return self
514
     */
515
    public function setCellMarginBottom($value = null)
516
    {
517
        return $this->setTableOnlyProperty('cellMarginBottom', $value);
13✔
518
    }
519

520
    /**
521
     * Get cell margin.
522
     *
523
     * @return int[]
524
     */
525
    public function getCellMargin()
526
    {
527
        return [
30✔
528
            $this->cellMarginTop,
30✔
529
            $this->cellMarginLeft,
30✔
530
            $this->cellMarginRight,
30✔
531
            $this->cellMarginBottom,
30✔
532
        ];
30✔
533
    }
534

535
    /**
536
     * Set TLRB cell margin.
537
     *
538
     * @param int $value Margin in twips
539
     *
540
     * @return self
541
     */
542
    public function setCellMargin($value = null)
543
    {
544
        $this->setCellMarginTop($value);
4✔
545
        $this->setCellMarginLeft($value);
4✔
546
        $this->setCellMarginRight($value);
4✔
547
        $this->setCellMarginBottom($value);
4✔
548

549
        return $this;
4✔
550
    }
551

552
    /**
553
     * Check if any of the margin is not null.
554
     *
555
     * @return bool
556
     */
557
    public function hasMargin()
558
    {
559
        $margins = $this->getCellMargin();
29✔
560

561
        return $margins !== array_filter($margins, 'is_null');
29✔
562
    }
563

564
    /**
565
     * Get shading.
566
     *
567
     * @return Shading
568
     */
569
    public function getShading()
570
    {
571
        return $this->shading;
28✔
572
    }
573

574
    /**
575
     * Set shading.
576
     *
577
     * @param mixed $value
578
     *
579
     * @return self
580
     */
581
    public function setShading($value = null)
582
    {
583
        $this->setObjectVal($value, 'Shading', $this->shading);
6✔
584

585
        return $this;
6✔
586
    }
587

588
    /**
589
     * @since 0.13.0
590
     *
591
     * @return string
592
     */
593
    public function getAlignment()
594
    {
595
        return $this->alignment;
29✔
596
    }
597

598
    /**
599
     * @since 0.13.0
600
     *
601
     * @param string $value
602
     *
603
     * @return self
604
     */
605
    public function setAlignment($value)
606
    {
607
        if (JcTable::isValid($value) || Jc::isValid($value)) {
5✔
608
            $this->alignment = $value;
5✔
609
        }
610

611
        return $this;
5✔
612
    }
613

614
    /**
615
     * Get width.
616
     *
617
     * @return float|int
618
     */
619
    public function getWidth()
620
    {
621
        return $this->width;
29✔
622
    }
623

624
    /**
625
     * Set width.
626
     *
627
     * @param float|int $value
628
     *
629
     * @return self
630
     */
631
    public function setWidth($value = null)
632
    {
633
        $this->width = $this->setNumericVal($value, $this->width);
17✔
634

635
        return $this;
17✔
636
    }
637

638
    /**
639
     * Get width unit.
640
     *
641
     * @return string
642
     */
643
    public function getUnit()
644
    {
645
        return $this->unit;
31✔
646
    }
647

648
    /**
649
     * Set width unit.
650
     *
651
     * @param string $value
652
     *
653
     * @return self
654
     */
655
    public function setUnit($value = null)
656
    {
657
        TblWidth::validate($value);
15✔
658
        $this->unit = $value;
15✔
659

660
        return $this;
15✔
661
    }
662

663
    /**
664
     * Get layout.
665
     *
666
     * @return string
667
     */
668
    public function getLayout()
669
    {
670
        return $this->layout;
33✔
671
    }
672

673
    /**
674
     * Set layout.
675
     *
676
     * @param string $value
677
     *
678
     * @return self
679
     */
680
    public function setLayout($value = null)
681
    {
682
        $enum = [self::LAYOUT_AUTO, self::LAYOUT_FIXED];
4✔
683
        $this->layout = $this->setEnumVal($value, $enum, $this->layout);
4✔
684

685
        return $this;
4✔
686
    }
687

688
    /**
689
     * Get table caption.
690
     *
691
     * @return string
692
     */
693
    public function getTblCaption()
694
    {
695
        return $this->tblCaption;
28✔
696
    }
697

698
    /**
699
     * Set table caption.
700
     *
701
     * @param string $value
702
     *
703
     * @return self
704
     */
705
    public function setTblCaption($value = null)
706
    {
NEW
707
        $this->tblCaption = $value;
×
708

NEW
709
        return $this;
×
710
    }
711

712
    /**
713
     * Get table description (alt text).
714
     *
715
     * @return string
716
     */
717
    public function getTblDescription()
718
    {
719
        return $this->tblDescription;
28✔
720
    }
721

722
    /**
723
     * Set table description (alt text).
724
     *
725
     * @param string $value
726
     *
727
     * @return self
728
     */
729
    public function setTblDescription($value = null)
730
    {
NEW
731
        $this->tblDescription = $value;
×
732

NEW
733
        return $this;
×
734
    }
735

736
    /**
737
     * Get table style only property by checking if it's a firstRow.
738
     *
739
     * This is necessary since firstRow style is cloned from table style but
740
     * without certain properties activated, e.g. margins
741
     *
742
     * @param string $property
743
     *
744
     * @return null|int|string
745
     */
746
    private function getTableOnlyProperty($property)
747
    {
748
        if (false === $this->isFirstRow) {
33✔
749
            return $this->$property;
33✔
750
        }
751

752
        return null;
1✔
753
    }
754

755
    /**
756
     * Set table style only property by checking if it's a firstRow.
757
     *
758
     * This is necessary since firstRow style is cloned from table style but
759
     * without certain properties activated, e.g. margins
760
     *
761
     * @param string $property
762
     * @param int|string $value
763
     * @param bool $isNumeric
764
     *
765
     * @return self
766
     */
767
    private function setTableOnlyProperty($property, $value, $isNumeric = true)
768
    {
769
        if (false === $this->isFirstRow) {
21✔
770
            if (true === $isNumeric) {
21✔
771
                $this->$property = $this->setNumericVal($value, $this->$property);
20✔
772
            } else {
773
                $this->$property = $value;
10✔
774
            }
775
        }
776

777
        return $this;
21✔
778
    }
779

780
    /**
781
     * Get position.
782
     *
783
     * @return ?TablePosition
784
     */
785
    public function getPosition()
786
    {
787
        return $this->position;
30✔
788
    }
789

790
    /**
791
     * Set position.
792
     *
793
     * @param mixed $value
794
     *
795
     * @return self
796
     */
797
    public function setPosition($value = null)
798
    {
799
        $this->setObjectVal($value, 'TablePosition', $this->position);
3✔
800

801
        return $this;
3✔
802
    }
803

804
    /**
805
     * @return ?TblWidthComplexType
806
     */
807
    public function getIndent()
808
    {
809
        return $this->indent;
31✔
810
    }
811

812
    /**
813
     * @return self
814
     *
815
     * @see http://www.datypic.com/sc/ooxml/e-w_tblInd-1.html
816
     */
817
    public function setIndent(TblWidthComplexType $indent)
818
    {
819
        $this->indent = $indent;
9✔
820

821
        return $this;
9✔
822
    }
823

824
    /**
825
     * Get the columnWidths.
826
     *
827
     * @return null|int[]
828
     */
829
    public function getColumnWidths()
830
    {
831
        return $this->columnWidths;
3✔
832
    }
833

834
    /**
835
     * The column widths.
836
     *
837
     * @param int[] $value
838
     */
839
    public function setColumnWidths(?array $value = null): void
840
    {
841
        $this->columnWidths = $value;
3✔
842
    }
843

844
    /**
845
     * Get bidiVisual.
846
     *
847
     * @return ?bool
848
     */
849
    public function isBidiVisual()
850
    {
851
        return $this->bidiVisual ?? Settings::isDefaultRtl();
36✔
852
    }
853

854
    /**
855
     * Set bidiVisual.
856
     *
857
     * @param ?bool $bidi
858
     *            Set to true to visually present table as Right to Left
859
     *
860
     * @return self
861
     */
862
    public function setBidiVisual($bidi)
863
    {
864
        $this->bidiVisual = $bidi;
3✔
865

866
        return $this;
3✔
867
    }
868
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc