GH-16 : Initial addition of basic footnote support

This commit is contained in:
Progi1984 2014-03-07 23:08:09 +01:00
parent db5252541d
commit 86abe7e275
12 changed files with 600 additions and 2 deletions

View File

@ -0,0 +1,125 @@
<?php
/**
* PHPWord
*
* Copyright (c) 2011 PHPWord
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category PHPWord
* @package PHPWord
* @copyright Copyright (c) 010 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version Beta 0.6.3, 08.07.2011
*/
/**
* PHPWord_Footnote
*
* @category PHPWord
* @package PHPWord
* @copyright Copyright (c) 2011 PHPWord
*/
class PHPWord_Footnote {
/**
* Footnote Elements
*
* @var array
*/
private static $_footnoteCollection = array();
/**
* Footnote Link Elements
*
* @var array
*/
private static $_footnoteLink = array();
/**
* Add new Footnote Element
*
* @param string $linkSrc
* @param string $linkName
*
* @return mixed
*/
public static function addFootnoteElement(PHPWord_Section_Footnote $footnote) {
$refID = self::countFootnoteElements() + 2;
self::$_footnoteCollection[] = $footnote;
return $refID;
}
/**
* Get Footnote Elements
*
* @return array
*/
public static function getFootnoteElements() {
return self::$_footnoteCollection;
}
/**
* Get Footnote Elements Count
*
* @return int
*/
public static function countFootnoteElements() {
return count(self::$_footnoteCollection);
}
/**
* Add new Footnote Link Element
*
* @param string $src
* @param string $type
*
* @return mixed
*/
public static function addFootnoteLinkElement($linkSrc) {
$rID = self::countFootnoteLinkElements() + 1;
$link = array();
$link['target'] = $linkSrc;
$link['rID'] = $rID;
$link['type'] = 'hyperlink';
self::$_footnoteLink[] = $link;
return $rID;
}
/**
* Get Footnote Link Elements
*
* @return array
*/
public static function getFootnoteLinkElements() {
return self::$_footnoteLink;
}
/**
* Get Footnote Link Elements Count
*
* @return int
*/
public static function countFootnoteLinkElements() {
return count(self::$_footnoteLink);
}
}

View File

@ -409,4 +409,18 @@ class PHPWord_Section
{
return $this->_footer;
}
/**
* Create a new Footnote Element
*
* @param string $text
* @return PHPWord_Section_Footnote
*/
public function createFootnote($styleParagraph = null) {
$footnote = new PHPWord_Section_Footnote($styleParagraph);
$refID = PHPWord_Footnote::addFootnoteElement($footnote);
$footnote->setReferenceId($refID);
$this->_elementCollection[] = $footnote;
return $footnote;
}
}

View File

@ -0,0 +1,148 @@
<?php
/**
* PHPWord
*
* Copyright (c) 2011 PHPWord
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category PHPWord
* @package PHPWord
* @copyright Copyright (c) 010 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version Beta 0.6.3, 08.07.2011
*/
/**
* PHPWord_Section_Footnote
*
* @category PHPWord
* @package PHPWord_Section
* @copyright Copyright (c) 2011 PHPWord
*/
class PHPWord_Section_Footnote {
/**
* Paragraph style
*
* @var PHPWord_Style_Font
*/
private $_styleParagraph;
/**
* Footnote Reference ID
*
* @var string
*/
private $_refId;
/**
* Text collection
*
* @var array
*/
private $_elementCollection;
/**
* Create a new Footnote Element
*/
public function __construct($styleParagraph = null) {
$this->_elementCollection = array();
// Set paragraph style
if(is_array($styleParagraph)) {
$this->_styleParagraph = new PHPWord_Style_Paragraph();
foreach($styleParagraph as $key => $value) {
if(substr($key, 0, 1) != '_') {
$key = '_'.$key;
}
$this->_styleParagraph->setStyleValue($key, $value);
}
} else {
$this->_styleParagraph = $styleParagraph;
}
}
/**
* Add a Text Element
*
* @var string $text
* @var mixed $styleFont
* @return PHPWord_Section_Text
*/
public function addText($text = null, $styleFont = null) {
$givenText = $text;
$text = new PHPWord_Section_Text($givenText, $styleFont);
$this->_elementCollection[] = $text;
return $text;
}
/**
* Add a Link Element
*
* @param string $linkSrc
* @param string $linkName
* @param mixed $styleFont
* @return PHPWord_Section_Link
*/
public function addLink($linkSrc, $linkName = null, $styleFont = null) {
$link = new PHPWord_Section_Link($linkSrc, $linkName, $styleFont);
$rID = PHPWord_Footnote::addFootnoteLinkElement($linkSrc);
$link->setRelationId($rID);
$this->_elementCollection[] = $link;
return $link;
}
/**
* Get Footnote content
*
* @return string
*/
public function getElements() {
return $this->_elementCollection;
}
/**
* Get Paragraph style
*
* @return PHPWord_Style_Paragraph
*/
public function getParagraphStyle() {
return $this->_styleParagraph;
}
/**
* Get Footnote Reference ID
*
* @return int
*/
public function getReferenceId() {
return $this->_refId;
}
/**
* Set Footnote Reference ID
*
* @param int $refId
*/
public function setReferenceId($refId) {
$this->_refId = $refId;
}
}

