Skip to content

Commit 255af43

Browse files
committed
Bugfix for footnote reference number and additional feature to insert text break and style the reference number
1 parent 92588cc commit 255af43

File tree

10 files changed

+235
-109
lines changed

10 files changed

+235
-109
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ This is the changelog between releases of PHPWord. Releases are listed in revers
88

99
- Image: Get image dimensions without EXIF extension - @andrew-kzoo GH-184
1010
- Table: Add tblGrid element for Libre/Open Office table sizing - @gianis6 GH-183
11+
- Footnote: Ability to insert textbreak in footnote `$footnote->addTextBreak()` - @ivanlanin
12+
- Footnote: Ability to style footnote reference mark by using `FootnoteReference` style - @ivanlanin
1113

1214
### Bugfixes
1315

14-
-
16+
- Footnote: Footnote content doesn't show footnote reference number - @ivanlanin GH-170
1517

1618
### Miscellaneous
1719

docs/elements.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ Footnotes
326326
---------
327327

328328
You can create footnotes in texts or textruns, but it's recommended to
329-
use textrun to have better layout.
329+
use textrun to have better layout. You can use ``addText``, ``addLink``,
330+
and ``addTextBreak`` on a footnote.
330331

331332
On textrun:
332333

@@ -335,7 +336,11 @@ On textrun:
335336
$textrun = $section->createTextRun();
336337
$textrun->addText('Lead text.');
337338
$footnote = $textrun->createFootnote();
338-
$footnote->addText('Footnote text.');
339+
$footnote->addText('Footnote text can have ');
340+
$footnote->addLink('http://test.com', 'links');
341+
$footnote->addText('.');
342+
$footnote->addTextBreak();
343+
$footnote->addText('And text break.');
339344
$textrun->addText('Trailing text.');
340345
341346
On text:
@@ -345,3 +350,8 @@ On text:
345350
$section->addText('Lead text.');
346351
$footnote = $section->createFootnote();
347352
$footnote->addText('Footnote text.');
353+
354+
The footnote reference number will be displayed with decimal number starting
355+
from 1. This number use ``FooterReference`` style which you can redefine by
356+
``addFontStyle`` method. Default value for this style is
357+
``array('superScript' => true)``;

samples/Sample_06_Footnote.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
$footnote->addText(' All elements are placed inside a paragraph.', 'ColoredText');
2525
$footnote->addText(' The best search engine: ');
2626
$footnote->addLink('http://www.google.com', null, 'NLink');
27-
$footnote->addText('. Also not bad: ');
27+
$footnote->addText('. Also not bad:');
28+
$footnote->addTextBreak();
2829
$footnote->addLink('http://www.bing.com', null, 'NLink');
2930

3031
$textrun->addText('The trailing text in the paragraph.');

src/PhpWord/Section/Footnote.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,20 @@ public function addText($text = null, $styleFont = null)
7777
return $text;
7878
}
7979

