Skip to content

Commit 29f7cfb

Browse files
authored
Merge pull request #1068 from troosan/footnote_properties
Add possibility to control the footnote number
2 parents ce49213 + eff532e commit 29f7cfb

File tree

7 files changed

+344
-4
lines changed

7 files changed

+344
-4
lines changed

docs/elements.rst

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,28 @@ On text:
333333
$footnote = $section->addFootnote();
334334
$footnote->addText('Footnote text.');
335335
336-
The footnote reference number will be displayed with decimal number
337-
starting from 1. This number use ``FooterReference`` style which you can
338-
redefine by ``addFontStyle`` method. Default value for this style is
336+
By default the footnote reference number will be displayed with decimal number
337+
starting from 1. This number uses the ``FooterReference`` style which you can
338+
redefine with the ``addFontStyle`` method. Default value for this style is
339339
``array('superScript' => true)``;
340340

341+
The footnote numbering can be controlled by setting the FootnoteProperties on the Section.
342+
343+
.. code-block:: php
344+
345+
$fp = new PhpWord\SimpleType\FootnoteProperties();
346+
//sets the position of the footnote (pageBottom (default), beneathText, sectEnd, docEnd)
347+
$fp->setPos(FootnoteProperties::POSITION_DOC_END);
348+
//set the number format to use (decimal (default), upperRoman, upperLetter, ...)
349+
$fp->setNumFmt(FootnoteProperties::NUMBER_FORMAT_LOWER_ROMAN);
350+
//force starting at other than 1
351+
$fp->setNumStart(2);
352+
//when to restart counting (continuous (default), eachSect, eachPage)
353+
$fp->setNumRestart(FootnoteProperties::RESTART_NUMBER_EACH_PAGE);
354+
355+
//And finaly, set it on the Section
356+
$section->setFootnoteProperties($properties);
357+
341358
Checkboxes
342359
----------
343360

samples/Sample_06_Footnote.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<?php
2+
use PhpOffice\PhpWord\SimpleType\FootnoteProperties;
3+
24
include_once 'Sample_Header.php';
35

46
// New Word Document
@@ -42,11 +44,15 @@
4244

4345
$section->addText(
4446
'You can also create the footnote directly from the section making it wrap in a paragraph '
45-
. 'like the footnote below this paragraph. But is is best used from within a textrun.'
47+
. 'like the footnote below this paragraph. But is best used from within a textrun.'
4648
);
4749
$footnote = $section->addFootnote();
4850
$footnote->addText('The reference for this is wrapped in its own line');
4951