View File

@ -130,6 +130,20 @@ class PHPWord_Section_TextRun
}
}
/**
* Create a new Footnote Element
*
* @param string $text
* @return PHPWord_Section_Footnote
*/
public function createFootnote($styleParagraph = null) {
$footnote = new PHPWord_Section_Footnote($styleParagraph);
$refID = PHPWord_Footnote::addFootnoteElement($footnote);
$footnote->setReferenceId($refID);
$this->_elementCollection[] = $footnote;
return $footnote;
}
/**
* Get TextRun content
*

View File

@ -52,6 +52,8 @@ class PHPWord_Writer_Word2007 implements PHPWord_Writer_IWriter
$this->_writerParts['styles'] = new PHPWord_Writer_Word2007_Styles();
$this->_writerParts['header'] = new PHPWord_Writer_Word2007_Header();
$this->_writerParts['footer'] = new PHPWord_Writer_Word2007_Footer();
$this->_writerParts['footnotes'] = new PHPWord_Writer_Word2007_Footnotes();
$this->_writerParts['footnotesrels'] = new PHPWord_Writer_Word2007_FootnotesRels();
foreach ($this->_writerParts as $writer) {
$writer->setParentWriter($this);
@ -111,6 +113,11 @@ class PHPWord_Writer_Word2007 implements PHPWord_Writer_IWriter
}
}
$footnoteLinks = array();
$_footnoteElements = PHPWord_Footnote::getFootnoteLinkElements();
foreach($_footnoteElements as $element) { // loop through footnote link elements
$footnoteLinks[] = $element;
}
$_cHdrs = 0;
$_cFtrs = 0;
@ -138,6 +145,16 @@ class PHPWord_Writer_Word2007 implements PHPWord_Writer_IWriter
}
}
if (PHPWord_Footnote::countFootnoteElements() > 0) {
$_allFootnotesCollection = PHPWord_Footnote::getFootnoteElements();
$_footnoteFile = 'footnotes.xml';
$sectionElements[] = array('target'=>$_footnoteFile, 'type'=>'footnotes', 'rID'=>++$rID);
$objZip->addFromString('word/'.$_footnoteFile, $this->getWriterPart('footnotes')->writeFootnotes($_allFootnotesCollection));
if (count($footnoteLinks) > 0) {
$objZip->addFromString('word/_rels/footnotes.xml.rels', $this->getWriterPart('footnotesrels')->writeFootnotesRels($footnoteLinks));
}
}
// build docx file
// Write dynamic files
$objZip->addFromString('[Content_Types].xml', $this->getWriterPart('contenttypes')->writeContentTypes($this->_imageTypes, $this->_objectTypes, $_cHdrs, $_cFtrs));

View File

@ -108,6 +108,8 @@ class PHPWord_Writer_Word2007_Base extends PHPWord_Writer_Word2007_WriterPart
$this->_writeLink($objWriter, $element, true);
} elseif ($element instanceof PHPWord_Section_Image) {
$this->_writeImage($objWriter, $element, true);
} elseif($element instanceof PHPWord_Section_Footnote) {
$this->_writeFootnoteReference($objWriter, $element, true);
}
}
}
@ -827,4 +829,56 @@ class PHPWord_Writer_Word2007_Base extends PHPWord_Writer_Word2007_WriterPart
$objWriter->endElement();
}
protected function _writeFootnote(PHPWord_Shared_XMLWriter $objWriter = null, PHPWord_Section_Footnote $footnote) {
$objWriter->startElement('w:footnote');
$objWriter->writeAttribute('w:id', $footnote->getReferenceId());
$styleParagraph = $footnote->getParagraphStyle();
$SpIsObject = ($styleParagraph instanceof PHPWord_Style_Paragraph) ? true : false;
$objWriter->startElement('w:p');
if($SpIsObject) {
$this->_writeParagraphStyle($objWriter, $styleParagraph);
} elseif(!$SpIsObject && !is_null($styleParagraph)) {
$objWriter->startElement('w:pPr');
$objWriter->startElement('w:pStyle');
$objWriter->writeAttribute('w:val', $styleParagraph);
$objWriter->endElement();
$objWriter->endElement();
}
$elements = $footnote->getElements();
if(count($elements) > 0) {
foreach($elements as $element) {
if($element instanceof PHPWord_Section_Text) {
$this->_writeText($objWriter, $element, true);
} elseif($element instanceof PHPWord_Section_Link) {
$this->_writeLink($objWriter, $element, true);
}
}
}
$objWriter->endElement(); // w:p
$objWriter->endElement(); // w:footnote
}
protected function _writeFootnoteReference(PHPWord_Shared_XMLWriter $objWriter = null, PHPWord_Section_Footnote $footnote, $withoutP = false) {
if (!$withoutP) {
$objWriter->startElement('w:p');
}
$objWriter->startElement('w:r');
$objWriter->startElement('w:footnoteReference');
$objWriter->writeAttribute('w:id', $footnote->getReferenceId());
$objWriter->endElement(); // w:footnoteReference
$objWriter->endElement(); // w:r
if (!$withoutP) {
$objWriter->endElement(); // w:p
}
}
}

View File

@ -94,6 +94,8 @@ class PHPWord_Writer_Word2007_Document extends PHPWord_Writer_Word2007_Base
$this->_writeObject($objWriter, $element);
} elseif ($element instanceof PHPWord_TOC) {
$this->_writeTOC($objWriter);
} elseif($element instanceof PHPWord_Section_Footnote) {
$this->_writeFootnoteReference($objWriter, $element);
}
}

View File

@ -0,0 +1,81 @@
<?php
/**
* PHPWord
*
* Copyright (c) 2011 PHPWord
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category PHPWord
* @package PHPWord
* @copyright Copyright (c) 010 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version Beta 0.6.3, 08.07.2011
*/
class PHPWord_Writer_Word2007_Footnotes extends PHPWord_Writer_Word2007_Base {
public function writeFootnotes($allFootnotesCollection) {
// Create XML writer
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {
$objWriter = new PHPWord_Shared_XMLWriter(PHPWord_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
} else {
$objWriter = new PHPWord_Shared_XMLWriter(PHPWord_Shared_XMLWriter::STORAGE_MEMORY);
}
// XML header
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
$objWriter->startElement('w:footnotes');
$objWriter->writeAttribute('xmlns:r','http://schemas.openxmlformats.org/officeDocument/2006/relationships');
$objWriter->writeAttribute('xmlns:w','http://schemas.openxmlformats.org/wordprocessingml/2006/main');
// write separator and continuation separator
$objWriter->startElement('w:footnote');
$objWriter->writeAttribute('w:id', 0);
$objWriter->writeAttribute('w:type', 'separator');
$objWriter->startElement('w:p');
$objWriter->startElement('w:r');
$objWriter->startElement('w:separator');
$objWriter->endElement(); // w:separator
$objWriter->endElement(); // w:r
$objWriter->endElement(); // w:p
$objWriter->endElement(); // w:footnote
$objWriter->startElement('w:footnote');
$objWriter->writeAttribute('w:id', 1);
$objWriter->writeAttribute('w:type', 'continuationSeparator');
$objWriter->startElement('w:p');
$objWriter->startElement('w:r');
$objWriter->startElement('w:continuationSeparator');
$objWriter->endElement(); // w:continuationSeparator
$objWriter->endElement(); // w:r
$objWriter->endElement(); // w:p
$objWriter->endElement(); // w:footnote
foreach($allFootnotesCollection as $footnote) {
if($footnote instanceof PHPWord_Section_Footnote) {
$this->_writeFootnote($objWriter, $footnote);
}
}
$objWriter->endElement();
// Return
return $objWriter->getData();
}
}

View File

@ -0,0 +1,89 @@
<?php
/**
* PHPWord
*
* Copyright (c) 2011 PHPWord
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category PHPWord
* @package PHPWord
* @copyright Copyright (c) 010 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version Beta 0.6.3, 08.07.2011
*/
class PHPWord_Writer_Word2007_FootnotesRels extends PHPWord_Writer_Word2007_WriterPart {
public function writeFootnotesRels($_relsCollection) {
// Create XML writer
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {
$objWriter = new PHPWord_Shared_XMLWriter(PHPWord_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
} else {
$objWriter = new PHPWord_Shared_XMLWriter(PHPWord_Shared_XMLWriter::STORAGE_MEMORY);
}
// XML header
$objWriter->startDocument('1.0','UTF-8','yes');
// Relationships
$objWriter->startElement('Relationships');
$objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
// Relationships to Links
foreach($_relsCollection as $relation) {
$relationType = $relation['type'];
$relationName = $relation['target'];
$relationId = $relation['rID'];
$targetMode = ($relationType == 'hyperlink') ? 'External' : '';
$this->_writeRelationship(
$objWriter,
$relationId,
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/'.$relationType,
$relationName,
$targetMode
);
}
$objWriter->endElement();
// Return
return $objWriter->getData();
}
private function _writeRelationship(PHPWord_Shared_XMLWriter $objWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '') {
if($pType != '' && $pTarget != '') {
if(strpos($pId, 'rId') === false) {
$pId = 'rId' . $pId;
}
// Write relationship
$objWriter->startElement('Relationship');
$objWriter->writeAttribute('Id', $pId);
$objWriter->writeAttribute('Type', $pType);
$objWriter->writeAttribute('Target', $pTarget);
if($pTargetMode != '') {
$objWriter->writeAttribute('TargetMode', $pTargetMode);
}
$objWriter->endElement();
} else {
throw new Exception("Invalid parameters passed.");
}
}
}

View File

@ -43,6 +43,7 @@ Changes in branch for release 0.7.1 :
- Feature: (ivanlanin) GH-87 - Paragraph: Ability to define normal paragraph style with PHPWord::setNormalStyle()
- Feature: (ivanlanin) GH-87 - Paragraph: Ability to define parent style (basedOn) and style for following paragraph (next)
- Feature: (jeroenmoors) GH-44 GH-88 - Clone table rows on the fly when using a template document
- Feature: (deds) GH-16 - Initial addition of basic footnote support
- QA: (Progi1984) - UnitTests
Changes in branch for release 0.7.0 :

View File

@ -4,8 +4,7 @@ error_reporting(E_ALL);
if(php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR'])) {
define('EOL', PHP_EOL);
}
else {
} else {
define('EOL', '<br />');
}

54
samples/Sample_08_Footnote.php Executable file
View File

@ -0,0 +1,54 @@
<?php
error_reporting(E_ALL);
if(php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR'])) {
define('EOL', PHP_EOL);
} else {
define('EOL', '<br />');
}
require_once '../Classes/PHPWord.php';
// New Word Document
echo date('H:i:s') , " Create new PHPWord object" , EOL;
$PHPWord = new PHPWord();
// New portrait section
$section = $PHPWord->createSection();
// Add style definitions
$PHPWord->addParagraphStyle('pStyle', array('spacing'=>100));
$PHPWord->addFontStyle('BoldText', array('bold'=>true));
$PHPWord->addFontStyle('ColoredText', array('color'=>'FF8080'));
$PHPWord->addLinkStyle('NLink', array('color'=>'0000FF', 'underline'=>PHPWord_Style_Font::UNDERLINE_SINGLE));
// Add text elements
$textrun = $section->createTextRun('pStyle');
$textrun->addText('This is some lead text in a paragraph with a following footnote. ','pStyle');
$footnote = $textrun->createFootnote();
$footnote->addText('Just like a textrun a footnote can contain native text and link elements.');
$footnote->addText(' No break is placed after adding an element.', 'BoldText');
$footnote->addText(' All elements are placed inside a paragraph.', 'ColoredText');
$footnote->addText(' The best search engine: ');
$footnote->addLink('http://www.google.com', null, 'NLink');
$footnote->addText('. Also not bad: ');
$footnote->addLink('http://www.bing.com', null, 'NLink');
$textrun->addText('The trailing text in the paragraph.');
$section->addText('You can also create the footnote directly from the section making it wrap in a paragraph like the footnote below this paragraph. But is is best used from within a textrun.');
$footnote = $section->createFootnote();
$footnote->addText('The reference for this is wrapped in its own line');
// Save File
echo date('H:i:s') , " Write to Word2007 format" , EOL;
$objWriter = PHPWord_IOFactory::createWriter($PHPWord, 'Word2007');
$objWriter->save(str_replace('.php', '.docx', __FILE__));
// Echo memory peak usage
echo date('H:i:s') , " Peak memory usage: " , (memory_get_peak_usage(true) / 1024 / 1024) , " MB" , EOL;
// Echo done
echo date('H:i:s') , " Done writing file" , EOL;