Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ v0.15.0 (?? ??? 2018)
### Added
- Parsing of "align" HTML attribute - @troosan #1231
- Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508
- Add support for Track changes @Cip @troosan #354 #1262

### Fixed
- fix reading of docx default style - @troosan #1238
Expand Down
41 changes: 36 additions & 5 deletions docs/elements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ column shows the containers while the rows lists the elements.
+-------+-----------------+-----------+----------+----------+---------+------------+------------+
| 11 | Watermark | - | v | - | - | - | - |
+-------+-----------------+-----------+----------+----------+---------+------------+------------+
| 12 | Object | v | v | v | v | v | v |
| 12 | OLEObject | v | v | v | v | v | v |
+-------+-----------------+-----------+----------+----------+---------+------------+------------+
| 13 | TOC | v | - | - | - | - | - |
+-------+-----------------+-----------+----------+----------+---------+------------+------------+
Expand Down Expand Up @@ -77,6 +77,13 @@ italics, etc) or other elements, e.g. images or links. The syntaxes are as follo

For available styling options see :ref:`font-style` and :ref:`paragraph-style`.

If you want to enable track changes on added text you can mark it as INSERTED or DELETED by a specific user at a given time:

.. code-block:: php

$text = $section->addText('Hello World!');
$text->setChanged(\PhpOffice\PhpWord\Element\ChangedElement::TYPE_INSERTED, 'Fred', (new \DateTime()));

Titles
~~~~~~

Expand Down Expand Up @@ -276,11 +283,11 @@ Objects
-------

You can add OLE embeddings, such as Excel spreadsheets or PowerPoint
presentations to the document by using ``addObject`` method.
presentations to the document by using ``addOLEObject`` method.

.. code-block:: php

$section->addObject($src, [$style]);
$section->addOLEObject($src, [$style]);

Table of contents
-----------------
Expand Down Expand Up @@ -309,7 +316,7 @@ Footnotes & endnotes
You can create footnotes with ``addFootnote`` and endnotes with
``addEndnote`` in texts or textruns, but it's recommended to use textrun
to have better layout. You can use ``addText``, ``addLink``,
``addTextBreak``, ``addImage``, ``addObject`` on footnotes and endnotes.
``addTextBreak``, ``addImage``, ``addOLEObject`` on footnotes and endnotes.

On textrun:

Expand Down Expand Up @@ -465,4 +472,28 @@ The comment can contain formatted text. Once the comment has been added, it can
// link the comment to the text you just created
$text->setCommentStart($comment);

If no end is set for a comment using the ``setCommentEnd``, the comment will be ended automatically at the end of the element it is started on.
If no end is set for a comment using the ``setCommentEnd``, the comment will be ended automatically at the end of the element it is started on.

Track Changes
-------------

Track changes can be set on text elements. There are 2 ways to set the change information on an element.
Either by calling the `setChangeInfo()`, or by setting the `TrackChange` instance on the element with `setTrackChange()`.

.. code-block:: php
$phpWord = new \PhpOffice\PhpWord\PhpWord();

// New portrait section
$section = $phpWord->addSection();
$textRun = $section->addTextRun();

$text = $textRun->addText('Hello World! Time to ');

$text = $textRun->addText('wake ', array('bold' => true));
$text->setChangeInfo(TrackChange::INSERTED, 'Fred', time() - 1800);

$text = $textRun->addText('up');
$text->setTrackChange(new TrackChange(TrackChange::INSERTED, 'Fred'));

$text = $textRun->addText('go to sleep');
$text->setChangeInfo(TrackChange::DELETED, 'Barney', new \DateTime('@' . (time() - 3600)));
2 changes: 1 addition & 1 deletion samples/Sample_16_Object.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
$section = $phpWord->addSection();
$section->addText('You can open this OLE object by double clicking on the icon:');
$section->addTextBreak(2);
$section->addObject('resources/_sheet.xls');
$section->addOLEObject('resources/_sheet.xls');

