Skip to content

Commit

Permalink
Writer ODText: Support for ListItemRun (#2669)
Browse files Browse the repository at this point in the history
  • Loading branch information
Progi1984 authored Sep 5, 2024
1 parent a0d00e7 commit 2e4f3cf
Show file tree
Hide file tree
Showing 12 changed files with 338 additions and 60 deletions.
1 change: 1 addition & 0 deletions docs/changes/1.x/1.4.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## Enhancements

- Writer ODText: Support for ListItemRun by [@Progi1984](https://github.com/Progi1984) fixing [#2159](https://github.com/PHPOffice/PHPWord/issues/2159), [#2620](https://github.com/PHPOffice/PHPWord/issues/2620) in [#2669](https://github.com/PHPOffice/PHPWord/pull/2669)

### Bug fixes

Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Below are the supported features for each file formats.
| | Preserve Text | :material-check: | | | | |
| | Text Break | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: |
| | Page Break | :material-check: | | :material-check: | | |
| | List | :material-check: | | | | |
| | List | :material-check: | :material-check: | | | |
| | Table | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: |
| | Image | :material-check: | :material-check: | :material-check: | :material-check: | |
| | Object | :material-check: | | | | |
Expand Down
18 changes: 9 additions & 9 deletions src/PhpWord/Shared/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -627,15 +627,15 @@ protected static function getListStyle($isOrderedList)
return [
'type' => 'hybridMultilevel',
'levels' => [
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
],
];
}
Expand Down
28 changes: 6 additions & 22 deletions src/PhpWord/Style/Numbering.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,16 @@ class Numbering extends AbstractStyle

/**
* Get Id.
*
* @return int
*/
public function getNumId()
public function getNumId(): ?int
{
return $this->numId;
}

/**
* Set Id.
*
* @param int $value
*
* @return self
*/
public function setNumId($value)
public function setNumId(int $value): self
{
$this->numId = $this->setIntVal($value, $this->numId);

Expand All @@ -78,22 +72,16 @@ public function setNumId($value)

/**
* Get multilevel type.
*
* @return string
*/
public function getType()
public function getType(): ?string
{
return $this->type;
}

/**
* Set multilevel type.
*
* @param string $value
*
* @return self
*/
public function setType($value)
public function setType(string $value): self
{
$enum = ['singleLevel', 'multilevel', 'hybridMultilevel'];
$this->type = $this->setEnumVal($value, $enum, $this->type);
Expand All @@ -106,19 +94,15 @@ public function setType($value)
*
* @return NumberingLevel[]
*/
public function getLevels()
public function getLevels(): array
{
return $this->levels;
}

/**
* Set multilevel type.
*
* @param array $values
*
* @return self
*/
public function setLevels($values)
public function setLevels(array $values): self
{
if (is_array($values)) {
foreach ($values as $key => $value) {
Expand Down
5 changes: 5 additions & 0 deletions src/PhpWord/Writer/ODText/Element/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ class Container extends Word2007Container
* @var string
*/
protected $namespace = 'PhpOffice\\PhpWord\\Writer\\ODText\\Element';

/**
* @var array<string>
*/
protected $containerWithoutP = ['TextRun', 'Footnote', 'Endnote'];
}
56 changes: 56 additions & 0 deletions src/PhpWord/Writer/ODText/Element/ListItemRun.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/

namespace PhpOffice\PhpWord\Writer\ODText\Element;

use PhpOffice\PhpWord\Element\ListItemRun as ListItemRunElement;

/**
* ListItemRun element writer.
*
* @since 0.10.0
*/
class ListItemRun extends AbstractElement
{
/**
* Write list item element.
*/
public function write(): void
{
$element = $this->getElement();
if (!$element instanceof ListItemRunElement) {
return;
}
$depth = $element->getDepth() + 1;

$xmlWriter = $this->getXmlWriter();

for ($iDepth = 1; $iDepth <= $depth; ++$iDepth) {
$xmlWriter->startElement('text:list');
$xmlWriter->writeAttribute('text:style-name', $element->getStyle()->getNumStyle());
$xmlWriter->startElement('text:list-item');
}

$containerWriter = new Container($xmlWriter, $element, false);
$containerWriter->write();

for ($iDepth = 1; $iDepth <= $depth; ++$iDepth) {
$xmlWriter->endElement(); // text:list-item
$xmlWriter->endElement(); // text:list
}
}
}
40 changes: 16 additions & 24 deletions src/PhpWord/Writer/ODText/Element/Text.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,37 +57,29 @@ public function write(): void
$xmlWriter->writeAttribute('text:change-id', $element->getTrackChange()->getElementId());
$xmlWriter->endElement();
} else {
if (empty($fontStyle)) {
if (empty($paragraphStyle)) {
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', 'Normal');
}
} elseif (is_string($paragraphStyle)) {
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
}
if (empty($paragraphStyle)) {
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', 'Normal');
}
$this->writeChangeInsertion(true, $element->getTrackChange());
$this->replaceTabs($element->getText(), $xmlWriter);
$this->writeChangeInsertion(false, $element->getTrackChange());
} else {
if (empty($paragraphStyle)) {
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', 'Normal');
}
} elseif (is_string($paragraphStyle)) {
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
}
} elseif (is_string($paragraphStyle)) {
if (!$this->withoutP) {
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
}
}

if (!empty($fontStyle)) {
// text:span
$xmlWriter->startElement('text:span');
if (is_string($fontStyle)) {
$xmlWriter->writeAttribute('text:style-name', $fontStyle);
}
$this->writeChangeInsertion(true, $element->getTrackChange());
$this->replaceTabs($element->getText(), $xmlWriter);
$this->writeChangeInsertion(false, $element->getTrackChange());
}

$this->writeChangeInsertion(true, $element->getTrackChange());
$this->replaceTabs($element->getText(), $xmlWriter);
$this->writeChangeInsertion(false, $element->getTrackChange());

if (!empty($fontStyle)) {
$xmlWriter->endElement();
}
}
Expand Down
86 changes: 86 additions & 0 deletions src/PhpWord/Writer/ODText/Style/Numbering.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/

namespace PhpOffice\PhpWord\Writer\ODText\Style;

use PhpOffice\PhpWord\Shared\Converter;
use PhpOffice\PhpWord\Style\Numbering as StyleNumbering;

/**
* Numbering style writer.
*/
class Numbering extends AbstractStyle
{
/**
* Write style.
*/
public function write(): void
{
/** @var StyleNumbering $style Type hint */
$style = $this->getStyle();
if (!$style instanceof StyleNumbering) {
return;
}
$xmlWriter = $this->getXmlWriter();

$xmlWriter->startElement('text:list-style');
$xmlWriter->writeAttribute('style:name', $style->getStyleName());

foreach ($style->getLevels() as $styleLevel) {
$numLevel = $styleLevel->getLevel() + 1;

// In Twips
$tabPos = $styleLevel->getTabPos();
// In Inches
$tabPos /= Converter::INCH_TO_TWIP;
// In Centimeters
$tabPos *= Converter::INCH_TO_CM;

// In Twips
$hanging = $styleLevel->getHanging();
// In Inches
$hanging /= Converter::INCH_TO_TWIP;
// In Centimeters
$hanging *= Converter::INCH_TO_CM;

$xmlWriter->startElement('text:list-level-style-bullet');
$xmlWriter->writeAttribute('text:level', $numLevel);
$xmlWriter->writeAttribute('text:style-name', $style->getStyleName() . '_' . $numLevel);
$xmlWriter->writeAttribute('text:bullet-char', $styleLevel->getText());

$xmlWriter->startElement('style:list-level-properties');
$xmlWriter->writeAttribute('text:list-level-position-and-space-mode', 'label-alignment');

$xmlWriter->startElement('style:list-level-label-alignment');
$xmlWriter->writeAttribute('text:label-followed-by', 'listtab');
$xmlWriter->writeAttribute('text:list-tab-stop-position', number_format($tabPos, 2, '.', '') . 'cm');
$xmlWriter->writeAttribute('fo:text-indent', '-' . number_format($hanging, 2, '.', '') . 'cm');
$xmlWriter->writeAttribute('fo:margin-left', number_format($tabPos, 2, '.', '') . 'cm');

$xmlWriter->endElement(); // style:list-level-label-alignment
$xmlWriter->endElement(); // style:list-level-properties

$xmlWriter->startElement('style:text-properties');
$xmlWriter->writeAttribute('style:font-name', $styleLevel->getFont());
$xmlWriter->endElement(); // style:text-properties

$xmlWriter->endElement(); // text:list-level-style-bullet
}

$xmlWriter->endElement(); // text:list-style
}
}
4 changes: 1 addition & 3 deletions src/PhpWord/Writer/Word2007/Element/AbstractElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,8 @@ abstract public function write();

/**
* Create new instance.
*
* @param bool $withoutP
*/
public function __construct(XMLWriter $xmlWriter, Element $element, $withoutP = false)
public function __construct(XMLWriter $xmlWriter, Element $element, bool $withoutP = false)
{
$this->xmlWriter = $xmlWriter;
$this->element = $element;
Expand Down
7 changes: 6 additions & 1 deletion src/PhpWord/Writer/Word2007/Element/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class Container extends AbstractElement
*/
protected $namespace = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element';

/**
* @var array<string>
*/
protected $containerWithoutP = ['TextRun', 'Footnote', 'Endnote', 'ListItemRun'];

/**
* Write element.
*/
Expand All @@ -46,7 +51,7 @@ public function write(): void
return;
}
$containerClass = substr(get_class($container), strrpos(get_class($container), '\\') + 1);
$withoutP = in_array($containerClass, ['TextRun', 'Footnote', 'Endnote', 'ListItemRun']);
$withoutP = in_array($containerClass, $this->containerWithoutP);
$xmlWriter = $this->getXmlWriter();

// Loop through elements
Expand Down
Loading

0 comments on commit 2e4f3cf

Please sign in to comment.