80+
/**
81+
* Add TextBreak
82+
*
83+
* @param int $count
84+
* @param mixed $fontStyle
85+
* @param mixed $paragraphStyle
86+
*/
87+
public function addTextBreak($count = 1, $fontStyle = null, $paragraphStyle = null)
88+
{
89+
for ($i = 1; $i <= $count; $i++) {
90+
$this->_elementCollection[] = new TextBreak($fontStyle, $paragraphStyle);
91+
}
92+
}
93+
8094
/**
8195
* Add a Link Element
8296
*

src/PhpWord/Writer/Word2007/Base.php

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ protected function _writeTextRun(XMLWriter $xmlWriter, TextRun $textrun)
125125
} elseif ($element instanceof Image) {
126126
$this->_writeImage($xmlWriter, $element, true);
127127
} elseif ($element instanceof Footnote) {
128-
$this->_writeFootnoteReference($xmlWriter, $element, true);
128+
$this->_writeFootnote($xmlWriter, $element, true);
129129
} elseif ($element instanceof TextBreak) {
130130
$xmlWriter->writeElement('w:br');
131131
}
@@ -1172,61 +1172,24 @@ protected function _writeTitle(XMLWriter $xmlWriter, Title $title)
11721172
}
11731173

11741174
/**
1175-
* Write footnote element
1176-
*
1177-
* @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
1178-
* @param PhpOffice\PhpWord\Section\Footnote $footnote
1179-
*/
1180-
protected function _writeFootnote(XMLWriter $xmlWriter, Footnote $footnote)
1181-
{
1182-
$xmlWriter->startElement('w:footnote');
1183-
$xmlWriter->writeAttribute('w:id', $footnote->getReferenceId());
1184-
1185-
$styleParagraph = $footnote->getParagraphStyle();
1186-
$SpIsObject = ($styleParagraph instanceof Paragraph) ? true : false;
1187-
1188-
$xmlWriter->startElement('w:p');
1189-
1190-
if ($SpIsObject) {
1191-
$this->_writeParagraphStyle($xmlWriter, $styleParagraph);
1192-
} elseif (!$SpIsObject && !is_null($styleParagraph)) {
1193-
$xmlWriter->startElement('w:pPr');
1194-
$xmlWriter->startElement('w:pStyle');
1195-
$xmlWriter->writeAttribute('w:val', $styleParagraph);
1196-
$xmlWriter->endElement();
1197-
$xmlWriter->endElement();
1198-
}
1199-
1200-
$elements = $footnote->getElements();
1201-
if (count($elements) > 0) {
1202-
foreach ($elements as $element) {
1203-
if ($element instanceof Text) {
1204-
$this->_writeText($xmlWriter, $element, true);
1205-
} elseif ($element instanceof Link) {
1206-
$this->_writeLink($xmlWriter, $element, true);
1207-
}
1208-
}
1209-
}
1210-
1211-
$xmlWriter->endElement(); // w:p
1212-
$xmlWriter->endElement(); // w:footnote
1213-
}
1214-
1215-
/**
1216-
* Write footnote reference element
1175+
* Write footnote element which links to the actual content in footnotes.xml
12171176
*
12181177
* @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
12191178
* @param PhpOffice\PhpWord\Section\Footnote $footnote
12201179
* @param boolean $withoutP
12211180
*/
1222-
protected function _writeFootnoteReference(XMLWriter $xmlWriter, Footnote $footnote, $withoutP = false)
1181+
protected function _writeFootnote(XMLWriter $xmlWriter, Footnote $footnote, $withoutP = false)
12231182
{
12241183
if (!$withoutP) {
12251184
$xmlWriter->startElement('w:p');
12261185
}
12271186

12281187
$xmlWriter->startElement('w:r');
1229-
1188+
$xmlWriter->startElement('w:rPr');
1189+
$xmlWriter->startElement('w:rStyle');
1190+
$xmlWriter->writeAttribute('w:val', 'FootnoteReference');
1191+
$xmlWriter->endElement(); // w:rStyle
1192+
$xmlWriter->endElement(); // w:rPr
12301193
$xmlWriter->startElement('w:footnoteReference');
12311194
$xmlWriter->writeAttribute('w:id', $footnote->getReferenceId());
12321195
$xmlWriter->endElement(); // w:footnoteReference

src/PhpWord/Writer/Word2007/Document.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public function writeDocument(PhpWord $phpWord = null)
9898
} elseif ($element instanceof TOC) {
9999
$this->_writeTOC($xmlWriter);
100100
} elseif ($element instanceof Footnote) {
101-
$this->_writeFootnoteReference($xmlWriter, $element);
101+
$this->_writeFootnote($xmlWriter, $element);
102102
}
103103
}
104104

src/PhpWord/Writer/Word2007/Footnotes.php

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
namespace PhpOffice\PhpWord\Writer\Word2007;
1111

1212
use PhpOffice\PhpWord\Section\Footnote;
13+
use PhpOffice\PhpWord\Section\Text;
14+
use PhpOffice\PhpWord\Section\Link;
15+
use PhpOffice\PhpWord\Section\TextBreak;
16+
use PhpOffice\PhpWord\Style\Paragraph;
1317
use PhpOffice\PhpWord\Shared\XMLWriter;
1418