52+
$footnoteProperties = new FootnoteProperties();
53+
$footnoteProperties->setNumFmt(FootnoteProperties::NUMBER_FORMAT_UPPER_ROMAN);
54+
$section->setFootnoteProperties($footnoteProperties);
55+
5056
// Save file
5157
echo write($phpWord, basename(__FILE__, '.php'), $writers);
5258
if (!CLI) {

src/PhpWord/Element/Section.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
namespace PhpOffice\PhpWord\Element;
1919

2020
use PhpOffice\PhpWord\Style\Section as SectionStyle;
21+
use PhpOffice\PhpWord\SimpleType\FootnoteProperties;
2122

2223
class Section extends AbstractContainer
2324
{
@@ -47,6 +48,13 @@ class Section extends AbstractContainer
4748
*/
4849
private $footers = array();
4950

51+
/**
52+
* The properties for the footnote of this section
53+
*
54+
* @var FootnoteProperties
55+
*/
56+
private $footnoteProperties;
57+
5058
/**
5159
* Create new instance
5260
*
@@ -138,6 +146,26 @@ public function getFooters()
138146
return $this->footers;
139147
}
140148

149+
/**
150+
* Get the footnote properties
151+
*
152+
* @return \PhpOffice\PhpWord\Element\FooterProperties
153+
*/
154+
public function getFootnotePropoperties()
155+
{
156+
return $this->footnoteProperties;
157+
}
158+
159+
/**
160+
* Set the footnote properties
161+
*
162+
* @param FootnoteProperties $footnoteProperties
163+
*/
164+
public function setFootnoteProperties(FootnoteProperties $footnoteProperties = null)
165+
{
166+
$this->footnoteProperties = $footnoteProperties;
167+
}
168+
141169
/**
142170
* Is there a header for this section that is for the first page only?
143171
*
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
/**
3+
* This file is part of PHPWord - A pure PHP library for reading and writing
4+
* word processing documents.
5+
*
6+
* PHPWord 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/PHPWord/contributors.
12+
*
13+
* @link https://github.com/PHPOffice/PHPWord
14+
* @copyright 2010-2016 PHPWord contributors
15+
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16+
*/
17+
namespace PhpOffice\PhpWord\SimpleType;
18+
19+
/**
20+
* Footnote properties
21+
*
22+
* @see http://www.datypic.com/sc/ooxml/e-w_footnotePr-1.html
23+
*/
24+
final class FootnoteProperties
25+
{
26+
27+
const RESTART_NUMBER_CONTINUOUS = 'continuous';
28+
const RESTART_NUMBER_EACH_SECTION = 'eachSect';
29+
const RESTART_NUMBER_EACH_PAGE = 'eachPage';
30+
31+
const NUMBER_FORMAT_DECIMAL = 'decimal';
32+
const NUMBER_FORMAT_UPPER_ROMAN = 'upperRoman';
33+
const NUMBER_FORMAT_LOWER_ROMAN = 'lowerRoman';
34+
const NUMBER_FORMAT_UPPER_LETTER = 'upperLetter';
35+
const NUMBER_FORMAT_LOWER_LETTER = 'lowerLetter';
36+
const NUMBER_FORMAT_ORDINAL = 'ordinal';
37+
const NUMBER_FORMAT_CARDINAL_TEXT = 'cardinalText';
38+
const NUMBER_FORMAT_ORDINAL_TEXT = 'ordinalText';
39+
const NUMBER_FORMAT_NONE = 'none';
40+
const NUMBER_FORMAT_BULLET = 'bullet';
41+
42+
const POSITION_PAGE_BOTTOM = 'pageBottom';
43+
const POSITION_BENEATH_TEXT = 'beneathText';
44+
const POSITION_SECTION_END = 'sectEnd';
45+
const POSITION_DOC_END = 'docEnd';
46+
47+
/**
48+
* Footnote Positioning Location
49+
*
50+
* @var string
51+
*/
52+
private $pos;
53+
54+
/**
55+
* Footnote Numbering Format
56+
*
57+
* @var string
58+
*/
59+
private $numFmt;
60+
61+
/**
62+
* Footnote and Endnote Numbering Starting Value
63+
*
64+
* @var decimal
65+
*/
66+
private $numStart;
67+
68+
/**
69+
* Footnote and Endnote Numbering Restart Location
70+
*
71+
* @var string
72+
*/
73+
private $numRestart;
74+
75+
public function getPos()
76+
{
77+
return $this->pos;
78+
}
79+
80+
public function setPos($pos)
81+
{
82+
$position = array(
83+
self::POSITION_PAGE_BOTTOM,
84+
self::POSITION_BENEATH_TEXT,
85+
self::POSITION_SECTION_END,
86+
self::POSITION_DOC_END
87+
);
88+
89+
if (in_array($pos, $position)) {
90+
$this->pos = $pos;
91+
} else {
92+
throw new \InvalidArgumentException("Invalid value, on of " . implode(', ', $position) . " possible");
93+
}
94+
}
95+
96+
public function getNumFmt()
97+
{
98+
return $this->numFmt;
99+
}
100+
101+
public function setNumFmt($numFmt)
102+
{
103+
$numberFormat = array(
104+
self::NUMBER_FORMAT_DECIMAL,
105+
self::NUMBER_FORMAT_UPPER_ROMAN,
106+
self::NUMBER_FORMAT_LOWER_ROMAN,
107+
self::NUMBER_FORMAT_UPPER_LETTER,
108+
self::NUMBER_FORMAT_LOWER_LETTER,
109+
self::NUMBER_FORMAT_ORDINAL,
110+
self::NUMBER_FORMAT_CARDINAL_TEXT,
111+
self::NUMBER_FORMAT_ORDINAL_TEXT,
112+
self::NUMBER_FORMAT_NONE,
113+
self::NUMBER_FORMAT_BULLET
114+
);
115+
116+
if (in_array($numFmt, $numberFormat)) {
117+
$this->numFmt = $numFmt;
118+
} else {
119+
throw new \InvalidArgumentException("Invalid value, on of " . implode(', ', $numberFormat) . " possible");
120+
}
121+
}
122+
123+
public function getNumStart()
124+
{
125+
return $this->numStart;
126+
}
127+
128+
public function setNumStart($numStart)
129+
{
130+
$this->numStart = $numStart;
131+
}
132+
133+
public function getNumRestart()
134+
{
135+
return $this->numRestart;
136+
}
137+
138+
public function setNumRestart($numRestart)
139+
{
140+
$restartNumbers = array(
141+
self::RESTART_NUMBER_CONTINUOUS,
142+
self::RESTART_NUMBER_EACH_SECTION,
143+
self::RESTART_NUMBER_EACH_PAGE
144+
);
145+
146+
if (in_array($numRestart, $restartNumbers)) {
147+
$this->numRestart= $numRestart;
148+
} else {
149+
throw new \InvalidArgumentException("Invalid value, on of " . implode(', ', $restartNumbers) . " possible");
150+
}
151+
}
152+
}

src/PhpWord/Writer/Word2007/Part/Document.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use PhpOffice\PhpWord\Element\Section;
2222
use PhpOffice\PhpWord\Writer\Word2007\Element\Container;
2323
use PhpOffice\PhpWord\Writer\Word2007\Style\Section as SectionStyleWriter;
24+
use PhpOffice\PhpWord\SimpleType\FootnoteProperties;
2425

2526
/**
2627
* Word2007 document part writer: word/document.xml
@@ -129,6 +130,32 @@ private function writeSectionSettings(XMLWriter $xmlWriter, Section $section)
129130
$xmlWriter->endElement();
130131
}
131132

133+
//footnote properties
134+
if ($section->getFootnotePropoperties() !== null) {
135+
$xmlWriter->startElement('w:footnotePr');
136+
if ($section->getFootnotePropoperties()->getPos() != null) {
137+
$xmlWriter->startElement('w:pos');
138+
$xmlWriter->writeAttribute('w:val', $section->getFootnotePropoperties()->getPos());
139+
$xmlWriter->endElement();
140+
}
141+
if ($section->getFootnotePropoperties()->getNumFmt() != null) {
142+
$xmlWriter->startElement('w:numFmt');
143+
$xmlWriter->writeAttribute('w:val', $section->getFootnotePropoperties()->getNumFmt());
144+
$xmlWriter->endElement();
145+
}
146+
if ($section->getFootnotePropoperties()->getNumStart() != null) {
147+
$xmlWriter->startElement('w:numStart');
148+
$xmlWriter->writeAttribute('w:val', $section->getFootnotePropoperties()->getNumStart());
149+
$xmlWriter->endElement();
150+
}
151+
if ($section->getFootnotePropoperties()->getNumRestart() != null) {
152+
$xmlWriter->startElement('w:numRestart');
153+
$xmlWriter->writeAttribute('w:val', $section->getFootnotePropoperties()->getNumRestart());
154+
$xmlWriter->endElement();
155+
}
156+
$xmlWriter->endElement();
157+
}
158+
132159
// Section settings
133160
$styleWriter = new SectionStyleWriter($xmlWriter, $section->getStyle());
134161
$styleWriter->write();
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
/**
3+
* This file is part of PHPWord - A pure PHP library for reading and writing
4+
* word processing documents.
5+
*
6+
* PHPWord 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/PHPWord/contributors.
12+
*
13+
* @link https://github.com/PHPOffice/PHPWord
14+
* @copyright 2010-2016 PHPWord contributors
15+
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16+
*/
17+
18+
namespace PhpOffice\PhpWord\SimpleType;
19+
20+
use PhpOffice\PhpWord\SimpleType\FootnoteProperties;
21+
22+
/**
23+
* Test class for PhpOffice\PhpWord\SimpleType\FootnoteProperties
24+
*
25+
* @coversDefaultClass \PhpOffice\PhpWord\SimpleType\FootnoteProperties
26+
* @runTestsInSeparateProcesses
27+
*/
28+
class FootnotePropertiesTest extends \PHPUnit_Framework_TestCase
29+
{
30+
/**
31+
* Test setting style with normal value
32+
*/
33+
public function testSetGetNormal()
34+
{
35+
$footnoteProp = new FootnoteProperties();
36+
$footnoteProp->setPos(FootnoteProperties::POSITION_DOC_END);
37+
$footnoteProp->setNumFmt(FootnoteProperties::NUMBER_FORMAT_LOWER_ROMAN);
38+
$footnoteProp->setNumStart(2);
39+
$footnoteProp->setNumRestart(FootnoteProperties::RESTART_NUMBER_EACH_PAGE);
40+
41+
$this->assertEquals(FootnoteProperties::POSITION_DOC_END, $footnoteProp->getPos());
42+
$this->assertEquals(FootnoteProperties::NUMBER_FORMAT_LOWER_ROMAN, $footnoteProp->getNumFmt());
43+
$this->assertEquals(2, $footnoteProp->getNumStart());
44+
$this->assertEquals(FootnoteProperties::RESTART_NUMBER_EACH_PAGE, $footnoteProp->getNumRestart());
45+
}
46+
47+
/**
48+
* Test throws exception if wrong position given
49+
*
50+
* @expectedException \InvalidArgumentException
51+
*/
52+
public function testWrongPos()
53+
{
54+
$footnoteProp= new FootnoteProperties();
55+
$footnoteProp->setPos(FootnoteProperties::NUMBER_FORMAT_LOWER_ROMAN);
56+
}
57+
58+
/**
59+
* Test throws exception if wrong number format given
60+
*
61+
* @expectedException \InvalidArgumentException
62+
*/
63+
public function testWrongNumFmt()
64+
{
65+
$footnoteProp= new FootnoteProperties();
66+
$footnoteProp->setNumFmt(FootnoteProperties::POSITION_DOC_END);
67+
}
68+
69+
/**
70+
* Test throws exception if wrong number restart given
71+
*
72+
* @expectedException \InvalidArgumentException
73+
*/
74+
public function testWrongNumRestart()
75+
{
76+
$footnoteProp= new FootnoteProperties();
77+
$footnoteProp->setNumRestart(FootnoteProperties::NUMBER_FORMAT_LOWER_ROMAN);
78+
}
79+
}

0 commit comments

Comments
 (0)