Skip to content

Commit a25ba4f

Browse files
Progi1984ling
authored andcommitted
Writer/Reader Word2007: Added support for the firstLineChars for Indentation (PHPOffice#2753)
* Add support for the firstLineChars style in Word2007. * Writer Word2007: Added support for the firstLineChars for Indentation * Fixed Changelog * Fixed PHPStan & PHPCSFixer * Fixed PHPStan --------- Co-authored-by: ling <ling@yundian>
1 parent 5cfd43e commit a25ba4f

File tree

15 files changed

+273
-24
lines changed

15 files changed

+273
-24
lines changed

docs/changes/1.x/1.4.0.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
- Add basic ruby text (phonetic guide) support for Word2007 and HTML Reader/Writer, RTF Writer, basic support for ODT writing by [@Deadpikle](https://github.com/Deadpikle) in [#2727](https://github.com/PHPOffice/PHPWord/pull/2727)
1818
- Reader HTML: Support font styles for h1/h6 by [@Progi1984](https://github.com/Progi1984) fixing [#2619](https://github.com/PHPOffice/PHPWord/issues/2619) in [#2737](https://github.com/PHPOffice/PHPWord/pull/2737)
1919
- Writer EPub3: Basic support by [@Sambit003](https://github.com/Sambit003) fixing [#55](https://github.com/PHPOffice/PHPWord/issues/55) in [#2724](https://github.com/PHPOffice/PHPWord/pull/2724)
20-
- Writer2007: Added support for background and border color transparency in Text Box element [@chudy20007](https://github.com/Chudy20007) in [#2555](https://github.com/PHPOffice/PHPWord/pull/2555)
20+
- Writer Word2007: Added support for background and border color transparency in Text Box element by [@chudy20007](https://github.com/Chudy20007) in [#2555](https://github.com/PHPOffice/PHPWord/pull/2555)
21+
- Writer/Reader Word2007: Added support for the firstLineChars for Indentation by [@liuzhilinux](https://github.com/liuzhilinux) & [@Progi1984](https://github.com/Progi1984) in [#2753](https://github.com/PHPOffice/PHPWord/pull/2753)
2122

2223
### Bug fixes
2324

docs/usage/styles/paragraph.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Available Paragraph style options:
77
- ``basedOn``. Parent style.
88
- ``hanging``. Hanging indentation in *half inches*.
99
- ``indent``. Indent (left indentation) in *half inches*.
10-
- ``indentation``. An array of indentation key => value pairs in *twip*. Supports *left*, *right*, *firstLine* and *hanging* indentation.
10+
- ``indentation``. An array of indentation key => value pairs in *twip*. Supports *left*, *right*, *firstLine*, *firstLineChars* and *hanging* indentation.
1111
See ``\PhpOffice\PhpWord\Style\Indentation`` for possible identation types.
1212
- ``keepLines``. Keep all lines on one page, *true* or *false*.
1313
- ``keepNext``. Keep paragraph with next paragraph, *true* or *false*.

src/PhpWord/Reader/Word2007/AbstractPart.php

+1
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ protected function readParagraphStyle(XMLReader $xmlReader, DOMElement $domNode)
708708
'indentRight' => [self::READ_VALUE, 'w:ind', 'w:right'],
709709
'indentHanging' => [self::READ_VALUE, 'w:ind', 'w:hanging'],
710710
'indentFirstLine' => [self::READ_VALUE, 'w:ind', 'w:firstLine'],
711+
'indentFirstLineChars' => [self::READ_VALUE, 'w:ind', 'w:firstLineChars'],
711712
'spaceAfter' => [self::READ_VALUE, 'w:spacing', 'w:after'],
712713
'spaceBefore' => [self::READ_VALUE, 'w:spacing', 'w:before'],
713714
'widowControl' => [self::READ_FALSE, 'w:widowControl'],

src/PhpWord/Style/Indentation.php

+25
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ class Indentation extends AbstractStyle
4747
*/
4848
private $firstLine = 0;
4949

50+
/**
51+
* Additional first line chars indentation (twip).
52+
*
53+
* @var int
54+
*/
55+
private $firstLineChars = 0;
56+
5057
/**
5158
* Indentation removed from first line (twip).
5259
*
@@ -118,6 +125,24 @@ public function setFirstLine(?float $value): self
118125
return $this;
119126
}
120127

128+
/**
129+
* Get first line chars.
130+
*/
131+
public function getFirstLineChars(): int
132+
{
133+
return $this->firstLineChars;
134+
}
135+
136+
/**
137+
* Set first line chars.
138+
*/
139+
public function setFirstLineChars(int $value): self
140+
{
141+
$this->firstLineChars = $this->setIntVal($value, $this->firstLineChars);
142+
143+
return $this;
144+
}
145+
121146
/**
122147
* Get hanging.
123148
*/

src/PhpWord/Style/Paragraph.php

+8
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,14 @@ public function setIndentFirstLine(?float $value = null): self
432432
return $this->setIndentation(['firstLine' => $value]);
433433
}
434434

435+
/**
436+
* Set firstlineChars indentation.
437+
*/
438+
public function setIndentFirstLineChars(int $value = 0): self
439+
{
440+
return $this->setIndentation(['firstLineChars' => $value]);
441+
}
442+
435443
/**
436444
* Set left indentation.
437445
*/

src/PhpWord/Writer/Word2007/Style/Indentation.php

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ public function write(): void
4444
$firstLine = $style->getFirstLine();
4545
$xmlWriter->writeAttributeIf(null !== $firstLine, 'w:firstLine', $this->convertTwip($firstLine));
4646

47+
$firstLineChars = $style->getFirstLineChars();
48+
$xmlWriter->writeAttributeIf(0 !== $firstLineChars, 'w:firstLineChars', $this->convertTwip($firstLineChars));
49+
4750
$hanging = $style->getHanging();
4851
$xmlWriter->writeAttributeIf(null !== $hanging, 'w:hanging', $this->convertTwip($hanging));
4952

tests/PhpWordTests/Element/AbstractElementTest.php

+14-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ class AbstractElementTest extends \PHPUnit\Framework\TestCase
3030
*/
3131
public function testElementIndex(): void
3232
{
33-
$stub = $this->getMockForAbstractClass(AbstractElement::class);
33+
if (method_exists($this, 'getMockForAbstractClass')) {
34+
$stub = $this->getMockForAbstractClass(AbstractElement::class);
35+
} else {
36+
/** @var AbstractElement $stub */
37+
$stub = new class() extends AbstractElement {
38+
};
39+
}
3440
$ival = mt_rand(0, 100);
3541
$stub->setElementIndex($ival);
3642
self::assertEquals($ival, $stub->getElementIndex());
@@ -41,7 +47,13 @@ public function testElementIndex(): void
4147
*/
4248
public function testElementId(): void
4349
{
44-
$stub = $this->getMockForAbstractClass(AbstractElement::class);
50+
if (method_exists($this, 'getMockForAbstractClass')) {
51+
$stub = $this->getMockForAbstractClass(AbstractElement::class);
52+
} else {
53+
/** @var AbstractElement $stub */
54+
$stub = new class() extends AbstractElement {
55+
};
56+
}
4557
$stub->setElementId();
4658
self::assertEquals(6, strlen($stub->getElementId()));
4759
}

tests/PhpWordTests/Reader/Word2007/StyleTest.php

+50-7
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,14 @@ public function testPageVerticalAlign(): void
334334
/**
335335
* @dataProvider providerIndentation
336336
*/
337-
public function testIndentation(string $indent, float $left, float $right, ?float $hanging, float $firstLine): void
338-
{
337+
public function testIndentation(
338+
string $indent,
339+
float $left,
340+
float $right,
341+
?float $hanging,
342+
float $firstLine,
343+
int $firstLineChars
344+
): void {
339345
$documentXml = "<w:p>
340346
<w:pPr>
341347
$indent
@@ -359,16 +365,53 @@ public function testIndentation(string $indent, float $left, float $right, ?floa
359365
self::assertSame($right, $indentation->getRight());
360366
self::assertSame($hanging, $indentation->getHanging());
361367
self::assertSame($firstLine, $indentation->getFirstLine());
368+
self::assertSame($firstLineChars, $indentation->getFirstLineChars());
362369
}
363370

364371
/**
365-
* @return Generator<array{0:string, 1:float, 2:float, 3:null|float, 4: float}>
372+
* @return Generator<array{0:string, 1:float, 2:float, 3:null|float, 4: float, 5: int}>
366373
*/
367374
public static function providerIndentation()
368375
{
369-
yield ['<w:ind w:left="709" w:right="488" w:hanging="10" w:firstLine="490"/>', 709.00, 488.00, 10.0, 490.00];
370-
yield ['<w:ind w:hanging="10" w:firstLine="490"/>', 0, 0, 10.0, 490.00];
371-
yield ['<w:ind w:left="709"/>', 709.00, 0, 0, 0];
372-
yield ['<w:ind w:right="488"/>', 0, 488.00, 0, 0];
376+
yield [
377+
'<w:ind w:left="709" w:right="488" w:hanging="10" w:firstLine="490" w:firstLineChars="140"/>',
378+
709.00,
379+
488.00,
380+
10.0,
381+
490.00,
382+
140,
383+
];
384+
yield [
385+
'<w:ind w:left="709" w:right="488" w:hanging="10" w:firstLine="490"/>',
386+
709.00,
387+
488.00,
388+
10.0,
389+
490.00,
390+
0,
391+
];
392+
yield [
393+
'<w:ind w:hanging="10" w:firstLine="490"/>',
394+
0,
395+
0,
396+
10.0,
397+
490.00,
398+
0,
399+
];
400+
yield [
401+
'<w:ind w:left="709"/>',
402+
709.00,
403+
0,
404+
0,
405+
0,
406+
0,
407+
];
408+
yield [
409+
'<w:ind w:right="488"/>',
410+
0,
411+
488.00,
412+
0,
413+
0,
414+
0,
415+
];
373416
}
374417
}

tests/PhpWordTests/Style/AbstractStyleTest.php

+29-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
use InvalidArgumentException;
2222
use PhpOffice\PhpWord\SimpleType\Jc;
23+
use PhpOffice\PhpWord\Style\AbstractStyle;
2324
use PhpOffice\PhpWord\Style\Paragraph;
2425
use ReflectionClass;
2526

@@ -35,7 +36,13 @@ class AbstractStyleTest extends \PHPUnit\Framework\TestCase
3536
*/
3637
public function testSetStyleByArray(): void
3738
{
38-
$stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle');
39+
if (method_exists($this, 'getMockForAbstractClass')) {
40+
$stub = $this->getMockForAbstractClass(AbstractStyle::class);
41+
} else {
42+
/** @var AbstractStyle $stub */
43+
$stub = new class() extends AbstractStyle {
44+
};
45+
}
3946
$stub->setStyleByArray(['index' => 1]);
4047

4148
self::assertEquals(1, $stub->getIndex());
@@ -62,7 +69,13 @@ public function testSetStyleByArrayWithAlignment(): void
6269
*/
6370
public function testSetValNormal(): void
6471
{
65-
$stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle');
72+
if (method_exists($this, 'getMockForAbstractClass')) {
73+
$stub = $this->getMockForAbstractClass(AbstractStyle::class);
74+
} else {
75+
/** @var AbstractStyle $stub */
76+
$stub = new class() extends AbstractStyle {
77+
};
78+
}
6679

6780
self::assertTrue(self::callProtectedMethod($stub, 'setBoolVal', [true, false]));
6881
self::assertEquals(12, self::callProtectedMethod($stub, 'setIntVal', [12, 200]));
@@ -76,7 +89,13 @@ public function testSetValNormal(): void
7689
*/
7790
public function testSetValDefault(): void
7891
{
79-
$stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle');
92+
if (method_exists($this, 'getMockForAbstractClass')) {
93+
$stub = $this->getMockForAbstractClass(AbstractStyle::class);
94+
} else {
95+
/** @var AbstractStyle $stub */
96+
$stub = new class() extends AbstractStyle {
97+
};
98+
}
8099

81100
self::assertNotTrue(self::callProtectedMethod($stub, 'setBoolVal', ['a', false]));
82101
self::assertEquals(200, self::callProtectedMethod($stub, 'setIntVal', ['foo', 200]));
@@ -90,7 +109,13 @@ public function testSetValDefault(): void
90109
public function testSetValEnumException(): void
91110
{
92111
$this->expectException(InvalidArgumentException::class);
93-
$stub = $this->getMockForAbstractClass('\PhpOffice\PhpWord\Style\AbstractStyle');
112+
if (method_exists($this, 'getMockForAbstractClass')) {
113+
$stub = $this->getMockForAbstractClass(AbstractStyle::class);
114+
} else {
115+
/** @var AbstractStyle $stub */
116+
$stub = new class() extends AbstractStyle {
117+
};
118+
}
94119

95120
self::assertEquals('b', self::callProtectedMethod($stub, 'setEnumVal', ['z', ['a', 'b'], 'b']));
96121
}

tests/PhpWordTests/Style/IndentationTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function testGetSetProperties(): void
3737
'left' => [0, 10],
3838
'right' => [0, 10],
3939
'firstLine' => [null, 20],
40+
'firstLineChars' => [0, 20],
4041
'hanging' => [null, 20],
4142
];
4243
foreach ($properties as $property => $value) {

tests/PhpWordTests/Writer/EPub3/Part/AbstractPartTest.php

+10-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,16 @@ class AbstractPartTest extends TestCase
1515

1616
protected function setUp(): void
1717
{
18-
$this->part = $this->getMockForAbstractClass(AbstractPart::class);
18+
if (method_exists($this, 'getMockForAbstractClass')) {
19+
$this->part = $this->getMockForAbstractClass(AbstractPart::class);
20+
} else {
21+
$this->part = new class() extends AbstractPart {
22+
public function write(): string
23+
{
24+
return '';
25+
}
26+
};
27+
}
1928
}
2029

2130
public function testParentWriter(): void

tests/PhpWordTests/Writer/EPub3/Style/AbstractStyleTest.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,17 @@ class AbstractStyleTest extends TestCase
1414
public function testParentWriter(): void
1515
{
1616
$parentWriter = new EPub3();
17-
$style = $this->getMockForAbstractClass(AbstractStyle::class);
17+
if (method_exists($this, 'getMockForAbstractClass')) {
18+
$style = $this->getMockForAbstractClass(AbstractStyle::class);
19+
} else {
20+
/** @var AbstractStyle $style */
21+
$style = new class() extends AbstractStyle {
22+
public function write(): string
23+
{
24+
return '';
25+
}
26+
};
27+
}
1828

1929
$result = $style->setParentWriter($parentWriter);
2030

tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php

+22-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,17 @@ class AbstractPartTest extends \PHPUnit\Framework\TestCase
3434
*/
3535
public function testSetGetParentWriter(): void
3636
{
37-
$object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class);
37+
if (method_exists($this, 'getMockForAbstractClass')) {
38+
$object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class);
39+
} else {
40+
/** @var ODText\Part\AbstractPart $object */
41+
$object = new class() extends ODText\Part\AbstractPart {
42+
public function write(): string
43+
{
44+
return '';
45+
}
46+
};
47+
}
3848
$object->setParentWriter(new ODText());
3949
self::assertEquals(new ODText(), $object->getParentWriter());
4050
}
@@ -46,7 +56,17 @@ public function testSetGetParentWriterNull(): void
4656
{
4757
$this->expectException(Exception::class);
4858
$this->expectExceptionMessage('No parent WriterInterface assigned.');
49-
$object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class);
59+
if (method_exists($this, 'getMockForAbstractClass')) {
60+
$object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class);
61+
} else {
62+
/** @var ODText\Part\AbstractPart $object */
63+
$object = new class() extends ODText\Part\AbstractPart {
64+
public function write(): string
65+
{
66+
return '';
67+
}
68+
};
69+
}
5070
$object->getParentWriter();
5171
}
5272
}

tests/PhpWordTests/Writer/Word2007/Part/AbstractPartTest.php

+25-5
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,19 @@ class AbstractPartTest extends \PHPUnit\Framework\TestCase
3232
*/
3333
public function testSetGetParentWriter(): void
3434
{
35-
$object = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class);
36-
$object->setParentWriter(new Word2007());
37-
self::assertEquals(new Word2007(), $object->getParentWriter());
35+
if (method_exists($this, 'getMockForAbstractClass')) {
36+
$stub = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class);
37+
} else {
38+
/** @var Word2007\Part\AbstractPart $stub */
39+
$stub = new class() extends Word2007\Part\AbstractPart {
40+
public function write(): string
41+
{
42+
return '';
43+
}
44+
};
45+
}
46+
$stub->setParentWriter(new Word2007());
47+
self::assertEquals(new Word2007(), $stub->getParentWriter());
3848
}
3949

4050
/**
@@ -44,7 +54,17 @@ public function testSetGetParentWriterNull(): void
4454
{
4555
$this->expectException(Exception::class);
4656
$this->expectExceptionMessage('No parent WriterInterface assigned.');
47-
$object = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class);
48-
$object->getParentWriter();
57+
if (method_exists($this, 'getMockForAbstractClass')) {
58+
$stub = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class);
59+
} else {
60+
/** @var Word2007\Part\AbstractPart $stub */
61+
$stub = new class() extends Word2007\Part\AbstractPart {
62+
public function write(): string
63+
{
64+
return '';
65+
}
66+
};
67+
}
68+
$stub->getParentWriter();
4969
}
5070
}

0 commit comments

Comments
 (0)