Skip to content

Commit ac89cc3

Browse files
committed
Add possibility to control the footnote number
1 parent 4decaff commit ac89cc3

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 RESTART_NUMBER = array(
32+
self::RESTART_NUMBER_CONTINUOUS,
33+
self::RESTART_NUMBER_EACH_SECTION,
34+
self::RESTART_NUMBER_EACH_PAGE
35+
);
36+
37+
const NUMBER_FORMAT_DECIMAL = 'decimal';
38+
const NUMBER_FORMAT_UPPER_ROMAN = 'upperRoman';
39+
const NUMBER_FORMAT_LOWER_ROMAN = 'lowerRoman';
40+
const NUMBER_FORMAT_UPPER_LETTER = 'upperLetter';
41+
const NUMBER_FORMAT_LOWER_LETTER = 'lowerLetter';
42+
const NUMBER_FORMAT_ORDINAL = 'ordinal';
43+
const NUMBER_FORMAT_CARDINAL_TEXT = 'cardinalText';
44+
const NUMBER_FORMAT_ORDINAL_TEXT = 'ordinalText';
45+
const NUMBER_FORMAT_NONE = 'none';
46+
const NUMBER_FORMAT_BULLET = 'bullet';
47+
48+
const NUMBER_FORMAT = array(
49+
self::NUMBER_FORMAT_DECIMAL,
50+
self::NUMBER_FORMAT_UPPER_ROMAN,
51+
self::NUMBER_FORMAT_LOWER_ROMAN,
52+
self::NUMBER_FORMAT_UPPER_LETTER,
53+
self::NUMBER_FORMAT_LOWER_LETTER,
54+
self::NUMBER_FORMAT_ORDINAL,
55+
self::NUMBER_FORMAT_CARDINAL_TEXT,
56+
self::NUMBER_FORMAT_ORDINAL_TEXT,
57+
self::NUMBER_FORMAT_NONE,
58+
self::NUMBER_FORMAT_BULLET
59+
);
60+
61+
const POSITION_PAGE_BOTTOM = 'pageBottom';
62+
const POSITION_BENEATH_TEXT = 'beneathText';
63+
const POSITION_SECTION_END = 'sectEnd';
64+
const POSITION_DOC_END = 'docEnd';
65+
66+
const POSITION = array(
67+
self::POSITION_PAGE_BOTTOM,
68+
self::POSITION_BENEATH_TEXT,
69+
self::POSITION_SECTION_END,
70+
self::POSITION_DOC_END
71+
);
72+
73+
/**
74+
* Footnote Positioning Location
75+
*
76+
* @var string
77+
*/
78+
private $pos;
79+
80+
/**
81+
* Footnote Numbering Format
82+
*
83+
* @var string
84+
*/
85+
private $numFmt;
86+
87+
/**
88+
* Footnote and Endnote Numbering Starting Value
89+
*
90+
* @var decimal
91+
*/
92+
private $numStart;
93+
94+
/**
95+
* Footnote and Endnote Numbering Restart Location
96+
*
97+
* @var string
98+
*/
99+
private $numRestart;
100+
101+
public function getPos()
102+
{
103+
return $this->pos;
104+
}
105+
106+
public function setPos($pos)
107+
{
108+
if (in_array($pos, self::POSITION)) {
109+
$this->pos = $pos;
110+
} else {
111+
throw new \InvalidArgumentException("Invalid value, on of " . implode(', ', self::POSITION) . " possible");
112+
}
113+
}
114+
115+
public function getNumFmt()
116+
{
117+
return $this->numFmt;
118+
}
119+
120+
public function setNumFmt($numFmt)
121+
{
122+
if (in_array($numFmt, self::NUMBER_FORMAT)) {
123+
$this->numFmt = $numFmt;
124+
} else {
125+
throw new \InvalidArgumentException("Invalid value, on of " . implode(', ', self::NUMBER_FORMAT) . " possible");
126+
}
127+
}
128+
129+
public function getNumStart()
130+
{
131+
return $this->numStart;
132+
}
133+
134+
public function setNumStart($numStart)
135+
{
136+
$this->numStart = $numStart;
137+
}
138+
139+
public function getNumRestart()
140+
{
141+
return $this->numRestart;
142+
}
143+
144+
public function setNumRestart($numRestart)
145+
{
146+
if (in_array($numRestart, self::RESTART_NUMBER)) {
147+
$this->numRestart= $numRestart;
148+
} else {
149+
throw new \InvalidArgumentException("Invalid value, on of " . implode(', ', self::RESTART_NUMBER) . " 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\Style;
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)