1519
/**
@@ -27,19 +31,25 @@ public function writeFootnotes($allFootnotesCollection)
2731
// Create XML writer
2832
$xmlWriter = null;
2933
if ($this->getParentWriter()->getUseDiskCaching()) {
30-
$xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
34+
$xmlWriter = new XMLWriter(
35+
XMLWriter::STORAGE_DISK,
36+
$this->getParentWriter()->getDiskCachingDirectory()
37+
);
3138
} else {
3239
$xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
3340
}
34-
3541
// XML header
3642
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
37-
3843
$xmlWriter->startElement('w:footnotes');
39-
$xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
40-
$xmlWriter->writeAttribute('xmlns:w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main');
41-
42-
// write separator and continuation separator
44+
$xmlWriter->writeAttribute(
45+
'xmlns:r',
46+
'http://schemas.openxmlformats.org/officeDocument/2006/relationships'
47+
);
48+
$xmlWriter->writeAttribute(
49+
'xmlns:w',
50+
'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
51+
);
52+
// Separator and continuation separator
4353
$xmlWriter->startElement('w:footnote');
4454
$xmlWriter->writeAttribute('w:id', 0);
4555
$xmlWriter->writeAttribute('w:type', 'separator');
@@ -50,7 +60,7 @@ public function writeFootnotes($allFootnotesCollection)
5060
$xmlWriter->endElement(); // w:r
5161
$xmlWriter->endElement(); // w:p
5262
$xmlWriter->endElement(); // w:footnote
53-
63+
// Content
5464
$xmlWriter->startElement('w:footnote');
5565
$xmlWriter->writeAttribute('w:id', 1);
5666
$xmlWriter->writeAttribute('w:type', 'continuationSeparator');
@@ -61,16 +71,69 @@ public function writeFootnotes($allFootnotesCollection)
6171
$xmlWriter->endElement(); // w:r
6272
$xmlWriter->endElement(); // w:p
6373
$xmlWriter->endElement(); // w:footnote
64-
6574
foreach ($allFootnotesCollection as $footnote) {
6675
if ($footnote instanceof Footnote) {
67-
$this->_writeFootnote($xmlWriter, $footnote);
76+
$this->writeFootnote($xmlWriter, $footnote);
6877
}
6978
}
70-
7179
$xmlWriter->endElement();
7280

73-
// Return
7481
return $xmlWriter->getData();
7582
}
83+
84+
/**
85+
* Write footnote content, overrides method in parent class
86+
*
87+
* @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
88+
* @param PhpOffice\PhpWord\Section\Footnote $footnote
89+
*/
90+
private function writeFootnote(XMLWriter $xmlWriter, Footnote $footnote)
91+
{
92+
$xmlWriter->startElement('w:footnote');
93+
$xmlWriter->writeAttribute('w:id', $footnote->getReferenceId());
94+
$xmlWriter->startElement('w:p');
95+
// Paragraph style
96+
$paragraphStyle = $footnote->getParagraphStyle();
97+
$spIsObject = ($paragraphStyle instanceof Paragraph) ? true : false;
98+
if ($spIsObject) {
99+
$this->_writeParagraphStyle($xmlWriter, $paragraphStyle);
100+
} elseif (!$spIsObject && !is_null($paragraphStyle)) {
101+
$xmlWriter->startElement('w:pPr');
102+
$xmlWriter->startElement('w:pStyle');
103+
$xmlWriter->writeAttribute('w:val', $paragraphStyle);
104+
$xmlWriter->endElement();
105+
$xmlWriter->endElement();
106+
}
107+
// Reference symbol
108+
$xmlWriter->startElement('w:r');
109+
$xmlWriter->startElement('w:rPr');
110+
$xmlWriter->startElement('w:rStyle');
111+
$xmlWriter->writeAttribute('w:val', 'FootnoteReference');
112+
$xmlWriter->endElement(); // w:rStyle
113+
$xmlWriter->endElement(); // w:rPr
114+
$xmlWriter->writeElement('w:footnoteRef');
115+
$xmlWriter->endElement(); // w:r
116+
// Empty space after refence symbol
117+
$xmlWriter->startElement('w:r');
118+
$xmlWriter->startElement('w:t');
119+
$xmlWriter->writeAttribute('xml:space', 'preserve');
120+
$xmlWriter->writeRaw(' ');
121+
$xmlWriter->endElement(); // w:t
122+
$xmlWriter->endElement(); // w:r
123+
// Actual footnote contents
124+
$elements = $footnote->getElements();
125+
if (count($elements) > 0) {
126+
foreach ($elements as $element) {
127+
if ($element instanceof Text) {
128+
$this->_writeText($xmlWriter, $element, true);
129+
} elseif ($element instanceof Link) {
130+
$this->_writeLink($xmlWriter, $element, true);
131+
} elseif ($element instanceof TextBreak) {
132+
$xmlWriter->writeElement('w:br');
133+
}
134+
}
135+
}
136+
$xmlWriter->endElement(); // w:p
137+
$xmlWriter->endElement(); // w:footnote
138+
}
76139
}

0 commit comments

Comments
 (0)