// Save file
echo write($phpWord, basename(__FILE__, '.php'), $writers);
Expand Down
29 changes: 29 additions & 0 deletions samples/Sample_39_TrackChanges.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
use PhpOffice\PhpWord\Element\TrackChange;

include_once 'Sample_Header.php';

// New Word Document
echo date('H:i:s') , ' Create new PhpWord object' , EOL;
$phpWord = new \PhpOffice\PhpWord\PhpWord();

// New portrait section
$section = $phpWord->addSection();
$textRun = $section->addTextRun();

$text = $textRun->addText('Hello World! Time to ');

$text = $textRun->addText('wake ', array('bold' => true));
$text->setChangeInfo(TrackChange::INSERTED, 'Fred', time() - 1800);

$text = $textRun->addText('up');
$text->setTrackChange(new TrackChange(TrackChange::INSERTED, 'Fred'));

$text = $textRun->addText('go to sleep');
$text->setChangeInfo(TrackChange::DELETED, 'Barney', new \DateTime('@' . (time() - 3600)));

// Save file
echo write($phpWord, basename(__FILE__, '.php'), $writers);
if (!CLI) {
include_once 'Sample_Footer.php';
}
Binary file modified samples/resources/Sample_11_ReadWord2007.docx
Binary file not shown.
Binary file modified samples/resources/Sample_24_ReadODText.odt
Binary file not shown.
4 changes: 2 additions & 2 deletions src/PhpWord/Element/AbstractContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function __call($function, $args)
{
$elements = array(
'Text', 'TextRun', 'Bookmark', 'Link', 'PreserveText', 'TextBreak',
'ListItem', 'ListItemRun', 'Table', 'Image', 'Object',
'ListItem', 'ListItemRun', 'Table', 'Image', 'Object', 'OLEObject',
'Footnote', 'Endnote', 'CheckBox', 'TextBox', 'Field',
'Line', 'Shape', 'Title', 'TOC', 'PageBreak',
'Chart', 'FormField', 'SDT', 'Comment',
Expand Down Expand Up @@ -157,7 +157,7 @@ protected function addElement($elementName)
/**
* Get all elements
*
* @return array
* @return \PhpOffice\PhpWord\Element\AbstractElement[]
*/
public function getElements()
{
Expand Down
39 changes: 39 additions & 0 deletions src/PhpWord/Element/AbstractElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ abstract class AbstractElement
*/
private $nestedLevel = 0;

/**
* changed element info
*
* @var TrackChange
*/
private $trackChange;

/**
* Parent container type
*
Expand Down Expand Up @@ -425,6 +432,38 @@ protected function setNewStyle($styleObject, $styleValue = null, $returnObject =
return $style;
}

/**
* Sets the trackChange information
*
* @param TrackChange $trackChange
*/
public function setTrackChange(TrackChange $trackChange)
{
$this->trackChange = $trackChange;
}

/**
* Gets the trackChange information
*
* @return TrackChange
*/
public function getTrackChange()
{
return $this->trackChange;
}

/**
* Set changed
*
* @param string $type INSERTED|DELETED
* @param string $author
* @param null|int|\DateTime $date allways in UTC
*/
public function setChangeInfo($type, $author, $date = null)
{
$this->trackChange = new TrackChange($type, $author, $date);
}

/**
* Set enum value
*
Expand Down
4 changes: 2 additions & 2 deletions src/PhpWord/Element/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ class Comment extends TrackChange
* Create a new Comment Element
*
* @param string $author
* @param \DateTime $date
* @param null|\DateTime $date
* @param string $initials
*/
public function __construct($author, $date = null, $initials = null)
{
parent::__construct($author, $date);
parent::__construct(null, $author, $date);
$this->initials = $initials;
}

Expand Down
31 changes: 28 additions & 3 deletions src/PhpWord/Element/TrackChange.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,25 @@
/**
* TrackChange element
* @see http://datypic.com/sc/ooxml/t-w_CT_TrackChange.html
* @see http://datypic.com/sc/ooxml/t-w_CT_RunTrackChange.html
*/
class TrackChange extends AbstractContainer
{
const INSERTED = 'INSERTED';
const DELETED = 'DELETED';

/**
* @var string Container type
*/
protected $container = 'TrackChange';

/**
* The type of change, (insert or delete), not applicable for PhpOffice\PhpWord\Element\Comment
*
* @var string
*/
private $changeType;

/**
* Author
*
Expand All @@ -45,13 +56,17 @@ class TrackChange extends AbstractContainer
/**
* Create a new TrackChange Element
*
* @param string $changeType
* @param string $author
* @param \DateTime $date
* @param null|int|\DateTime $date
*/
public function __construct($author, \DateTime $date = null)
public function __construct($changeType = null, $author = null, $date = null)
{
$this->changeType = $changeType;
$this->author = $author;
$this->date = $date;
if ($date !== null) {
$this->date = ($date instanceof \DateTime) ? $date : new \DateTime('@' . $date);
}
}

/**
Expand All @@ -73,4 +88,14 @@ public function getDate()
{
return $this->date;
}

/**
* Get the Change type
*
* @return string
*/
public function getChangeType()
{
return $this->changeType;
}
}
50 changes: 49 additions & 1 deletion src/PhpWord/Reader/ODText/Content.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
namespace PhpOffice\PhpWord\Reader\ODText;

use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\Element\TrackChange;
use PhpOffice\PhpWord\PhpWord;

/**
Expand All @@ -37,6 +38,8 @@ public function read(PhpWord $phpWord)
$xmlReader = new XMLReader();
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);

$trackedChanges = array();

$nodes = $xmlReader->getElements('office:body/office:text/*');
if ($nodes->length > 0) {
$section = $phpWord->addSection();
Expand All @@ -48,7 +51,37 @@ public function read(PhpWord $phpWord)
$section->addTitle($node->nodeValue, $depth);
break;
case 'text:p': // Paragraph
$section->addText($node->nodeValue);
$children = $node->childNodes;
foreach ($children as $child) {
switch ($child->nodeName) {
case 'text:change-start':
$changeId = $child->getAttribute('text:change-id');
if (isset($trackedChanges[$changeId])) {
$changed = $trackedChanges[$changeId];
}
break;
case 'text:change-end':
unset($changed);
break;
case 'text:change':
$changeId = $child->getAttribute('text:change-id');
if (isset($trackedChanges[$changeId])) {
$changed = $trackedChanges[$changeId];
}
break;
}
}

$element = $section->addText($node->nodeValue);
if (isset($changed) && is_array($changed)) {
$element->setTrackChange($changed['changed']);
if (isset($changed['textNodes'])) {
foreach ($changed['textNodes'] as $changedNode) {
$element = $section->addText($changedNode->nodeValue);
$element->setTrackChange($changed['changed']);
}
}
}
break;
case 'text:list': // List
$listItems = $xmlReader->getElements('text:list-item/text:p', $node);
Expand All @@ -57,6 +90,21 @@ public function read(PhpWord $phpWord)
$section->addListItem($listItem->nodeValue, 0);
}
break;
case 'text:tracked-changes':
$changedRegions = $xmlReader->getElements('text:changed-region', $node);
foreach ($changedRegions as $changedRegion) {
$type = ($changedRegion->firstChild->nodeName == 'text:insertion') ? TrackChange::INSERTED : TrackChange::DELETED;
$creatorNode = $xmlReader->getElements('office:change-info/dc:creator', $changedRegion->firstChild);
$author = $creatorNode[0]->nodeValue;
$dateNode = $xmlReader->getElements('office:change-info/dc:date', $changedRegion->firstChild);
$date = $dateNode[0]->nodeValue;
$date = preg_replace('/\.\d+$/', '', $date);
$date = \DateTime::createFromFormat('Y-m-d\TH:i:s', $date);
$changed = new TrackChange($type, $author, $date);
$textNodes = $xmlReader->getElements('text:deletion/text:p', $changedRegion);
$trackedChanges[$changedRegion->getAttribute('text:id')] = array('changed' => $changed, 'textNodes'=> $textNodes);
}
break;
}
}
}
Expand Down
Loading