commit
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpOffice\PhpWord;
|
||||
|
||||
class Autoloader
|
||||
{
|
||||
/** @const string */
|
||||
const NAMESPACE_PREFIX = 'PhpOffice\\PhpWord\\';
|
||||
|
||||
public static function register(): void
|
||||
{
|
||||
spl_autoload_register([new self(), 'autoload']);
|
||||
}
|
||||
|
||||
public static function autoload(string $class): void
|
||||
{
|
||||
$prefixLength = strlen(self::NAMESPACE_PREFIX);
|
||||
if (0 === strncmp(self::NAMESPACE_PREFIX, $class, $prefixLength)) {
|
||||
$file = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, $prefixLength));
|
||||
$file = realpath(__DIR__ . (empty($file) ? '' : DIRECTORY_SEPARATOR) . $file . '.php');
|
||||
if (!$file) {
|
||||
return;
|
||||
}
|
||||
if (file_exists($file)) {
|
||||
/** @noinspection PhpIncludeInspection Dynamic includes */
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?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\Collection;
|
||||
|
||||
/**
|
||||
* Collection abstract class.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @template T
|
||||
*/
|
||||
abstract class AbstractCollection
|
||||
{
|
||||
/**
|
||||
* Items.
|
||||
*
|
||||
* @var T[]
|
||||
*/
|
||||
private $items = [];
|
||||
|
||||
/**
|
||||
* Get items.
|
||||
*
|
||||
* @return T[]
|
||||
*/
|
||||
public function getItems(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item by index.
|
||||
*
|
||||
* @return ?T
|
||||
*/
|
||||
public function getItem(int $index)
|
||||
{
|
||||
if (array_key_exists($index, $this->items)) {
|
||||
return $this->items[$index];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set item.
|
||||
*
|
||||
* @param ?T $item
|
||||
*/
|
||||
public function setItem(int $index, $item): void
|
||||
{
|
||||
if (array_key_exists($index, $this->items)) {
|
||||
$this->items[$index] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new item.
|
||||
*
|
||||
* @param T $item
|
||||
*/
|
||||
public function addItem($item): int
|
||||
{
|
||||
$index = $this->countItems();
|
||||
$this->items[$index] = $item;
|
||||
|
||||
return $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item count.
|
||||
*/
|
||||
public function countItems(): int
|
||||
{
|
||||
return count($this->items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Collection;
|
||||
|
||||
use PhpOffice\PhpWord\Element\Bookmark;
|
||||
|
||||
/**
|
||||
* Bookmarks collection.
|
||||
*
|
||||
* @since 0.12.0
|
||||
*
|
||||
* @extends AbstractCollection<Bookmark>
|
||||
*/
|
||||
class Bookmarks extends AbstractCollection
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Collection;
|
||||
|
||||
use PhpOffice\PhpWord\Element\Chart;
|
||||
|
||||
/**
|
||||
* Charts collection.
|
||||
*
|
||||
* @since 0.12.0
|
||||
*
|
||||
* @extends AbstractCollection<Chart>
|
||||
*/
|
||||
class Charts extends AbstractCollection
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Collection;
|
||||
|
||||
use PhpOffice\PhpWord\Element\Comment;
|
||||
|
||||
/**
|
||||
* Comments collection.
|
||||
*
|
||||
* @since 0.12.0
|
||||
*
|
||||
* @extends AbstractCollection<Comment>
|
||||
*/
|
||||
class Comments extends AbstractCollection
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Collection;
|
||||
|
||||
use PhpOffice\PhpWord\Element\Endnote;
|
||||
|
||||
/**
|
||||
* Endnotes collection.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @extends AbstractCollection<Endnote>
|
||||
*/
|
||||
class Endnotes extends AbstractCollection
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Collection;
|
||||
|
||||
use PhpOffice\PhpWord\Element\Footnote;
|
||||
|
||||
/**
|
||||
* Footnotes collection.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @extends AbstractCollection<Footnote>
|
||||
*/
|
||||
class Footnotes extends AbstractCollection
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Collection;
|
||||
|
||||
use PhpOffice\PhpWord\Element\Title;
|
||||
|
||||
/**
|
||||
* Titles collection.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @extends AbstractCollection<Title>
|
||||
*/
|
||||
class Titles extends AbstractCollection
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
<?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\ComplexType;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use PhpOffice\PhpWord\SimpleType\NumberFormat;
|
||||
|
||||
/**
|
||||
* Footnote properties.
|
||||
*
|
||||
* @see http://www.datypic.com/sc/ooxml/e-w_footnotePr-1.html
|
||||
*/
|
||||
final class FootnoteProperties
|
||||
{
|
||||
const RESTART_NUMBER_CONTINUOUS = 'continuous';
|
||||
const RESTART_NUMBER_EACH_SECTION = 'eachSect';
|
||||
const RESTART_NUMBER_EACH_PAGE = 'eachPage';
|
||||
|
||||
const POSITION_PAGE_BOTTOM = 'pageBottom';
|
||||
const POSITION_BENEATH_TEXT = 'beneathText';
|
||||
const POSITION_SECTION_END = 'sectEnd';
|
||||
const POSITION_DOC_END = 'docEnd';
|
||||
|
||||
/**
|
||||
* Footnote Positioning Location.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $pos;
|
||||
|
||||
/**
|
||||
* Footnote Numbering Format w:numFmt, one of PhpOffice\PhpWord\SimpleType\NumberFormat.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $numFmt;
|
||||
|
||||
/**
|
||||
* Footnote and Endnote Numbering Starting Value.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
private $numStart;
|
||||
|
||||
/**
|
||||
* Footnote and Endnote Numbering Restart Location.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $numRestart;
|
||||
|
||||
/**
|
||||
* Get the Footnote Positioning Location.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPos()
|
||||
{
|
||||
return $this->pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Footnote Positioning Location (pageBottom, beneathText, sectEnd, docEnd).
|
||||
*
|
||||
* @param string $pos
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setPos($pos)
|
||||
{
|
||||
$position = [
|
||||
self::POSITION_PAGE_BOTTOM,
|
||||
self::POSITION_BENEATH_TEXT,
|
||||
self::POSITION_SECTION_END,
|
||||
self::POSITION_DOC_END,
|
||||
];
|
||||
|
||||
if (in_array($pos, $position)) {
|
||||
$this->pos = $pos;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid value, on of ' . implode(', ', $position) . ' possible');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Footnote Numbering Format.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNumFmt()
|
||||
{
|
||||
return $this->numFmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Footnote Numbering Format.
|
||||
*
|
||||
* @param string $numFmt One of NumberFormat
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setNumFmt($numFmt)
|
||||
{
|
||||
NumberFormat::validate($numFmt);
|
||||
$this->numFmt = $numFmt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Footnote Numbering Format.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getNumStart()
|
||||
{
|
||||
return $this->numStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Footnote Numbering Format.
|
||||
*
|
||||
* @param float $numStart
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setNumStart($numStart)
|
||||
{
|
||||
$this->numStart = $numStart;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Footnote and Endnote Numbering Starting Value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNumRestart()
|
||||
{
|
||||
return $this->numRestart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Footnote and Endnote Numbering Starting Value (continuous, eachSect, eachPage).
|
||||
*
|
||||
* @param string $numRestart
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setNumRestart($numRestart)
|
||||
{
|
||||
$restartNumbers = [
|
||||
self::RESTART_NUMBER_CONTINUOUS,
|
||||
self::RESTART_NUMBER_EACH_SECTION,
|
||||
self::RESTART_NUMBER_EACH_PAGE,
|
||||
];
|
||||
|
||||
if (in_array($numRestart, $restartNumbers)) {
|
||||
$this->numRestart = $numRestart;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid value, on of ' . implode(', ', $restartNumbers) . ' possible');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?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\ComplexType;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Spelling and Grammatical Checking State.
|
||||
*
|
||||
* @see http://www.datypic.com/sc/ooxml/e-w_proofState-1.html
|
||||
*/
|
||||
final class ProofState
|
||||
{
|
||||
/**
|
||||
* Check Completed.
|
||||
*/
|
||||
const CLEAN = 'clean';
|
||||
|
||||
/**
|
||||
* Check Not Completed.
|
||||
*/
|
||||
const DIRTY = 'dirty';
|
||||
|
||||
/**
|
||||
* Spell Checking State.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $spelling;
|
||||
|
||||
/**
|
||||
* Grammatical Checking State.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $grammar;
|
||||
|
||||
/**
|
||||
* Set the Spell Checking State (dirty or clean).
|
||||
*
|
||||
* @param string $spelling
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setSpelling($spelling)
|
||||
{
|
||||
if ($spelling == self::CLEAN || $spelling == self::DIRTY) {
|
||||
$this->spelling = $spelling;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid value, dirty or clean possible');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Spell Checking State.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSpelling()
|
||||
{
|
||||
return $this->spelling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Grammatical Checking State (dirty or clean).
|
||||
*
|
||||
* @param string $grammar
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setGrammar($grammar)
|
||||
{
|
||||
if ($grammar == self::CLEAN || $grammar == self::DIRTY) {
|
||||
$this->grammar = $grammar;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid value, dirty or clean possible');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Grammatical Checking State.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGrammar()
|
||||
{
|
||||
return $this->grammar;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
<?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\ComplexType;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Ruby properties.
|
||||
*
|
||||
* @see https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.rubyproperties?view=openxml-3.0.1
|
||||
*/
|
||||
class RubyProperties
|
||||
{
|
||||
const ALIGNMENT_CENTER = 'center';
|
||||
const ALIGNMENT_DISTRIBUTE_LETTER = 'distributeLetter';
|
||||
const ALIGNMENT_DISTRIBUTE_SPACE = 'distributeSpace';
|
||||
const ALIGNMENT_LEFT = 'left';
|
||||
const ALIGNMENT_RIGHT = 'right';
|
||||
const ALIGNMENT_RIGHT_VERTICAL = 'rightVertical';
|
||||
|
||||
/**
|
||||
* Ruby alignment (w:rubyAlign).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $alignment;
|
||||
|
||||
/**
|
||||
* Ruby font face size (w:hps).
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
private $fontFaceSize;
|
||||
|
||||
/**
|
||||
* Ruby font points above base text (w:hpsRaise).
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
private $fontPointsAboveText;
|
||||
|
||||
/**
|
||||
* Ruby font size for base text (w:hpsBaseText).
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
private $baseTextFontSize;
|
||||
|
||||
/**
|
||||
* Ruby type/language id (w:lid).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $languageId;
|
||||
|
||||
/**
|
||||
* Create a new RubyProperties object.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// these defaults came from opening a new Word doc, adding some ruby text to some
|
||||
// Japanese text, and copying out the defaults.
|
||||
$this->alignment = self::ALIGNMENT_DISTRIBUTE_SPACE;
|
||||
$this->fontFaceSize = 12;
|
||||
$this->fontPointsAboveText = 22;
|
||||
$this->languageId = 'ja-JP';
|
||||
$this->baseTextFontSize = 24;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ruby alignment.
|
||||
*/
|
||||
public function getAlignment(): string
|
||||
{
|
||||
return $this->alignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Ruby Alignment (center, distributeLetter, distributeSpace, left, right, rightVertical).
|
||||
*/
|
||||
public function setAlignment(string $alignment): self
|
||||
{
|
||||
$alignmentTypes = [
|
||||
self::ALIGNMENT_CENTER,
|
||||
self::ALIGNMENT_DISTRIBUTE_LETTER,
|
||||
self::ALIGNMENT_DISTRIBUTE_SPACE,
|
||||
self::ALIGNMENT_LEFT,
|
||||
self::ALIGNMENT_RIGHT,
|
||||
self::ALIGNMENT_RIGHT_VERTICAL,
|
||||
];
|
||||
|
||||
if (in_array($alignment, $alignmentTypes)) {
|
||||
$this->alignment = $alignment;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid value, alignments of ' . implode(', ', $alignmentTypes) . ' possible');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ruby font face size.
|
||||
*/
|
||||
public function getFontFaceSize(): float
|
||||
{
|
||||
return $this->fontFaceSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ruby font face size.
|
||||
*/
|
||||
public function setFontFaceSize(float $size): self
|
||||
{
|
||||
$this->fontFaceSize = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ruby font points above base text.
|
||||
*/
|
||||
public function getFontPointsAboveBaseText(): float
|
||||
{
|
||||
return $this->fontPointsAboveText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ruby font points above base text.
|
||||
*/
|
||||
public function setFontPointsAboveBaseText(float $size): self
|
||||
{
|
||||
$this->fontPointsAboveText = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ruby font size for base text.
|
||||
*/
|
||||
public function getFontSizeForBaseText(): float
|
||||
{
|
||||
return $this->baseTextFontSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ruby font size for base text.
|
||||
*/
|
||||
public function setFontSizeForBaseText(float $size): self
|
||||
{
|
||||
$this->baseTextFontSize = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ruby language id.
|
||||
*/
|
||||
public function getLanguageId(): string
|
||||
{
|
||||
return $this->languageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ruby language id.
|
||||
*/
|
||||
public function setLanguageId(string $langId): self
|
||||
{
|
||||
$this->languageId = $langId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?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\ComplexType;
|
||||
|
||||
use PhpOffice\PhpWord\SimpleType\TblWidth as TblWidthSimpleType;
|
||||
|
||||
/**
|
||||
* @see http://www.datypic.com/sc/ooxml/t-w_CT_TblWidth.html
|
||||
*/
|
||||
final class TblWidth
|
||||
{
|
||||
/** @var string */
|
||||
private $type;
|
||||
|
||||
/** @var int */
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @param int $value If omitted, then its value shall be assumed to be 0
|
||||
* @param string $type If omitted, then its value shall be assumed to be dxa
|
||||
*/
|
||||
public function __construct($value = 0, $type = TblWidthSimpleType::TWIP)
|
||||
{
|
||||
$this->value = $value;
|
||||
TblWidthSimpleType::validate($type);
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
<?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\ComplexType;
|
||||
|
||||
/**
|
||||
* Visibility of Annotation Types.
|
||||
*
|
||||
* @see http://www.datypic.com/sc/ooxml/e-w_revisionView-1.html
|
||||
*/
|
||||
final class TrackChangesView
|
||||
{
|
||||
/**
|
||||
* Display Visual Indicator Of Markup Area.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $markup;
|
||||
|
||||
/**
|
||||
* Display Comments.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $comments;
|
||||
|
||||
/**
|
||||
* Display Content Revisions.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $insDel;
|
||||
|
||||
/**
|
||||
* Display Formatting Revisions.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $formatting;
|
||||
|
||||
/**
|
||||
* Display Ink Annotations.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $inkAnnotations;
|
||||
|
||||
/**
|
||||
* Get Display Visual Indicator Of Markup Area.
|
||||
*
|
||||
* @return bool True if markup is shown
|
||||
*/
|
||||
public function hasMarkup()
|
||||
{
|
||||
return $this->markup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Display Visual Indicator Of Markup Area.
|
||||
*
|
||||
* @param ?bool $markup
|
||||
* Set to true to show markup
|
||||
*/
|
||||
public function setMarkup($markup): void
|
||||
{
|
||||
$this->markup = $markup === null ? true : $markup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Display Comments.
|
||||
*
|
||||
* @return bool True if comments are shown
|
||||
*/
|
||||
public function hasComments()
|
||||
{
|
||||
return $this->comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Display Comments.
|
||||
*
|
||||
* @param ?bool $comments
|
||||
* Set to true to show comments
|
||||
*/
|
||||
public function setComments($comments): void
|
||||
{
|
||||
$this->comments = $comments === null ? true : $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Display Content Revisions.
|
||||
*
|
||||
* @return bool True if content revisions are shown
|
||||
*/
|
||||
public function hasInsDel()
|
||||
{
|
||||
return $this->insDel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Display Content Revisions.
|
||||
*
|
||||
* @param ?bool $insDel
|
||||
* Set to true to show content revisions
|
||||
*/
|
||||
public function setInsDel($insDel): void
|
||||
{
|
||||
$this->insDel = $insDel === null ? true : $insDel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Display Formatting Revisions.
|
||||
*
|
||||
* @return bool True if formatting revisions are shown
|
||||
*/
|
||||
public function hasFormatting()
|
||||
{
|
||||
return $this->formatting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Display Formatting Revisions.
|
||||
*
|
||||
* @param null|bool $formatting
|
||||
* Set to true to show formatting revisions
|
||||
*/
|
||||
public function setFormatting($formatting = null): void
|
||||
{
|
||||
$this->formatting = $formatting === null ? true : $formatting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Display Ink Annotations.
|
||||
*
|
||||
* @return bool True if ink annotations are shown
|
||||
*/
|
||||
public function hasInkAnnotations()
|
||||
{
|
||||
return $this->inkAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Display Ink Annotations.
|
||||
*
|
||||
* @param ?bool $inkAnnotations
|
||||
* Set to true to show ink annotations
|
||||
*/
|
||||
public function setInkAnnotations($inkAnnotations): void
|
||||
{
|
||||
$this->inkAnnotations = $inkAnnotations === null ? true : $inkAnnotations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
<?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\Element;
|
||||
|
||||
use BadMethodCallException;
|
||||
use PhpOffice\Math\Math;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Container abstract class.
|
||||
*
|
||||
* @method Text addText(string $text, mixed $fStyle = null, mixed $pStyle = null)
|
||||
* @method TextRun addTextRun(mixed $pStyle = null)
|
||||
* @method Bookmark addBookmark(string $name)
|
||||
* @method Link addLink(string $target, string $text = null, mixed $fStyle = null, mixed $pStyle = null, boolean $internal = false)
|
||||
* @method PreserveText addPreserveText(string $text, mixed $fStyle = null, mixed $pStyle = null)
|
||||
* @method void addTextBreak(int $count = 1, mixed $fStyle = null, mixed $pStyle = null)
|
||||
* @method ListItem addListItem(string $txt, int $depth = 0, mixed $font = null, mixed $list = null, mixed $para = null)
|
||||
* @method ListItemRun addListItemRun(int $depth = 0, mixed $listStyle = null, mixed $pStyle = null)
|
||||
* @method Footnote addFootnote(mixed $pStyle = null)
|
||||
* @method Endnote addEndnote(mixed $pStyle = null)
|
||||
* @method CheckBox addCheckBox(string $name, $text, mixed $fStyle = null, mixed $pStyle = null)
|
||||
* @method Title addTitle(mixed $text, int $depth = 1, int $pageNumber = null)
|
||||
* @method TOC addTOC(mixed $fontStyle = null, mixed $tocStyle = null, int $minDepth = 1, int $maxDepth = 9)
|
||||
* @method PageBreak addPageBreak()
|
||||
* @method Table addTable(mixed $style = null)
|
||||
* @method Image addImage(string $source, mixed $style = null, bool $isWatermark = false, $name = null)
|
||||
* @method OLEObject addOLEObject(string $source, mixed $style = null)
|
||||
* @method TextBox addTextBox(mixed $style = null)
|
||||
* @method Field addField(string $type = null, array $properties = array(), array $options = array(), mixed $text = null)
|
||||
* @method Line addLine(mixed $lineStyle = null)
|
||||
* @method Shape addShape(string $type, mixed $style = null)
|
||||
* @method Chart addChart(string $type, array $categories, array $values, array $style = null, $seriesName = null)
|
||||
* @method FormField addFormField(string $type, mixed $fStyle = null, mixed $pStyle = null)
|
||||
* @method SDT addSDT(string $type)
|
||||
* @method Formula addFormula(Math $math)
|
||||
* @method Ruby addRuby(TextRun $baseText, TextRun $rubyText, \PhpOffice\PhpWord\ComplexType\RubyProperties $properties)
|
||||
* @method \PhpOffice\PhpWord\Element\OLEObject addObject(string $source, mixed $style = null) deprecated, use addOLEObject instead
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
abstract class AbstractContainer extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Elements collection.
|
||||
*
|
||||
* @var AbstractElement[]
|
||||
*/
|
||||
protected $elements = [];
|
||||
|
||||
/**
|
||||
* Container type Section|Header|Footer|Footnote|Endnote|Cell|TextRun|TextBox|ListItemRun|TrackChange.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Magic method to catch all 'addElement' variation.
|
||||
*
|
||||
* This removes addText, addTextRun, etc. When adding new element, we have to
|
||||
* add the model in the class docblock with `@method`.
|
||||
*
|
||||
* Warning: This makes capitalization matters, e.g. addCheckbox or addcheckbox won't work.
|
||||
*
|
||||
* @param mixed $function
|
||||
* @param mixed $args
|
||||
*
|
||||
* @return AbstractElement
|
||||
*/
|
||||
public function __call($function, $args)
|
||||
{
|
||||
$elements = [
|
||||
'Text', 'TextRun', 'Bookmark', 'Link', 'PreserveText', 'TextBreak',
|
||||
'ListItem', 'ListItemRun', 'Table', 'Image', 'Object', 'OLEObject',
|
||||
'Footnote', 'Endnote', 'CheckBox', 'TextBox', 'Field',
|
||||
'Line', 'Shape', 'Title', 'TOC', 'PageBreak',
|
||||
'Chart', 'FormField', 'SDT', 'Comment',
|
||||
'Formula', 'Ruby',
|
||||
];
|
||||
$functions = [];
|
||||
foreach ($elements as $element) {
|
||||
$functions['add' . strtolower($element)] = $element == 'Object' ? 'OLEObject' : $element;
|
||||
}
|
||||
|
||||
// Run valid `add` command
|
||||
$function = strtolower($function);
|
||||
if (isset($functions[$function])) {
|
||||
$element = $functions[$function];
|
||||
|
||||
// Special case for TextBreak
|
||||
// @todo Remove the `$count` parameter in 1.0.0 to make this element similiar to other elements?
|
||||
if ($element == 'TextBreak') {
|
||||
[$count, $fontStyle, $paragraphStyle] = array_pad($args, 3, null);
|
||||
if ($count === null) {
|
||||
$count = 1;
|
||||
}
|
||||
for ($i = 1; $i <= $count; ++$i) {
|
||||
$this->addElement($element, $fontStyle, $paragraphStyle);
|
||||
}
|
||||
} else {
|
||||
// All other elements
|
||||
array_unshift($args, $element); // Prepend element name to the beginning of args array
|
||||
|
||||
return call_user_func_array([$this, 'addElement'], $args);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add element.
|
||||
*
|
||||
* Each element has different number of parameters passed
|
||||
*
|
||||
* @param string $elementName
|
||||
*
|
||||
* @return AbstractElement
|
||||
*/
|
||||
protected function addElement($elementName)
|
||||
{
|
||||
$elementClass = __NAMESPACE__ . '\\' . $elementName;
|
||||
$this->checkValidity($elementName);
|
||||
|
||||
// Get arguments
|
||||
$args = func_get_args();
|
||||
$withoutP = in_array($this->container, ['TextRun', 'Footnote', 'Endnote', 'ListItemRun', 'Field']);
|
||||
if ($withoutP && ($elementName == 'Text' || $elementName == 'PreserveText')) {
|
||||
$args[3] = null; // Remove paragraph style for texts in textrun
|
||||
}
|
||||
|
||||
// Create element using reflection
|
||||
$reflection = new ReflectionClass($elementClass);
|
||||
$elementArgs = $args;
|
||||
array_shift($elementArgs); // Shift the $elementName off the beginning of array
|
||||
|
||||
/** @var AbstractElement $element Type hint */
|
||||
$element = $reflection->newInstanceArgs($elementArgs);
|
||||
|
||||
// Set parent container
|
||||
$element->setParentContainer($this);
|
||||
$element->setElementIndex($this->countElements() + 1);
|
||||
$element->setElementId();
|
||||
|
||||
$this->elements[] = $element;
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all elements.
|
||||
*
|
||||
* @return AbstractElement[]
|
||||
*/
|
||||
public function getElements()
|
||||
{
|
||||
return $this->elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element at the requested position.
|
||||
*
|
||||
* @param int $index
|
||||
*
|
||||
* @return null|AbstractElement
|
||||
*/
|
||||
public function getElement($index)
|
||||
{
|
||||
if (array_key_exists($index, $this->elements)) {
|
||||
return $this->elements[$index];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at requested index.
|
||||
*
|
||||
* @param AbstractElement|int $toRemove
|
||||
*/
|
||||
public function removeElement($toRemove): void
|
||||
{
|
||||
if (is_int($toRemove) && array_key_exists($toRemove, $this->elements)) {
|
||||
unset($this->elements[$toRemove]);
|
||||
} elseif ($toRemove instanceof AbstractElement) {
|
||||
foreach ($this->elements as $key => $element) {
|
||||
if ($element->getElementId() === $toRemove->getElementId()) {
|
||||
unset($this->elements[$key]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count elements.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countElements()
|
||||
{
|
||||
return count($this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a method is allowed for the current container.
|
||||
*
|
||||
* @param string $method
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function checkValidity($method)
|
||||
{
|
||||
$generalContainers = [
|
||||
'Section', 'Header', 'Footer', 'Footnote', 'Endnote', 'Cell', 'TextRun', 'TextBox', 'ListItemRun', 'TrackChange',
|
||||
];
|
||||
|
||||
$validContainers = [
|
||||
'Text' => $generalContainers,
|
||||
'Bookmark' => $generalContainers,
|
||||
'Link' => $generalContainers,
|
||||
'TextBreak' => $generalContainers,
|
||||
'Image' => $generalContainers,
|
||||
'OLEObject' => $generalContainers,
|
||||
'Field' => $generalContainers,
|
||||
'Line' => $generalContainers,
|
||||
'Shape' => $generalContainers,
|
||||
'FormField' => $generalContainers,
|
||||
'SDT' => $generalContainers,
|
||||
'TrackChange' => $generalContainers,
|
||||
'TextRun' => ['Section', 'Header', 'Footer', 'Cell', 'TextBox', 'TrackChange', 'ListItemRun'],
|
||||
'ListItem' => ['Section', 'Header', 'Footer', 'Cell', 'TextBox'],
|
||||
'ListItemRun' => ['Section', 'Header', 'Footer', 'Cell', 'TextBox'],
|
||||
'Table' => ['Section', 'Header', 'Footer', 'Cell', 'TextBox'],
|
||||
'CheckBox' => ['Section', 'Header', 'Footer', 'Cell', 'TextRun'],
|
||||
'TextBox' => ['Section', 'Header', 'Footer', 'Cell'],
|
||||
'Footnote' => ['Section', 'TextRun', 'Cell', 'ListItemRun'],
|
||||
'Endnote' => ['Section', 'TextRun', 'Cell'],
|
||||
'PreserveText' => ['Section', 'Header', 'Footer', 'Cell'],
|
||||
'Title' => ['Section', 'Cell', 'Header'],
|
||||
'TOC' => ['Section'],
|
||||
'PageBreak' => ['Section'],
|
||||
'Chart' => ['Section', 'Cell'],
|
||||
];
|
||||
|
||||
// Special condition, e.g. preservetext can only exists in cell when
|
||||
// the cell is located in header or footer
|
||||
$validSubcontainers = [
|
||||
'PreserveText' => [['Cell'], ['Header', 'Footer', 'Section']],
|
||||
'Footnote' => [['Cell', 'TextRun'], ['Section']],
|
||||
'Endnote' => [['Cell', 'TextRun'], ['Section']],
|
||||
];
|
||||
|
||||
// Check if a method is valid for current container
|
||||
if (isset($validContainers[$method])) {
|
||||
if (!in_array($this->container, $validContainers[$method])) {
|
||||
throw new BadMethodCallException("Cannot add {$method} in {$this->container}.");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a method is valid for current container, located in other container
|
||||
if (isset($validSubcontainers[$method])) {
|
||||
$rules = $validSubcontainers[$method];
|
||||
$containers = $rules[0];
|
||||
$allowedDocParts = $rules[1];
|
||||
foreach ($containers as $container) {
|
||||
if ($this->container == $container && !in_array($this->getDocPart(), $allowedDocParts)) {
|
||||
throw new BadMethodCallException("Cannot add {$method} in {$this->container}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,544 @@
|
||||
<?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\Element;
|
||||
|
||||
use DateTime;
|
||||
use InvalidArgumentException;
|
||||
use PhpOffice\PhpWord\Collection\Comments;
|
||||
use PhpOffice\PhpWord\Media;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Style;
|
||||
|
||||
/**
|
||||
* Element abstract class.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
abstract class AbstractElement
|
||||
{
|
||||
/**
|
||||
* PhpWord object.
|
||||
*
|
||||
* @var ?PhpWord
|
||||
*/
|
||||
protected $phpWord;
|
||||
|
||||
/**
|
||||
* Section Id.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $sectionId;
|
||||
|
||||
/**
|
||||
* Document part type: Section|Header|Footer|Footnote|Endnote.
|
||||
*
|
||||
* Used by textrun and cell container to determine where the element is
|
||||
* located because it will affect the availability of other element,
|
||||
* e.g. footnote will not be available when $docPart is header or footer.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $docPart = 'Section';
|
||||
|
||||
/**
|
||||
* Document part Id.
|
||||
*
|
||||
* For header and footer, this will be = ($sectionId - 1) * 3 + $index
|
||||
* because the max number of header/footer in every page is 3, i.e.
|
||||
* AUTO, FIRST, and EVEN (AUTO = ODD)
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $docPartId = 1;
|
||||
|
||||
/**
|
||||
* Index of element in the elements collection (start with 1).
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $elementIndex = 1;
|
||||
|
||||
/**
|
||||
* Unique Id for element.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $elementId;
|
||||
|
||||
/**
|
||||
* Relation Id.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $relationId;
|
||||
|
||||
/**
|
||||
* Depth of table container nested level; Primarily used for RTF writer/reader.
|
||||
*
|
||||
* 0 = Not in a table; 1 = in a table; 2 = in a table inside another table, etc.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $nestedLevel = 0;
|
||||
|
||||
/**
|
||||
* A reference to the parent.
|
||||
*
|
||||
* @var null|AbstractElement
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* changed element info.
|
||||
*
|
||||
* @var TrackChange
|
||||
*/
|
||||
private $trackChange;
|
||||
|
||||
/**
|
||||
* Parent container type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $parentContainer;
|
||||
|
||||
/**
|
||||
* Has media relation flag; true for Link, Image, and Object.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $mediaRelation = false;
|
||||
|
||||
/**
|
||||
* Is part of collection; true for Title, Footnote, Endnote, Chart, and Comment.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $collectionRelation = false;
|
||||
|
||||
/**
|
||||
* The start position for the linked comments.
|
||||
*
|
||||
* @var Comments
|
||||
*/
|
||||
protected $commentsRangeStart;
|
||||
|
||||
/**
|
||||
* The end position for the linked comments.
|
||||
*
|
||||
* @var Comments
|
||||
*/
|
||||
protected $commentsRangeEnd;
|
||||
|
||||
/**
|
||||
* Get PhpWord.
|
||||
*/
|
||||
public function getPhpWord(): ?PhpWord
|
||||
{
|
||||
return $this->phpWord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set PhpWord as reference.
|
||||
*/
|
||||
public function setPhpWord(?PhpWord $phpWord = null): void
|
||||
{
|
||||
$this->phpWord = $phpWord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get section number.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSectionId()
|
||||
{
|
||||
return $this->sectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set doc part.
|
||||
*
|
||||
* @param string $docPart
|
||||
* @param int $docPartId
|
||||
*/
|
||||
public function setDocPart($docPart, $docPartId = 1): void
|
||||
{
|
||||
$this->docPart = $docPart;
|
||||
$this->docPartId = $docPartId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get doc part.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDocPart()
|
||||
{
|
||||
return $this->docPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get doc part Id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDocPartId()
|
||||
{
|
||||
return $this->docPartId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return media element (image, object, link) container name.
|
||||
*
|
||||
* @return string section|headerx|footerx|footnote|endnote
|
||||
*/
|
||||
private function getMediaPart()
|
||||
{
|
||||
$mediaPart = $this->docPart;
|
||||
if ($mediaPart == 'Header' || $mediaPart == 'Footer') {
|
||||
$mediaPart .= $this->docPartId;
|
||||
}
|
||||
|
||||
return strtolower($mediaPart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get element index.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getElementIndex()
|
||||
{
|
||||
return $this->elementIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set element index.
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setElementIndex($value): void
|
||||
{
|
||||
$this->elementIndex = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get element unique ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getElementId()
|
||||
{
|
||||
return $this->elementId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set element unique ID from 6 first digit of md5.
|
||||
*/
|
||||
public function setElementId(): void
|
||||
{
|
||||
$this->elementId = substr(md5((string) mt_rand()), 0, 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get relation Id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRelationId()
|
||||
{
|
||||
return $this->relationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set relation Id.
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setRelationId($value): void
|
||||
{
|
||||
$this->relationId = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nested level.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNestedLevel()
|
||||
{
|
||||
return $this->nestedLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get comments start.
|
||||
*/
|
||||
public function getCommentsRangeStart(): ?Comments
|
||||
{
|
||||
return $this->commentsRangeStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get comment start.
|
||||
*/
|
||||
public function getCommentRangeStart(): ?Comment
|
||||
{
|
||||
if ($this->commentsRangeStart != null) {
|
||||
return $this->commentsRangeStart->getItem($this->commentsRangeStart->countItems());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set comment start.
|
||||
*/
|
||||
public function setCommentRangeStart(Comment $value): void
|
||||
{
|
||||
if ($this instanceof Comment) {
|
||||
throw new InvalidArgumentException('Cannot set a Comment on a Comment');
|
||||
}
|
||||
if ($this->commentsRangeStart == null) {
|
||||
$this->commentsRangeStart = new Comments();
|
||||
}
|
||||
// Set ID early to avoid duplicates.
|
||||
if ($value->getElementId() == null) {
|
||||
$value->setElementId();
|
||||
}
|
||||
foreach ($this->commentsRangeStart->getItems() as $comment) {
|
||||
if ($value->getElementId() == $comment->getElementId()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$idxItem = $this->commentsRangeStart->addItem($value);
|
||||
$this->commentsRangeStart->getItem($idxItem)->setStartElement($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get comments end.
|
||||
*/
|
||||
public function getCommentsRangeEnd(): ?Comments
|
||||
{
|
||||
return $this->commentsRangeEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get comment end.
|
||||
*/
|
||||
public function getCommentRangeEnd(): ?Comment
|
||||
{
|
||||
if ($this->commentsRangeEnd != null) {
|
||||
return $this->commentsRangeEnd->getItem($this->commentsRangeEnd->countItems());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set comment end.
|
||||
*/
|
||||
public function setCommentRangeEnd(Comment $value): void
|
||||
{
|
||||
if ($this instanceof Comment) {
|
||||
throw new InvalidArgumentException('Cannot set a Comment on a Comment');
|
||||
}
|
||||
if ($this->commentsRangeEnd == null) {
|
||||
$this->commentsRangeEnd = new Comments();
|
||||
}
|
||||
// Set ID early to avoid duplicates.
|
||||
if ($value->getElementId() == null) {
|
||||
$value->setElementId();
|
||||
}
|
||||
foreach ($this->commentsRangeEnd->getItems() as $comment) {
|
||||
if ($value->getElementId() == $comment->getElementId()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$idxItem = $this->commentsRangeEnd->addItem($value);
|
||||
$this->commentsRangeEnd->getItem($idxItem)->setEndElement($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent element.
|
||||
*
|
||||
* @return null|AbstractElement
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set parent container.
|
||||
*
|
||||
* Passed parameter should be a container, except for Table (contain Row) and Row (contain Cell)
|
||||
*/
|
||||
public function setParentContainer(self $container): void
|
||||
{
|
||||
$this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1);
|
||||
$this->parent = $container;
|
||||
|
||||
// Set nested level
|
||||
$this->nestedLevel = $container->getNestedLevel();
|
||||
if ($this->parentContainer == 'Cell') {
|
||||
++$this->nestedLevel;
|
||||
}
|
||||
|
||||
// Set phpword
|
||||
$this->setPhpWord($container->getPhpWord());
|
||||
|
||||
// Set doc part
|
||||
if (!$this instanceof Footnote) {
|
||||
$this->setDocPart($container->getDocPart(), $container->getDocPartId());
|
||||
}
|
||||
|
||||
$this->setMediaRelation();
|
||||
$this->setCollectionRelation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set relation Id for media elements (link, image, object; legacy of OOXML).
|
||||
*
|
||||
* - Image element needs to be passed to Media object
|
||||
* - Icon needs to be set for Object element
|
||||
*/
|
||||
private function setMediaRelation(): void
|
||||
{
|
||||
if (!$this instanceof Link && !$this instanceof Image && !$this instanceof OLEObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
$elementName = substr(static::class, strrpos(static::class, '\\') + 1);
|
||||
if ($elementName == 'OLEObject') {
|
||||
$elementName = 'Object';
|
||||
}
|
||||
$mediaPart = $this->getMediaPart();
|
||||
$source = $this->getSource();
|
||||
$image = null;
|
||||
if ($this instanceof Image) {
|
||||
$image = $this;
|
||||
}
|
||||
$rId = Media::addElement($mediaPart, strtolower($elementName), $source, $image);
|
||||
$this->setRelationId($rId);
|
||||
|
||||
if ($this instanceof OLEObject) {
|
||||
$icon = $this->getIcon();
|
||||
$rId = Media::addElement($mediaPart, 'image', $icon, new Image($icon));
|
||||
$this->setImageRelationId($rId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set relation Id for elements that will be registered in the Collection subnamespaces.
|
||||
*/
|
||||
private function setCollectionRelation(): void
|
||||
{
|
||||
if ($this->collectionRelation === true && $this->phpWord instanceof PhpWord) {
|
||||
$elementName = substr(static::class, strrpos(static::class, '\\') + 1);
|
||||
$addMethod = "add{$elementName}";
|
||||
$rId = $this->phpWord->$addMethod($this);
|
||||
$this->setRelationId($rId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if element is located in Section doc part (as opposed to Header/Footer).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInSection()
|
||||
{
|
||||
return $this->docPart == 'Section';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new style value.
|
||||
*
|
||||
* @param mixed $styleObject Style object
|
||||
* @param null|array|string|Style $styleValue Style value
|
||||
* @param bool $returnObject Always return object
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function setNewStyle($styleObject, $styleValue = null, $returnObject = false)
|
||||
{
|
||||
if (null !== $styleValue && is_array($styleValue)) {
|
||||
$styleObject->setStyleByArray($styleValue);
|
||||
$style = $styleObject;
|
||||
} else {
|
||||
$style = $returnObject ? $styleObject : $styleValue;
|
||||
}
|
||||
|
||||
return $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the trackChange information.
|
||||
*/
|
||||
public function setTrackChange(TrackChange $trackChange): void
|
||||
{
|
||||
$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|DateTime|int $date allways in UTC
|
||||
*/
|
||||
public function setChangeInfo($type, $author, $date = null): void
|
||||
{
|
||||
$this->trackChange = new TrackChange($type, $author, $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set enum value.
|
||||
*
|
||||
* @param null|string $value
|
||||
* @param string[] $enum
|
||||
* @param null|string $default
|
||||
*
|
||||
* @return null|string
|
||||
*
|
||||
* @todo Merge with the same method in AbstractStyle
|
||||
*/
|
||||
protected function setEnumVal($value = null, $enum = [], $default = null)
|
||||
{
|
||||
if ($value !== null && trim($value) != '' && !empty($enum) && !in_array($value, $enum)) {
|
||||
throw new InvalidArgumentException("Invalid style value: {$value}");
|
||||
} elseif ($value === null || trim($value) == '') {
|
||||
$value = $default;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Shared\Text as SharedText;
|
||||
|
||||
/**
|
||||
* Bookmark element.
|
||||
*/
|
||||
class Bookmark extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Bookmark Name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Is part of collection.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $collectionRelation = true;
|
||||
|
||||
/**
|
||||
* Create a new Bookmark Element.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct($name = '')
|
||||
{
|
||||
$this->name = SharedText::toUTF8($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bookmark name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\Cell as CellStyle;
|
||||
|
||||
/**
|
||||
* Table cell element.
|
||||
*/
|
||||
class Cell extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* @var string Container type
|
||||
*/
|
||||
protected $container = 'Cell';
|
||||
|
||||
/**
|
||||
* Cell width.
|
||||
*
|
||||
* @var ?int
|
||||
*/
|
||||
private $width;
|
||||
|
||||
/**
|
||||
* Cell style.
|
||||
*
|
||||
* @var ?CellStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param null|int $width
|
||||
* @param array|CellStyle $style
|
||||
*/
|
||||
public function __construct($width = null, $style = null)
|
||||
{
|
||||
$this->width = $width;
|
||||
$this->style = $this->setNewStyle(new CellStyle(), $style, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cell style.
|
||||
*
|
||||
* @return ?CellStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cell width.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getWidth()
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\Chart as ChartStyle;
|
||||
|
||||
/**
|
||||
* Chart element.
|
||||
*
|
||||
* @since 0.12.0
|
||||
*/
|
||||
class Chart extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Is part of collection.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $collectionRelation = true;
|
||||
|
||||
/**
|
||||
* Type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $type = 'pie';
|
||||
|
||||
/**
|
||||
* Series.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $series = [];
|
||||
|
||||
/**
|
||||
* Chart style.
|
||||
*
|
||||
* @var ?ChartStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $categories
|
||||
* @param array $values
|
||||
* @param array $style
|
||||
* @param null|mixed $seriesName
|
||||
*/
|
||||
public function __construct($type, $categories, $values, $style = null, $seriesName = null)
|
||||
{
|
||||
$this->setType($type);
|
||||
$this->addSeries($categories, $values, $seriesName);
|
||||
$this->style = $this->setNewStyle(new ChartStyle(), $style, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function setType($value): void
|
||||
{
|
||||
$enum = ['pie', 'doughnut', 'line', 'bar', 'stacked_bar', 'percent_stacked_bar', 'column', 'stacked_column', 'percent_stacked_column', 'area', 'radar', 'scatter'];
|
||||
$this->type = $this->setEnumVal($value, $enum, 'pie');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add series.
|
||||
*
|
||||
* @param array $categories
|
||||
* @param array $values
|
||||
* @param null|mixed $name
|
||||
*/
|
||||
public function addSeries($categories, $values, $name = null): void
|
||||
{
|
||||
$this->series[] = [
|
||||
'categories' => $categories,
|
||||
'values' => $values,
|
||||
'name' => $name,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get series.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSeries()
|
||||
{
|
||||
return $this->series;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get chart style.
|
||||
*
|
||||
* @return ?ChartStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Shared\Text as SharedText;
|
||||
|
||||
/**
|
||||
* Check box element.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class CheckBox extends Text
|
||||
{
|
||||
/**
|
||||
* Name content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $text
|
||||
* @param mixed $fontStyle
|
||||
* @param mixed $paragraphStyle
|
||||
*/
|
||||
public function __construct($name = null, $text = null, $fontStyle = null, $paragraphStyle = null)
|
||||
{
|
||||
$this->setName($name);
|
||||
parent::__construct($text, $fontStyle, $paragraphStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name content.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = SharedText::toUTF8($name);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name content.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?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\Element;
|
||||
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* Comment element.
|
||||
*
|
||||
* @see http://datypic.com/sc/ooxml/t-w_CT_Comment.html
|
||||
*/
|
||||
class Comment extends TrackChange
|
||||
{
|
||||
/**
|
||||
* Initials.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $initials;
|
||||
|
||||
/**
|
||||
* The Element where this comment starts.
|
||||
*
|
||||
* @var AbstractElement
|
||||
*/
|
||||
private $startElement;
|
||||
|
||||
/**
|
||||
* The Element where this comment ends.
|
||||
*
|
||||
* @var AbstractElement
|
||||
*/
|
||||
private $endElement;
|
||||
|
||||
/**
|
||||
* Is part of collection.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $collectionRelation = true;
|
||||
|
||||
/**
|
||||
* Create a new Comment Element.
|
||||
*
|
||||
* @param string $author
|
||||
* @param null|DateTime $date
|
||||
* @param string $initials
|
||||
*/
|
||||
public function __construct($author, $date = null, $initials = null)
|
||||
{
|
||||
parent::__construct(null, $author, $date);
|
||||
$this->initials = $initials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Initials.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInitials()
|
||||
{
|
||||
return $this->initials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the element where this comment starts.
|
||||
*/
|
||||
public function setStartElement(AbstractElement $value): void
|
||||
{
|
||||
$this->startElement = $value;
|
||||
$value->setCommentRangeStart($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element where this comment starts.
|
||||
*
|
||||
* @return AbstractElement
|
||||
*/
|
||||
public function getStartElement()
|
||||
{
|
||||
return $this->startElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the element where this comment ends.
|
||||
*/
|
||||
public function setEndElement(AbstractElement $value): void
|
||||
{
|
||||
$this->endElement = $value;
|
||||
$value->setCommentRangeEnd($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element where this comment ends.
|
||||
*
|
||||
* @return AbstractElement
|
||||
*/
|
||||
public function getEndElement()
|
||||
{
|
||||
return $this->endElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?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\Element;
|
||||
|
||||
/**
|
||||
* Endnote element.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class Endnote extends Footnote
|
||||
{
|
||||
/**
|
||||
* @var string Container type
|
||||
*/
|
||||
protected $container = 'Endnote';
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param array|\PhpOffice\PhpWord\Style\Paragraph|string $paragraphStyle
|
||||
*/
|
||||
public function __construct($paragraphStyle = null)
|
||||
{
|
||||
parent::__construct($paragraphStyle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
<?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\Element;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use PhpOffice\PhpWord\Style\Font;
|
||||
|
||||
/**
|
||||
* Field element.
|
||||
*
|
||||
* @since 0.11.0
|
||||
* @see http://www.schemacentral.com/sc/ooxml/t-w_CT_SimpleField.html
|
||||
*/
|
||||
class Field extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Field properties and options. Depending on type, a field can have different properties
|
||||
* and options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldsArray = [
|
||||
'PAGE' => [
|
||||
'properties' => [
|
||||
'format' => ['Arabic', 'ArabicDash', 'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN'],
|
||||
],
|
||||
'options' => ['PreserveFormat'],
|
||||
],
|
||||
'NUMPAGES' => [
|
||||
'properties' => [
|
||||
'format' => ['Arabic', 'ArabicDash', 'CardText', 'DollarText', 'Ordinal', 'OrdText',
|
||||
'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN', 'Caps', 'FirstCap', 'Lower', 'Upper', ],
|
||||
'numformat' => ['0', '0,00', '#.##0', '#.##0,00', '€ #.##0,00(€ #.##0,00)', '0%', '0,00%'],
|
||||
],
|
||||
'options' => ['PreserveFormat'],
|
||||
],
|
||||
'DATE' => [
|
||||
'properties' => [
|
||||
'dateformat' => [
|
||||
// Generic formats
|
||||
'yyyy-MM-dd', 'yyyy-MM', 'MMM-yy', 'MMM-yyyy', 'h:mm am/pm', 'h:mm:ss am/pm', 'HH:mm', 'HH:mm:ss',
|
||||
// Day-Month-Year formats
|
||||
'dddd d MMMM yyyy', 'd MMMM yyyy', 'd-MMM-yy', 'd MMM. yy',
|
||||
'd-M-yy', 'd-M-yy h:mm', 'd-M-yy h:mm:ss', 'd-M-yy h:mm am/pm', 'd-M-yy h:mm:ss am/pm', 'd-M-yy HH:mm', 'd-M-yy HH:mm:ss',
|
||||
'd/M/yy', 'd/M/yy h:mm', 'd/M/yy h:mm:ss', 'd/M/yy h:mm am/pm', 'd/M/yy h:mm:ss am/pm', 'd/M/yy HH:mm', 'd/M/yy HH:mm:ss',
|
||||
'd-M-yyyy', 'd-M-yyyy h:mm', 'd-M-yyyy h:mm:ss', 'd-M-yyyy h:mm am/pm', 'd-M-yyyy h:mm:ss am/pm', 'd-M-yyyy HH:mm', 'd-M-yyyy HH:mm:ss',
|
||||
'd/M/yyyy', 'd/M/yyyy h:mm', 'd/M/yyyy h:mm:ss', 'd/M/yyyy h:mm am/pm', 'd/M/yyyy h:mm:ss am/pm', 'd/M/yyyy HH:mm', 'd/M/yyyy HH:mm:ss',
|
||||
// Month-Day-Year formats
|
||||
'dddd, MMMM d yyyy', 'MMMM d yyyy', 'MMM-d-yy', 'MMM. d yy',
|
||||
'M-d-yy', 'M-d-yy h:mm', 'M-d-yy h:mm:ss', 'M-d-yy h:mm am/pm', 'M-d-yy h:mm:ss am/pm', 'M-d-yy HH:mm', 'M-d-yy HH:mm:ss',
|
||||
'M/d/yy', 'M/d/yy h:mm', 'M/d/yy h:mm:ss', 'M/d/yy h:mm am/pm', 'M/d/yy h:mm:ss am/pm', 'M/d/yy HH:mm', 'M/d/yy HH:mm:ss',
|
||||
'M-d-yyyy', 'M-d-yyyy h:mm', 'M-d-yyyy h:mm:ss', 'M-d-yyyy h:mm am/pm', 'M-d-yyyy h:mm:ss am/pm', 'M-d-yyyy HH:mm', 'M-d-yyyy HH:mm:ss',
|
||||
'M/d/yyyy', 'M/d/yyyy h:mm', 'M/d/yyyy h:mm:ss', 'M/d/yyyy h:mm am/pm', 'M/d/yyyy h:mm:ss am/pm', 'M/d/yyyy HH:mm', 'M/d/yyyy HH:mm:ss',
|
||||
],
|
||||
],
|
||||
'options' => ['PreserveFormat', 'LunarCalendar', 'SakaEraCalendar', 'LastUsedFormat'],
|
||||
],
|
||||
'MACROBUTTON' => [
|
||||
'properties' => ['macroname' => ''],
|
||||
],
|
||||
'XE' => [
|
||||
'properties' => [],
|
||||
'options' => ['Bold', 'Italic'],
|
||||
],
|
||||
'INDEX' => [
|
||||
'properties' => [],
|
||||
'options' => ['PreserveFormat'],
|
||||
],
|
||||
'STYLEREF' => [
|
||||
'properties' => ['StyleIdentifier' => ''],
|
||||
'options' => ['PreserveFormat'],
|
||||
],
|
||||
'FILENAME' => [
|
||||
'properties' => [
|
||||
'format' => ['Upper', 'Lower', 'FirstCap', 'Caps'],
|
||||
],
|
||||
'options' => ['Path', 'PreserveFormat'],
|
||||
],
|
||||
'REF' => [
|
||||
'properties' => ['name' => ''],
|
||||
'options' => ['f', 'h', 'n', 'p', 'r', 't', 'w'],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Field type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* Field text.
|
||||
*
|
||||
* @var string|TextRun
|
||||
*/
|
||||
protected $text;
|
||||
|
||||
/**
|
||||
* Field properties.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $properties = [];
|
||||
|
||||
/**
|
||||
* Field options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* Font style.
|
||||
*
|
||||
* @var Font|string
|
||||
*/
|
||||
protected $fontStyle;
|
||||
|
||||
/**
|
||||
* Set Font style.
|
||||
*
|
||||
* @param array|Font|string $style
|
||||
*
|
||||
* @return Font|string
|
||||
*/
|
||||
public function setFontStyle($style = null)
|
||||
{
|
||||
if ($style instanceof Font) {
|
||||
$this->fontStyle = $style;
|
||||
} elseif (is_array($style)) {
|
||||
$this->fontStyle = new Font('text');
|
||||
$this->fontStyle->setStyleByArray($style);
|
||||
} elseif (null === $style) {
|
||||
$this->fontStyle = null;
|
||||
} else {
|
||||
$this->fontStyle = $style;
|
||||
}
|
||||
|
||||
return $this->fontStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Font style.
|
||||
*
|
||||
* @return Font|string
|
||||
*/
|
||||
public function getFontStyle()
|
||||
{
|
||||
return $this->fontStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Field Element.
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $properties
|
||||
* @param array $options
|
||||
* @param null|string|TextRun $text
|
||||
* @param array|Font|string $fontStyle
|
||||
*/
|
||||
public function __construct($type = null, $properties = [], $options = [], $text = null, $fontStyle = null)
|
||||
{
|
||||
$this->setType($type);
|
||||
$this->setProperties($properties);
|
||||
$this->setOptions($options);
|
||||
$this->setText($text);
|
||||
$this->setFontStyle($fontStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Field type.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setType($type = null)
|
||||
{
|
||||
if (isset($type)) {
|
||||
if (isset($this->fieldsArray[$type])) {
|
||||
$this->type = $type;
|
||||
} else {
|
||||
throw new InvalidArgumentException("Invalid type '$type'");
|
||||
}
|
||||
}
|
||||
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Field type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Field properties.
|
||||
*
|
||||
* @param array $properties
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setProperties($properties = [])
|
||||
{
|
||||
if (is_array($properties)) {
|
||||
foreach (array_keys($properties) as $propkey) {
|
||||
if (!(isset($this->fieldsArray[$this->type]['properties'][$propkey]))) {
|
||||
throw new InvalidArgumentException("Invalid property '$propkey'");
|
||||
}
|
||||
}
|
||||
$this->properties = array_merge($this->properties, $properties);
|
||||
}
|
||||
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Field properties.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProperties()
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Field options.
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setOptions($options = [])
|
||||
{
|
||||
if (is_array($options)) {
|
||||
foreach (array_keys($options) as $optionkey) {
|
||||
if (!(isset($this->fieldsArray[$this->type]['options'][$optionkey])) && substr($optionkey, 0, 1) !== '\\') {
|
||||
throw new InvalidArgumentException("Invalid option '$optionkey', possible values are " . implode(', ', $this->fieldsArray[$this->type]['options']));
|
||||
}
|
||||
}
|
||||
$this->options = array_merge($this->options, $options);
|
||||
}
|
||||
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Field properties.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Field text.
|
||||
*
|
||||
* @param null|string|TextRun $text
|
||||
*
|
||||
* @return null|string|TextRun
|
||||
*/
|
||||
public function setText($text = null)
|
||||
{
|
||||
if (isset($text)) {
|
||||
if (is_string($text) || $text instanceof TextRun) {
|
||||
$this->text = $text;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid text');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Field text.
|
||||
*
|
||||
* @return string|TextRun
|
||||
*/
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?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\Element;
|
||||
|
||||
/**
|
||||
* Footer element.
|
||||
*/
|
||||
class Footer extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* Header/footer types constants.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @see http://www.datypic.com/sc/ooxml/t-w_ST_HdrFtr.html Header or Footer Type
|
||||
*/
|
||||
const AUTO = 'default'; // default and odd pages
|
||||
const FIRST = 'first';
|
||||
const EVEN = 'even';
|
||||
|
||||
/**
|
||||
* @var string Container type
|
||||
*/
|
||||
protected $container = 'Footer';
|
||||
|
||||
/**
|
||||
* Header type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = self::AUTO;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param int $sectionId
|
||||
* @param int $containerId
|
||||
* @param string $type
|
||||
*/
|
||||
public function __construct($sectionId, $containerId = 1, $type = self::AUTO)
|
||||
{
|
||||
$this->sectionId = $sectionId;
|
||||
$this->setType($type);
|
||||
$this->setDocPart($this->container, ($sectionId - 1) * 3 + $containerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function setType($value = self::AUTO): void
|
||||
{
|
||||
if (!in_array($value, [self::AUTO, self::FIRST, self::EVEN])) {
|
||||
$value = self::AUTO;
|
||||
}
|
||||
$this->type = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset type to default.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function resetType()
|
||||
{
|
||||
return $this->type = self::AUTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* First page only header.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function firstPage()
|
||||
{
|
||||
return $this->type = self::FIRST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Even numbered pages only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function evenPage()
|
||||
{
|
||||
return $this->type = self::EVEN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\Paragraph;
|
||||
|
||||
class Footnote extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* @var string Container type
|
||||
*/
|
||||
protected $container = 'Footnote';
|
||||
|
||||
/**
|
||||
* Paragraph style.
|
||||
*
|
||||
* @var null|Paragraph|string
|
||||
*/
|
||||
protected $paragraphStyle;
|
||||
|
||||
/**
|
||||
* Is part of collection.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $collectionRelation = true;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param array|Paragraph|string $paragraphStyle
|
||||
*/
|
||||
public function __construct($paragraphStyle = null)
|
||||
{
|
||||
$this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle);
|
||||
$this->setDocPart($this->container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get paragraph style.
|
||||
*
|
||||
* @return null|Paragraph|string
|
||||
*/
|
||||
public function getParagraphStyle()
|
||||
{
|
||||
return $this->paragraphStyle;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
<?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\Element;
|
||||
|
||||
/**
|
||||
* Form field element.
|
||||
*
|
||||
* @since 0.12.0
|
||||
* @see http://www.datypic.com/sc/ooxml/t-w_CT_FFData.html
|
||||
*/
|
||||
class FormField extends Text
|
||||
{
|
||||
/**
|
||||
* Form field type: textinput|checkbox|dropdown.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $type = 'textinput';
|
||||
|
||||
/**
|
||||
* Form field name.
|
||||
*
|
||||
* @var ?string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Default value.
|
||||
*
|
||||
* - TextInput: string
|
||||
* - CheckBox: bool
|
||||
* - DropDown: int Index of entries (zero based)
|
||||
*
|
||||
* @var bool|int|string
|
||||
*/
|
||||
private $default;
|
||||
|
||||
/**
|
||||
* Value.
|
||||
*
|
||||
* @var null|bool|int|string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* Dropdown entries.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $entries = [];
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $fontStyle
|
||||
* @param mixed $paragraphStyle
|
||||
*/
|
||||
public function __construct($type, $fontStyle = null, $paragraphStyle = null)
|
||||
{
|
||||
parent::__construct(null, $fontStyle, $paragraphStyle);
|
||||
$this->setType($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setType($value)
|
||||
{
|
||||
$enum = ['textinput', 'checkbox', 'dropdown'];
|
||||
$this->type = $this->setEnumVal($value, $enum, $this->type);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name.
|
||||
*
|
||||
* @param ?string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setName($value)
|
||||
{
|
||||
$this->name = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default.
|
||||
*
|
||||
* @return bool|int|string
|
||||
*/
|
||||
public function getDefault()
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default.
|
||||
*
|
||||
* @param bool|int|string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setDefault($value)
|
||||
{
|
||||
$this->default = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value.
|
||||
*
|
||||
* @return null|bool|int|string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value.
|
||||
*
|
||||
* @param null|bool|int|string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entries.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEntries()
|
||||
{
|
||||
return $this->entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set entries.
|
||||
*
|
||||
* @param array $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setEntries($value)
|
||||
{
|
||||
$this->entries = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpOffice\PhpWord\Element;
|
||||
|
||||
use PhpOffice\Math\Math;
|
||||
|
||||
/**
|
||||
* Formula element.
|
||||
*/
|
||||
class Formula extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* @var Math
|
||||
*/
|
||||
protected $math;
|
||||
|
||||
/**
|
||||
* Create a new Formula Element.
|
||||
*/
|
||||
public function __construct(Math $math)
|
||||
{
|
||||
$this->setMath($math);
|
||||
}
|
||||
|
||||
public function setMath(Math $math): self
|
||||
{
|
||||
$this->math = $math;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMath(): Math
|
||||
{
|
||||
return $this->math;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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\Element;
|
||||
|
||||
/**
|
||||
* Header element.
|
||||
*/
|
||||
class Header extends Footer
|
||||
{
|
||||
/**
|
||||
* @var string Container type
|
||||
*/
|
||||
protected $container = 'Header';
|
||||
|
||||
/**
|
||||
* Add a Watermark Element.
|
||||
*
|
||||
* @param string $src
|
||||
* @param mixed $style
|
||||
*
|
||||
* @return Image
|
||||
*/
|
||||
public function addWatermark($src, $style = null)
|
||||
{
|
||||
return $this->addImage($src, $style, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,601 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Exception\CreateTemporaryFileException;
|
||||
use PhpOffice\PhpWord\Exception\InvalidImageException;
|
||||
use PhpOffice\PhpWord\Exception\UnsupportedImageTypeException;
|
||||
use PhpOffice\PhpWord\Settings;
|
||||
use PhpOffice\PhpWord\Shared\ZipArchive;
|
||||
use PhpOffice\PhpWord\Style\Image as ImageStyle;
|
||||
|
||||
/**
|
||||
* Image element.
|
||||
*/
|
||||
class Image extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Image source type constants.
|
||||
*/
|
||||
const SOURCE_LOCAL = 'local'; // Local images
|
||||
const SOURCE_GD = 'gd'; // Generated using GD
|
||||
const SOURCE_ARCHIVE = 'archive'; // Image in archives zip://$archive#$image
|
||||
const SOURCE_STRING = 'string'; // Image from string
|
||||
|
||||
/**
|
||||
* Image source.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $source;
|
||||
|
||||
/**
|
||||
* Source type: local|gd|archive.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $sourceType;
|
||||
|
||||
/**
|
||||
* Image style.
|
||||
*
|
||||
* @var ?ImageStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Is watermark.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $watermark;
|
||||
|
||||
/**
|
||||
* Name of image.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Image type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $imageType;
|
||||
|
||||
/**
|
||||
* Image create function.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $imageCreateFunc;
|
||||
|
||||
/**
|
||||
* Image function.
|
||||
*
|
||||
* @var null|callable(resource): void
|
||||
*/
|
||||
private $imageFunc;
|
||||
|
||||
/**
|
||||
* Image extension.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $imageExtension;
|
||||
|
||||
/**
|
||||
* Image quality.
|
||||
*
|
||||
* Functions imagepng() and imagejpeg() have an optional parameter for
|
||||
* quality.
|
||||
*
|
||||
* @var null|int
|
||||
*/
|
||||
private $imageQuality;
|
||||
|
||||
/**
|
||||
* Is memory image.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $memoryImage;
|
||||
|
||||
/**
|
||||
* Image target file name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $target;
|
||||
|
||||
/**
|
||||
* Image media index.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $mediaIndex;
|
||||
|
||||
/**
|
||||
* Has media relation flag; true for Link, Image, and Object.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $mediaRelation = true;
|
||||
|
||||
/**
|
||||
* Create new image element.
|
||||
*
|
||||
* @param string $source
|
||||
* @param mixed $style
|
||||
* @param bool $watermark
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct($source, $style = null, $watermark = false, $name = null)
|
||||
{
|
||||
$this->source = $source;
|
||||
$this->style = $this->setNewStyle(new ImageStyle(), $style, true);
|
||||
$this->setIsWatermark($watermark);
|
||||
$this->setName($name);
|
||||
|
||||
$this->checkImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Image style.
|
||||
*
|
||||
* @return ?ImageStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image source.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image source type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSourceType()
|
||||
{
|
||||
return $this->sourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the image name.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function setName($value): void
|
||||
{
|
||||
$this->name = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image name.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image media ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMediaId()
|
||||
{
|
||||
return md5($this->source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get is watermark.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isWatermark()
|
||||
{
|
||||
return $this->watermark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set is watermark.
|
||||
*
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setIsWatermark($value): void
|
||||
{
|
||||
$this->watermark = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getImageType()
|
||||
{
|
||||
return $this->imageType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image create function.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getImageCreateFunction()
|
||||
{
|
||||
return $this->imageCreateFunc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image function.
|
||||
*
|
||||
* @return null|callable(resource): void
|
||||
*/
|
||||
public function getImageFunction(): ?callable
|
||||
{
|
||||
return $this->imageFunc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image quality.
|
||||
*/
|
||||
public function getImageQuality(): ?int
|
||||
{
|
||||
return $this->imageQuality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image extension.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getImageExtension()
|
||||
{
|
||||
return $this->imageExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get is memory image.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMemImage()
|
||||
{
|
||||
return $this->memoryImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get target file name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTarget()
|
||||
{
|
||||
return $this->target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set target file name.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function setTarget($value): void
|
||||
{
|
||||
$this->target = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get media index.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getMediaIndex()
|
||||
{
|
||||
return $this->mediaIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set media index.
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setMediaIndex($value): void
|
||||
{
|
||||
$this->mediaIndex = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image string.
|
||||
*/
|
||||
public function getImageString(): ?string
|
||||
{
|
||||
$source = $this->source;
|
||||
$actualSource = null;
|
||||
$imageBinary = null;
|
||||
$isTemp = false;
|
||||
|
||||
// Get actual source from archive image or other source
|
||||
// Return null if not found
|
||||
if ($this->sourceType == self::SOURCE_ARCHIVE) {
|
||||
$source = substr($source, 6);
|
||||
[$zipFilename, $imageFilename] = explode('#', $source);
|
||||
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($zipFilename) !== false) {
|
||||
if ($zip->locateName($imageFilename) !== false) {
|
||||
$isTemp = true;
|
||||
$zip->extractTo(Settings::getTempDir(), $imageFilename);
|
||||
$actualSource = Settings::getTempDir() . DIRECTORY_SEPARATOR . $imageFilename;
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
} else {
|
||||
$actualSource = $source;
|
||||
}
|
||||
|
||||
// Can't find any case where $actualSource = null hasn't captured by
|
||||
// preceding exceptions. Please uncomment when you find the case and
|
||||
// put the case into Element\ImageTest.
|
||||
// if ($actualSource === null) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// Read image binary data and convert to hex/base64 string
|
||||
if ($this->sourceType == self::SOURCE_GD) {
|
||||
$imageResource = call_user_func($this->imageCreateFunc, $actualSource);
|
||||
if ($this->imageType === 'image/png') {
|
||||
// PNG images need to preserve alpha channel information
|
||||
imagesavealpha($imageResource, true);
|
||||
}
|
||||
ob_start();
|
||||
$callback = $this->imageFunc;
|
||||
$callback($imageResource);
|
||||
$imageBinary = ob_get_contents();
|
||||
ob_end_clean();
|
||||
} elseif ($this->sourceType == self::SOURCE_STRING) {
|
||||
$imageBinary = $this->source;
|
||||
} else {
|
||||
$fileHandle = fopen($actualSource, 'rb', false);
|
||||
$fileSize = filesize($actualSource);
|
||||
if ($fileHandle !== false && $fileSize > 0) {
|
||||
$imageBinary = fread($fileHandle, $fileSize);
|
||||
fclose($fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete temporary file if necessary
|
||||
if ($isTemp === true) {
|
||||
@unlink($actualSource);
|
||||
}
|
||||
|
||||
return $imageBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image string data.
|
||||
*
|
||||
* @param bool $base64
|
||||
*
|
||||
* @return null|string
|
||||
*
|
||||
* @since 0.11.0
|
||||
*/
|
||||
public function getImageStringData($base64 = false)
|
||||
{
|
||||
$imageBinary = $this->getImageString();
|
||||
if ($imageBinary === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($base64) {
|
||||
return base64_encode($imageBinary);
|
||||
}
|
||||
|
||||
return bin2hex($imageBinary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check memory image, supported type, image functions, and proportional width/height.
|
||||
*/
|
||||
private function checkImage(): void
|
||||
{
|
||||
$this->setSourceType();
|
||||
|
||||
// Check image data
|
||||
if ($this->sourceType == self::SOURCE_ARCHIVE) {
|
||||
$imageData = $this->getArchiveImageSize($this->source);
|
||||
} elseif ($this->sourceType == self::SOURCE_STRING) {
|
||||
$imageData = @getimagesizefromstring($this->source);
|
||||
} else {
|
||||
$imageData = @getimagesize($this->source);
|
||||
}
|
||||
if (!is_array($imageData)) {
|
||||
throw new InvalidImageException(sprintf('Invalid image: %s', $this->source));
|
||||
}
|
||||
[$actualWidth, $actualHeight, $imageType] = $imageData;
|
||||
|
||||
// Check image type support
|
||||
$supportedTypes = [IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG];
|
||||
if ($this->sourceType != self::SOURCE_GD && $this->sourceType != self::SOURCE_STRING) {
|
||||
$supportedTypes = array_merge($supportedTypes, [IMAGETYPE_BMP, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM]);
|
||||
}
|
||||
if (!in_array($imageType, $supportedTypes)) {
|
||||
throw new UnsupportedImageTypeException();
|
||||
}
|
||||
|
||||
// Define image functions
|
||||
$this->imageType = image_type_to_mime_type($imageType);
|
||||
$this->setFunctions();
|
||||
$this->setProportionalSize($actualWidth, $actualHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source type.
|
||||
*/
|
||||
private function setSourceType(): void
|
||||
{
|
||||
if (stripos(strrev($this->source), strrev('.php')) === 0) {
|
||||
$this->memoryImage = true;
|
||||
$this->sourceType = self::SOURCE_GD;
|
||||
} elseif (strpos($this->source, 'zip://') !== false) {
|
||||
$this->memoryImage = false;
|
||||
$this->sourceType = self::SOURCE_ARCHIVE;
|
||||
} elseif (filter_var($this->source, FILTER_VALIDATE_URL) !== false) {
|
||||
$this->memoryImage = true;
|
||||
if (strpos($this->source, 'https') === 0) {
|
||||
$fileContent = file_get_contents($this->source);
|
||||
$this->source = $fileContent;
|
||||
$this->sourceType = self::SOURCE_STRING;
|
||||
} else {
|
||||
$this->sourceType = self::SOURCE_GD;
|
||||
}
|
||||
} elseif ((strpos($this->source, chr(0)) === false) && @file_exists($this->source)) {
|
||||
$this->memoryImage = false;
|
||||
$this->sourceType = self::SOURCE_LOCAL;
|
||||
} else {
|
||||
$this->memoryImage = true;
|
||||
$this->sourceType = self::SOURCE_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image size from archive.
|
||||
*
|
||||
* @since 0.12.0 Throws CreateTemporaryFileException.
|
||||
*
|
||||
* @param string $source
|
||||
*
|
||||
* @return null|array
|
||||
*/
|
||||
private function getArchiveImageSize($source)
|
||||
{
|
||||
$imageData = null;
|
||||
$source = substr($source, 6);
|
||||
[$zipFilename, $imageFilename] = explode('#', $source);
|
||||
|
||||
$tempFilename = tempnam(Settings::getTempDir(), 'PHPWordImage');
|
||||
if (false === $tempFilename) {
|
||||
throw new CreateTemporaryFileException(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($zipFilename) !== false) {
|
||||
if ($zip->locateName($imageFilename) !== false) {
|
||||
$imageContent = $zip->getFromName($imageFilename);
|
||||
if ($imageContent !== false) {
|
||||
file_put_contents($tempFilename, $imageContent);
|
||||
$imageData = getimagesize($tempFilename);
|
||||
unlink($tempFilename);
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
return $imageData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set image functions and extensions.
|
||||
*/
|
||||
private function setFunctions(): void
|
||||
{
|
||||
switch ($this->imageType) {
|
||||
case 'image/png':
|
||||
$this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefrompng';
|
||||
$this->imageFunc = function ($resource): void {
|
||||
imagepng($resource, null, $this->imageQuality);
|
||||
};
|
||||
$this->imageExtension = 'png';
|
||||
$this->imageQuality = -1;
|
||||
|
||||
break;
|
||||
case 'image/gif':
|
||||
$this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromgif';
|
||||
$this->imageFunc = function ($resource): void {
|
||||
imagegif($resource);
|
||||
};
|
||||
$this->imageExtension = 'gif';
|
||||
$this->imageQuality = null;
|
||||
|
||||
break;
|
||||
case 'image/jpeg':
|
||||
case 'image/jpg':
|
||||
$this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromjpeg';
|
||||
$this->imageFunc = function ($resource): void {
|
||||
imagejpeg($resource, null, $this->imageQuality);
|
||||
};
|
||||
$this->imageExtension = 'jpg';
|
||||
$this->imageQuality = 100;
|
||||
|
||||
break;
|
||||
case 'image/bmp':
|
||||
case 'image/x-ms-bmp':
|
||||
$this->imageType = 'image/bmp';
|
||||
$this->imageFunc = null;
|
||||
$this->imageExtension = 'bmp';
|
||||
$this->imageQuality = null;
|
||||
|
||||
break;
|
||||
case 'image/tiff':
|
||||
$this->imageType = 'image/tiff';
|
||||
$this->imageFunc = null;
|
||||
$this->imageExtension = 'tif';
|
||||
$this->imageQuality = null;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set proportional width/height if one dimension not available.
|
||||
*
|
||||
* @param int $actualWidth
|
||||
* @param int $actualHeight
|
||||
*/
|
||||
private function setProportionalSize($actualWidth, $actualHeight): void
|
||||
{
|
||||
$styleWidth = $this->style->getWidth();
|
||||
$styleHeight = $this->style->getHeight();
|
||||
if (!($styleWidth && $styleHeight)) {
|
||||
if ($styleWidth == null && $styleHeight == null) {
|
||||
$this->style->setWidth($actualWidth);
|
||||
$this->style->setHeight($actualHeight);
|
||||
} elseif ($styleWidth) {
|
||||
$this->style->setHeight($actualHeight * ($styleWidth / $actualWidth));
|
||||
} else {
|
||||
$this->style->setWidth($actualWidth * ($styleHeight / $actualHeight));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\Line as LineStyle;
|
||||
|
||||
/**
|
||||
* Line element.
|
||||
*/
|
||||
class Line extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Line style.
|
||||
*
|
||||
* @var ?LineStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Create new line element.
|
||||
*
|
||||
* @param mixed $style
|
||||
*/
|
||||
public function __construct($style = null)
|
||||
{
|
||||
$this->style = $this->setNewStyle(new LineStyle(), $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get line style.
|
||||
*
|
||||
* @return ?LineStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Shared\Text as SharedText;
|
||||
use PhpOffice\PhpWord\Style\Font;
|
||||
use PhpOffice\PhpWord\Style\Paragraph;
|
||||
|
||||
/**
|
||||
* Link element.
|
||||
*/
|
||||
class Link extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Link source.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $source;
|
||||
|
||||
/**
|
||||
* Link text.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $text;
|
||||
|
||||
/**
|
||||
* Font style.
|
||||
*
|
||||
* @var null|Font|string
|
||||
*/
|
||||
private $fontStyle;
|
||||
|
||||
/**
|
||||
* Paragraph style.
|
||||
*
|
||||
* @var null|Paragraph|string
|
||||
*/
|
||||
private $paragraphStyle;
|
||||
|
||||
/**
|
||||
* Has media relation flag; true for Link, Image, and Object.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $mediaRelation = true;
|
||||
|
||||
/**
|
||||
* Has internal flag - anchor to internal bookmark.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $internal = false;
|
||||
|
||||
/**
|
||||
* Create a new Link Element.
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $text
|
||||
* @param mixed $fontStyle
|
||||
* @param mixed $paragraphStyle
|
||||
* @param bool $internal
|
||||
*/
|
||||
public function __construct($source, $text = null, $fontStyle = null, $paragraphStyle = null, $internal = false)
|
||||
{
|
||||
$this->source = SharedText::toUTF8($source);
|
||||
$this->text = null === $text ? $this->source : SharedText::toUTF8($text);
|
||||
$this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle);
|
||||
$this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle);
|
||||
$this->internal = $internal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get link source.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get link text.
|
||||
*/
|
||||
public function getText(): string
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Text style.
|
||||
*
|
||||
* @return null|Font|string
|
||||
*/
|
||||
public function getFontStyle()
|
||||
{
|
||||
return $this->fontStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Paragraph style.
|
||||
*
|
||||
* @return null|Paragraph|string
|
||||
*/
|
||||
public function getParagraphStyle()
|
||||
{
|
||||
return $this->paragraphStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* is internal.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInternal()
|
||||
{
|
||||
return $this->internal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Shared\Text as SharedText;
|
||||
use PhpOffice\PhpWord\Style\ListItem as ListItemStyle;
|
||||
|
||||
/**
|
||||
* List item element.
|
||||
*/
|
||||
class ListItem extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Element style.
|
||||
*
|
||||
* @var ?ListItemStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Text object.
|
||||
*
|
||||
* @var Text
|
||||
*/
|
||||
private $textObject;
|
||||
|
||||
/**
|
||||
* Depth.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $depth;
|
||||
|
||||
/**
|
||||
* Create a new ListItem.
|
||||
*
|
||||
* @param string $text
|
||||
* @param int $depth
|
||||
* @param mixed $fontStyle
|
||||
* @param null|array|string $listStyle
|
||||
* @param mixed $paragraphStyle
|
||||
*/
|
||||
public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = null, $paragraphStyle = null)
|
||||
{
|
||||
$this->textObject = new Text(SharedText::toUTF8($text), $fontStyle, $paragraphStyle);
|
||||
$this->depth = $depth;
|
||||
|
||||
// Version >= 0.10.0 will pass numbering style name. Older version will use old method
|
||||
if (null !== $listStyle && is_string($listStyle)) {
|
||||
$this->style = new ListItemStyle($listStyle); // @codeCoverageIgnore
|
||||
} else {
|
||||
$this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get style.
|
||||
*
|
||||
* @return ?ListItemStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Text object.
|
||||
*
|
||||
* @return Text
|
||||
*/
|
||||
public function getTextObject()
|
||||
{
|
||||
return $this->textObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get depth.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDepth()
|
||||
{
|
||||
return $this->depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get text.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 0.11.0
|
||||
*/
|
||||
public function getText()
|
||||
{
|
||||
return $this->textObject->getText();
|
||||
}
|
||||
}
|
||||
@@ -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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\ListItem as ListItemStyle;
|
||||
|
||||
/**
|
||||
* List item element.
|
||||
*/
|
||||
class ListItemRun extends TextRun
|
||||
{
|
||||
/**
|
||||
* @var string Container type
|
||||
*/
|
||||
protected $container = 'ListItemRun';
|
||||
|
||||
/**
|
||||
* ListItem Style.
|
||||
*
|
||||
* @var ?ListItemStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* ListItem Depth.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $depth;
|
||||
|
||||
/**
|
||||
* Create a new ListItem.
|
||||
*
|
||||
* @param int $depth
|
||||
* @param null|array|string $listStyle
|
||||
* @param mixed $paragraphStyle
|
||||
*/
|
||||
public function __construct($depth = 0, $listStyle = null, $paragraphStyle = null)
|
||||
{
|
||||
$this->depth = $depth;
|
||||
|
||||
// Version >= 0.10.0 will pass numbering style name. Older version will use old method
|
||||
if (null !== $listStyle && is_string($listStyle)) {
|
||||
$this->style = new ListItemStyle($listStyle);
|
||||
} else {
|
||||
$this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true);
|
||||
}
|
||||
parent::__construct($paragraphStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ListItem style.
|
||||
*
|
||||
* @return ?ListItemStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ListItem depth.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDepth()
|
||||
{
|
||||
return $this->depth;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Exception\InvalidObjectException;
|
||||
use PhpOffice\PhpWord\Style\Image as ImageStyle;
|
||||
|
||||
/**
|
||||
* OLEObject element.
|
||||
*/
|
||||
class OLEObject extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Ole-Object Src.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $source;
|
||||
|
||||
/**
|
||||
* Image Style.
|
||||
*
|
||||
* @var ?ImageStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Icon.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $icon;
|
||||
|
||||
/**
|
||||
* Image Relation ID.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $imageRelationId;
|
||||
|
||||
/**
|
||||
* Has media relation flag; true for Link, Image, and Object.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $mediaRelation = true;
|
||||
|
||||
/**
|
||||
* Create a new Ole-Object Element.
|
||||
*
|
||||
* @param string $source
|
||||
* @param mixed $style
|
||||
*/
|
||||
public function __construct($source, $style = null)
|
||||
{
|
||||
$supportedTypes = ['xls', 'doc', 'ppt', 'xlsx', 'docx', 'pptx'];
|
||||
$pathInfo = pathinfo($source);
|
||||
|
||||
if (file_exists($source) && in_array($pathInfo['extension'], $supportedTypes)) {
|
||||
$ext = $pathInfo['extension'];
|
||||
if (strlen($ext) == 4 && strtolower(substr($ext, -1)) == 'x') {
|
||||
$ext = substr($ext, 0, -1);
|
||||
}
|
||||
|
||||
$this->source = $source;
|
||||
$this->style = $this->setNewStyle(new ImageStyle(), $style, true);
|
||||
$this->icon = realpath(__DIR__ . "/../resources/{$ext}.png");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidObjectException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object source.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object style.
|
||||
*
|
||||
* @return ?ImageStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object icon.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIcon()
|
||||
{
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image relation ID.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getImageRelationId()
|
||||
{
|
||||
return $this->imageRelationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Image Relation ID.
|
||||
*
|
||||
* @param int $rId
|
||||
*/
|
||||
public function setImageRelationId($rId): void
|
||||
{
|
||||
$this->imageRelationId = $rId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Element;
|
||||
|
||||
/**
|
||||
* Page break element.
|
||||
*/
|
||||
class PageBreak extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Create new page break.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Shared\Text as SharedText;
|
||||
use PhpOffice\PhpWord\Style\Font;
|
||||
use PhpOffice\PhpWord\Style\Paragraph;
|
||||
|
||||
/**
|
||||
* Preserve text/field element.
|
||||
*/
|
||||
class PreserveText extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Text content.
|
||||
*
|
||||
* @var null|array|string
|
||||
*/
|
||||
private $text;
|
||||
|
||||
/**
|
||||
* Text style.
|
||||
*
|
||||
* @var null|Font|string
|
||||
*/
|
||||
private $fontStyle;
|
||||
|
||||
/**
|
||||
* Paragraph style.
|
||||
*
|
||||
* @var null|Paragraph|string
|
||||
*/
|
||||
private $paragraphStyle;
|
||||
|
||||
/**
|
||||
* Create a new Preserve Text Element.
|
||||
*
|
||||
* @param string $text
|
||||
* @param mixed $fontStyle
|
||||
* @param mixed $paragraphStyle
|
||||
*/
|
||||
public function __construct($text = null, $fontStyle = null, $paragraphStyle = null)
|
||||
{
|
||||
$this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle);
|
||||
$this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle);
|
||||
|
||||
$this->text = SharedText::toUTF8($text);
|
||||
$matches = preg_split('/({.*?})/', $this->text ?? '', -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
|
||||
if (isset($matches[0])) {
|
||||
$this->text = $matches;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Text style.
|
||||
*
|
||||
* @return null|Font|string
|
||||
*/
|
||||
public function getFontStyle()
|
||||
{
|
||||
return $this->fontStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Paragraph style.
|
||||
*
|
||||
* @return null|Paragraph|string
|
||||
*/
|
||||
public function getParagraphStyle()
|
||||
{
|
||||
return $this->paragraphStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Text content.
|
||||
*
|
||||
* @return null|array|string
|
||||
*/
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\Row as RowStyle;
|
||||
|
||||
/**
|
||||
* Table row element.
|
||||
*
|
||||
* @since 0.8.0
|
||||
*/
|
||||
class Row extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Row height.
|
||||
*
|
||||
* @var ?int
|
||||
*/
|
||||
private $height;
|
||||
|
||||
/**
|
||||
* Row style.
|
||||
*
|
||||
* @var ?RowStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Row cells.
|
||||
*
|
||||
* @var Cell[]
|
||||
*/
|
||||
private $cells = [];
|
||||
|
||||
/**
|
||||
* Create a new table row.
|
||||
*
|
||||
* @param int $height
|
||||
* @param mixed $style
|
||||
*/
|
||||
public function __construct($height = null, $style = null)
|
||||
{
|
||||
$this->height = $height;
|
||||
$this->style = $this->setNewStyle(new RowStyle(), $style, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a cell.
|
||||
*
|
||||
* @param int $width
|
||||
* @param mixed $style
|
||||
*
|
||||
* @return Cell
|
||||
*/
|
||||
public function addCell($width = null, $style = null)
|
||||
{
|
||||
$cell = new Cell($width, $style);
|
||||
$cell->setParentContainer($this);
|
||||
$this->cells[] = $cell;
|
||||
|
||||
return $cell;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cells.
|
||||
*
|
||||
* @return Cell[]
|
||||
*/
|
||||
public function getCells()
|
||||
{
|
||||
return $this->cells;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get row style.
|
||||
*
|
||||
* @return ?RowStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get row height.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getHeight()
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\ComplexType\RubyProperties;
|
||||
|
||||
/**
|
||||
* Ruby element.
|
||||
*
|
||||
* @see https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.ruby?view=openxml-3.0.1
|
||||
*/
|
||||
class Ruby extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Ruby properties.
|
||||
*
|
||||
* @var RubyProperties
|
||||
*/
|
||||
protected $properties;
|
||||
|
||||
/**
|
||||
* Ruby text run.
|
||||
*
|
||||
* @var TextRun
|
||||
*/
|
||||
protected $rubyTextRun;
|
||||
|
||||
/**
|
||||
* Ruby base text run.
|
||||
*
|
||||
* @var TextRun
|
||||
*/
|
||||
protected $baseTextRun;
|
||||
|
||||
/**
|
||||
* Create a new Ruby Element.
|
||||
*/
|
||||
public function __construct(TextRun $baseTextRun, TextRun $rubyTextRun, RubyProperties $properties)
|
||||
{
|
||||
$this->baseTextRun = $baseTextRun;
|
||||
$this->rubyTextRun = $rubyTextRun;
|
||||
$this->properties = $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base text run.
|
||||
*/
|
||||
public function getBaseTextRun(): TextRun
|
||||
{
|
||||
return $this->baseTextRun;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base text run.
|
||||
*/
|
||||
public function setBaseTextRun(TextRun $textRun): self
|
||||
{
|
||||
$this->baseTextRun = $textRun;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ruby text run.
|
||||
*/
|
||||
public function getRubyTextRun(): TextRun
|
||||
{
|
||||
return $this->rubyTextRun;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ruby text run.
|
||||
*/
|
||||
public function setRubyTextRun(TextRun $textRun): self
|
||||
{
|
||||
$this->rubyTextRun = $textRun;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ruby properties.
|
||||
*/
|
||||
public function getProperties(): RubyProperties
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ruby properties.
|
||||
*/
|
||||
public function setProperties(RubyProperties $properties): self
|
||||
{
|
||||
$this->properties = $properties;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
<?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\Element;
|
||||
|
||||
/**
|
||||
* Structured document tag (SDT) element.
|
||||
*
|
||||
* @since 0.12.0
|
||||
*/
|
||||
class SDT extends Text
|
||||
{
|
||||
/**
|
||||
* Form field type: comboBox|dropDownList|date.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* Value.
|
||||
*
|
||||
* @var null|bool|int|string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* CheckBox/DropDown list entries.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $listItems = [];
|
||||
|
||||
/**
|
||||
* Alias.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $alias;
|
||||
|
||||
/**
|
||||
* Tag.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $tag;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $fontStyle
|
||||
* @param mixed $paragraphStyle
|
||||
*/
|
||||
public function __construct($type, $fontStyle = null, $paragraphStyle = null)
|
||||
{
|
||||
parent::__construct(null, $fontStyle, $paragraphStyle);
|
||||
$this->setType($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setType($value)
|
||||
{
|
||||
$enum = ['plainText', 'comboBox', 'dropDownList', 'date'];
|
||||
$this->type = $this->setEnumVal($value, $enum, 'comboBox');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value.
|
||||
*
|
||||
* @return null|bool|int|string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value.
|
||||
*
|
||||
* @param null|bool|int|string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get listItems.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getListItems()
|
||||
{
|
||||
return $this->listItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set listItems.
|
||||
*
|
||||
* @param array $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setListItems($value)
|
||||
{
|
||||
$this->listItems = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tag.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTag()
|
||||
{
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set tag.
|
||||
*
|
||||
* @param string $tag
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setTag($tag)
|
||||
{
|
||||
$this->tag = $tag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alias.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAlias()
|
||||
{
|
||||
return $this->alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set alias.
|
||||
*
|
||||
* @param string $alias
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setAlias($alias)
|
||||
{
|
||||
$this->alias = $alias;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
<?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\Element;
|
||||
|
||||
use Exception;
|
||||
use PhpOffice\PhpWord\ComplexType\FootnoteProperties;
|
||||
use PhpOffice\PhpWord\Style\Section as SectionStyle;
|
||||
|
||||
class Section extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* @var string Container type
|
||||
*/
|
||||
protected $container = 'Section';
|
||||
|
||||
/**
|
||||
* Section style.
|
||||
*
|
||||
* @var ?SectionStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Section headers, indexed from 1, not zero.
|
||||
*
|
||||
* @var Header[]
|
||||
*/
|
||||
private $headers = [];
|
||||
|
||||
/**
|
||||
* Section footers, indexed from 1, not zero.
|
||||
*
|
||||
* @var Footer[]
|
||||
*/
|
||||
private $footers = [];
|
||||
|
||||
/**
|
||||
* The properties for the footnote of this section.
|
||||
*
|
||||
* @var FootnoteProperties
|
||||
*/
|
||||
private $footnoteProperties;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param int $sectionCount
|
||||
* @param null|array|\PhpOffice\PhpWord\Style|string $style
|
||||
*/
|
||||
public function __construct($sectionCount, $style = null)
|
||||
{
|
||||
$this->sectionId = $sectionCount;
|
||||
$this->setDocPart($this->container, $this->sectionId);
|
||||
if (null === $style) {
|
||||
$style = new SectionStyle();
|
||||
}
|
||||
$this->style = $this->setNewStyle(new SectionStyle(), $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set section style.
|
||||
*
|
||||
* @param array $style
|
||||
*/
|
||||
public function setStyle($style = null): void
|
||||
{
|
||||
if (null !== $style && is_array($style)) {
|
||||
$this->style->setStyleByArray($style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get section style.
|
||||
*
|
||||
* @return ?SectionStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add header.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return Header
|
||||
*/
|
||||
public function addHeader($type = Header::AUTO)
|
||||
{
|
||||
return $this->addHeaderFooter($type, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add footer.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return Footer
|
||||
*/
|
||||
public function addFooter($type = Header::AUTO)
|
||||
{
|
||||
return $this->addHeaderFooter($type, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get header elements.
|
||||
*
|
||||
* @return Header[]
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get footer elements.
|
||||
*
|
||||
* @return Footer[]
|
||||
*/
|
||||
public function getFooters()
|
||||
{
|
||||
return $this->footers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the footnote properties.
|
||||
*
|
||||
* @return FootnoteProperties
|
||||
*/
|
||||
public function getFootnoteProperties()
|
||||
{
|
||||
return $this->footnoteProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the footnote properties.
|
||||
*/
|
||||
public function setFootnoteProperties(?FootnoteProperties $footnoteProperties = null): void
|
||||
{
|
||||
$this->footnoteProperties = $footnoteProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a header for this section that is for the first page only?
|
||||
*
|
||||
* If any of the Header instances have a type of Header::FIRST then this method returns true.
|
||||
* False otherwise.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDifferentFirstPage()
|
||||
{
|
||||
foreach ($this->headers as $header) {
|
||||
if ($header->getType() == Header::FIRST) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
foreach ($this->footers as $footer) {
|
||||
if ($footer->getType() == Header::FIRST) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add header/footer.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @param string $type
|
||||
* @param bool $header
|
||||
*
|
||||
* @return Footer|Header
|
||||
*/
|
||||
private function addHeaderFooter($type = Header::AUTO, $header = true)
|
||||
{
|
||||
$containerClass = substr(static::class, 0, strrpos(static::class, '\\') ?: 0) . '\\' .
|
||||
($header ? 'Header' : 'Footer');
|
||||
$collectionArray = $header ? 'headers' : 'footers';
|
||||
$collection = &$this->$collectionArray;
|
||||
|
||||
if (in_array($type, [Header::AUTO, Header::FIRST, Header::EVEN])) {
|
||||
$index = count($collection);
|
||||
/** @var AbstractContainer $container Type hint */
|
||||
$container = new $containerClass($this->sectionId, ++$index, $type);
|
||||
$container->setPhpWord($this->phpWord);
|
||||
|
||||
$collection[$index] = $container;
|
||||
|
||||
return $container;
|
||||
}
|
||||
|
||||
throw new Exception('Invalid header/footer type.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\Shape as ShapeStyle;
|
||||
|
||||
/**
|
||||
* Shape element.
|
||||
*
|
||||
* @since 0.12.0
|
||||
*/
|
||||
class Shape extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Shape type arc|curve|line|polyline|rect|oval.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* Shape style.
|
||||
*
|
||||
* @var ?ShapeStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $style
|
||||
*/
|
||||
public function __construct($type, $style = null)
|
||||
{
|
||||
$this->setType($type);
|
||||
$this->style = $this->setNewStyle(new ShapeStyle(), $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set pattern.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setType($value = null)
|
||||
{
|
||||
$enum = ['arc', 'curve', 'line', 'polyline', 'rect', 'oval'];
|
||||
$this->type = $this->setEnumVal($value, $enum, null);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shape style.
|
||||
*
|
||||
* @return ?ShapeStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Style\Font;
|
||||
use PhpOffice\PhpWord\Style\TOC as TOCStyle;
|
||||
|
||||
/**
|
||||
* Table of contents.
|
||||
*/
|
||||
class TOC extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* TOC style.
|
||||
*
|
||||
* @var TOCStyle
|
||||
*/
|
||||
private $tocStyle;
|
||||
|
||||
/**
|
||||
* Font style.
|
||||
*
|
||||
* @var Font|string
|
||||
*/
|
||||
private $fontStyle;
|
||||
|
||||
/**
|
||||
* Min title depth to show.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $minDepth = 1;
|
||||
|
||||
/**
|
||||
* Max title depth to show.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $maxDepth = 9;
|
||||
|
||||
/**
|
||||
* Create a new Table-of-Contents Element.
|
||||
*
|
||||
* @param mixed $fontStyle
|
||||
* @param array $tocStyle
|
||||
* @param int $minDepth
|
||||
* @param int $maxDepth
|
||||
*/
|
||||
public function __construct($fontStyle = null, $tocStyle = null, $minDepth = 1, $maxDepth = 9)
|
||||
{
|
||||
$this->tocStyle = new TOCStyle();
|
||||
|
||||
if (null !== $tocStyle && is_array($tocStyle)) {
|
||||
$this->tocStyle->setStyleByArray($tocStyle);
|
||||
}
|
||||
|
||||
if (null !== $fontStyle && is_array($fontStyle)) {
|
||||
$this->fontStyle = new Font();
|
||||
$this->fontStyle->setStyleByArray($fontStyle);
|
||||
} else {
|
||||
$this->fontStyle = $fontStyle;
|
||||
}
|
||||
|
||||
$this->minDepth = $minDepth;
|
||||
$this->maxDepth = $maxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all titles.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTitles()
|
||||
{
|
||||
if (!$this->phpWord instanceof PhpWord) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$titles = $this->phpWord->getTitles()->getItems();
|
||||
foreach ($titles as $i => $title) {
|
||||
/** @var Title $title Type hint */
|
||||
$depth = $title->getDepth();
|
||||
if ($this->minDepth > $depth) {
|
||||
unset($titles[$i]);
|
||||
}
|
||||
if (($this->maxDepth != 0) && ($this->maxDepth < $depth)) {
|
||||
unset($titles[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
return $titles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TOC Style.
|
||||
*
|
||||
* @return TOCStyle
|
||||
*/
|
||||
public function getStyleTOC()
|
||||
{
|
||||
return $this->tocStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Font Style.
|
||||
*
|
||||
* @return Font|string
|
||||
*/
|
||||
public function getStyleFont()
|
||||
{
|
||||
return $this->fontStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set max depth.
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setMaxDepth($value): void
|
||||
{
|
||||
$this->maxDepth = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Max Depth.
|
||||
*
|
||||
* @return int Max depth of titles
|
||||
*/
|
||||
public function getMaxDepth()
|
||||
{
|
||||
return $this->maxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set min depth.
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setMinDepth($value): void
|
||||
{
|
||||
$this->minDepth = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Min Depth.
|
||||
*
|
||||
* @return int Min depth of titles
|
||||
*/
|
||||
public function getMinDepth()
|
||||
{
|
||||
return $this->minDepth;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\Table as TableStyle;
|
||||
|
||||
/**
|
||||
* Table element.
|
||||
*/
|
||||
class Table extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Table style.
|
||||
*
|
||||
* @var ?TableStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Table rows.
|
||||
*
|
||||
* @var Row[]
|
||||
*/
|
||||
private $rows = [];
|
||||
|
||||
/**
|
||||
* Table width.
|
||||
*
|
||||
* @var ?int
|
||||
*/
|
||||
private $width;
|
||||
|
||||
/**
|
||||
* Create a new table.
|
||||
*
|
||||
* @param mixed $style
|
||||
*/
|
||||
public function __construct($style = null)
|
||||
{
|
||||
$this->style = $this->setNewStyle(new TableStyle(), $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a row.
|
||||
*
|
||||
* @param int $height
|
||||
* @param mixed $style
|
||||
*
|
||||
* @return Row
|
||||
*/
|
||||
public function addRow($height = null, $style = null)
|
||||
{
|
||||
$row = new Row($height, $style);
|
||||
$row->setParentContainer($this);
|
||||
$this->rows[] = $row;
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a cell.
|
||||
*
|
||||
* @param int $width
|
||||
* @param mixed $style
|
||||
*
|
||||
* @return Cell
|
||||
*/
|
||||
public function addCell($width = null, $style = null)
|
||||
{
|
||||
$index = count($this->rows) - 1;
|
||||
$row = $this->rows[$index];
|
||||
$cell = $row->addCell($width, $style);
|
||||
|
||||
return $cell;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all rows.
|
||||
*
|
||||
* @return Row[]
|
||||
*/
|
||||
public function getRows()
|
||||
{
|
||||
return $this->rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table style.
|
||||
*
|
||||
* @return null|string|TableStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table width.
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getWidth()
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set table width.
|
||||
*
|
||||
* @param int $width
|
||||
*/
|
||||
public function setWidth($width): void
|
||||
{
|
||||
$this->width = $width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get column count.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countColumns()
|
||||
{
|
||||
$columnCount = 0;
|
||||
|
||||
$rowCount = count($this->rows);
|
||||
for ($i = 0; $i < $rowCount; ++$i) {
|
||||
/** @var Row $row Type hint */
|
||||
$row = $this->rows[$i];
|
||||
$cellCount = count($row->getCells());
|
||||
if ($columnCount < $cellCount) {
|
||||
$columnCount = $cellCount;
|
||||
}
|
||||
}
|
||||
|
||||
return $columnCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The first declared cell width for each column.
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public function findFirstDefinedCellWidths()
|
||||
{
|
||||
$cellWidths = [];
|
||||
|
||||
foreach ($this->rows as $row) {
|
||||
$cells = $row->getCells();
|
||||
if (count($cells) <= count($cellWidths)) {
|
||||
continue;
|
||||
}
|
||||
$cellWidths = [];
|
||||
foreach ($cells as $cell) {
|
||||
$cellWidths[] = $cell->getWidth();
|
||||
}
|
||||
}
|
||||
|
||||
return $cellWidths;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Shared\Text as SharedText;
|
||||
use PhpOffice\PhpWord\Style\Font;
|
||||
use PhpOffice\PhpWord\Style\Paragraph;
|
||||
|
||||
/**
|
||||
* Text element.
|
||||
*/
|
||||
class Text extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Text content.
|
||||
*
|
||||
* @var ?string
|
||||
*/
|
||||
protected $text;
|
||||
|
||||
/**
|
||||
* Text style.
|
||||
*
|
||||
* @var Font|string
|
||||
*/
|
||||
protected $fontStyle;
|
||||
|
||||
/**
|
||||
* Paragraph style.
|
||||
*
|
||||
* @var Paragraph|string
|
||||
*/
|
||||
protected $paragraphStyle;
|
||||
|
||||
/**
|
||||
* Create a new Text Element.
|
||||
*
|
||||
* @param string $text
|
||||
* @param mixed $fontStyle
|
||||
* @param mixed $paragraphStyle
|
||||
*/
|
||||
public function __construct($text = null, $fontStyle = null, $paragraphStyle = null)
|
||||
{
|
||||
$this->setText($text);
|
||||
$paragraphStyle = $this->setParagraphStyle($paragraphStyle);
|
||||
$this->setFontStyle($fontStyle, $paragraphStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Text style.
|
||||
*
|
||||
* @param array|Font|string $style
|
||||
* @param array|Paragraph|string $paragraphStyle
|
||||
*
|
||||
* @return Font|string
|
||||
*/
|
||||
public function setFontStyle($style = null, $paragraphStyle = null)
|
||||
{
|
||||
if ($style instanceof Font) {
|
||||
$this->fontStyle = $style;
|
||||
$this->setParagraphStyle($paragraphStyle);
|
||||
} elseif (is_array($style)) {
|
||||
$this->fontStyle = new Font('text', $paragraphStyle);
|
||||
$this->fontStyle->setStyleByArray($style);
|
||||
} elseif (null === $style) {
|
||||
$this->fontStyle = new Font('text', $paragraphStyle);
|
||||
} else {
|
||||
$this->fontStyle = $style;
|
||||
$this->setParagraphStyle($paragraphStyle);
|
||||
}
|
||||
|
||||
return $this->fontStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Text style.
|
||||
*
|
||||
* @return Font|string
|
||||
*/
|
||||
public function getFontStyle()
|
||||
{
|
||||
return $this->fontStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Paragraph style.
|
||||
*
|
||||
* @param array|Paragraph|string $style
|
||||
*
|
||||
* @return Paragraph|string
|
||||
*/
|
||||
public function setParagraphStyle($style = null)
|
||||
{
|
||||
if (is_array($style)) {
|
||||
$this->paragraphStyle = new Paragraph();
|
||||
$this->paragraphStyle->setStyleByArray($style);
|
||||
} elseif ($style instanceof Paragraph) {
|
||||
$this->paragraphStyle = $style;
|
||||
} elseif (null === $style) {
|
||||
$this->paragraphStyle = new Paragraph();
|
||||
} else {
|
||||
$this->paragraphStyle = $style;
|
||||
}
|
||||
|
||||
return $this->paragraphStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Paragraph style.
|
||||
*
|
||||
* @return Paragraph|string
|
||||
*/
|
||||
public function getParagraphStyle()
|
||||
{
|
||||
return $this->paragraphStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text content.
|
||||
*
|
||||
* @param string $text
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setText($text)
|
||||
{
|
||||
$this->text = SharedText::toUTF8($text);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Text content.
|
||||
*/
|
||||
public function getText(): ?string
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\TextBox as TextBoxStyle;
|
||||
|
||||
/**
|
||||
* TextBox element.
|
||||
*
|
||||
* @since 0.11.0
|
||||
*/
|
||||
class TextBox extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* @var string Container type
|
||||
*/
|
||||
protected $container = 'TextBox';
|
||||
|
||||
/**
|
||||
* TextBox style.
|
||||
*
|
||||
* @var ?TextBoxStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Create a new textbox.
|
||||
*
|
||||
* @param mixed $style
|
||||
*/
|
||||
public function __construct($style = null)
|
||||
{
|
||||
$this->style = $this->setNewStyle(new TextBoxStyle(), $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get textbox style.
|
||||
*
|
||||
* @return ?TextBoxStyle
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\Font;
|
||||
use PhpOffice\PhpWord\Style\Paragraph;
|
||||
|
||||
/**
|
||||
* Text break element.
|
||||
*/
|
||||
class TextBreak extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Paragraph style.
|
||||
*
|
||||
* @var null|Paragraph|string
|
||||
*/
|
||||
private $paragraphStyle;
|
||||
|
||||
/**
|
||||
* Text style.
|
||||
*
|
||||
* @var null|Font|string
|
||||
*/
|
||||
private $fontStyle;
|
||||
|
||||
/**
|
||||
* Create a new TextBreak Element.
|
||||
*
|
||||
* @param mixed $fontStyle
|
||||
* @param mixed $paragraphStyle
|
||||
*/
|
||||
public function __construct($fontStyle = null, $paragraphStyle = null)
|
||||
{
|
||||
if (null !== $paragraphStyle) {
|
||||
$paragraphStyle = $this->setParagraphStyle($paragraphStyle);
|
||||
}
|
||||
if (null !== $fontStyle) {
|
||||
$this->setFontStyle($fontStyle, $paragraphStyle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Text style.
|
||||
*
|
||||
* @param mixed $style
|
||||
* @param mixed $paragraphStyle
|
||||
*
|
||||
* @return Font|string
|
||||
*/
|
||||
public function setFontStyle($style = null, $paragraphStyle = null)
|
||||
{
|
||||
if ($style instanceof Font) {
|
||||
$this->fontStyle = $style;
|
||||
$this->setParagraphStyle($paragraphStyle);
|
||||
} elseif (is_array($style)) {
|
||||
$this->fontStyle = new Font('text', $paragraphStyle);
|
||||
$this->fontStyle->setStyleByArray($style);
|
||||
} else {
|
||||
$this->fontStyle = $style;
|
||||
$this->setParagraphStyle($paragraphStyle);
|
||||
}
|
||||
|
||||
return $this->fontStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Text style.
|
||||
*
|
||||
* @return null|Font|string
|
||||
*/
|
||||
public function getFontStyle()
|
||||
{
|
||||
return $this->fontStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Paragraph style.
|
||||
*
|
||||
* @param array|Paragraph|string $style
|
||||
*
|
||||
* @return Paragraph|string
|
||||
*/
|
||||
public function setParagraphStyle($style = null)
|
||||
{
|
||||
if (is_array($style)) {
|
||||
$this->paragraphStyle = new Paragraph();
|
||||
$this->paragraphStyle->setStyleByArray($style);
|
||||
} elseif ($style instanceof Paragraph) {
|
||||
$this->paragraphStyle = $style;
|
||||
} else {
|
||||
$this->paragraphStyle = $style;
|
||||
}
|
||||
|
||||
return $this->paragraphStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Paragraph style.
|
||||
*
|
||||
* @return null|Paragraph|string
|
||||
*/
|
||||
public function getParagraphStyle()
|
||||
{
|
||||
return $this->paragraphStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has font/paragraph style defined.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasStyle()
|
||||
{
|
||||
return null !== $this->fontStyle || null !== $this->paragraphStyle;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?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\Element;
|
||||
|
||||
use PhpOffice\PhpWord\Style\Paragraph;
|
||||
|
||||
/**
|
||||
* Textrun/paragraph element.
|
||||
*/
|
||||
class TextRun extends AbstractContainer
|
||||
{
|
||||
/**
|
||||
* @var string Container type
|
||||
*/
|
||||
protected $container = 'TextRun';
|
||||
|
||||
/**
|
||||
* Paragraph style.
|
||||
*
|
||||
* @var Paragraph|string
|
||||
*/
|
||||
protected $paragraphStyle;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* @param array|Paragraph|string $paragraphStyle
|
||||
*/
|
||||
public function __construct($paragraphStyle = null)
|
||||
{
|
||||
$this->paragraphStyle = $this->setParagraphStyle($paragraphStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Paragraph style.
|
||||
*
|
||||
* @return Paragraph|string
|
||||
*/
|
||||
public function getParagraphStyle()
|
||||
{
|
||||
return $this->paragraphStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Paragraph style.
|
||||
*
|
||||
* @param array|Paragraph|string $style
|
||||
*
|
||||
* @return Paragraph|string
|
||||
*/
|
||||
public function setParagraphStyle($style = null)
|
||||
{
|
||||
if (is_array($style)) {
|
||||
$this->paragraphStyle = new Paragraph();
|
||||
$this->paragraphStyle->setStyleByArray($style);
|
||||
} elseif ($style instanceof Paragraph) {
|
||||
$this->paragraphStyle = $style;
|
||||
} elseif (null === $style) {
|
||||
$this->paragraphStyle = new Paragraph();
|
||||
} else {
|
||||
$this->paragraphStyle = $style;
|
||||
}
|
||||
|
||||
return $this->paragraphStyle;
|
||||
}
|
||||
|
||||
public function getText(): string
|
||||
{
|
||||
$outstr = '';
|
||||
foreach ($this->getElements() as $element) {
|
||||
if ($element instanceof Text) {
|
||||
$outstr .= $element->getText();
|
||||
} elseif ($element instanceof Ruby) {
|
||||
$outstr .= $element->getBaseTextRun()->getText() .
|
||||
' (' . $element->getRubyTextRun()->getText() . ')';
|
||||
}
|
||||
}
|
||||
|
||||
return $outstr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?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\Element;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use PhpOffice\PhpWord\Shared\Text as SharedText;
|
||||
use PhpOffice\PhpWord\Style;
|
||||
|
||||
/**
|
||||
* Title element.
|
||||
*/
|
||||
class Title extends AbstractElement
|
||||
{
|
||||
/**
|
||||
* Title Text content.
|
||||
*
|
||||
* @var string|TextRun
|
||||
*/
|
||||
private $text;
|
||||
|
||||
/**
|
||||
* Title depth.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $depth = 1;
|
||||
|
||||
/**
|
||||
* Name of the heading style, e.g. 'Heading1'.
|
||||
*
|
||||
* @var ?string
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Is part of collection.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $collectionRelation = true;
|
||||
|
||||
/**
|
||||
* Page number.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $pageNumber;
|
||||
|
||||
/**
|
||||
* Create a new Title Element.
|
||||
*
|
||||
* @param string|TextRun $text
|
||||
* @param int $depth
|
||||
*/
|
||||
public function __construct($text, $depth = 1, ?int $pageNumber = null)
|
||||
{
|
||||
if (is_string($text)) {
|
||||
$this->text = SharedText::toUTF8($text);
|
||||
} elseif ($text instanceof TextRun) {
|
||||
$this->text = $text;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid text, should be a string or a TextRun');
|
||||
}
|
||||
|
||||
$this->depth = $depth;
|
||||
$styleName = $depth === 0 ? 'Title' : "Heading_{$this->depth}";
|
||||
if (array_key_exists($styleName, Style::getStyles())) {
|
||||
$this->style = str_replace('_', '', $styleName);
|
||||
}
|
||||
|
||||
if ($pageNumber !== null) {
|
||||
$this->pageNumber = $pageNumber;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Title Text content.
|
||||
*
|
||||
* @return string|TextRun
|
||||
*/
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get depth.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDepth()
|
||||
{
|
||||
return $this->depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Title style.
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getStyle()
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get page number.
|
||||
*/
|
||||
public function getPageNumber(): ?int
|
||||
{
|
||||
return $this->pageNumber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?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\Element;
|
||||
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $author;
|
||||
|
||||
/**
|
||||
* Date.
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
private $date;
|
||||
|
||||
/**
|
||||
* Create a new TrackChange Element.
|
||||
*
|
||||
* @param string $changeType
|
||||
* @param string $author
|
||||
* @param null|bool|DateTime|int $date
|
||||
*/
|
||||
public function __construct($changeType = null, $author = null, $date = null)
|
||||
{
|
||||
$this->changeType = $changeType;
|
||||
$this->author = $author;
|
||||
if ($date !== null && $date !== false) {
|
||||
$this->date = ($date instanceof DateTime) ? $date : new DateTime('@' . $date);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TrackChange Author.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthor()
|
||||
{
|
||||
return $this->author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TrackChange Date.
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Change type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getChangeType()
|
||||
{
|
||||
return $this->changeType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?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\Escaper;
|
||||
|
||||
/**
|
||||
* @since 0.13.0
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
abstract class AbstractEscaper implements EscaperInterface
|
||||
{
|
||||
/**
|
||||
* @param ?string $input
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function escapeSingleValue($input);
|
||||
|
||||
public function escape($input)
|
||||
{
|
||||
if (is_array($input)) {
|
||||
foreach ($input as &$item) {
|
||||
$item = $this->escapeSingleValue($item);
|
||||
}
|
||||
} else {
|
||||
$input = $this->escapeSingleValue($input);
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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\Escaper;
|
||||
|
||||
/**
|
||||
* @since 0.13.0
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
interface EscaperInterface
|
||||
{
|
||||
/**
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function escape($input);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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\Escaper;
|
||||
|
||||
/**
|
||||
* @since 0.13.0
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class RegExp extends AbstractEscaper
|
||||
{
|
||||
const REG_EXP_DELIMITER = '/';
|
||||
|
||||
protected function escapeSingleValue($input)
|
||||
{
|
||||
return self::REG_EXP_DELIMITER . preg_quote($input, self::REG_EXP_DELIMITER) . self::REG_EXP_DELIMITER . 'u';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?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\Escaper;
|
||||
|
||||
/**
|
||||
* @since 0.13.0
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Rtf extends AbstractEscaper
|
||||
{
|
||||
protected function escapeAsciiCharacter($code)
|
||||
{
|
||||
if ($code == 9) {
|
||||
return '{\\tab}';
|
||||
}
|
||||
if (0x20 > $code || $code >= 0x80) {
|
||||
return '{\\u' . $code . '}';
|
||||
}
|
||||
if ($code == 123 || $code == 125 || $code == 92) { // open or close brace or backslash
|
||||
return '\\' . chr($code);
|
||||
}
|
||||
|
||||
return chr($code);
|
||||
}
|
||||
|
||||
protected function escapeMultibyteCharacter($code)
|
||||
{
|
||||
return '\\uc0{\\u' . $code . '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* @see http://www.randomchaos.com/documents/?source=php_and_unicode
|
||||
*
|
||||
* @param ?string $input
|
||||
*/
|
||||
protected function escapeSingleValue($input)
|
||||
{
|
||||
$escapedValue = '';
|
||||
|
||||
$numberOfBytes = 1;
|
||||
$bytes = [];
|
||||
for ($i = 0; $i < strlen($input); ++$i) {
|
||||
$character = $input[$i];
|
||||
$asciiCode = ord($character);
|
||||
|
||||
if ($asciiCode < 128) {
|
||||
$escapedValue .= $this->escapeAsciiCharacter($asciiCode);
|
||||
} else {
|
||||
if (0 == count($bytes)) {
|
||||
if ($asciiCode < 224) {
|
||||
$numberOfBytes = 2;
|
||||
} elseif ($asciiCode < 240) {
|
||||
$numberOfBytes = 3;
|
||||
} elseif ($asciiCode < 248) {
|
||||
$numberOfBytes = 4;
|
||||
}
|
||||
}
|
||||
|
||||
$bytes[] = $asciiCode;
|
||||
|
||||
if ($numberOfBytes == count($bytes)) {
|
||||
if (4 == $numberOfBytes) {
|
||||
$multibyteCode = ($bytes[0] % 8) * 262144 + ($bytes[1] % 64) * 4096 + ($bytes[2] % 64) * 64 + ($bytes[3] % 64);
|
||||
} elseif (3 == $numberOfBytes) {
|
||||
$multibyteCode = ($bytes[0] % 16) * 4096 + ($bytes[1] % 64) * 64 + ($bytes[2] % 64);
|
||||
} else {
|
||||
$multibyteCode = ($bytes[0] % 32) * 64 + ($bytes[1] % 64);
|
||||
}
|
||||
|
||||
if (65279 != $multibyteCode) {
|
||||
$escapedValue .= $multibyteCode < 128 ? $this->escapeAsciiCharacter($multibyteCode) : $this->escapeMultibyteCharacter($multibyteCode);
|
||||
}
|
||||
|
||||
$numberOfBytes = 1;
|
||||
$bytes = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $escapedValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Escaper;
|
||||
|
||||
/**
|
||||
* @since 0.13.0
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Xml extends AbstractEscaper
|
||||
{
|
||||
protected function escapeSingleValue($input)
|
||||
{
|
||||
return (null !== $input) ? htmlspecialchars($input, ENT_QUOTES) : '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?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\Exception;
|
||||
|
||||
/**
|
||||
* @since 0.12.0
|
||||
*/
|
||||
final class CopyFileException extends Exception
|
||||
{
|
||||
/**
|
||||
* @param string $source The fully qualified source file name
|
||||
* @param string $destination The fully qualified destination file name
|
||||
* @param int $code The user defined exception code
|
||||
* @param \Exception $previous The previous exception used for the exception chaining
|
||||
*/
|
||||
public function __construct($source, $destination, $code = 0, ?\Exception $previous = null)
|
||||
{
|
||||
parent::__construct(
|
||||
sprintf('Could not copy \'%s\' file to \'%s\'.', $source, $destination),
|
||||
$code,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
<?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\Exception;
|
||||
|
||||
/**
|
||||
* @since 0.12.0
|
||||
*/
|
||||
final class CreateTemporaryFileException extends Exception
|
||||
{
|
||||
/**
|
||||
* @param int $code The user defined exception code
|
||||
* @param \Exception $previous The previous exception used for the exception chaining
|
||||
*/
|
||||
public function __construct($code = 0, ?\Exception $previous = null)
|
||||
{
|
||||
parent::__construct(
|
||||
'Could not create a temporary file with unique name in the specified directory.',
|
||||
$code,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?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\Exception;
|
||||
|
||||
/**
|
||||
* General exception.
|
||||
*/
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?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\Exception;
|
||||
|
||||
/**
|
||||
* Exception used for when an image is not found.
|
||||
*/
|
||||
class InvalidImageException extends Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?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\Exception;
|
||||
|
||||
/**
|
||||
* Exception used for when an image is not found.
|
||||
*/
|
||||
class InvalidObjectException extends Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?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\Exception;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Exception used for when a style value is invalid.
|
||||
*/
|
||||
class InvalidStyleException extends InvalidArgumentException
|
||||
{
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<?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\Exception;
|
||||
|
||||
/**
|
||||
* Exception used for when an image type is unsupported.
|
||||
*/
|
||||
class UnsupportedImageTypeException extends Exception
|
||||
{
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
<?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;
|
||||
|
||||
use PhpOffice\PhpWord\Element\Text;
|
||||
use PhpOffice\PhpWord\Element\TextRun;
|
||||
use PhpOffice\PhpWord\Exception\Exception;
|
||||
use PhpOffice\PhpWord\Reader\ReaderInterface;
|
||||
use PhpOffice\PhpWord\Writer\WriterInterface;
|
||||
use ReflectionClass;
|
||||
|
||||
abstract class IOFactory
|
||||
{
|
||||
/**
|
||||
* Create new writer.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return WriterInterface
|
||||
*/
|
||||
public static function createWriter(PhpWord $phpWord, $name = 'Word2007')
|
||||
{
|
||||
if ($name !== 'WriterInterface' && !in_array($name, ['ODText', 'RTF', 'Word2007', 'HTML', 'PDF', 'EPub3'], true)) {
|
||||
throw new Exception("\"{$name}\" is not a valid writer.");
|
||||
}
|
||||
|
||||
$fqName = "PhpOffice\\PhpWord\\Writer\\{$name}";
|
||||
|
||||
return new $fqName($phpWord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new reader.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return ReaderInterface
|
||||
*/
|
||||
public static function createReader($name = 'Word2007')
|
||||
{
|
||||
return self::createObject('Reader', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new object.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $name
|
||||
* @param PhpWord $phpWord
|
||||
*
|
||||
* @return ReaderInterface|WriterInterface
|
||||
*/
|
||||
private static function createObject($type, $name, $phpWord = null)
|
||||
{
|
||||
$class = "PhpOffice\\PhpWord\\{$type}\\{$name}";
|
||||
if (class_exists($class) && self::isConcreteClass($class)) {
|
||||
return new $class($phpWord);
|
||||
}
|
||||
|
||||
throw new Exception("\"{$name}\" is not a valid {$type}.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PhpWord from file.
|
||||
*
|
||||
* @param string $filename The name of the file
|
||||
* @param string $readerName
|
||||
*
|
||||
* @return PhpWord $phpWord
|
||||
*/
|
||||
public static function load($filename, $readerName = 'Word2007')
|
||||
{
|
||||
/** @var ReaderInterface $reader */
|
||||
$reader = self::createReader($readerName);
|
||||
|
||||
return $reader->load($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PhpWord ${variable} from file.
|
||||
*
|
||||
* @param string $filename The name of the file
|
||||
*
|
||||
* @return array The extracted variables
|
||||
*/
|
||||
public static function extractVariables(string $filename, string $readerName = 'Word2007'): array
|
||||
{
|
||||
/** @var ReaderInterface $reader */
|
||||
$reader = self::createReader($readerName);
|
||||
$document = $reader->load($filename);
|
||||
$extractedVariables = [];
|
||||
foreach ($document->getSections() as $section) {
|
||||
$concatenatedText = '';
|
||||
foreach ($section->getElements() as $element) {
|
||||
if ($element instanceof TextRun) {
|
||||
foreach ($element->getElements() as $textElement) {
|
||||
if ($textElement instanceof Text) {
|
||||
$text = $textElement->getText();
|
||||
$concatenatedText .= $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
preg_match_all('/\$\{([^}]+)\}/', $concatenatedText, $matches);
|
||||
if (!empty($matches[1])) {
|
||||
foreach ($matches[1] as $match) {
|
||||
$trimmedMatch = trim($match);
|
||||
$extractedVariables[] = $trimmedMatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $extractedVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it's a concrete class (not abstract nor interface).
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function isConcreteClass($class)
|
||||
{
|
||||
$reflection = new ReflectionClass($class);
|
||||
|
||||
return !$reflection->isAbstract() && !$reflection->isInterface();
|
||||
}
|
||||
}
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
<?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;
|
||||
|
||||
use PhpOffice\PhpWord\Element\Image;
|
||||
use PhpOffice\PhpWord\Exception\Exception;
|
||||
|
||||
/**
|
||||
* Media collection.
|
||||
*/
|
||||
class Media
|
||||
{
|
||||
/**
|
||||
* Media elements.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $elements = [];
|
||||
|
||||
/**
|
||||
* Add new media element.
|
||||
*
|
||||
* @since 0.10.0
|
||||
* @since 0.9.2
|
||||
*
|
||||
* @param string $container section|headerx|footerx|footnote|endnote
|
||||
* @param string $mediaType image|object|link
|
||||
* @param string $source
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function addElement($container, $mediaType, $source, ?Image $image = null)
|
||||
{
|
||||
// Assign unique media Id and initiate media container if none exists
|
||||
$mediaId = md5($container . $source);
|
||||
if (!isset(self::$elements[$container])) {
|
||||
self::$elements[$container] = [];
|
||||
}
|
||||
|
||||
// Add media if not exists or point to existing media
|
||||
if (!isset(self::$elements[$container][$mediaId])) {
|
||||
$mediaCount = self::countElements($container);
|
||||
$mediaTypeCount = self::countElements($container, $mediaType);
|
||||
++$mediaTypeCount;
|
||||
$rId = ++$mediaCount;
|
||||
$target = null;
|
||||
$mediaData = ['mediaIndex' => $mediaTypeCount];
|
||||
|
||||
switch ($mediaType) {
|
||||
// Images
|
||||
case 'image':
|
||||
if (null === $image) {
|
||||
throw new Exception('Image object not assigned.');
|
||||
}
|
||||
$isMemImage = $image->isMemImage();
|
||||
$extension = $image->getImageExtension();
|
||||
$mediaData['imageExtension'] = $extension;
|
||||
$mediaData['imageType'] = $image->getImageType();
|
||||
if ($isMemImage) {
|
||||
$mediaData['isMemImage'] = true;
|
||||
$mediaData['imageString'] = $image->getImageString();
|
||||
}
|
||||
$target = "{$container}_image{$mediaTypeCount}.{$extension}";
|
||||
$image->setTarget($target);
|
||||
$image->setMediaIndex($mediaTypeCount);
|
||||
|
||||
break;
|
||||
// Objects
|
||||
case 'object':
|
||||
$target = "{$container}_oleObject{$mediaTypeCount}.bin";
|
||||
|
||||
break;
|
||||
// Links
|
||||
case 'link':
|
||||
$target = $source;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$mediaData['source'] = $source;
|
||||
$mediaData['target'] = $target;
|
||||
$mediaData['type'] = $mediaType;
|
||||
$mediaData['rID'] = $rId;
|
||||
self::$elements[$container][$mediaId] = $mediaData;
|
||||
|
||||
return $rId;
|
||||
}
|
||||
|
||||
$mediaData = self::$elements[$container][$mediaId];
|
||||
if (null !== $image) {
|
||||
$image->setTarget($mediaData['target']);
|
||||
$image->setMediaIndex($mediaData['mediaIndex']);
|
||||
}
|
||||
|
||||
return $mediaData['rID'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get media elements count.
|
||||
*
|
||||
* @param string $container section|headerx|footerx|footnote|endnote
|
||||
* @param string $mediaType image|object|link
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
public static function countElements($container, $mediaType = null)
|
||||
{
|
||||
$mediaCount = 0;
|
||||
|
||||
if (isset(self::$elements[$container])) {
|
||||
foreach (self::$elements[$container] as $mediaData) {
|
||||
if (null !== $mediaType) {
|
||||
if ($mediaType == $mediaData['type']) {
|
||||
++$mediaCount;
|
||||
}
|
||||
} else {
|
||||
++$mediaCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mediaCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get media elements.
|
||||
*
|
||||
* @param string $container section|headerx|footerx|footnote|endnote
|
||||
* @param string $type image|object|link
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
public static function getElements($container, $type = null)
|
||||
{
|
||||
$elements = [];
|
||||
|
||||
// If header/footer, search for headerx and footerx where x is number
|
||||
if ($container == 'header' || $container == 'footer') {
|
||||
foreach (self::$elements as $key => $val) {
|
||||
if (substr($key, 0, 6) == $container) {
|
||||
$elements[$key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
if (!isset(self::$elements[$container])) {
|
||||
return $elements;
|
||||
}
|
||||
|
||||
return self::getElementsByType($container, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elements by media type.
|
||||
*
|
||||
* @param string $container section|footnote|endnote
|
||||
* @param string $type image|object|link
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 0.11.0 Splitted from `getElements` to reduce complexity
|
||||
*/
|
||||
private static function getElementsByType($container, $type = null)
|
||||
{
|
||||
$elements = [];
|
||||
|
||||
foreach (self::$elements[$container] as $key => $data) {
|
||||
if ($type !== null) {
|
||||
if ($type == $data['type']) {
|
||||
$elements[$key] = $data;
|
||||
}
|
||||
} else {
|
||||
$elements[$key] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset media elements.
|
||||
*/
|
||||
public static function resetElements(): void
|
||||
{
|
||||
self::$elements = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?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\Metadata;
|
||||
|
||||
/**
|
||||
* Compatibility setting class.
|
||||
*
|
||||
* @since 0.12.0
|
||||
* @see http://www.datypic.com/sc/ooxml/t-w_CT_Compat.html
|
||||
*/
|
||||
class Compatibility
|
||||
{
|
||||
/**
|
||||
* OOXML version.
|
||||
*
|
||||
* 12 = 2007
|
||||
* 14 = 2010
|
||||
* 15 = 2013
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @see http://msdn.microsoft.com/en-us/library/dd909048%28v=office.12%29.aspx
|
||||
*/
|
||||
private $ooxmlVersion = 12;
|
||||
|
||||
/**
|
||||
* Get OOXML version.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOoxmlVersion()
|
||||
{
|
||||
return $this->ooxmlVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set OOXML version.
|
||||
*
|
||||
* @param int $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setOoxmlVersion($value)
|
||||
{
|
||||
$this->ooxmlVersion = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,603 @@
|
||||
<?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\Metadata;
|
||||
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* Document information.
|
||||
*/
|
||||
class DocInfo
|
||||
{
|
||||
/** @const string Property type constants */
|
||||
const PROPERTY_TYPE_BOOLEAN = 'b';
|
||||
const PROPERTY_TYPE_INTEGER = 'i';
|
||||
const PROPERTY_TYPE_FLOAT = 'f';
|
||||
const PROPERTY_TYPE_DATE = 'd';
|
||||
const PROPERTY_TYPE_STRING = 's';
|
||||
const PROPERTY_TYPE_UNKNOWN = 'u';
|
||||
|
||||
/**
|
||||
* Creator.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $creator;
|
||||
|
||||
/**
|
||||
* LastModifiedBy.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $lastModifiedBy;
|
||||
|
||||
/**
|
||||
* Created.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $created;
|
||||
|
||||
/**
|
||||
* Modified.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $modified;
|
||||
|
||||
/**
|
||||
* Title.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* Description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* Subject.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $subject;
|
||||
|
||||
/**
|
||||
* Keywords.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $keywords;
|
||||
|
||||
/**
|
||||
* Category.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $category;
|
||||
|
||||
/**
|
||||
* Company.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $company;
|
||||
|
||||
/**
|
||||
* Manager.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $manager;
|
||||
|
||||
/**
|
||||
* Custom Properties.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $customProperties = [];
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->creator = '';
|
||||
$this->lastModifiedBy = $this->creator;
|
||||
$this->created = time();
|
||||
$this->modified = time();
|
||||
$this->title = '';
|
||||
$this->subject = '';
|
||||
$this->description = '';
|
||||
$this->keywords = '';
|
||||
$this->category = '';
|
||||
$this->company = '';
|
||||
$this->manager = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Creator.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCreator()
|
||||
{
|
||||
return $this->creator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Creator.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setCreator($value = '')
|
||||
{
|
||||
$this->creator = $this->setValue($value, '');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Last Modified By.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLastModifiedBy()
|
||||
{
|
||||
return $this->lastModifiedBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Last Modified By.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setLastModifiedBy($value = '')
|
||||
{
|
||||
$this->lastModifiedBy = $this->setValue($value, $this->creator);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Created.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCreated()
|
||||
{
|
||||
return $this->created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Created.
|
||||
*
|
||||
* @param int $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setCreated($value = null)
|
||||
{
|
||||
$this->created = $this->setValue($value, time());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Modified.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getModified()
|
||||
{
|
||||
return $this->modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Modified.
|
||||
*
|
||||
* @param int $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setModified($value = null)
|
||||
{
|
||||
$this->modified = $this->setValue($value, time());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Title.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setTitle($value = '')
|
||||
{
|
||||
$this->title = $this->setValue($value, '');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Description.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setDescription($value = '')
|
||||
{
|
||||
$this->description = $this->setValue($value, '');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Subject.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Subject.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setSubject($value = '')
|
||||
{
|
||||
$this->subject = $this->setValue($value, '');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Keywords.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKeywords()
|
||||
{
|
||||
return $this->keywords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Keywords.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setKeywords($value = '')
|
||||
{
|
||||
$this->keywords = $this->setValue($value, '');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Category.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCategory()
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Category.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setCategory($value = '')
|
||||
{
|
||||
$this->category = $this->setValue($value, '');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Company.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCompany()
|
||||
{
|
||||
return $this->company;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Company.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setCompany($value = '')
|
||||
{
|
||||
$this->company = $this->setValue($value, '');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Manager.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getManager()
|
||||
{
|
||||
return $this->manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Manager.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setManager($value = '')
|
||||
{
|
||||
$this->manager = $this->setValue($value, '');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a List of Custom Property Names.
|
||||
*
|
||||
* @return array of string
|
||||
*/
|
||||
public function getCustomProperties()
|
||||
{
|
||||
return array_keys($this->customProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Custom Property is defined.
|
||||
*
|
||||
* @param string $propertyName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCustomPropertySet($propertyName)
|
||||
{
|
||||
return isset($this->customProperties[$propertyName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Custom Property Value.
|
||||
*
|
||||
* @param string $propertyName
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCustomPropertyValue($propertyName)
|
||||
{
|
||||
if ($this->isCustomPropertySet($propertyName)) {
|
||||
return $this->customProperties[$propertyName]['value'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Custom Property Type.
|
||||
*
|
||||
* @param string $propertyName
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public function getCustomPropertyType($propertyName)
|
||||
{
|
||||
if ($this->isCustomPropertySet($propertyName)) {
|
||||
return $this->customProperties[$propertyName]['type'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Custom Property.
|
||||
*
|
||||
* @param string $propertyName
|
||||
* @param mixed $propertyValue
|
||||
* @param string $propertyType
|
||||
* 'i': Integer
|
||||
* 'f': Floating Point
|
||||
* 's': String
|
||||
* 'd': Date/Time
|
||||
* 'b': Boolean
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null)
|
||||
{
|
||||
$propertyTypes = [
|
||||
self::PROPERTY_TYPE_INTEGER,
|
||||
self::PROPERTY_TYPE_FLOAT,
|
||||
self::PROPERTY_TYPE_STRING,
|
||||
self::PROPERTY_TYPE_DATE,
|
||||
self::PROPERTY_TYPE_BOOLEAN,
|
||||
];
|
||||
if (($propertyType === null) || (!in_array($propertyType, $propertyTypes))) {
|
||||
if ($propertyValue === null) {
|
||||
$propertyType = self::PROPERTY_TYPE_STRING;
|
||||
} elseif (is_float($propertyValue)) {
|
||||
$propertyType = self::PROPERTY_TYPE_FLOAT;
|
||||
} elseif (is_int($propertyValue)) {
|
||||
$propertyType = self::PROPERTY_TYPE_INTEGER;
|
||||
} elseif (is_bool($propertyValue)) {
|
||||
$propertyType = self::PROPERTY_TYPE_BOOLEAN;
|
||||
} elseif ($propertyValue instanceof DateTime) {
|
||||
$propertyType = self::PROPERTY_TYPE_DATE;
|
||||
} else {
|
||||
$propertyType = self::PROPERTY_TYPE_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
$this->customProperties[$propertyName] = [
|
||||
'value' => $propertyValue,
|
||||
'type' => $propertyType,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert document property based on type.
|
||||
*
|
||||
* @param string $propertyValue
|
||||
* @param string $propertyType
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function convertProperty($propertyValue, $propertyType)
|
||||
{
|
||||
$conversion = self::getConversion($propertyType);
|
||||
|
||||
switch ($conversion) {
|
||||
case 'empty': // Empty
|
||||
return '';
|
||||
case 'null': // Null
|
||||
return null;
|
||||
case 'int': // Signed integer
|
||||
return (int) $propertyValue;
|
||||
case 'uint': // Unsigned integer
|
||||
return abs((int) $propertyValue);
|
||||
case 'float': // Float
|
||||
return (float) $propertyValue;
|
||||
case 'date': // Date
|
||||
return strtotime($propertyValue);
|
||||
case 'bool': // Boolean
|
||||
return $propertyValue == 'true';
|
||||
}
|
||||
|
||||
return $propertyValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert document property type.
|
||||
*
|
||||
* @param string $propertyType
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function convertPropertyType($propertyType)
|
||||
{
|
||||
$typeGroups = [
|
||||
self::PROPERTY_TYPE_INTEGER => ['i1', 'i2', 'i4', 'i8', 'int', 'ui1', 'ui2', 'ui4', 'ui8', 'uint'],
|
||||
self::PROPERTY_TYPE_FLOAT => ['r4', 'r8', 'decimal'],
|
||||
self::PROPERTY_TYPE_STRING => ['empty', 'null', 'lpstr', 'lpwstr', 'bstr'],
|
||||
self::PROPERTY_TYPE_DATE => ['date', 'filetime'],
|
||||
self::PROPERTY_TYPE_BOOLEAN => ['bool'],
|
||||
];
|
||||
foreach ($typeGroups as $groupId => $groupMembers) {
|
||||
if (in_array($propertyType, $groupMembers)) {
|
||||
return $groupId;
|
||||
}
|
||||
}
|
||||
|
||||
return self::PROPERTY_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default for null and empty value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function setValue($value, $default)
|
||||
{
|
||||
if ($value === null || $value == '') {
|
||||
$value = $default;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get conversion model depending on property type.
|
||||
*
|
||||
* @param string $propertyType
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getConversion($propertyType)
|
||||
{
|
||||
$conversions = [
|
||||
'empty' => ['empty'],
|
||||
'null' => ['null'],
|
||||
'int' => ['i1', 'i2', 'i4', 'i8', 'int'],
|
||||
'uint' => ['ui1', 'ui2', 'ui4', 'ui8', 'uint'],
|
||||
'float' => ['r4', 'r8', 'decimal'],
|
||||
'bool' => ['bool'],
|
||||
'date' => ['date', 'filetime'],
|
||||
];
|
||||
foreach ($conversions as $conversion => $types) {
|
||||
if (in_array($propertyType, $types)) {
|
||||
return $conversion;
|
||||
}
|
||||
}
|
||||
|
||||
return 'string';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
<?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\Metadata;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder;
|
||||
use PhpOffice\PhpWord\SimpleType\DocProtect;
|
||||
|
||||
/**
|
||||
* Document protection class.
|
||||
*
|
||||
* @since 0.12.0
|
||||
* @see http://www.datypic.com/sc/ooxml/t-w_CT_DocProtect.html
|
||||
*/
|
||||
class Protection
|
||||
{
|
||||
/**
|
||||
* Editing restriction none|readOnly|comments|trackedChanges|forms.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @see http://www.datypic.com/sc/ooxml/a-w_edit-1.html
|
||||
*/
|
||||
private $editing;
|
||||
|
||||
/**
|
||||
* password.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $password;
|
||||
|
||||
/**
|
||||
* Iterations to Run Hashing Algorithm.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $spinCount = 100000;
|
||||
|
||||
/**
|
||||
* Cryptographic Hashing Algorithm (see constants defined in \PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $algorithm = PasswordEncoder::ALGORITHM_SHA_1;
|
||||
|
||||
/**
|
||||
* Salt for Password Verifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $salt;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param string $editing
|
||||
*/
|
||||
public function __construct($editing = null)
|
||||
{
|
||||
if ($editing != null) {
|
||||
$this->setEditing($editing);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get editing protection.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEditing()
|
||||
{
|
||||
return $this->editing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set editing protection.
|
||||
*
|
||||
* @param string $editing Any value of \PhpOffice\PhpWord\SimpleType\DocProtect
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setEditing($editing = null)
|
||||
{
|
||||
DocProtect::validate($editing);
|
||||
$this->editing = $editing;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get password.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setPassword($password)
|
||||
{
|
||||
$this->password = $password;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count for hash iterations.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSpinCount()
|
||||
{
|
||||
return $this->spinCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set count for hash iterations.
|
||||
*
|
||||
* @param int $spinCount
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setSpinCount($spinCount)
|
||||
{
|
||||
$this->spinCount = $spinCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get algorithm.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAlgorithm()
|
||||
{
|
||||
return $this->algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set algorithm.
|
||||
*
|
||||
* @param string $algorithm
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setAlgorithm($algorithm)
|
||||
{
|
||||
$this->algorithm = $algorithm;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get salt.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSalt()
|
||||
{
|
||||
return $this->salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set salt. Salt HAS to be 16 characters, or an exception will be thrown.
|
||||
*
|
||||
* @param string $salt
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setSalt($salt)
|
||||
{
|
||||
if ($salt !== null && strlen($salt) !== 16) {
|
||||
throw new InvalidArgumentException('salt has to be of exactly 16 bytes length');
|
||||
}
|
||||
|
||||
$this->salt = $salt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,500 @@
|
||||
<?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\Metadata;
|
||||
|
||||
use PhpOffice\PhpWord\ComplexType\ProofState;
|
||||
use PhpOffice\PhpWord\ComplexType\TrackChangesView;
|
||||
use PhpOffice\PhpWord\SimpleType\Zoom;
|
||||
use PhpOffice\PhpWord\Style\Language;
|
||||
|
||||
/**
|
||||
* Setting class.
|
||||
*
|
||||
* @since 0.14.0
|
||||
* @see http://www.datypic.com/sc/ooxml/t-w_CT_Settings.html
|
||||
*/
|
||||
class Settings
|
||||
{
|
||||
/**
|
||||
* Magnification Setting.
|
||||
*
|
||||
* @see http://www.datypic.com/sc/ooxml/e-w_zoom-1.html
|
||||
*
|
||||
* @var mixed either integer, in which case it treated as a percent, or one of PhpOffice\PhpWord\SimpleType\Zoom
|
||||
*/
|
||||
private $zoom = 100;
|
||||
|
||||
/**
|
||||
* Mirror Page Margins.
|
||||
*
|
||||
* @see http://www.datypic.com/sc/ooxml/e-w_mirrorMargins-1.html
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $mirrorMargins;
|
||||
|
||||
/**
|
||||
* Hide spelling errors.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $hideSpellingErrors = false;
|
||||
|
||||
/**
|
||||
* Hide grammatical errors.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $hideGrammaticalErrors = false;
|
||||
|
||||
/**
|
||||
* Visibility of Annotation Types.
|
||||
*
|
||||
* @var TrackChangesView
|
||||
*/
|
||||
private $revisionView;
|
||||
|
||||
/**
|
||||
* Track Revisions to Document.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $trackRevisions = false;
|
||||
|
||||
/**
|
||||
* Do Not Use Move Syntax When Tracking Revisions.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $doNotTrackMoves = false;
|
||||
|
||||
/**
|
||||
* Do Not Track Formatting Revisions When Tracking Revisions.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $doNotTrackFormatting = false;
|
||||
|
||||
/**
|
||||
* Spelling and Grammatical Checking State.
|
||||
*
|
||||
* @var ProofState
|
||||
*/
|
||||
private $proofState;
|
||||
|
||||
/**
|
||||
* Document Editing Restrictions.
|
||||
*
|
||||
* @var Protection
|
||||
*/
|
||||
private $documentProtection;
|
||||
|
||||
/**
|
||||
* Enables different header for odd and even pages.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $evenAndOddHeaders = false;
|
||||
|
||||
/**
|
||||
* Theme Font Languages.
|
||||
*
|
||||
* @var ?Language
|
||||
*/
|
||||
private $themeFontLang;
|
||||
|
||||
/**
|
||||
* Automatically Recalculate Fields on Open.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $updateFields = false;
|
||||
|
||||
/**
|
||||
* Radix Point for Field Code Evaluation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $decimalSymbol = '.';
|
||||
|
||||
/**
|
||||
* Automatically hyphenate document contents when displayed.
|
||||
*
|
||||
* @var null|bool
|
||||
*/
|
||||
private $autoHyphenation;
|
||||
|
||||
/**
|
||||
* Maximum number of consecutively hyphenated lines.
|
||||
*
|
||||
* @var null|int
|
||||
*/
|
||||
private $consecutiveHyphenLimit;
|
||||
|
||||
/**
|
||||
* The allowed amount of whitespace before hyphenation is applied.
|
||||
*
|
||||
* @var null|float|int
|
||||
*/
|
||||
private $hyphenationZone;
|
||||
|
||||
/**
|
||||
* Do not hyphenate words in all capital letters.
|
||||
*
|
||||
* @var null|bool
|
||||
*/
|
||||
private $doNotHyphenateCaps;
|
||||
|
||||
/**
|
||||
* Enable or disable book-folded printing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $bookFoldPrinting = false;
|
||||
|
||||
/**
|
||||
* @return Protection
|
||||
*/
|
||||
public function getDocumentProtection()
|
||||
{
|
||||
if ($this->documentProtection == null) {
|
||||
$this->documentProtection = new Protection();
|
||||
}
|
||||
|
||||
return $this->documentProtection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Protection $documentProtection
|
||||
*/
|
||||
public function setDocumentProtection($documentProtection): void
|
||||
{
|
||||
$this->documentProtection = $documentProtection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ProofState
|
||||
*/
|
||||
public function getProofState()
|
||||
{
|
||||
if ($this->proofState == null) {
|
||||
$this->proofState = new ProofState();
|
||||
}
|
||||
|
||||
return $this->proofState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProofState $proofState
|
||||
*/
|
||||
public function setProofState($proofState): void
|
||||
{
|
||||
$this->proofState = $proofState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are spelling errors hidden.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasHideSpellingErrors()
|
||||
{
|
||||
return $this->hideSpellingErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide spelling errors.
|
||||
*
|
||||
* @param ?bool $hideSpellingErrors
|
||||
*/
|
||||
public function setHideSpellingErrors($hideSpellingErrors): void
|
||||
{
|
||||
$this->hideSpellingErrors = $hideSpellingErrors === null ? true : $hideSpellingErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are grammatical errors hidden.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasHideGrammaticalErrors()
|
||||
{
|
||||
return $this->hideGrammaticalErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide grammatical errors.
|
||||
*
|
||||
* @param ?bool $hideGrammaticalErrors
|
||||
*/
|
||||
public function setHideGrammaticalErrors($hideGrammaticalErrors): void
|
||||
{
|
||||
$this->hideGrammaticalErrors = $hideGrammaticalErrors === null ? true : $hideGrammaticalErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasEvenAndOddHeaders()
|
||||
{
|
||||
return $this->evenAndOddHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ?bool $evenAndOddHeaders
|
||||
*/
|
||||
public function setEvenAndOddHeaders($evenAndOddHeaders): void
|
||||
{
|
||||
$this->evenAndOddHeaders = $evenAndOddHeaders === null ? true : $evenAndOddHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Visibility of Annotation Types.
|
||||
*
|
||||
* @return TrackChangesView
|
||||
*/
|
||||
public function getRevisionView()
|
||||
{
|
||||
return $this->revisionView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Visibility of Annotation Types.
|
||||
*/
|
||||
public function setRevisionView(?TrackChangesView $trackChangesView = null): void
|
||||
{
|
||||
$this->revisionView = $trackChangesView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTrackRevisions()
|
||||
{
|
||||
return $this->trackRevisions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ?bool $trackRevisions
|
||||
*/
|
||||
public function setTrackRevisions($trackRevisions): void
|
||||
{
|
||||
$this->trackRevisions = $trackRevisions === null ? true : $trackRevisions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDoNotTrackMoves()
|
||||
{
|
||||
return $this->doNotTrackMoves;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ?bool $doNotTrackMoves
|
||||
*/
|
||||
public function setDoNotTrackMoves($doNotTrackMoves): void
|
||||
{
|
||||
$this->doNotTrackMoves = $doNotTrackMoves === null ? true : $doNotTrackMoves;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDoNotTrackFormatting()
|
||||
{
|
||||
return $this->doNotTrackFormatting;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ?bool $doNotTrackFormatting
|
||||
*/
|
||||
public function setDoNotTrackFormatting($doNotTrackFormatting): void
|
||||
{
|
||||
$this->doNotTrackFormatting = $doNotTrackFormatting === null ? true : $doNotTrackFormatting;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getZoom()
|
||||
{
|
||||
return $this->zoom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $zoom
|
||||
*/
|
||||
public function setZoom($zoom): void
|
||||
{
|
||||
if (is_numeric($zoom)) {
|
||||
// zoom is a percentage
|
||||
$this->zoom = $zoom;
|
||||
} else {
|
||||
Zoom::validate($zoom);
|
||||
$this->zoom = $zoom;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasMirrorMargins()
|
||||
{
|
||||
return $this->mirrorMargins;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $mirrorMargins
|
||||
*/
|
||||
public function setMirrorMargins($mirrorMargins): void
|
||||
{
|
||||
$this->mirrorMargins = $mirrorMargins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Language.
|
||||
*/
|
||||
public function getThemeFontLang(): ?Language
|
||||
{
|
||||
return $this->themeFontLang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Language for this document.
|
||||
*/
|
||||
public function setThemeFontLang(Language $themeFontLang): self
|
||||
{
|
||||
$this->themeFontLang = $themeFontLang;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasUpdateFields()
|
||||
{
|
||||
return $this->updateFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ?bool $updateFields
|
||||
*/
|
||||
public function setUpdateFields($updateFields): void
|
||||
{
|
||||
$this->updateFields = $updateFields === null ? false : $updateFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Radix Point for Field Code Evaluation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDecimalSymbol()
|
||||
{
|
||||
return $this->decimalSymbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the Radix Point for Field Code Evaluation.
|
||||
*
|
||||
* @param string $decimalSymbol
|
||||
*/
|
||||
public function setDecimalSymbol($decimalSymbol): void
|
||||
{
|
||||
$this->decimalSymbol = $decimalSymbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|bool
|
||||
*/
|
||||
public function hasAutoHyphenation()
|
||||
{
|
||||
return $this->autoHyphenation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $autoHyphenation
|
||||
*/
|
||||
public function setAutoHyphenation($autoHyphenation): void
|
||||
{
|
||||
$this->autoHyphenation = (bool) $autoHyphenation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|int
|
||||
*/
|
||||
public function getConsecutiveHyphenLimit()
|
||||
{
|
||||
return $this->consecutiveHyphenLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $consecutiveHyphenLimit
|
||||
*/
|
||||
public function setConsecutiveHyphenLimit($consecutiveHyphenLimit): void
|
||||
{
|
||||
$this->consecutiveHyphenLimit = (int) $consecutiveHyphenLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|float|int
|
||||
*/
|
||||
public function getHyphenationZone()
|
||||
{
|
||||
return $this->hyphenationZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|float|int $hyphenationZone Measurement unit is twip
|
||||
*/
|
||||
public function setHyphenationZone($hyphenationZone): void
|
||||
{
|
||||
$this->hyphenationZone = $hyphenationZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|bool
|
||||
*/
|
||||
public function hasDoNotHyphenateCaps()
|
||||
{
|
||||
return $this->doNotHyphenateCaps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $doNotHyphenateCaps
|
||||
*/
|
||||
public function setDoNotHyphenateCaps($doNotHyphenateCaps): void
|
||||
{
|
||||
$this->doNotHyphenateCaps = (bool) $doNotHyphenateCaps;
|
||||
}
|
||||
|
||||
public function hasBookFoldPrinting(): bool
|
||||
{
|
||||
return $this->bookFoldPrinting;
|
||||
}
|
||||
|
||||
public function setBookFoldPrinting(bool $bookFoldPrinting): self
|
||||
{
|
||||
$this->bookFoldPrinting = $bookFoldPrinting;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
+411
@@ -0,0 +1,411 @@
|
||||
<?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;
|
||||
|
||||
use BadMethodCallException;
|
||||
use PhpOffice\PhpWord\Element\Section;
|
||||
use PhpOffice\PhpWord\Exception\Exception;
|
||||
|
||||
/**
|
||||
* PHPWord main class.
|
||||
*
|
||||
* @method Collection\Titles getTitles()
|
||||
* @method Collection\Footnotes getFootnotes()
|
||||
* @method Collection\Endnotes getEndnotes()
|
||||
* @method Collection\Charts getCharts()
|
||||
* @method Collection\Comments getComments()
|
||||
* @method int addBookmark(Element\Bookmark $bookmark)
|
||||
* @method int addTitle(Element\Title $title)
|
||||
* @method int addFootnote(Element\Footnote $footnote)
|
||||
* @method int addEndnote(Element\Endnote $endnote)
|
||||
* @method int addChart(Element\Chart $chart)
|
||||
* @method int addComment(Element\Comment $comment)
|
||||
* @method Style\Paragraph addParagraphStyle(string $styleName, mixed $styles)
|
||||
* @method Style\Font addFontStyle(string $styleName, mixed $fontStyle, mixed $paragraphStyle = null)
|
||||
* @method Style\Font addLinkStyle(string $styleName, mixed $styles)
|
||||
* @method Style\Font addTitleStyle(mixed $depth, mixed $fontStyle, mixed $paragraphStyle = null)
|
||||
* @method Style\Table addTableStyle(string $styleName, mixed $styleTable, mixed $styleFirstRow = null)
|
||||
* @method Style\Numbering addNumberingStyle(string $styleName, mixed $styles)
|
||||
*/
|
||||
class PhpWord
|
||||
{
|
||||
/**
|
||||
* Collection of sections.
|
||||
*
|
||||
* @var Section[]
|
||||
*/
|
||||
private $sections = [];
|
||||
|
||||
/**
|
||||
* Collections.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $collections = [];
|
||||
|
||||
/**
|
||||
* Metadata.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 0.12.0
|
||||
*/
|
||||
private $metadata = [];
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
* Collections are created dynamically
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Reset Media and styles
|
||||
Media::resetElements();
|
||||
Style::resetStyles();
|
||||
Settings::setDefaultRtl(null);
|
||||
|
||||
// Collection
|
||||
$collections = ['Bookmarks', 'Titles', 'Footnotes', 'Endnotes', 'Charts', 'Comments'];
|
||||
foreach ($collections as $collection) {
|
||||
$class = 'PhpOffice\\PhpWord\\Collection\\' . $collection;
|
||||
$this->collections[$collection] = new $class();
|
||||
}
|
||||
|
||||
// Metadata
|
||||
$metadata = ['DocInfo', 'Settings', 'Compatibility'];
|
||||
foreach ($metadata as $meta) {
|
||||
$class = 'PhpOffice\\PhpWord\\Metadata\\' . $meta;
|
||||
$this->metadata[$meta] = new $class();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamic function call to reduce static dependency.
|
||||
*
|
||||
* @since 0.12.0
|
||||
*
|
||||
* @param mixed $function
|
||||
* @param mixed $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($function, $args)
|
||||
{
|
||||
$function = strtolower($function);
|
||||
|
||||
$getCollection = [];
|
||||
$addCollection = [];
|
||||
$addStyle = [];
|
||||
|
||||
$collections = ['Bookmark', 'Title', 'Footnote', 'Endnote', 'Chart', 'Comment'];
|
||||
foreach ($collections as $collection) {
|
||||
$getCollection[] = strtolower("get{$collection}s");
|
||||
$addCollection[] = strtolower("add{$collection}");
|
||||
}
|
||||
|
||||
$styles = ['Paragraph', 'Font', 'Table', 'Numbering', 'Link', 'Title'];
|
||||
foreach ($styles as $style) {
|
||||
$addStyle[] = strtolower("add{$style}Style");
|
||||
}
|
||||
|
||||
// Run get collection method
|
||||
if (in_array($function, $getCollection)) {
|
||||
$key = ucfirst(str_replace('get', '', $function));
|
||||
|
||||
return $this->collections[$key];
|
||||
}
|
||||
|
||||
// Run add collection item method
|
||||
if (in_array($function, $addCollection)) {
|
||||
$key = ucfirst(str_replace('add', '', $function) . 's');
|
||||
|
||||
$collectionObject = $this->collections[$key];
|
||||
|
||||
return $collectionObject->addItem($args[0] ?? null);
|
||||
}
|
||||
|
||||
// Run add style method
|
||||
if (in_array($function, $addStyle)) {
|
||||
return forward_static_call_array(['PhpOffice\\PhpWord\\Style', $function], $args);
|
||||
}
|
||||
|
||||
// Exception
|
||||
throw new BadMethodCallException("Method $function is not defined.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get document properties object.
|
||||
*
|
||||
* @return Metadata\DocInfo
|
||||
*/
|
||||
public function getDocInfo()
|
||||
{
|
||||
return $this->metadata['DocInfo'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get compatibility.
|
||||
*
|
||||
* @return Metadata\Compatibility
|
||||
*
|
||||
* @since 0.12.0
|
||||
*/
|
||||
public function getCompatibility()
|
||||
{
|
||||
return $this->metadata['Compatibility'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get compatibility.
|
||||
*
|
||||
* @return Metadata\Settings
|
||||
*
|
||||
* @since 0.14.0
|
||||
*/
|
||||
public function getSettings()
|
||||
{
|
||||
return $this->metadata['Settings'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all sections.
|
||||
*
|
||||
* @return Section[]
|
||||
*/
|
||||
public function getSections()
|
||||
{
|
||||
return $this->sections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the section at the requested position.
|
||||
*
|
||||
* @param int $index
|
||||
*
|
||||
* @return null|Section
|
||||
*/
|
||||
public function getSection($index)
|
||||
{
|
||||
if (array_key_exists($index, $this->sections)) {
|
||||
return $this->sections[$index];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new section.
|
||||
*
|
||||
* @param null|array|string $style
|
||||
*
|
||||
* @return Section
|
||||
*/
|
||||
public function addSection($style = null)
|
||||
{
|
||||
$section = new Section(count($this->sections) + 1, $style);
|
||||
$section->setPhpWord($this);
|
||||
$this->sections[] = $section;
|
||||
|
||||
return $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the sections using the callable passed.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.usort.php for usage
|
||||
*
|
||||
* @param callable $sorter
|
||||
*/
|
||||
public function sortSections($sorter): void
|
||||
{
|
||||
usort($this->sections, $sorter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default font name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultFontName()
|
||||
{
|
||||
return Settings::getDefaultFontName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default font name.
|
||||
*
|
||||
* @param string $fontName
|
||||
*/
|
||||
public function setDefaultFontName($fontName): void
|
||||
{
|
||||
Settings::setDefaultFontName($fontName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default asian font name.
|
||||
*/
|
||||
public function getDefaultAsianFontName(): string
|
||||
{
|
||||
return Settings::getDefaultAsianFontName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default asian font name.
|
||||
*
|
||||
* @param string $fontName
|
||||
*/
|
||||
public function setDefaultAsianFontName($fontName): void
|
||||
{
|
||||
Settings::setDefaultAsianFontName($fontName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default font color.
|
||||
*/
|
||||
public function setDefaultFontColor(string $fontColor): void
|
||||
{
|
||||
Settings::setDefaultFontColor($fontColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default font color.
|
||||
*/
|
||||
public function getDefaultFontColor(): string
|
||||
{
|
||||
return Settings::getDefaultFontColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default font size.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDefaultFontSize()
|
||||
{
|
||||
return Settings::getDefaultFontSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default font size.
|
||||
*
|
||||
* @param int $fontSize
|
||||
*/
|
||||
public function setDefaultFontSize($fontSize): void
|
||||
{
|
||||
Settings::setDefaultFontSize($fontSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default paragraph style definition to styles.xml.
|
||||
*
|
||||
* @param array $styles Paragraph style definition
|
||||
*
|
||||
* @return Style\Paragraph
|
||||
*/
|
||||
public function setDefaultParagraphStyle($styles)
|
||||
{
|
||||
return Style::setDefaultParagraphStyle($styles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save to file or download.
|
||||
*
|
||||
* All exceptions should already been handled by the writers
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string $format
|
||||
* @param bool $download
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function save($filename, $format = 'Word2007', $download = false)
|
||||
{
|
||||
$mime = [
|
||||
'Word2007' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'ODText' => 'application/vnd.oasis.opendocument.text',
|
||||
'RTF' => 'application/rtf',
|
||||
'HTML' => 'text/html',
|
||||
'PDF' => 'application/pdf',
|
||||
];
|
||||
|
||||
$writer = IOFactory::createWriter($this, $format);
|
||||
|
||||
if ($download === true) {
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||
header('Content-Type: ' . $mime[$format]);
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
||||
header('Expires: 0');
|
||||
$filename = 'php://output'; // Change filename to force download
|
||||
}
|
||||
|
||||
$writer->save($filename);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new section.
|
||||
*
|
||||
* @deprecated 0.10.0
|
||||
*
|
||||
* @param array $settings
|
||||
*
|
||||
* @return Section
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function createSection($settings = null)
|
||||
{
|
||||
return $this->addSection($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get document properties object.
|
||||
*
|
||||
* @deprecated 0.12.0
|
||||
*
|
||||
* @return Metadata\DocInfo
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getDocumentProperties()
|
||||
{
|
||||
return $this->getDocInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set document properties object.
|
||||
*
|
||||
* @deprecated 0.12.0
|
||||
*
|
||||
* @param Metadata\DocInfo $documentProperties
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function setDocumentProperties($documentProperties)
|
||||
{
|
||||
$this->metadata['Document'] = $documentProperties;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?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\Reader;
|
||||
|
||||
use PhpOffice\PhpWord\Exception\Exception;
|
||||
|
||||
/**
|
||||
* Reader abstract class.
|
||||
*
|
||||
* @since 0.8.0
|
||||
*
|
||||
* @codeCoverageIgnore Abstract class
|
||||
*/
|
||||
abstract class AbstractReader implements ReaderInterface
|
||||
{
|
||||
/**
|
||||
* Read data only?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $readDataOnly = true;
|
||||
|
||||
/**
|
||||
* File pointer.
|
||||
*
|
||||
* @var bool|resource
|
||||
*/
|
||||
protected $fileHandle;
|
||||
|
||||
/**
|
||||
* Load images.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $imageLoading = true;
|
||||
|
||||
/**
|
||||
* Read data only?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isReadDataOnly()
|
||||
{
|
||||
// return $this->readDataOnly;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set read data only.
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setReadDataOnly($value = true)
|
||||
{
|
||||
$this->readDataOnly = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasImageLoading(): bool
|
||||
{
|
||||
return $this->imageLoading;
|
||||
}
|
||||
|
||||
public function setImageLoading(bool $value): self
|
||||
{
|
||||
$this->imageLoading = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open file for reading.
|
||||
*
|
||||
* @param string $filename
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
protected function openFile($filename)
|
||||
{
|
||||
// Check if file exists
|
||||
if (!file_exists($filename) || !is_readable($filename)) {
|
||||
throw new Exception("Could not open $filename for reading! File does not exist.");
|
||||
}
|
||||
|
||||
// Open file
|
||||
$this->fileHandle = fopen($filename, 'rb');
|
||||
if ($this->fileHandle === false) {
|
||||
throw new Exception("Could not open file $filename for reading.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the current ReaderInterface read the file?
|
||||
*
|
||||
* @param string $filename
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canRead($filename)
|
||||
{
|
||||
// Check if file exists
|
||||
try {
|
||||
$this->openFile($filename);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
if (is_resource($this->fileHandle)) {
|
||||
fclose($this->fileHandle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?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\Reader;
|
||||
|
||||
use Exception;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\Html as HTMLParser;
|
||||
|
||||
/**
|
||||
* HTML Reader class.
|
||||
*
|
||||
* @since 0.11.0
|
||||
*/
|
||||
class HTML extends AbstractReader implements ReaderInterface
|
||||
{
|
||||
/**
|
||||
* Loads PhpWord from file.
|
||||
*
|
||||
* @param string $docFile
|
||||
*
|
||||
* @return PhpWord
|
||||
*/
|
||||
public function load($docFile)
|
||||
{
|
||||
$phpWord = new PhpWord();
|
||||
|
||||
if ($this->canRead($docFile)) {
|
||||
$section = $phpWord->addSection();
|
||||
HTMLParser::addHtml($section, file_get_contents($docFile), true);
|
||||
} else {
|
||||
throw new Exception("Cannot read {$docFile}.");
|
||||
}
|
||||
|
||||
return $phpWord;
|
||||
}
|
||||
}
|
||||
+2462
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
<?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\Reader;
|
||||
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
|
||||
/**
|
||||
* Reader for ODText.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class ODText extends AbstractReader implements ReaderInterface
|
||||
{
|
||||
/**
|
||||
* Loads PhpWord from file.
|
||||
*
|
||||
* @param string $docFile
|
||||
*
|
||||
* @return PhpWord
|
||||
*/
|
||||
public function load($docFile)
|
||||
{
|
||||
$phpWord = new PhpWord();
|
||||
$relationships = $this->readRelationships($docFile);
|
||||
|
||||
$readerParts = [
|
||||
'content.xml' => 'Content',
|
||||
'meta.xml' => 'Meta',
|
||||
];
|
||||
|
||||
foreach ($readerParts as $xmlFile => $partName) {
|
||||
$this->readPart($phpWord, $relationships, $partName, $docFile, $xmlFile);
|
||||
}
|
||||
|
||||
return $phpWord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read document part.
|
||||
*/
|
||||
private function readPart(PhpWord $phpWord, array $relationships, string $partName, string $docFile, string $xmlFile): void
|
||||
{
|
||||
$partClass = "PhpOffice\\PhpWord\\Reader\\ODText\\{$partName}";
|
||||
if (class_exists($partClass)) {
|
||||
/** @var ODText\AbstractPart $part Type hint */
|
||||
$part = new $partClass($docFile, $xmlFile);
|
||||
$part->setRels($relationships);
|
||||
$part->read($phpWord);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all relationship files.
|
||||
*/
|
||||
private function readRelationships(string $docFile): array
|
||||
{
|
||||
$rels = [];
|
||||
$xmlFile = 'META-INF/manifest.xml';
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($docFile, $xmlFile);
|
||||
$nodes = $xmlReader->getElements('manifest:file-entry');
|
||||
foreach ($nodes as $node) {
|
||||
$type = $xmlReader->getAttribute('manifest:media-type', $node);
|
||||
$target = $xmlReader->getAttribute('manifest:full-path', $node);
|
||||
$rels[] = ['type' => $type, 'target' => $target];
|
||||
}
|
||||
|
||||
return $rels;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Reader\ODText;
|
||||
|
||||
use PhpOffice\PhpWord\Reader\Word2007\AbstractPart as Word2007AbstractPart;
|
||||
|
||||
/**
|
||||
* Abstract part reader.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
abstract class AbstractPart extends Word2007AbstractPart
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
<?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\Reader\ODText;
|
||||
|
||||
use DateTime;
|
||||
use DOMElement;
|
||||
use DOMNodeList;
|
||||
use PhpOffice\Math\Reader\MathML;
|
||||
use PhpOffice\PhpWord\Element\Section;
|
||||
use PhpOffice\PhpWord\Element\TrackChange;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
|
||||
/**
|
||||
* Content reader.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class Content extends AbstractPart
|
||||
{
|
||||
/** @var ?Section */
|
||||
private $section;
|
||||
|
||||
/**
|
||||
* Read content.xml.
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
|
||||
$trackedChanges = [];
|
||||
|
||||
$nodes = $xmlReader->getElements('office:body/office:text/*');
|
||||
$this->section = null;
|
||||
$this->processNodes($nodes, $xmlReader, $phpWord);
|
||||
$this->section = null;
|
||||
}
|
||||
|
||||
/** @param DOMNodeList<DOMElement> $nodes */
|
||||
public function processNodes(DOMNodeList $nodes, XMLReader $xmlReader, PhpWord $phpWord): void
|
||||
{
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
// $styleName = $xmlReader->getAttribute('text:style-name', $node);
|
||||
switch ($node->nodeName) {
|
||||
case 'text:h': // Heading
|
||||
$depth = $xmlReader->getAttribute('text:outline-level', $node);
|
||||
$this->getSection($phpWord)->addTitle($node->nodeValue, $depth);
|
||||
|
||||
break;
|
||||
case 'text:p': // Paragraph
|
||||
$styleName = $xmlReader->getAttribute('text:style-name', $node);
|
||||
if (substr($styleName, 0, 2) === 'SB') {
|
||||
break;
|
||||
}
|
||||
$element = $xmlReader->getElement('draw:frame/draw:object', $node);
|
||||
if ($element) {
|
||||
$mathFile = str_replace('./', '', $element->getAttribute('xlink:href')) . '/content.xml';
|
||||
|
||||
$xmlReaderObject = new XMLReader();
|
||||
$mathElement = $xmlReaderObject->getDomFromZip($this->docFile, $mathFile);
|
||||
if ($mathElement) {
|
||||
$mathXML = $mathElement->saveXML($mathElement);
|
||||
|
||||
if (is_string($mathXML)) {
|
||||
$reader = new MathML();
|
||||
$math = $reader->read($mathXML);
|
||||
|
||||
$this->getSection($phpWord)->addFormula($math);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$children = $node->childNodes;
|
||||
$spans = false;
|
||||
/** @var DOMElement $child */
|
||||
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;
|
||||
case 'text:span':
|
||||
$spans = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($spans) {
|
||||
$element = $this->getSection($phpWord)->addTextRun();
|
||||
foreach ($children as $child) {
|
||||
switch ($child->nodeName) {
|
||||
case 'text:span':
|
||||
/** @var DOMElement $child2 */
|
||||
foreach ($child->childNodes as $child2) {
|
||||
switch ($child2->nodeName) {
|
||||
case '#text':
|
||||
$element->addText($child2->nodeValue);
|
||||
|
||||
break;
|
||||
case 'text:tab':
|
||||
$element->addText("\t");
|
||||
|
||||
break;
|
||||
case 'text:s':
|
||||
$spaces = (int) $child2->getAttribute('text:c') ?: 1;
|
||||
$element->addText(str_repeat(' ', $spaces));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$element = $this->getSection($phpWord)->addText($node->nodeValue);
|
||||
}
|
||||
if (isset($changed) && is_array($changed)) {
|
||||
$element->setTrackChange($changed['changed']);
|
||||
if (isset($changed['textNodes'])) {
|
||||
foreach ($changed['textNodes'] as $changedNode) {
|
||||
$element = $this->getSection($phpWord)->addText($changedNode->nodeValue);
|
||||
$element->setTrackChange($changed['changed']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'text:list': // List
|
||||
$listItems = $xmlReader->getElements('text:list-item/text:p', $node);
|
||||
foreach ($listItems as $listItem) {
|
||||
// $listStyleName = $xmlReader->getAttribute('text:style-name', $listItem);
|
||||
$this->getSection($phpWord)->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')] = ['changed' => $changed, 'textNodes' => $textNodes];
|
||||
}
|
||||
|
||||
break;
|
||||
case 'text:section': // Section
|
||||
// $sectionStyleName = $xmlReader->getAttribute('text:style-name', $listItem);
|
||||
$this->section = $phpWord->addSection();
|
||||
$children = $node->childNodes;
|
||||
$this->processNodes($children, $xmlReader, $phpWord);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getSection(PhpWord $phpWord): Section
|
||||
{
|
||||
$section = $this->section;
|
||||
if ($section === null) {
|
||||
$section = $this->section = $phpWord->addSection();
|
||||
}
|
||||
|
||||
return $section;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?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\Reader\ODText;
|
||||
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
|
||||
/**
|
||||
* Meta reader.
|
||||
*
|
||||
* @since 0.11.0
|
||||
*/
|
||||
class Meta extends AbstractPart
|
||||
{
|
||||
/**
|
||||
* Read meta.xml.
|
||||
*
|
||||
* @todo Process property type
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
$docProps = $phpWord->getDocInfo();
|
||||
|
||||
$metaNode = $xmlReader->getElement('office:meta');
|
||||
|
||||
// Standard properties
|
||||
$properties = [
|
||||
'title' => 'dc:title',
|
||||
'subject' => 'dc:subject',
|
||||
'description' => 'dc:description',
|
||||
'keywords' => 'meta:keyword',
|
||||
'creator' => 'meta:initial-creator',
|
||||
'lastModifiedBy' => 'dc:creator',
|
||||
// 'created' => 'meta:creation-date',
|
||||
// 'modified' => 'dc:date',
|
||||
];
|
||||
foreach ($properties as $property => $path) {
|
||||
$method = "set{$property}";
|
||||
$propertyNode = $xmlReader->getElement($path, $metaNode);
|
||||
if ($propertyNode !== null && method_exists($docProps, $method)) {
|
||||
$docProps->$method($propertyNode->nodeValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Custom properties
|
||||
$propertyNodes = $xmlReader->getElements('meta:user-defined', $metaNode);
|
||||
foreach ($propertyNodes as $propertyNode) {
|
||||
$property = $xmlReader->getAttribute('meta:name', $propertyNode);
|
||||
|
||||
// Set category, company, and manager property
|
||||
if (in_array($property, ['Category', 'Company', 'Manager'])) {
|
||||
$method = "set{$property}";
|
||||
$docProps->$method($propertyNode->nodeValue);
|
||||
} else {
|
||||
// Set other custom properties
|
||||
$docProps->setCustomProperty($property, $propertyNode->nodeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?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\Reader;
|
||||
|
||||
use Exception;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Reader\RTF\Document;
|
||||
|
||||
/**
|
||||
* RTF Reader class.
|
||||
*
|
||||
* @since 0.11.0
|
||||
*/
|
||||
class RTF extends AbstractReader implements ReaderInterface
|
||||
{
|
||||
/**
|
||||
* Loads PhpWord from file.
|
||||
*
|
||||
* @param string $docFile
|
||||
*
|
||||
* @return PhpWord
|
||||
*/
|
||||
public function load($docFile)
|
||||
{
|
||||
$phpWord = new PhpWord();
|
||||
|
||||
if ($this->canRead($docFile)) {
|
||||
$doc = new Document();
|
||||
$doc->rtf = file_get_contents($docFile);
|
||||
$doc->read($phpWord);
|
||||
} else {
|
||||
throw new Exception("Cannot read {$docFile}.");
|
||||
}
|
||||
|
||||
return $phpWord;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
<?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\Reader\RTF;
|
||||
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\SimpleType\Jc;
|
||||
|
||||
/**
|
||||
* RTF document reader.
|
||||
*
|
||||
* References:
|
||||
* - How to Write an RTF Reader http://latex2rtf.sourceforge.net/rtfspec_45.html
|
||||
* - PHP rtfclass by Markus Fischer https://github.com/mfn/rtfclass
|
||||
* - JavaScript RTF-parser by LazyGyu https://github.com/lazygyu/RTF-parser
|
||||
*
|
||||
* @since 0.11.0
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedPrivateMethod)
|
||||
*/
|
||||
class Document
|
||||
{
|
||||
/** @const int */
|
||||
const PARA = 'readParagraph';
|
||||
const STYL = 'readStyle';
|
||||
const SKIP = 'readSkip';
|
||||
|
||||
/**
|
||||
* PhpWord object.
|
||||
*
|
||||
* @var PhpWord
|
||||
*/
|
||||
private $phpWord;
|
||||
|
||||
/**
|
||||
* Section object.
|
||||
*
|
||||
* @var \PhpOffice\PhpWord\Element\Section
|
||||
*/
|
||||
private $section;
|
||||
|
||||
/**
|
||||
* Textrun object.
|
||||
*
|
||||
* @var \PhpOffice\PhpWord\Element\TextRun
|
||||
*/
|
||||
private $textrun;
|
||||
|
||||
/**
|
||||
* RTF content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $rtf;
|
||||
|
||||
/**
|
||||
* Content length.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $length = 0;
|
||||
|
||||
/**
|
||||
* Character index.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $offset = 0;
|
||||
|
||||
/**
|
||||
* Current control word.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $control = '';
|
||||
|
||||
/**
|
||||
* Text content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $text = '';
|
||||
|
||||
/**
|
||||
* Parsing a control word flag.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $isControl = false;
|
||||
|
||||
/**
|
||||
* First character flag: watch out for control symbols.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $isFirst = false;
|
||||
|
||||
/**
|
||||
* Group groups.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $groups = [];
|
||||
|
||||
/**
|
||||
* Parser flags; not used.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $flags = [];
|
||||
|
||||
/**
|
||||
* Parse RTF content.
|
||||
*
|
||||
* - Marks controlling characters `{`, `}`, and `\`
|
||||
* - Removes line endings
|
||||
* - Builds control words and control symbols
|
||||
* - Pushes every other character into the text queue
|
||||
*
|
||||
* @todo Use `fread` stream for scalability
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$markers = [
|
||||
123 => 'markOpening', // {
|
||||
125 => 'markClosing', // }
|
||||
92 => 'markBackslash', // \
|
||||
10 => 'markNewline', // LF
|
||||
13 => 'markNewline', // CR
|
||||
];
|
||||
|
||||
$this->phpWord = $phpWord;
|
||||
$this->section = $phpWord->addSection();
|
||||
$this->textrun = $this->section->addTextRun();
|
||||
$this->length = strlen($this->rtf);
|
||||
|
||||
$this->flags['paragraph'] = true; // Set paragraph flag from the beginning
|
||||
|
||||
// Walk each characters
|
||||
while ($this->offset < $this->length) {
|
||||
$char = $this->rtf[$this->offset];
|
||||
$ascii = ord($char);
|
||||
|
||||
if (isset($markers[$ascii])) { // Marker found: {, }, \, LF, or CR
|
||||
$markerFunction = $markers[$ascii];
|
||||
$this->$markerFunction();
|
||||
} else {
|
||||
if (false === $this->isControl) { // Non control word: Push character
|
||||
$this->pushText($char);
|
||||
} else {
|
||||
if (preg_match('/^[a-zA-Z0-9-]?$/', $char)) { // No delimiter: Buffer control
|
||||
$this->control .= $char;
|
||||
$this->isFirst = false;
|
||||
} else { // Delimiter found: Parse buffered control
|
||||
if ($this->isFirst) {
|
||||
$this->isFirst = false;
|
||||
} else {
|
||||
if (' ' == $char) { // Discard space as a control word delimiter
|
||||
$this->flushControl(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++$this->offset;
|
||||
}
|
||||
$this->flushText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark opening braket `{` character.
|
||||
*/
|
||||
private function markOpening(): void
|
||||
{
|
||||
$this->flush(true);
|
||||
array_push($this->groups, $this->flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark closing braket `}` character.
|
||||
*/
|
||||
private function markClosing(): void
|
||||
{
|
||||
$this->flush(true);
|
||||
$this->flags = array_pop($this->groups);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark backslash `\` character.
|
||||
*/
|
||||
private function markBackslash(): void
|
||||
{
|
||||
if ($this->isFirst) {
|
||||
$this->setControl(false);
|
||||
$this->text .= '\\';
|
||||
} else {
|
||||
$this->flush();
|
||||
$this->setControl(true);
|
||||
$this->control = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark newline character: Flush control word because it's not possible to span multiline.
|
||||
*/
|
||||
private function markNewline(): void
|
||||
{
|
||||
if ($this->isControl) {
|
||||
$this->flushControl(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush control word or text.
|
||||
*
|
||||
* @param bool $isControl
|
||||
*/
|
||||
private function flush($isControl = false): void
|
||||
{
|
||||
if ($this->isControl) {
|
||||
$this->flushControl($isControl);
|
||||
} else {
|
||||
$this->flushText();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush control word.
|
||||
*
|
||||
* @param bool $isControl
|
||||
*/
|
||||
private function flushControl($isControl = false): void
|
||||
{
|
||||
if (1 === preg_match('/^([A-Za-z]+)(-?[0-9]*) ?$/', $this->control, $match)) {
|
||||
[, $control, $parameter] = $match;
|
||||
$this->parseControl($control, $parameter);
|
||||
}
|
||||
|
||||
if (true === $isControl) {
|
||||
$this->setControl(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush text in queue.
|
||||
*/
|
||||
private function flushText(): void
|
||||
{
|
||||
if ($this->text != '') {
|
||||
if (isset($this->flags['property'])) { // Set property
|
||||
$this->flags['value'] = $this->text;
|
||||
} else { // Set text
|
||||
if (true === $this->flags['paragraph']) {
|
||||
$this->flags['paragraph'] = false;
|
||||
$this->flags['text'] = $this->text;
|
||||
}
|
||||
}
|
||||
|
||||
// Add text if it's not flagged as skipped
|
||||
if (!isset($this->flags['skipped'])) {
|
||||
$this->readText();
|
||||
}
|
||||
|
||||
$this->text = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset control word and first char state.
|
||||
*
|
||||
* @param bool $value
|
||||
*/
|
||||
private function setControl($value): void
|
||||
{
|
||||
$this->isControl = $value;
|
||||
$this->isFirst = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push text into queue.
|
||||
*
|
||||
* @param string $char
|
||||
*/
|
||||
private function pushText($char): void
|
||||
{
|
||||
if ('<' == $char) {
|
||||
$this->text .= '<';
|
||||
} elseif ('>' == $char) {
|
||||
$this->text .= '>';
|
||||
} else {
|
||||
$this->text .= $char;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse control.
|
||||
*
|
||||
* @param string $control
|
||||
* @param string $parameter
|
||||
*/
|
||||
private function parseControl($control, $parameter): void
|
||||
{
|
||||
$controls = [
|
||||
'par' => [self::PARA, 'paragraph', true],
|
||||
'b' => [self::STYL, 'font', 'bold', true],
|
||||
'i' => [self::STYL, 'font', 'italic', true],
|
||||
'u' => [self::STYL, 'font', 'underline', true],
|
||||
'strike' => [self::STYL, 'font', 'strikethrough', true],
|
||||
'fs' => [self::STYL, 'font', 'size', $parameter],
|
||||
'qc' => [self::STYL, 'paragraph', 'alignment', Jc::CENTER],
|
||||
'sa' => [self::STYL, 'paragraph', 'spaceAfter', $parameter],
|
||||
'fonttbl' => [self::SKIP, 'fonttbl', null],
|
||||
'colortbl' => [self::SKIP, 'colortbl', null],
|
||||
'info' => [self::SKIP, 'info', null],
|
||||
'generator' => [self::SKIP, 'generator', null],
|
||||
'title' => [self::SKIP, 'title', null],
|
||||
'subject' => [self::SKIP, 'subject', null],
|
||||
'category' => [self::SKIP, 'category', null],
|
||||
'keywords' => [self::SKIP, 'keywords', null],
|
||||
'comment' => [self::SKIP, 'comment', null],
|
||||
'shppict' => [self::SKIP, 'pic', null],
|
||||
'fldinst' => [self::SKIP, 'link', null],
|
||||
];
|
||||
|
||||
if (isset($controls[$control])) {
|
||||
[$function] = $controls[$control];
|
||||
if (method_exists($this, $function)) {
|
||||
$directives = $controls[$control];
|
||||
array_shift($directives); // remove the function variable; we won't need it
|
||||
$this->$function($directives);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read paragraph.
|
||||
*
|
||||
* @param array $directives
|
||||
*/
|
||||
private function readParagraph($directives): void
|
||||
{
|
||||
[$property, $value] = $directives;
|
||||
$this->textrun = $this->section->addTextRun();
|
||||
$this->flags[$property] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read style.
|
||||
*
|
||||
* @param array $directives
|
||||
*/
|
||||
private function readStyle($directives): void
|
||||
{
|
||||
[$style, $property, $value] = $directives;
|
||||
$this->flags['styles'][$style][$property] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read skip.
|
||||
*
|
||||
* @param array $directives
|
||||
*/
|
||||
private function readSkip($directives): void
|
||||
{
|
||||
[$property] = $directives;
|
||||
$this->flags['property'] = $property;
|
||||
$this->flags['skipped'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read text.
|
||||
*/
|
||||
private function readText(): void
|
||||
{
|
||||
$text = $this->textrun->addText($this->text);
|
||||
if (isset($this->flags['styles']['font'])) {
|
||||
$text->getFontStyle()->setStyleByArray($this->flags['styles']['font']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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\Reader;
|
||||
|
||||
/**
|
||||
* Reader interface.
|
||||
*
|
||||
* @since 0.8.0
|
||||
*/
|
||||
interface ReaderInterface
|
||||
{
|
||||
/**
|
||||
* Can the current ReaderInterface read the file?
|
||||
*
|
||||
* @param string $filename
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canRead($filename);
|
||||
|
||||
/**
|
||||
* Loads PhpWord from file.
|
||||
*
|
||||
* @param string $filename
|
||||
*/
|
||||
public function load($filename);
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
<?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\Reader;
|
||||
|
||||
use Exception;
|
||||
use PhpOffice\PhpWord\Element\AbstractElement;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Reader\Word2007\AbstractPart;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
use PhpOffice\PhpWord\Shared\ZipArchive;
|
||||
|
||||
/**
|
||||
* Reader for Word2007.
|
||||
*
|
||||
* @since 0.8.0
|
||||
*
|
||||
* @todo watermark, checkbox, toc
|
||||
* @todo Partly done: image, object
|
||||
*/
|
||||
class Word2007 extends AbstractReader implements ReaderInterface
|
||||
{
|
||||
/**
|
||||
* Loads PhpWord from file.
|
||||
*
|
||||
* @param string $docFile
|
||||
*
|
||||
* @return PhpWord
|
||||
*/
|
||||
public function load($docFile)
|
||||
{
|
||||
$phpWord = new PhpWord();
|
||||
$relationships = $this->readRelationships($docFile);
|
||||
$commentRefs = [];
|
||||
|
||||
$steps = [
|
||||
[
|
||||
'stepPart' => 'document',
|
||||
'stepItems' => [
|
||||
'styles' => 'Styles',
|
||||
'numbering' => 'Numbering',
|
||||
],
|
||||
],
|
||||
[
|
||||
'stepPart' => 'main',
|
||||
'stepItems' => [
|
||||
'officeDocument' => 'Document',
|
||||
'core-properties' => 'DocPropsCore',
|
||||
'extended-properties' => 'DocPropsApp',
|
||||
'custom-properties' => 'DocPropsCustom',
|
||||
],
|
||||
],
|
||||
[
|
||||
'stepPart' => 'document',
|
||||
'stepItems' => [
|
||||
'endnotes' => 'Endnotes',
|
||||
'footnotes' => 'Footnotes',
|
||||
'settings' => 'Settings',
|
||||
'comments' => 'Comments',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($steps as $step) {
|
||||
$stepPart = $step['stepPart'];
|
||||
$stepItems = $step['stepItems'];
|
||||
if (!isset($relationships[$stepPart])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($relationships[$stepPart] as $relItem) {
|
||||
$relType = $relItem['type'];
|
||||
if (isset($stepItems[$relType])) {
|
||||
$partName = $stepItems[$relType];
|
||||
$xmlFile = $relItem['target'];
|
||||
$part = $this->readPart($phpWord, $relationships, $commentRefs, $partName, $docFile, $xmlFile);
|
||||
$commentRefs = $part->getCommentReferences();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $phpWord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read document part.
|
||||
*
|
||||
* @param array<string, array<string, null|AbstractElement>> $commentRefs
|
||||
*/
|
||||
private function readPart(PhpWord $phpWord, array $relationships, array $commentRefs, string $partName, string $docFile, string $xmlFile): AbstractPart
|
||||
{
|
||||
$partClass = "PhpOffice\\PhpWord\\Reader\\Word2007\\{$partName}";
|
||||
if (!class_exists($partClass)) {
|
||||
throw new Exception(sprintf('The part "%s" doesn\'t exist', $partClass));
|
||||
}
|
||||
|
||||
/** @var AbstractPart $part Type hint */
|
||||
$part = new $partClass($docFile, $xmlFile);
|
||||
$part->setImageLoading($this->hasImageLoading());
|
||||
$part->setRels($relationships);
|
||||
$part->setCommentReferences($commentRefs);
|
||||
$part->read($phpWord);
|
||||
|
||||
return $part;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all relationship files.
|
||||
*
|
||||
* @param string $docFile
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function readRelationships($docFile)
|
||||
{
|
||||
$relationships = [];
|
||||
|
||||
// _rels/.rels
|
||||
$relationships['main'] = $this->getRels($docFile, '_rels/.rels');
|
||||
|
||||
// word/_rels/*.xml.rels
|
||||
$wordRelsPath = 'word/_rels/';
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($docFile) === true) {
|
||||
for ($i = 0; $i < $zip->numFiles; ++$i) {
|
||||
$xmlFile = $zip->getNameIndex($i);
|
||||
if ((substr($xmlFile, 0, strlen($wordRelsPath))) == $wordRelsPath && (substr($xmlFile, -1)) != '/') {
|
||||
$docPart = str_replace('.xml.rels', '', str_replace($wordRelsPath, '', $xmlFile));
|
||||
$relationships[$docPart] = $this->getRels($docFile, $xmlFile, 'word/');
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
return $relationships;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get relationship array.
|
||||
*
|
||||
* @param string $docFile
|
||||
* @param string $xmlFile
|
||||
* @param string $targetPrefix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getRels($docFile, $xmlFile, $targetPrefix = '')
|
||||
{
|
||||
$metaPrefix = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/';
|
||||
$officePrefix = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/';
|
||||
|
||||
$rels = [];
|
||||
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($docFile, $xmlFile);
|
||||
$nodes = $xmlReader->getElements('*');
|
||||
foreach ($nodes as $node) {
|
||||
$rId = $xmlReader->getAttribute('Id', $node);
|
||||
$type = $xmlReader->getAttribute('Type', $node);
|
||||
$target = $xmlReader->getAttribute('Target', $node);
|
||||
$mode = $xmlReader->getAttribute('TargetMode', $node);
|
||||
|
||||
// Remove URL prefixes from $type to make it easier to read
|
||||
$type = str_replace($metaPrefix, '', $type);
|
||||
$type = str_replace($officePrefix, '', $type);
|
||||
$docPart = str_replace('.xml', '', $target);
|
||||
|
||||
// Do not add prefix to link source
|
||||
if ($type != 'hyperlink' && $mode != 'External') {
|
||||
$target = $targetPrefix . $target;
|
||||
}
|
||||
|
||||
// Push to return array
|
||||
$rels[$rId] = ['type' => $type, 'target' => $target, 'docPart' => $docPart, 'targetMode' => $mode];
|
||||
}
|
||||
ksort($rels);
|
||||
|
||||
return $rels;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpWord\Reader\Word2007;
|
||||
|
||||
use DateTime;
|
||||
use PhpOffice\PhpWord\Element\Comment;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
|
||||
class Comments extends AbstractPart
|
||||
{
|
||||
/**
|
||||
* Collection name comments.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $collection = 'comments';
|
||||
|
||||
/**
|
||||
* Read settings.xml.
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
|
||||
$comments = $phpWord->getComments();
|
||||
|
||||
$nodes = $xmlReader->getElements('*');
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
$name = str_replace('w:', '', $node->nodeName);
|
||||
|
||||
$author = $xmlReader->getAttribute('w:author', $node);
|
||||
$date = $xmlReader->getAttribute('w:date', $node);
|
||||
$initials = $xmlReader->getAttribute('w:initials', $node);
|
||||
|
||||
$element = new Comment($author, new DateTime($date), $initials);
|
||||
|
||||
$range = $this->getCommentReference($xmlReader->getAttribute('w:id', $node));
|
||||
if ($range['start']) {
|
||||
$range['start']->setCommentRangeStart($element);
|
||||
}
|
||||
if ($range['end']) {
|
||||
$range['end']->setCommentRangeEnd($element);
|
||||
}
|
||||
|
||||
$pNodes = $xmlReader->getElements('w:p/w:r', $node);
|
||||
foreach ($pNodes as $pNode) {
|
||||
$this->readRun($xmlReader, $pNode, $element, $this->collection);
|
||||
}
|
||||
|
||||
$phpWord->getComments()->addItem($element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?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\Reader\Word2007;
|
||||
|
||||
/**
|
||||
* Extended properties reader.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class DocPropsApp extends DocPropsCore
|
||||
{
|
||||
/**
|
||||
* Property mapping.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mapping = ['Company' => 'setCompany', 'Manager' => 'setManager'];
|
||||
|
||||
/**
|
||||
* Callback functions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $callbacks = [];
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?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\Reader\Word2007;
|
||||
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
|
||||
/**
|
||||
* Core properties reader.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class DocPropsCore extends AbstractPart
|
||||
{
|
||||
/**
|
||||
* Property mapping.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mapping = [
|
||||
'dc:creator' => 'setCreator',
|
||||
'dc:title' => 'setTitle',
|
||||
'dc:description' => 'setDescription',
|
||||
'dc:subject' => 'setSubject',
|
||||
'cp:keywords' => 'setKeywords',
|
||||
'cp:category' => 'setCategory',
|
||||
'cp:lastModifiedBy' => 'setLastModifiedBy',
|
||||
'dcterms:created' => 'setCreated',
|
||||
'dcterms:modified' => 'setModified',
|
||||
];
|
||||
|
||||
/**
|
||||
* Callback functions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $callbacks = ['dcterms:created' => 'strtotime', 'dcterms:modified' => 'strtotime'];
|
||||
|
||||
/**
|
||||
* Read core/extended document properties.
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
|
||||
$docProps = $phpWord->getDocInfo();
|
||||
|
||||
$nodes = $xmlReader->getElements('*');
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
if (!isset($this->mapping[$node->nodeName])) {
|
||||
continue;
|
||||
}
|
||||
$method = $this->mapping[$node->nodeName];
|
||||
$value = $node->nodeValue == '' ? null : $node->nodeValue;
|
||||
if (isset($this->callbacks[$node->nodeName])) {
|
||||
$value = $this->callbacks[$node->nodeName]($value);
|
||||
}
|
||||
if (method_exists($docProps, $method)) {
|
||||
$docProps->$method($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?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\Reader\Word2007;
|
||||
|
||||
use PhpOffice\PhpWord\Metadata\DocInfo;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
|
||||
/**
|
||||
* Custom properties reader.
|
||||
*
|
||||
* @since 0.11.0
|
||||
*/
|
||||
class DocPropsCustom extends AbstractPart
|
||||
{
|
||||
/**
|
||||
* Read custom document properties.
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
$docProps = $phpWord->getDocInfo();
|
||||
|
||||
$nodes = $xmlReader->getElements('*');
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
$propertyName = $xmlReader->getAttribute('name', $node);
|
||||
$attributeNode = $xmlReader->getElement('*', $node);
|
||||
$attributeType = $attributeNode->nodeName;
|
||||
$attributeValue = $attributeNode->nodeValue;
|
||||
$attributeValue = DocInfo::convertProperty($attributeValue, $attributeType);
|
||||
$attributeType = DocInfo::convertPropertyType($attributeType);
|
||||
$docProps->setCustomProperty($propertyName, $attributeValue, $attributeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
<?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\Reader\Word2007;
|
||||
|
||||
use DOMElement;
|
||||
use PhpOffice\PhpWord\Element\Section;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
|
||||
/**
|
||||
* Document reader.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedPrivateMethod) For readWPNode
|
||||
*/
|
||||
class Document extends AbstractPart
|
||||
{
|
||||
/**
|
||||
* PhpWord object.
|
||||
*
|
||||
* @var PhpWord
|
||||
*/
|
||||
private $phpWord;
|
||||
|
||||
/**
|
||||
* Read document.xml.
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$this->phpWord = $phpWord;
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
$readMethods = ['w:p' => 'readWPNode', 'w:tbl' => 'readTable', 'w:sectPr' => 'readWSectPrNode'];
|
||||
|
||||
$nodes = $xmlReader->getElements('w:body/*');
|
||||
if ($nodes->length > 0) {
|
||||
$section = $this->phpWord->addSection();
|
||||
foreach ($nodes as $node) {
|
||||
if (isset($readMethods[$node->nodeName])) {
|
||||
$readMethod = $readMethods[$node->nodeName];
|
||||
$this->$readMethod($xmlReader, $node, $section);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read header footer.
|
||||
*
|
||||
* @param array $settings
|
||||
*/
|
||||
private function readHeaderFooter($settings, Section &$section): void
|
||||
{
|
||||
$readMethods = ['w:p' => 'readParagraph', 'w:tbl' => 'readTable'];
|
||||
|
||||
if (is_array($settings) && isset($settings['hf'])) {
|
||||
foreach ($settings['hf'] as $rId => $hfSetting) {
|
||||
if (isset($this->rels['document'][$rId])) {
|
||||
[$hfType, $xmlFile, $docPart] = array_values($this->rels['document'][$rId]);
|
||||
$addMethod = "add{$hfType}";
|
||||
$hfObject = $section->$addMethod($hfSetting['type']);
|
||||
|
||||
// Read header/footer content
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $xmlFile);
|
||||
$nodes = $xmlReader->getElements('*');
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
if (isset($readMethods[$node->nodeName])) {
|
||||
$readMethod = $readMethods[$node->nodeName];
|
||||
$this->$readMethod($xmlReader, $node, $hfObject, $docPart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read w:sectPr.
|
||||
*
|
||||
* @ignoreScrutinizerPatch
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function readSectionStyle(XMLReader $xmlReader, DOMElement $domNode)
|
||||
{
|
||||
$styleDefs = [
|
||||
'breakType' => [self::READ_VALUE, 'w:type'],
|
||||
'vAlign' => [self::READ_VALUE, 'w:vAlign'],
|
||||
'pageSizeW' => [self::READ_VALUE, 'w:pgSz', 'w:w'],
|
||||
'pageSizeH' => [self::READ_VALUE, 'w:pgSz', 'w:h'],
|
||||
'orientation' => [self::READ_VALUE, 'w:pgSz', 'w:orient'],
|
||||
'colsNum' => [self::READ_VALUE, 'w:cols', 'w:num'],
|
||||
'colsSpace' => [self::READ_VALUE, 'w:cols', 'w:space'],
|
||||
'marginTop' => [self::READ_VALUE, 'w:pgMar', 'w:top'],
|
||||
'marginLeft' => [self::READ_VALUE, 'w:pgMar', 'w:left'],
|
||||
'marginBottom' => [self::READ_VALUE, 'w:pgMar', 'w:bottom'],
|
||||
'marginRight' => [self::READ_VALUE, 'w:pgMar', 'w:right'],
|
||||
'headerHeight' => [self::READ_VALUE, 'w:pgMar', 'w:header'],
|
||||
'footerHeight' => [self::READ_VALUE, 'w:pgMar', 'w:footer'],
|
||||
'gutter' => [self::READ_VALUE, 'w:pgMar', 'w:gutter'],
|
||||
];
|
||||
$styles = $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
|
||||
|
||||
// Header and footer
|
||||
// @todo Cleanup this part
|
||||
$nodes = $xmlReader->getElements('*', $domNode);
|
||||
foreach ($nodes as $node) {
|
||||
if ($node->nodeName == 'w:headerReference' || $node->nodeName == 'w:footerReference') {
|
||||
$id = $xmlReader->getAttribute('r:id', $node);
|
||||
$styles['hf'][$id] = [
|
||||
'method' => str_replace('w:', '', str_replace('Reference', '', $node->nodeName)),
|
||||
'type' => $xmlReader->getAttribute('w:type', $node),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read w:p node.
|
||||
*/
|
||||
private function readWPNode(XMLReader $xmlReader, DOMElement $node, Section &$section): void
|
||||
{
|
||||
// Page break
|
||||
if ($xmlReader->getAttribute('w:type', $node, 'w:r/w:br') == 'page') {
|
||||
$section->addPageBreak(); // PageBreak
|
||||
}
|
||||
|
||||
// Paragraph
|
||||
$this->readParagraph($xmlReader, $node, $section);
|
||||
|
||||
// Section properties
|
||||
if ($xmlReader->elementExists('w:pPr/w:sectPr', $node)) {
|
||||
$sectPrNode = $xmlReader->getElement('w:pPr/w:sectPr', $node);
|
||||
if ($sectPrNode !== null) {
|
||||
$this->readWSectPrNode($xmlReader, $sectPrNode, $section);
|
||||
}
|
||||
$section = $this->phpWord->addSection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read w:sectPr node.
|
||||
*/
|
||||
private function readWSectPrNode(XMLReader $xmlReader, DOMElement $node, Section &$section): void
|
||||
{
|
||||
$style = $this->readSectionStyle($xmlReader, $node);
|
||||
$section->setStyle($style);
|
||||
$this->readHeaderFooter($style, $section);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?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\Reader\Word2007;
|
||||
|
||||
/**
|
||||
* Endnotes reader.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class Endnotes extends Footnotes
|
||||
{
|
||||
/**
|
||||
* Collection name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $collection = 'endnotes';
|
||||
|
||||
/**
|
||||
* Element name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $element = 'endnote';
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?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\Reader\Word2007;
|
||||
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
|
||||
/**
|
||||
* Footnotes reader.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class Footnotes extends AbstractPart
|
||||
{
|
||||
/**
|
||||
* Collection name footnotes|endnotes.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $collection = 'footnotes';
|
||||
|
||||
/**
|
||||
* Element name footnote|endnote.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $element = 'footnote';
|
||||
|
||||
/**
|
||||
* Read (footnotes|endnotes).xml.
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
$nodes = $xmlReader->getElements('*');
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
$id = $xmlReader->getAttribute('w:id', $node);
|
||||
$type = $xmlReader->getAttribute('w:type', $node);
|
||||
|
||||
// Avoid w:type "separator" and "continuationSeparator"
|
||||
// Only look for <footnote> or <endnote> without w:type attribute, or with w:type = normal
|
||||
if ((null === $type || $type === 'normal')) {
|
||||
$element = $this->getElement($phpWord, $id);
|
||||
if ($element !== null) {
|
||||
$pNodes = $xmlReader->getElements('w:p/*', $node);
|
||||
foreach ($pNodes as $pNode) {
|
||||
$this->readRun($xmlReader, $pNode, $element, $this->collection);
|
||||
}
|
||||
$addMethod = "add{$this->element}";
|
||||
$phpWord->$addMethod($element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for the element with the given relationId.
|
||||
*
|
||||
* @param int $relationId
|
||||
*
|
||||
* @return null|\PhpOffice\PhpWord\Element\AbstractContainer
|
||||
*/
|
||||
private function getElement(PhpWord $phpWord, $relationId)
|
||||
{
|
||||
$getMethod = "get{$this->collection}";
|
||||
$collection = $phpWord->$getMethod()->getItems();
|
||||
|
||||
//not found by key, looping to search by relationId
|
||||
foreach ($collection as $collectionElement) {
|
||||
if ($collectionElement->getRelationId() == $relationId) {
|
||||
return $collectionElement;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?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\Reader\Word2007;
|
||||
|
||||
use DOMElement;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
|
||||
/**
|
||||
* Numbering reader.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class Numbering extends AbstractPart
|
||||
{
|
||||
/**
|
||||
* Read numbering.xml.
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$abstracts = [];
|
||||
$numberings = [];
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
|
||||
// Abstract numbering definition
|
||||
$nodes = $xmlReader->getElements('w:abstractNum');
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
$abstractId = $xmlReader->getAttribute('w:abstractNumId', $node);
|
||||
$abstracts[$abstractId] = ['levels' => []];
|
||||
$abstract = &$abstracts[$abstractId];
|
||||
$subnodes = $xmlReader->getElements('*', $node);
|
||||
foreach ($subnodes as $subnode) {
|
||||
switch ($subnode->nodeName) {
|
||||
case 'w:multiLevelType':
|
||||
$abstract['type'] = $xmlReader->getAttribute('w:val', $subnode);
|
||||
|
||||
break;
|
||||
case 'w:lvl':
|
||||
$levelId = $xmlReader->getAttribute('w:ilvl', $subnode);
|
||||
$abstract['levels'][$levelId] = $this->readLevel($xmlReader, $subnode, $levelId);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Numbering instance definition
|
||||
$nodes = $xmlReader->getElements('w:num');
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
$numId = $xmlReader->getAttribute('w:numId', $node);
|
||||
$abstractId = $xmlReader->getAttribute('w:val', $node, 'w:abstractNumId');
|
||||
$numberings[$numId] = $abstracts[$abstractId];
|
||||
$numberings[$numId]['numId'] = $numId;
|
||||
$subnodes = $xmlReader->getElements('w:lvlOverride/w:lvl', $node);
|
||||
foreach ($subnodes as $subnode) {
|
||||
$levelId = $xmlReader->getAttribute('w:ilvl', $subnode);
|
||||
$overrides = $this->readLevel($xmlReader, $subnode, $levelId);
|
||||
foreach ($overrides as $key => $value) {
|
||||
$numberings[$numId]['levels'][$levelId][$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push to Style collection
|
||||
foreach ($numberings as $numId => $numbering) {
|
||||
$phpWord->addNumberingStyle("PHPWordList{$numId}", $numbering);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read numbering level definition from w:abstractNum and w:num.
|
||||
*
|
||||
* @param int $levelId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function readLevel(XMLReader $xmlReader, DOMElement $subnode, $levelId)
|
||||
{
|
||||
$level = [];
|
||||
|
||||
$level['level'] = $levelId;
|
||||
$level['start'] = $xmlReader->getAttribute('w:val', $subnode, 'w:start');
|
||||
$level['format'] = $xmlReader->getAttribute('w:val', $subnode, 'w:numFmt');
|
||||
$level['restart'] = $xmlReader->getAttribute('w:val', $subnode, 'w:lvlRestart');
|
||||
$level['suffix'] = $xmlReader->getAttribute('w:val', $subnode, 'w:suff');
|
||||
$level['text'] = $xmlReader->getAttribute('w:val', $subnode, 'w:lvlText');
|
||||
$level['alignment'] = $xmlReader->getAttribute('w:val', $subnode, 'w:lvlJc');
|
||||
$level['tab'] = $xmlReader->getAttribute('w:pos', $subnode, 'w:pPr/w:tabs/w:tab');
|
||||
$level['left'] = $xmlReader->getAttribute('w:left', $subnode, 'w:pPr/w:ind');
|
||||
$level['hanging'] = $xmlReader->getAttribute('w:hanging', $subnode, 'w:pPr/w:ind');
|
||||
$level['font'] = $xmlReader->getAttribute('w:ascii', $subnode, 'w:rPr/w:rFonts');
|
||||
$level['hint'] = $xmlReader->getAttribute('w:hint', $subnode, 'w:rPr/w:rFonts');
|
||||
|
||||
foreach ($level as $key => $value) {
|
||||
if (null === $value) {
|
||||
unset($level[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $level;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<?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\Reader\Word2007;
|
||||
|
||||
use DOMElement;
|
||||
use PhpOffice\PhpWord\ComplexType\TrackChangesView;
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
use PhpOffice\PhpWord\Style\Language;
|
||||
|
||||
/**
|
||||
* Settings reader.
|
||||
*
|
||||
* @since 0.14.0
|
||||
*/
|
||||
class Settings extends AbstractPart
|
||||
{
|
||||
/**
|
||||
* @var array<string>
|
||||
*/
|
||||
private $booleanProperties = [
|
||||
'mirrorMargins',
|
||||
'hideSpellingErrors',
|
||||
'hideGrammaticalErrors',
|
||||
'trackRevisions',
|
||||
'doNotTrackMoves',
|
||||
'doNotTrackFormatting',
|
||||
'evenAndOddHeaders',
|
||||
'updateFields',
|
||||
'autoHyphenation',
|
||||
'doNotHyphenateCaps',
|
||||
'bookFoldPrinting',
|
||||
];
|
||||
|
||||
/**
|
||||
* Read settings.xml.
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
|
||||
$docSettings = $phpWord->getSettings();
|
||||
|
||||
$nodes = $xmlReader->getElements('*');
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
$name = str_replace('w:', '', $node->nodeName);
|
||||
$value = $xmlReader->getAttribute('w:val', $node);
|
||||
$method = 'set' . $name;
|
||||
|
||||
if (in_array($name, $this->booleanProperties)) {
|
||||
$docSettings->$method($value !== 'false');
|
||||
} elseif (method_exists($this, $method)) {
|
||||
$this->$method($xmlReader, $phpWord, $node);
|
||||
} elseif (method_exists($docSettings, $method)) {
|
||||
$docSettings->$method($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the document Language.
|
||||
*/
|
||||
protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void
|
||||
{
|
||||
$val = $xmlReader->getAttribute('w:val', $node);
|
||||
$eastAsia = $xmlReader->getAttribute('w:eastAsia', $node);
|
||||
$bidi = $xmlReader->getAttribute('w:bidi', $node);
|
||||
|
||||
$themeFontLang = new Language();
|
||||
$themeFontLang->setLatin($val);
|
||||
$themeFontLang->setEastAsia($eastAsia);
|
||||
$themeFontLang->setBidirectional($bidi);
|
||||
|
||||
$phpWord->getSettings()->setThemeFontLang($themeFontLang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the document protection.
|
||||
*/
|
||||
protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void
|
||||
{
|
||||
$documentProtection = $phpWord->getSettings()->getDocumentProtection();
|
||||
|
||||
$edit = $xmlReader->getAttribute('w:edit', $node);
|
||||
if ($edit !== null) {
|
||||
$documentProtection->setEditing($edit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the proof state.
|
||||
*/
|
||||
protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void
|
||||
{
|
||||
$proofState = $phpWord->getSettings()->getProofState();
|
||||
|
||||
$spelling = $xmlReader->getAttribute('w:spelling', $node);
|
||||
$grammar = $xmlReader->getAttribute('w:grammar', $node);
|
||||
|
||||
if ($spelling !== null) {
|
||||
$proofState->setSpelling($spelling);
|
||||
}
|
||||
if ($grammar !== null) {
|
||||
$proofState->setGrammar($grammar);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the proof state.
|
||||
*/
|
||||
protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void
|
||||
{
|
||||
$percent = $xmlReader->getAttribute('w:percent', $node);
|
||||
$val = $xmlReader->getAttribute('w:val', $node);
|
||||
|
||||
if ($percent !== null || $val !== null) {
|
||||
$phpWord->getSettings()->setZoom($percent === null ? $val : $percent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Revision view.
|
||||
*/
|
||||
protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void
|
||||
{
|
||||
$revisionView = new TrackChangesView();
|
||||
$revisionView->setMarkup(filter_var($xmlReader->getAttribute('w:markup', $node), FILTER_VALIDATE_BOOLEAN));
|
||||
$revisionView->setComments($xmlReader->getAttribute('w:comments', $node));
|
||||
$revisionView->setInsDel(filter_var($xmlReader->getAttribute('w:insDel', $node), FILTER_VALIDATE_BOOLEAN));
|
||||
$revisionView->setFormatting(filter_var($xmlReader->getAttribute('w:formatting', $node), FILTER_VALIDATE_BOOLEAN));
|
||||
$revisionView->setInkAnnotations(filter_var($xmlReader->getAttribute('w:inkAnnotations', $node), FILTER_VALIDATE_BOOLEAN));
|
||||
$phpWord->getSettings()->setRevisionView($revisionView);
|
||||
}
|
||||
|
||||
protected function setConsecutiveHyphenLimit(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void
|
||||
{
|
||||
$value = $xmlReader->getAttribute('w:val', $node);
|
||||
|
||||
if ($value !== null) {
|
||||
$phpWord->getSettings()->setConsecutiveHyphenLimit($value);
|
||||
}
|
||||
}
|
||||
|
||||
protected function setHyphenationZone(XMLReader $xmlReader, PhpWord $phpWord, DOMElement $node): void
|
||||
{
|
||||
$value = $xmlReader->getAttribute('w:val', $node);
|
||||
|
||||
if ($value !== null) {
|
||||
$phpWord->getSettings()->setHyphenationZone($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?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\Reader\Word2007;
|
||||
|
||||
use PhpOffice\PhpWord\PhpWord;
|
||||
use PhpOffice\PhpWord\Shared\XMLReader;
|
||||
use PhpOffice\PhpWord\Style\Language;
|
||||
|
||||
/**
|
||||
* Styles reader.
|
||||
*
|
||||
* @since 0.10.0
|
||||
*/
|
||||
class Styles extends AbstractPart
|
||||
{
|
||||
/**
|
||||
* Read styles.xml.
|
||||
*/
|
||||
public function read(PhpWord $phpWord): void
|
||||
{
|
||||
$xmlReader = new XMLReader();
|
||||
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
|
||||
|
||||
$fontDefaults = $xmlReader->getElement('w:docDefaults/w:rPrDefault');
|
||||
if ($fontDefaults !== null) {
|
||||
$fontDefaultStyle = $this->readFontStyle($xmlReader, $fontDefaults);
|
||||
if ($fontDefaultStyle) {
|
||||
if (array_key_exists('name', $fontDefaultStyle)) {
|
||||
$phpWord->setDefaultFontName($fontDefaultStyle['name']);
|
||||
}
|
||||
if (array_key_exists('size', $fontDefaultStyle)) {
|
||||
$phpWord->setDefaultFontSize($fontDefaultStyle['size']);
|
||||
}
|
||||
if (array_key_exists('color', $fontDefaultStyle)) {
|
||||
$phpWord->setDefaultFontColor($fontDefaultStyle['color']);
|
||||
}
|
||||
if (array_key_exists('lang', $fontDefaultStyle)) {
|
||||
$phpWord->getSettings()->setThemeFontLang(new Language($fontDefaultStyle['lang']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$paragraphDefaults = $xmlReader->getElement('w:docDefaults/w:pPrDefault');
|
||||
if ($paragraphDefaults !== null) {
|
||||
$paragraphDefaultStyle = $this->readParagraphStyle($xmlReader, $paragraphDefaults);
|
||||
if ($paragraphDefaultStyle != null) {
|
||||
$phpWord->setDefaultParagraphStyle($paragraphDefaultStyle);
|
||||
}
|
||||
}
|
||||
|
||||
$nodes = $xmlReader->getElements('w:style');
|
||||
if ($nodes->length > 0) {
|
||||
foreach ($nodes as $node) {
|
||||
$type = $xmlReader->getAttribute('w:type', $node);
|
||||
$name = $xmlReader->getAttribute('w:val', $node, 'w:name');
|
||||
if (null === $name) {
|
||||
$name = $xmlReader->getAttribute('w:styleId', $node);
|
||||
}
|
||||
$headingMatches = [];
|
||||
preg_match('/Heading\s*(\d)/i', $name, $headingMatches);
|
||||
// $default = ($xmlReader->getAttribute('w:default', $node) == 1);
|
||||
switch ($type) {
|
||||
case 'paragraph':
|
||||
$paragraphStyle = $this->readParagraphStyle($xmlReader, $node);
|
||||
$fontStyle = $this->readFontStyle($xmlReader, $node);
|
||||
if (!empty($headingMatches)) {
|
||||
$phpWord->addTitleStyle($headingMatches[1], $fontStyle, $paragraphStyle);
|
||||
} else {
|
||||
if (empty($fontStyle)) {
|
||||
if (is_array($paragraphStyle)) {
|
||||
$phpWord->addParagraphStyle($name, $paragraphStyle);
|
||||
}
|
||||
} else {
|
||||
$phpWord->addFontStyle($name, $fontStyle, $paragraphStyle);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 'character':
|
||||
$fontStyle = $this->readFontStyle($xmlReader, $node);
|
||||
if (!empty($fontStyle)) {
|
||||
$phpWord->addFontStyle($name, $fontStyle);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'table':
|
||||
$tStyle = $this->readTableStyle($xmlReader, $node);
|
||||
if (!empty($tStyle)) {
|
||||
$phpWord->addTableStyle($name, $tStyle);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+527
@@ -0,0 +1,527 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* PHPWord settings class.
|
||||
*
|
||||
* @since 0.8.0
|
||||
*/
|
||||
class Settings
|
||||
{
|
||||
/**
|
||||
* Zip libraries.
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
public const ZIPARCHIVE = 'ZipArchive';
|
||||
public const PCLZIP = 'PclZip';
|
||||
public const OLD_LIB = Shared\ZipArchive::class; // @deprecated 0.11
|
||||
|
||||
/**
|
||||
* PDF rendering libraries.
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
public const PDF_RENDERER_DOMPDF = 'DomPDF';
|
||||
public const PDF_RENDERER_TCPDF = 'TCPDF';
|
||||
public const PDF_RENDERER_MPDF = 'MPDF';
|
||||
|
||||
/**
|
||||
* Measurement units multiplication factor.
|
||||
* Applied to:
|
||||
* - Section: margins, header/footer height, gutter, column spacing
|
||||
* - Tab: position
|
||||
* - Indentation: left, right, firstLine, hanging
|
||||
* - Spacing: before, after.
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
public const UNIT_TWIP = 'twip'; // = 1/20 point
|
||||
public const UNIT_CM = 'cm';
|
||||
public const UNIT_MM = 'mm';
|
||||
public const UNIT_INCH = 'inch';
|
||||
public const UNIT_POINT = 'point'; // = 1/72 inch
|
||||
public const UNIT_PICA = 'pica'; // = 1/6 inch = 12 points
|
||||
|
||||
/**
|
||||
* Default font settings.
|
||||
* OOXML defined font size values in halfpoints, i.e. twice of what PhpWord
|
||||
* use, and the conversion will be conducted during XML writing.
|
||||
*/
|
||||
public const DEFAULT_FONT_NAME = 'Arial';
|
||||
public const DEFAULT_FONT_SIZE = 10;
|
||||
public const DEFAULT_FONT_COLOR = '000000';
|
||||
public const DEFAULT_FONT_CONTENT_TYPE = 'default'; // default|eastAsia|cs
|
||||
public const DEFAULT_PAPER = 'A4';
|
||||
|
||||
/**
|
||||
* Compatibility option for XMLWriter.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private static $xmlWriterCompatibility = true;
|
||||
|
||||
/**
|
||||
* Name of the class used for Zip file management.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $zipClass = self::ZIPARCHIVE;
|
||||
|
||||
/**
|
||||
* Name of the external Library used for rendering PDF files.
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
private static $pdfRendererName;
|
||||
|
||||
/**
|
||||
* Options used for rendering PDF files.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $pdfRendererOptions = [];
|
||||
|
||||
/**
|
||||
* Directory Path to the external Library used for rendering PDF files.
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
private static $pdfRendererPath;
|
||||
|
||||
/**
|
||||
* Measurement unit.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $measurementUnit = self::UNIT_TWIP;
|
||||
|
||||
/**
|
||||
* Default font name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $defaultFontName = self::DEFAULT_FONT_NAME;
|
||||
|
||||
/**
|
||||
* Default asian font name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $defaultAsianFontName = self::DEFAULT_FONT_NAME;
|
||||
|
||||
/**
|
||||
* Default font color.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $defaultFontColor = self::DEFAULT_FONT_COLOR;
|
||||
|
||||
/**
|
||||
* Default font size.
|
||||
*
|
||||
* @var float|int
|
||||
*/
|
||||
private static $defaultFontSize = self::DEFAULT_FONT_SIZE;
|
||||
|
||||
/**
|
||||
* Default paper.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $defaultPaper = self::DEFAULT_PAPER;
|
||||
|
||||
/**
|
||||
* Is RTL by default ?
|
||||
*
|
||||
* @var ?bool
|
||||
*/
|
||||
private static $defaultRtl;
|
||||
|
||||
/**
|
||||
* The user defined temporary directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $tempDir = '';
|
||||
|
||||
/**
|
||||
* Enables built-in output escaping mechanism.
|
||||
* Default value is `false` for backward compatibility with versions below 0.13.0.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private static $outputEscapingEnabled = false;
|
||||
|
||||
/**
|
||||
* Return the compatibility option used by the XMLWriter.
|
||||
*
|
||||
* @return bool Compatibility
|
||||
*/
|
||||
public static function hasCompatibility(): bool
|
||||
{
|
||||
return self::$xmlWriterCompatibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the compatibility option used by the XMLWriter.
|
||||
* This sets the setIndent and setIndentString for better compatibility.
|
||||
*/
|
||||
public static function setCompatibility(bool $compatibility): bool
|
||||
{
|
||||
self::$xmlWriterCompatibility = $compatibility;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get zip handler class.
|
||||
*/
|
||||
public static function getZipClass(): string
|
||||
{
|
||||
return self::$zipClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set zip handler class.
|
||||
*/
|
||||
public static function setZipClass(string $zipClass): bool
|
||||
{
|
||||
if (in_array($zipClass, [self::PCLZIP, self::ZIPARCHIVE, self::OLD_LIB])) {
|
||||
self::$zipClass = $zipClass;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set details of the external library for rendering PDF files.
|
||||
*
|
||||
* @return bool Success or failure
|
||||
*/
|
||||
public static function setPdfRenderer(string $libraryName, string $libraryBaseDir): bool
|
||||
{
|
||||
if (!self::setPdfRendererName($libraryName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::setPdfRendererPath($libraryBaseDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PDF Rendering Library.
|
||||
*/
|
||||
public static function getPdfRendererName(): ?string
|
||||
{
|
||||
return self::$pdfRendererName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify the external library to use for rendering PDF files.
|
||||
*/
|
||||
public static function setPdfRendererName(?string $libraryName): bool
|
||||
{
|
||||
$pdfRenderers = [self::PDF_RENDERER_DOMPDF, self::PDF_RENDERER_TCPDF, self::PDF_RENDERER_MPDF];
|
||||
if (!in_array($libraryName, $pdfRenderers)) {
|
||||
return false;
|
||||
}
|
||||
self::$pdfRendererName = $libraryName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the directory path to the PDF Rendering Library.
|
||||
*/
|
||||
public static function getPdfRendererPath(): ?string
|
||||
{
|
||||
return self::$pdfRendererPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set options of the external library for rendering PDF files.
|
||||
*/
|
||||
public static function setPdfRendererOptions(array $options): void
|
||||
{
|
||||
self::$pdfRendererOptions = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PDF Rendering Options.
|
||||
*/
|
||||
public static function getPdfRendererOptions(): array
|
||||
{
|
||||
return self::$pdfRendererOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location of external library to use for rendering PDF files.
|
||||
*
|
||||
* @param null|string $libraryBaseDir Directory path to the library's base folder
|
||||
*
|
||||
* @return bool Success or failure
|
||||
*/
|
||||
public static function setPdfRendererPath(?string $libraryBaseDir): bool
|
||||
{
|
||||
if (!$libraryBaseDir || false === file_exists($libraryBaseDir) || false === is_readable($libraryBaseDir)) {
|
||||
return false;
|
||||
}
|
||||
self::$pdfRendererPath = $libraryBaseDir;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get measurement unit.
|
||||
*/
|
||||
public static function getMeasurementUnit(): string
|
||||
{
|
||||
return self::$measurementUnit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set measurement unit.
|
||||
*/
|
||||
public static function setMeasurementUnit(string $value): bool
|
||||
{
|
||||
$units = [
|
||||
self::UNIT_TWIP,
|
||||
self::UNIT_CM,
|
||||
self::UNIT_MM,
|
||||
self::UNIT_INCH,
|
||||
self::UNIT_POINT,
|
||||
self::UNIT_PICA,
|
||||
];
|
||||
if (!in_array($value, $units)) {
|
||||
return false;
|
||||
}
|
||||
self::$measurementUnit = $value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user defined path to temporary directory.
|
||||
*
|
||||
* @param string $tempDir The user defined path to temporary directory
|
||||
*
|
||||
* @since 0.12.0
|
||||
*/
|
||||
public static function setTempDir(string $tempDir): void
|
||||
{
|
||||
self::$tempDir = $tempDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns path to temporary directory.
|
||||
*
|
||||
* @since 0.12.0
|
||||
*/
|
||||
public static function getTempDir(): string
|
||||
{
|
||||
if (!empty(self::$tempDir)) {
|
||||
$tempDir = self::$tempDir;
|
||||
} else {
|
||||
$tempDir = sys_get_temp_dir();
|
||||
}
|
||||
|
||||
return $tempDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.13.0
|
||||
*/
|
||||
public static function isOutputEscapingEnabled(): bool
|
||||
{
|
||||
return self::$outputEscapingEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.13.0
|
||||
*/
|
||||
public static function setOutputEscapingEnabled(bool $outputEscapingEnabled): void
|
||||
{
|
||||
self::$outputEscapingEnabled = $outputEscapingEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default font name.
|
||||
*/
|
||||
public static function getDefaultFontName(): string
|
||||
{
|
||||
return self::$defaultFontName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default font name.
|
||||
*/
|
||||
public static function getDefaultAsianFontName(): string
|
||||
{
|
||||
return self::$defaultAsianFontName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default font name.
|
||||
*/
|
||||
public static function setDefaultFontName(string $value): bool
|
||||
{
|
||||
if (trim($value) !== '') {
|
||||
self::$defaultFontName = $value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function setDefaultAsianFontName(string $value): bool
|
||||
{
|
||||
if (trim($value) !== '') {
|
||||
self::$defaultAsianFontName = $value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default font color.
|
||||
*/
|
||||
public static function getDefaultFontColor(): string
|
||||
{
|
||||
return self::$defaultFontColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default font color.
|
||||
*/
|
||||
public static function setDefaultFontColor(string $value): bool
|
||||
{
|
||||
if (trim($value) !== '') {
|
||||
self::$defaultFontColor = $value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default font size.
|
||||
*
|
||||
* @return float|int
|
||||
*/
|
||||
public static function getDefaultFontSize()
|
||||
{
|
||||
return self::$defaultFontSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default font size.
|
||||
*
|
||||
* @param null|float|int $value
|
||||
*/
|
||||
public static function setDefaultFontSize($value): bool
|
||||
{
|
||||
if ((is_int($value) || is_float($value)) && (int) $value > 0) {
|
||||
self::$defaultFontSize = $value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function setDefaultRtl(?bool $defaultRtl): void
|
||||
{
|
||||
self::$defaultRtl = $defaultRtl;
|
||||
}
|
||||
|
||||
public static function isDefaultRtl(): ?bool
|
||||
{
|
||||
return self::$defaultRtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load setting from phpword.yml or phpword.yml.dist.
|
||||
*/
|
||||
public static function loadConfig(?string $filename = null): array
|
||||
{
|
||||
// Get config file
|
||||
$configFile = null;
|
||||
$configPath = __DIR__ . '/../../';
|
||||
if ($filename !== null) {
|
||||
$files = [$filename];
|
||||
} else {
|
||||
$files = ["{$configPath}phpword.ini", "{$configPath}phpword.ini.dist"];
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
if (file_exists($file)) {
|
||||
$configFile = realpath($file);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse config file
|
||||
$config = [];
|
||||
if ($configFile !== null) {
|
||||
$config = @parse_ini_file($configFile);
|
||||
if ($config === false) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Set config value
|
||||
$appliedConfig = [];
|
||||
foreach ($config as $key => $value) {
|
||||
$method = "set{$key}";
|
||||
if (method_exists(__CLASS__, $method)) {
|
||||
self::$method($value);
|
||||
$appliedConfig[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $appliedConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default paper.
|
||||
*/
|
||||
public static function getDefaultPaper(): string
|
||||
{
|
||||
return self::$defaultPaper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default paper.
|
||||
*/
|
||||
public static function setDefaultPaper(string $value): bool
|
||||
{
|
||||
if (trim($value) !== '') {
|
||||
self::$defaultPaper = $value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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\Shared;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use ReflectionClass;
|
||||
|
||||
abstract class AbstractEnum
|
||||
{
|
||||
private static $constCacheArray;
|
||||
|
||||
private static function getConstants()
|
||||
{
|
||||
if (self::$constCacheArray == null) {
|
||||
self::$constCacheArray = [];
|
||||
}
|
||||
$calledClass = static::class;
|
||||
if (!array_key_exists($calledClass, self::$constCacheArray)) {
|
||||
$reflect = new ReflectionClass($calledClass);
|
||||
self::$constCacheArray[$calledClass] = $reflect->getConstants();
|
||||
}
|
||||
|
||||
return self::$constCacheArray[$calledClass];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all values for this enum.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function values()
|
||||
{
|
||||
return array_values(self::getConstants());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true the value is valid for this enum.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return bool true if value is valid
|
||||
*/
|
||||
public static function isValid($value)
|
||||
{
|
||||
$values = array_values(self::getConstants());
|
||||
|
||||
return in_array($value, $values, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the value passed is a valid value.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public static function validate($value): void
|
||||
{
|
||||
if (!self::isValid($value)) {
|
||||
$calledClass = static::class;
|
||||
$values = array_values(self::getConstants());
|
||||
|
||||
throw new InvalidArgumentException("$value is not a valid value for $calledClass, possible values are " . implode(', ', $values));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,456 @@
|
||||
<?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\Shared;
|
||||
|
||||
/**
|
||||
* Common converter functions.
|
||||
*/
|
||||
class Converter
|
||||
{
|
||||
const INCH_TO_CM = 2.54;
|
||||
const INCH_TO_TWIP = 1440;
|
||||
const INCH_TO_PIXEL = 96;
|
||||
const INCH_TO_POINT = 72;
|
||||
const INCH_TO_PICA = 6;
|
||||
const PIXEL_TO_EMU = 9525;
|
||||
const DEGREE_TO_ANGLE = 60000;
|
||||
|
||||
/**
|
||||
* Convert centimeter to twip.
|
||||
*
|
||||
* @param float $centimeter
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function cmToTwip($centimeter = 1)
|
||||
{
|
||||
return $centimeter / self::INCH_TO_CM * self::INCH_TO_TWIP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert centimeter to inch.
|
||||
*
|
||||
* @param float $centimeter
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function cmToInch($centimeter = 1)
|
||||
{
|
||||
return $centimeter / self::INCH_TO_CM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert centimeter to pixel.
|
||||
*
|
||||
* @param float $centimeter
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function cmToPixel($centimeter = 1)
|
||||
{
|
||||
return $centimeter / self::INCH_TO_CM * self::INCH_TO_PIXEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert centimeter to point.
|
||||
*
|
||||
* @param float $centimeter
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function cmToPoint($centimeter = 1)
|
||||
{
|
||||
return $centimeter / self::INCH_TO_CM * self::INCH_TO_POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert centimeter to EMU.
|
||||
*
|
||||
* @param float $centimeter
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function cmToEmu($centimeter = 1)
|
||||
{
|
||||
return round($centimeter / self::INCH_TO_CM * self::INCH_TO_PIXEL * self::PIXEL_TO_EMU);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert inch to twip.
|
||||
*
|
||||
* @param float $inch
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function inchToTwip($inch = 1)
|
||||
{
|
||||
return $inch * self::INCH_TO_TWIP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert inch to centimeter.
|
||||
*
|
||||
* @param float $inch
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function inchToCm($inch = 1)
|
||||
{
|
||||
return $inch * self::INCH_TO_CM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert inch to pixel.
|
||||
*
|
||||
* @param float $inch
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function inchToPixel($inch = 1)
|
||||
{
|
||||
return $inch * self::INCH_TO_PIXEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert inch to point.
|
||||
*
|
||||
* @param float $inch
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function inchToPoint($inch = 1)
|
||||
{
|
||||
return $inch * self::INCH_TO_POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert inch to EMU.
|
||||
*
|
||||
* @param float $inch
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function inchToEmu($inch = 1)
|
||||
{
|
||||
return round($inch * self::INCH_TO_PIXEL * self::PIXEL_TO_EMU);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert pixel to twip.
|
||||
*
|
||||
* @param float $pixel
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pixelToTwip($pixel = 1)
|
||||
{
|
||||
return $pixel / self::INCH_TO_PIXEL * self::INCH_TO_TWIP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert pixel to centimeter.
|
||||
*
|
||||
* @param float $pixel
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pixelToCm($pixel = 1)
|
||||
{
|
||||
return $pixel / self::INCH_TO_PIXEL * self::INCH_TO_CM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert pixel to point.
|
||||
*
|
||||
* @param float $pixel
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pixelToPoint($pixel = 1)
|
||||
{
|
||||
return $pixel / self::INCH_TO_PIXEL * self::INCH_TO_POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert pixel to EMU.
|
||||
*
|
||||
* @param float $pixel
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function pixelToEmu($pixel = 1)
|
||||
{
|
||||
return round($pixel * self::PIXEL_TO_EMU);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert point to twip unit.
|
||||
*
|
||||
* @param float $point
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pointToTwip($point = 1)
|
||||
{
|
||||
return $point / self::INCH_TO_POINT * self::INCH_TO_TWIP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert point to pixel.
|
||||
*
|
||||
* @param float $point
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pointToPixel($point = 1)
|
||||
{
|
||||
return $point / self::INCH_TO_POINT * self::INCH_TO_PIXEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert point to EMU.
|
||||
*
|
||||
* @param float $point
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pointToEmu($point = 1)
|
||||
{
|
||||
return round($point / self::INCH_TO_POINT * self::INCH_TO_PIXEL * self::PIXEL_TO_EMU);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert point to cm.
|
||||
*
|
||||
* @param float $point
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pointToCm($point = 1)
|
||||
{
|
||||
return $point / self::INCH_TO_POINT * self::INCH_TO_CM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert EMU to pixel.
|
||||
*
|
||||
* @param float $emu
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function emuToPixel($emu = 1)
|
||||
{
|
||||
return round($emu / self::PIXEL_TO_EMU);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert pica to point.
|
||||
*
|
||||
* @param float $pica
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function picaToPoint($pica = 1)
|
||||
{
|
||||
return $pica / self::INCH_TO_PICA * self::INCH_TO_POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert degree to angle.
|
||||
*
|
||||
* @param float $degree
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function degreeToAngle($degree = 1)
|
||||
{
|
||||
return (int) round($degree * self::DEGREE_TO_ANGLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert angle to degrees.
|
||||
*
|
||||
* @param float $angle
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function angleToDegree($angle = 1)
|
||||
{
|
||||
return round($angle / self::DEGREE_TO_ANGLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert colorname as string to RGB.
|
||||
*
|
||||
* @param string $value color name
|
||||
*
|
||||
* @return string color as hex RGB string, or original value if unknown
|
||||
*/
|
||||
public static function stringToRgb($value)
|
||||
{
|
||||
switch ($value) {
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW:
|
||||
return 'FFFF00';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_LIGHTGREEN:
|
||||
return '90EE90';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_CYAN:
|
||||
return '00FFFF';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_MAGENTA:
|
||||
return 'FF00FF';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_BLUE:
|
||||
return '0000FF';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_RED:
|
||||
return 'FF0000';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKBLUE:
|
||||
return '00008B';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKCYAN:
|
||||
return '008B8B';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKGREEN:
|
||||
return '006400';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKMAGENTA:
|
||||
return '8B008B';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKRED:
|
||||
return '8B0000';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKYELLOW:
|
||||
return '8B8B00';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKGRAY:
|
||||
return 'A9A9A9';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_LIGHTGRAY:
|
||||
return 'D3D3D3';
|
||||
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_BLACK:
|
||||
return '000000';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HTML hexadecimal to RGB.
|
||||
*
|
||||
* @param string $value HTML Color in hexadecimal
|
||||
*
|
||||
* @return array Value in RGB
|
||||
*/
|
||||
public static function htmlToRgb($value)
|
||||
{
|
||||
if ($value[0] == '#') {
|
||||
$value = substr($value, 1);
|
||||
} else {
|
||||
$value = self::stringToRgb($value);
|
||||
}
|
||||
|
||||
if (strlen($value) == 6) {
|
||||
[$red, $green, $blue] = [$value[0] . $value[1], $value[2] . $value[3], $value[4] . $value[5]];
|
||||
} elseif (strlen($value) == 3) {
|
||||
[$red, $green, $blue] = [$value[0] . $value[0], $value[1] . $value[1], $value[2] . $value[2]];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
$red = ctype_xdigit($red) ? hexdec($red) : 0;
|
||||
$green = ctype_xdigit($green) ? hexdec($green) : 0;
|
||||
$blue = ctype_xdigit($blue) ? hexdec($blue) : 0;
|
||||
|
||||
return [$red, $green, $blue];
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a size in CSS format (eg. 10px, 10px, ...) to points.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return ?float
|
||||
*/
|
||||
public static function cssToPoint($value)
|
||||
{
|
||||
if ($value == '0') {
|
||||
return 0;
|
||||
}
|
||||
$matches = [];
|
||||
if (preg_match('/^[+-]?([0-9]+\.?[0-9]*)?(px|em|ex|%|in|cm|mm|pt|pc)$/i', $value, $matches)) {
|
||||
$size = $matches[1];
|
||||
$unit = $matches[2];
|
||||
|
||||
switch ($unit) {
|
||||
case 'pt':
|
||||
return $size;
|
||||
case 'px':
|
||||
return self::pixelToPoint($size);
|
||||
case 'cm':
|
||||
return self::cmToPoint($size);
|
||||
case 'mm':
|
||||
return self::cmToPoint($size / 10);
|
||||
case 'in':
|
||||
return self::inchToPoint($size);
|
||||
case 'pc':
|
||||
return self::picaToPoint($size);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a size in CSS format (eg. 10px, 10px, ...) to twips.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function cssToTwip($value)
|
||||
{
|
||||
return self::pointToTwip(self::cssToPoint($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a size in CSS format (eg. 10px, 10px, ...) to pixel.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function cssToPixel($value)
|
||||
{
|
||||
return self::pointToPixel(self::cssToPoint($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a size in CSS format (eg. 10px, 10px, ...) to cm.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function cssToCm($value)
|
||||
{
|
||||
return self::pointToCm(self::cssToPoint($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a size in CSS format (eg. 10px, 10px, ...) to emu.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function cssToEmu($value)
|
||||
{
|
||||
return self::pointToEmu(self::cssToPoint($value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpOffice\PhpWord\Shared;
|
||||
|
||||
class Css
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $cssContent;
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, string>>
|
||||
*/
|
||||
private $styles = [];
|
||||
|
||||
public function __construct(string $cssContent)
|
||||
{
|
||||
$this->cssContent = $cssContent;
|
||||
}
|
||||
|
||||
public function process(): void
|
||||
{
|
||||
$cssContent = str_replace(["\r", "\n"], '', $this->cssContent);
|
||||
preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $cssContent, $cssExtracted);
|
||||
// Check if there are x selectors and x rules
|
||||
if (count($cssExtracted[1]) != count($cssExtracted[2])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($cssExtracted[1] as $key => $selector) {
|
||||
$rules = trim($cssExtracted[2][$key]);
|
||||
$rules = explode(';', $rules);
|
||||
foreach ($rules as $rule) {
|
||||
if (empty($rule)) {
|
||||
continue;
|
||||
}
|
||||
[$key, $value] = explode(':', trim($rule));
|
||||
$this->styles[$this->sanitize($selector)][$this->sanitize($key)] = $this->sanitize($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getStyles(): array
|
||||
{
|
||||
return $this->styles;
|
||||
}
|
||||
|
||||
public function getStyle(string $selector): array
|
||||
{
|
||||
$selector = $this->sanitize($selector);
|
||||
|
||||
return $this->styles[$selector] ?? [];
|
||||
}
|
||||
|
||||
private function sanitize(string $value): string
|
||||
{
|
||||
return addslashes(trim($value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
<?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\Shared;
|
||||
|
||||
/**
|
||||
* Drawing.
|
||||
*/
|
||||
class Drawing
|
||||
{
|
||||
const DPI_96 = 96;
|
||||
|
||||
/**
|
||||
* Convert pixels to EMU.
|
||||
*
|
||||
* @param int $pValue Value in pixels
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function pixelsToEmu($pValue = 0)
|
||||
{
|
||||
return round($pValue * 9525);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert EMU to pixels.
|
||||
*
|
||||
* @param int $pValue Value in EMU
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function emuToPixels($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return round($pValue / 9525);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert pixels to points.
|
||||
*
|
||||
* @param int $pValue Value in pixels
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pixelsToPoints($pValue = 0)
|
||||
{
|
||||
return $pValue * 0.67777777;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert points width to centimeters.
|
||||
*
|
||||
* @param int $pValue Value in points
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pointsToCentimeters($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (($pValue * 1.333333333) / self::DPI_96) * 2.54;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert points width to pixels.
|
||||
*
|
||||
* @param int $pValue Value in points
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pointsToPixels($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $pValue * 1.333333333;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert pixels to centimeters.
|
||||
*
|
||||
* @param int $pValue Value in pixels
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function pixelsToCentimeters($pValue = 0)
|
||||
{
|
||||
//return $pValue * 0.028;
|
||||
return ($pValue / self::DPI_96) * 2.54;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert centimeters width to pixels.
|
||||
*
|
||||
* @param int $pValue Value in centimeters
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function centimetersToPixels($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ($pValue / 2.54) * self::DPI_96;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert degrees to angle.
|
||||
*
|
||||
* @param int $pValue Degrees
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function degreesToAngle($pValue = 0)
|
||||
{
|
||||
return (int) round($pValue * 60000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert angle to degrees.
|
||||
*
|
||||
* @param int $pValue Angle
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function angleToDegrees($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return round($pValue / 60000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert centimeters width to twips.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function centimetersToTwips($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $pValue * 566.928;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert twips width to centimeters.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function twipsToCentimeters($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $pValue / 566.928;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert inches width to twips.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function inchesToTwips($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $pValue * 1440;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert twips width to inches.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function twipsToInches($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $pValue / 1440;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert twips width to pixels.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function twipsToPixels($pValue = 0)
|
||||
{
|
||||
if ($pValue == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return round($pValue / 15.873984);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HTML hexadecimal to RGB.
|
||||
*
|
||||
* @param string $pValue HTML Color in hexadecimal
|
||||
*
|
||||
* @return array|false Value in RGB
|
||||
*/
|
||||
public static function htmlToRGB($pValue)
|
||||
{
|
||||
if ($pValue[0] == '#') {
|
||||
$pValue = substr($pValue, 1);
|
||||
}
|
||||
|
||||
if (strlen($pValue) == 6) {
|
||||
[$colorR, $colorG, $colorB] = [$pValue[0] . $pValue[1], $pValue[2] . $pValue[3], $pValue[4] . $pValue[5]];
|
||||
} elseif (strlen($pValue) == 3) {
|
||||
[$colorR, $colorG, $colorB] = [$pValue[0] . $pValue[0], $pValue[1] . $pValue[1], $pValue[2] . $pValue[2]];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
$colorR = hexdec($colorR);
|
||||
$colorG = hexdec($colorG);
|
||||
$colorB = hexdec($colorB);
|
||||
|
||||
return [$colorR, $colorG, $colorB];
|
||||
}
|
||||
}
|
||||
+1334
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,252 @@
|
||||
<?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\Shared\Microsoft;
|
||||
|
||||
use PhpOffice\PhpWord\Exception\Exception;
|
||||
|
||||
/**
|
||||
* Password encoder for microsoft office applications.
|
||||
*/
|
||||
class PasswordEncoder
|
||||
{
|
||||
const ALGORITHM_MD2 = 'MD2';
|
||||
const ALGORITHM_MD4 = 'MD4';
|
||||
const ALGORITHM_MD5 = 'MD5';
|
||||
const ALGORITHM_SHA_1 = 'SHA-1';
|
||||
const ALGORITHM_SHA_256 = 'SHA-256';
|
||||
const ALGORITHM_SHA_384 = 'SHA-384';
|
||||
const ALGORITHM_SHA_512 = 'SHA-512';
|
||||
const ALGORITHM_RIPEMD = 'RIPEMD';
|
||||
const ALGORITHM_RIPEMD_160 = 'RIPEMD-160';
|
||||
const ALGORITHM_MAC = 'MAC';
|
||||
const ALGORITHM_HMAC = 'HMAC';
|
||||
|
||||
private const ALL_ONE_BITS = (PHP_INT_SIZE > 4) ? 0xFFFFFFFF : -1;
|
||||
private const HIGH_ORDER_BIT = (PHP_INT_SIZE > 4) ? 0x80000000 : PHP_INT_MIN;
|
||||
|
||||
/**
|
||||
* Mapping between algorithm name and algorithm ID.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @see https://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.writeprotection.cryptographicalgorithmsid(v=office.14).aspx
|
||||
*/
|
||||
private static $algorithmMapping = [
|
||||
self::ALGORITHM_MD2 => [1, 'md2'],
|
||||
self::ALGORITHM_MD4 => [2, 'md4'],
|
||||
self::ALGORITHM_MD5 => [3, 'md5'],
|
||||
self::ALGORITHM_SHA_1 => [4, 'sha1'],
|
||||
self::ALGORITHM_MAC => [5, ''], // 'mac' -> not possible with hash()
|
||||
self::ALGORITHM_RIPEMD => [6, 'ripemd'],
|
||||
self::ALGORITHM_RIPEMD_160 => [7, 'ripemd160'],
|
||||
self::ALGORITHM_HMAC => [9, ''], //'hmac' -> not possible with hash()
|
||||
self::ALGORITHM_SHA_256 => [12, 'sha256'],
|
||||
self::ALGORITHM_SHA_384 => [13, 'sha384'],
|
||||
self::ALGORITHM_SHA_512 => [14, 'sha512'],
|
||||
];
|
||||
|
||||
private static $initialCodeArray = [
|
||||
0xE1F0,
|
||||
0x1D0F,
|
||||
0xCC9C,
|
||||
0x84C0,
|
||||
0x110C,
|
||||
0x0E10,
|
||||
0xF1CE,
|
||||
0x313E,
|
||||
0x1872,
|
||||
0xE139,
|
||||
0xD40F,
|
||||
0x84F9,
|
||||
0x280C,
|
||||
0xA96A,
|
||||
0x4EC3,
|
||||
];
|
||||
|
||||
private static $encryptionMatrix = [
|
||||
[0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09],
|
||||
[0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF],
|
||||
[0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0],
|
||||
[0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40],
|
||||
[0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5],
|
||||
[0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A],
|
||||
[0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9],
|
||||
[0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0],
|
||||
[0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC],
|
||||
[0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10],
|
||||
[0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168],
|
||||
[0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C],
|
||||
[0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD],
|
||||
[0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC],
|
||||
[0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4],
|
||||
];
|
||||
|
||||
private static $passwordMaxLength = 15;
|
||||
|
||||
/**
|
||||
* Create a hashed password that MS Word will be able to work with.
|
||||
*
|
||||
* @see https://blogs.msdn.microsoft.com/vsod/2010/04/05/how-to-set-the-editing-restrictions-in-word-using-open-xml-sdk-2-0/
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $algorithmName
|
||||
* @param string $salt
|
||||
* @param int $spinCount
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function hashPassword($password, $algorithmName = self::ALGORITHM_SHA_1, $salt = null, $spinCount = 10000)
|
||||
{
|
||||
$origEncoding = mb_internal_encoding();
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
$password = mb_substr($password, 0, min(self::$passwordMaxLength, mb_strlen($password)));
|
||||
|
||||
// Get the single-byte values by iterating through the Unicode characters of the truncated password.
|
||||
// For each character, if the low byte is not equal to 0, take it. Otherwise, take the high byte.
|
||||
$passUtf8 = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8');
|
||||
if (!is_string($passUtf8)) {
|
||||
throw new Exception('Failed to convert password to UCS-2LE');
|
||||
}
|
||||
|
||||
$byteChars = [];
|
||||
for ($i = 0; $i < mb_strlen($password); ++$i) {
|
||||
$byteChars[$i] = ord(substr($passUtf8, $i * 2, 1));
|
||||
|
||||
if ($byteChars[$i] == 0) {
|
||||
$byteChars[$i] = ord(substr($passUtf8, $i * 2 + 1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// build low-order word and hig-order word and combine them
|
||||
$combinedKey = self::buildCombinedKey($byteChars);
|
||||
// build reversed hexadecimal string
|
||||
$hex = str_pad(strtoupper(dechex($combinedKey & self::ALL_ONE_BITS)), 8, '0', \STR_PAD_LEFT);
|
||||
$reversedHex = $hex[6] . $hex[7] . $hex[4] . $hex[5] . $hex[2] . $hex[3] . $hex[0] . $hex[1];
|
||||
|
||||
$generatedKey = mb_convert_encoding($reversedHex, 'UCS-2LE', 'UTF-8');
|
||||
|
||||
// Implementation Notes List:
|
||||
// Word requires that the initial hash of the password with the salt not be considered in the count.
|
||||
// The initial hash of salt + key is not included in the iteration count.
|
||||
$algorithm = self::getAlgorithm($algorithmName);
|
||||
$generatedKey = hash($algorithm, $salt . $generatedKey, true);
|
||||
|
||||
for ($i = 0; $i < $spinCount; ++$i) {
|
||||
$generatedKey = hash($algorithm, $generatedKey . pack('CCCC', $i, $i >> 8, $i >> 16, $i >> 24), true);
|
||||
}
|
||||
$generatedKey = base64_encode($generatedKey);
|
||||
|
||||
mb_internal_encoding($origEncoding);
|
||||
|
||||
return $generatedKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get algorithm from self::$algorithmMapping.
|
||||
*
|
||||
* @param string $algorithmName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getAlgorithm($algorithmName)
|
||||
{
|
||||
$algorithm = self::$algorithmMapping[$algorithmName][1];
|
||||
if ($algorithm == '') {
|
||||
$algorithm = 'sha1';
|
||||
}
|
||||
|
||||
return $algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the algorithm ID.
|
||||
*
|
||||
* @param string $algorithmName
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getAlgorithmId($algorithmName)
|
||||
{
|
||||
return self::$algorithmMapping[$algorithmName][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build combined key from low-order word and high-order word.
|
||||
*
|
||||
* @param array $byteChars byte array representation of password
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function buildCombinedKey($byteChars)
|
||||
{
|
||||
$byteCharsLength = count($byteChars);
|
||||
// Compute the high-order word
|
||||
// Initialize from the initial code array (see above), depending on the passwords length.
|
||||
$highOrderWord = self::$initialCodeArray[$byteCharsLength - 1];
|
||||
|
||||
// For each character in the password:
|
||||
// For every bit in the character, starting with the least significant and progressing to (but excluding)
|
||||
// the most significant, if the bit is set, XOR the key’s high-order word with the corresponding word from
|
||||
// the Encryption Matrix
|
||||
for ($i = 0; $i < $byteCharsLength; ++$i) {
|
||||
$tmp = self::$passwordMaxLength - $byteCharsLength + $i;
|
||||
$matrixRow = self::$encryptionMatrix[$tmp];
|
||||
for ($intBit = 0; $intBit < 7; ++$intBit) {
|
||||
if (($byteChars[$i] & (0x0001 << $intBit)) != 0) {
|
||||
$highOrderWord = ($highOrderWord ^ $matrixRow[$intBit]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute low-order word
|
||||
// Initialize with 0
|
||||
$lowOrderWord = 0;
|
||||
// For each character in the password, going backwards
|
||||
for ($i = $byteCharsLength - 1; $i >= 0; --$i) {
|
||||
// low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR character
|
||||
$lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteChars[$i]);
|
||||
}
|
||||
// Lastly, low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR strPassword length XOR 0xCE4B.
|
||||
$lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteCharsLength ^ 0xCE4B);
|
||||
|
||||
// Combine the Low and High Order Word
|
||||
return self::int32(($highOrderWord << 16) + $lowOrderWord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate behaviour of (signed) int32.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param int $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function int32($value)
|
||||
{
|
||||
$value = $value & self::ALL_ONE_BITS;
|
||||
|
||||
if ($value & self::HIGH_ORDER_BIT) {
|
||||
$value = -((~$value & self::ALL_ONE_BITS) + 1);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
<?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
|
||||
* @copyright 2010-2018 PHPWord contributors
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||
*/
|
||||
|
||||
namespace PhpOffice\PhpWord\Shared;
|
||||
|
||||
use PhpOffice\PhpWord\Exception\Exception;
|
||||
|
||||
defined('IDENTIFIER_OLE') ||
|
||||
define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1));
|
||||
|
||||
class OLERead
|
||||
{
|
||||
private $data = '';
|
||||
|
||||
// OLE identifier
|
||||
const IDENTIFIER_OLE = IDENTIFIER_OLE;
|
||||
|
||||
// Size of a sector = 512 bytes
|
||||
const BIG_BLOCK_SIZE = 0x200;
|
||||
|
||||
// Size of a short sector = 64 bytes
|
||||
const SMALL_BLOCK_SIZE = 0x40;
|
||||
|
||||
// Size of a directory entry always = 128 bytes
|
||||
const PROPERTY_STORAGE_BLOCK_SIZE = 0x80;
|
||||
|
||||
// Minimum size of a standard stream = 4096 bytes, streams smaller than this are stored as short streams
|
||||
const SMALL_BLOCK_THRESHOLD = 0x1000;
|
||||
|
||||
// header offsets
|
||||
const NUM_BIG_BLOCK_DEPOT_BLOCKS_POS = 0x2c;
|
||||
const ROOT_START_BLOCK_POS = 0x30;
|
||||
const SMALL_BLOCK_DEPOT_BLOCK_POS = 0x3c;
|
||||
const EXTENSION_BLOCK_POS = 0x44;
|
||||
const NUM_EXTENSION_BLOCK_POS = 0x48;
|
||||
const BIG_BLOCK_DEPOT_BLOCKS_POS = 0x4c;
|
||||
|
||||
// property storage offsets (directory offsets)
|
||||
const SIZE_OF_NAME_POS = 0x40;
|
||||
const TYPE_POS = 0x42;
|
||||
const START_BLOCK_POS = 0x74;
|
||||
const SIZE_POS = 0x78;
|
||||
|
||||
public $wrkdocument = null;
|
||||
public $wrk1Table = null;
|
||||
public $wrkData = null;
|
||||
public $wrkObjectPool = null;
|
||||
public $summaryInformation = null;
|
||||
public $docSummaryInfos = null;
|
||||
public $numBigBlockDepotBlocks = null;
|
||||
public $rootStartBlock = null;
|
||||
public $sbdStartBlock = null;
|
||||
public $extensionBlock = null;
|
||||
public $numExtensionBlocks = null;
|
||||
public $bigBlockChain = null;
|
||||
public $smallBlockChain = null;
|
||||
public $entry = null;
|
||||
public $rootentry = null;
|
||||
public $wrkObjectPoolelseif = null;
|
||||
public $props = array();
|
||||
|
||||
/**
|
||||
* Read the file
|
||||
*
|
||||
* @param $sFileName string Filename
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function read($sFileName)
|
||||
{
|
||||
// Check if file exists and is readable
|
||||
if (!is_readable($sFileName)) {
|
||||
throw new Exception('Could not open ' . $sFileName . ' for reading! File does not exist, or it is not readable.');
|
||||
}
|
||||
|
||||
// Get the file identifier
|
||||
// Don't bother reading the whole file until we know it's a valid OLE file
|
||||
$this->data = file_get_contents($sFileName, false, null, 0, 8);
|
||||
|
||||
// Check OLE identifier
|
||||
if ($this->data != self::IDENTIFIER_OLE) {
|
||||
throw new Exception('The filename ' . $sFileName . ' is not recognised as an OLE file');
|
||||
}
|
||||
|
||||
// Get the file data
|
||||
$this->data = file_get_contents($sFileName);
|
||||
|
||||
// Total number of sectors used for the SAT
|
||||
$this->numBigBlockDepotBlocks = self::getInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
|
||||
|
||||
// SecID of the first sector of the directory stream
|
||||
$this->rootStartBlock = self::getInt4d($this->data, self::ROOT_START_BLOCK_POS);
|
||||
|
||||
// SecID of the first sector of the SSAT (or -2 if not extant)
|
||||
$this->sbdStartBlock = self::getInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS);
|
||||
|
||||
// SecID of the first sector of the MSAT (or -2 if no additional sectors are used)
|
||||
$this->extensionBlock = self::getInt4d($this->data, self::EXTENSION_BLOCK_POS);
|
||||
|
||||
// Total number of sectors used by MSAT
|
||||
$this->numExtensionBlocks = self::getInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS);
|
||||
|
||||
$bigBlockDepotBlocks = array();
|
||||
$pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS;
|
||||
|
||||
$bbdBlocks = $this->numBigBlockDepotBlocks;
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($this->numExtensionBlocks != 0) {
|
||||
$bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS) / 4;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
for ($i = 0; $i < $bbdBlocks; ++$i) {
|
||||
$bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos);
|
||||
$pos += 4;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
for ($j = 0; $j < $this->numExtensionBlocks; ++$j) {
|
||||
$pos = ($this->extensionBlock + 1) * self::BIG_BLOCK_SIZE;
|
||||
$blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1);
|
||||
|
||||
for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) {
|
||||
$bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos);
|
||||
$pos += 4;
|
||||
}
|
||||
|
||||
$bbdBlocks += $blocksToRead;
|
||||
if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
|
||||
$this->extensionBlock = self::getInt4d($this->data, $pos);
|
||||
}
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$pos = 0;
|
||||
$this->bigBlockChain = '';
|
||||
$bbs = self::BIG_BLOCK_SIZE / 4;
|
||||
for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) {
|
||||
$pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE;
|
||||
|
||||
$this->bigBlockChain .= substr($this->data, $pos, 4 * $bbs);
|
||||
$pos += 4 * $bbs;
|
||||
}
|
||||
|
||||
$pos = 0;
|
||||
$sbdBlock = $this->sbdStartBlock;
|
||||
$this->smallBlockChain = '';
|
||||
while ($sbdBlock != -2) {
|
||||
$pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE;
|
||||
|
||||
$this->smallBlockChain .= substr($this->data, $pos, 4 * $bbs);
|
||||
$pos += 4 * $bbs;
|
||||
|
||||
$sbdBlock = self::getInt4d($this->bigBlockChain, $sbdBlock * 4);
|
||||
}
|
||||
|
||||
// read the directory stream
|
||||
$block = $this->rootStartBlock;
|
||||
$this->entry = $this->readData($block);
|
||||
|
||||
$this->readPropertySets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract binary stream data
|
||||
*
|
||||
* @param mixed $stream
|
||||
* @return string
|
||||
*/
|
||||
public function getStream($stream)
|
||||
{
|
||||
if ($stream === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$streamData = '';
|
||||
|
||||
if ($this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) {
|
||||
$rootdata = $this->readData($this->props[$this->rootentry]['startBlock']);
|
||||
|
||||
$block = $this->props[$stream]['startBlock'];
|
||||
|
||||
while ($block != -2) {
|
||||
$pos = $block * self::SMALL_BLOCK_SIZE;
|
||||
$streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE);
|
||||
|
||||
$block = self::getInt4d($this->smallBlockChain, $block * 4);
|
||||
}
|
||||
|
||||
return $streamData;
|
||||
}
|
||||
|
||||
$numBlocks = $this->props[$stream]['size'] / self::BIG_BLOCK_SIZE;
|
||||
if ($this->props[$stream]['size'] % self::BIG_BLOCK_SIZE != 0) {
|
||||
++$numBlocks;
|
||||
}
|
||||
|
||||
if ($numBlocks == 0) {
|
||||
return ''; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$block = $this->props[$stream]['startBlock'];
|
||||
|
||||
while ($block != -2) {
|
||||
$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
|
||||
$streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
|
||||
$block = self::getInt4d($this->bigBlockChain, $block * 4);
|
||||
}
|
||||
|
||||
return $streamData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a standard stream (by joining sectors using information from SAT)
|
||||
*
|
||||
* @param int $blSectorId Sector ID where the stream starts
|
||||
* @return string Data for standard stream
|
||||
*/
|
||||
private function readData($blSectorId)
|
||||
{
|
||||
$block = $blSectorId;
|
||||
$data = '';
|
||||
|
||||
while ($block != -2) {
|
||||
$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
|
||||
$data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
|
||||
$block = self::getInt4d($this->bigBlockChain, $block * 4);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read entries in the directory stream.
|
||||
*/
|
||||
private function readPropertySets()
|
||||
{
|
||||
$offset = 0;
|
||||
|
||||
// loop through entires, each entry is 128 bytes
|
||||
$entryLen = strlen($this->entry);
|
||||
while ($offset < $entryLen) {
|
||||
// entry data (128 bytes)
|
||||
$data = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE);
|
||||
|
||||
// size in bytes of name
|
||||
$nameSize = ord($data[self::SIZE_OF_NAME_POS]) | (ord($data[self::SIZE_OF_NAME_POS + 1]) << 8);
|
||||
|
||||
// type of entry
|
||||
$type = ord($data[self::TYPE_POS]);
|
||||
|
||||
// sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook)
|
||||
// sectorID of first sector of the short-stream container stream, if this entry is root entry
|
||||
$startBlock = self::getInt4d($data, self::START_BLOCK_POS);
|
||||
|
||||
$size = self::getInt4d($data, self::SIZE_POS);
|
||||
|
||||
$name = str_replace("\x00", '', substr($data, 0, $nameSize));
|
||||
|
||||
$this->props[] = array(
|
||||
'name' => $name,
|
||||
'type' => $type,
|
||||
'startBlock' => $startBlock,
|
||||
'size' => $size, );
|
||||
|
||||
// tmp helper to simplify checks
|
||||
$upName = strtoupper($name);
|
||||
|
||||
// Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook)
|
||||
// print_r($upName.PHP_EOL);
|
||||
if (($upName === 'WORDDOCUMENT')) {
|
||||
$this->wrkdocument = count($this->props) - 1;
|
||||
} elseif ($upName === '1TABLE') {
|
||||
$this->wrk1Table = count($this->props) - 1;
|
||||
} elseif ($upName === 'DATA') {
|
||||
$this->wrkData = count($this->props) - 1;
|
||||
} elseif ($upName === 'OBJECTPOOL') {
|
||||
$this->wrkObjectPoolelseif = count($this->props) - 1;
|
||||
} elseif ($upName === 'ROOT ENTRY' || $upName === 'R') {
|
||||
$this->rootentry = count($this->props) - 1;
|
||||
}
|
||||
|
||||
// Summary information
|
||||
if ($name == chr(5) . 'SummaryInformation') {
|
||||
$this->summaryInformation = count($this->props) - 1;
|
||||
}
|
||||
|
||||
// Additional Document Summary information
|
||||
if ($name == chr(5) . 'DocumentSummaryInformation') {
|
||||
$this->docSummaryInfos = count($this->props) - 1;
|
||||
}
|
||||
|
||||
$offset += self::PROPERTY_STORAGE_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 4 bytes of data at specified position
|
||||
*
|
||||
* @param string $data
|
||||
* @param int $pos
|
||||
* @return int
|
||||
*/
|
||||
private static function getInt4d($data, $pos)
|
||||
{
|
||||
// FIX: represent numbers correctly on 64-bit system
|
||||
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
|
||||
// Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
|
||||
$or24 = ord($data[$pos + 3]);
|
||||
if ($or24 >= 128) {
|
||||
// negative number
|
||||
$ord24 = -abs((256 - $or24) << 24);
|
||||
} else {
|
||||
$ord24 = ($or24 & 127) << 24;
|
||||
}
|
||||
|
||||
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $ord24;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,259 @@
|
||||
<?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\Shared;
|
||||
|
||||
use PhpOffice\PhpWord\Exception\Exception;
|
||||
|
||||
/**
|
||||
* Text.
|
||||
*/
|
||||
class Text
|
||||
{
|
||||
/**
|
||||
* Control characters array.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private static $controlCharacters = [];
|
||||
|
||||
/**
|
||||
* Build control characters array.
|
||||
*/
|
||||
private static function buildControlCharacters(): void
|
||||
{
|
||||
for ($i = 0; $i <= 19; ++$i) {
|
||||
if ($i != 9 && $i != 10 && $i != 13) {
|
||||
$find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_';
|
||||
$replace = chr($i);
|
||||
self::$controlCharacters[$find] = $replace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from PHP control character to OpenXML escaped control character.
|
||||
*
|
||||
* Excel 2007 team:
|
||||
* ----------------
|
||||
* That's correct, control characters are stored directly in the shared-strings table.
|
||||
* We do encode characters that cannot be represented in XML using the following escape sequence:
|
||||
* _xHHHH_ where H represents a hexadecimal character in the character's value...
|
||||
* So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
|
||||
* element or in the shared string <t> element.
|
||||
*
|
||||
* @param string $value Value to escape
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function controlCharacterPHP2OOXML($value = '')
|
||||
{
|
||||
if (empty(self::$controlCharacters)) {
|
||||
self::buildControlCharacters();
|
||||
}
|
||||
|
||||
return str_replace(array_values(self::$controlCharacters), array_keys(self::$controlCharacters), $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a number formatted for being integrated in xml files.
|
||||
*
|
||||
* @param float $number
|
||||
* @param int $decimals
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function numberFormat($number, $decimals)
|
||||
{
|
||||
return number_format($number, $decimals, '.', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $dec
|
||||
*
|
||||
* @see http://stackoverflow.com/a/7153133/2235790
|
||||
*
|
||||
* @author velcrow
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function chr($dec)
|
||||
{
|
||||
if ($dec <= 0x7F) {
|
||||
return chr($dec);
|
||||
}
|
||||
if ($dec <= 0x7FF) {
|
||||
return chr(($dec >> 6) + 192) . chr(($dec & 63) + 128);
|
||||
}
|
||||
if ($dec <= 0xFFFF) {
|
||||
return chr(($dec >> 12) + 224) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
|
||||
}
|
||||
if ($dec <= 0x1FFFFF) {
|
||||
return chr(($dec >> 18) + 240) . chr((($dec >> 12) & 63) + 128) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from OpenXML escaped control character to PHP control character.
|
||||
*
|
||||
* @param string $value Value to unescape
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function controlCharacterOOXML2PHP($value = '')
|
||||
{
|
||||
if (empty(self::$controlCharacters)) {
|
||||
self::buildControlCharacters();
|
||||
}
|
||||
|
||||
return str_replace(array_keys(self::$controlCharacters), array_values(self::$controlCharacters), $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string contains UTF-8 data.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isUTF8($value = '')
|
||||
{
|
||||
return is_string($value) && ($value === '' || preg_match('/^./su', $value) == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return UTF8 encoded value.
|
||||
*
|
||||
* @param null|string $value
|
||||
*
|
||||
* @return ?string
|
||||
*/
|
||||
public static function toUTF8($value = '')
|
||||
{
|
||||
if (null !== $value && !self::isUTF8($value)) {
|
||||
// PHP8.2 : utf8_encode is deprecated, but mb_convert_encoding always usable
|
||||
$value = (function_exists('mb_convert_encoding')) ? mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1') : utf8_encode($value);
|
||||
if ($value === false) {
|
||||
throw new Exception('Unable to convert text to UTF-8');
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns unicode from UTF8 text.
|
||||
*
|
||||
* The function is splitted to reduce cyclomatic complexity
|
||||
*
|
||||
* @param string $text UTF8 text
|
||||
*
|
||||
* @return string Unicode text
|
||||
*
|
||||
* @since 0.11.0
|
||||
*/
|
||||
public static function toUnicode($text)
|
||||
{
|
||||
return self::unicodeToEntities(self::utf8ToUnicode($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns unicode array from UTF8 text.
|
||||
*
|
||||
* @param string $text UTF8 text
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 0.11.0
|
||||
* @see http://www.randomchaos.com/documents/?source=php_and_unicode
|
||||
*/
|
||||
public static function utf8ToUnicode($text)
|
||||
{
|
||||
$unicode = [];
|
||||
$values = [];
|
||||
$lookingFor = 1;
|
||||
|
||||
// Gets unicode for each character
|
||||
for ($i = 0; $i < strlen($text); ++$i) {
|
||||
$thisValue = ord($text[$i]);
|
||||
if ($thisValue < 128) {
|
||||
$unicode[] = $thisValue;
|
||||
} else {
|
||||
if (count($values) == 0) {
|
||||
$lookingFor = $thisValue < 224 ? 2 : 3;
|
||||
}
|
||||
$values[] = $thisValue;
|
||||
if (count($values) == $lookingFor) {
|
||||
if ($lookingFor == 3) {
|
||||
$number = (($values[0] % 16) * 4096) + (($values[1] % 64) * 64) + ($values[2] % 64);
|
||||
} else {
|
||||
$number = (($values[0] % 32) * 64) + ($values[1] % 64);
|
||||
}
|
||||
$unicode[] = $number;
|
||||
$values = [];
|
||||
$lookingFor = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $unicode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns entites from unicode array.
|
||||
*
|
||||
* @param array $unicode
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 0.11.0
|
||||
* @see http://www.randomchaos.com/documents/?source=php_and_unicode
|
||||
*/
|
||||
private static function unicodeToEntities($unicode)
|
||||
{
|
||||
$entities = '';
|
||||
|
||||
foreach ($unicode as $value) {
|
||||
if ($value != 65279) {
|
||||
$entities .= $value > 127 ? '\uc0{\u' . $value . '}' : chr($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return name without underscore for < 0.10.0 variable name compatibility.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function removeUnderscorePrefix($value)
|
||||
{
|
||||
if (null !== $value) {
|
||||
if (substr($value, 0, 1) == '_') {
|
||||
$value = substr($value, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?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
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpOffice\PhpWord\Shared;
|
||||
|
||||
class Validate
|
||||
{
|
||||
public const CSS_WHITESPACE = [
|
||||
'pre-wrap',
|
||||
'normal',
|
||||
'nowrap',
|
||||
'pre',
|
||||
'pre-line',
|
||||
'initial',
|
||||
'inherit',
|
||||
];
|
||||
|
||||
public const CSS_GENERICFONT = [
|
||||
'serif',
|
||||
'sans-serif',
|
||||
'monospace',
|
||||
'cursive',
|
||||
'fantasy',
|
||||
'system-ui',
|
||||
'math',
|
||||
'emoji',
|
||||
'fangsong',
|
||||
];
|
||||
|
||||
/**
|
||||
* Validate html css white-space value. It is expected that only pre-wrap and normal (default) are useful.
|
||||
*
|
||||
* @param string $value CSS White space
|
||||
*
|
||||
* @return string value if valid, empty string if not
|
||||
*/
|
||||
public static function validateCSSWhiteSpace(?string $value): string
|
||||
{
|
||||
if (in_array($value, self::CSS_WHITESPACE)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate generic font for fallback for html.
|
||||
*
|
||||
* @param string $value Generic font name
|
||||
*
|
||||
* @return string Value if legitimate, empty string if not
|
||||
*/
|
||||
public static function validateCSSGenericFont(?string $value): string
|
||||
{
|
||||
if (in_array($value, self::CSS_GENERICFONT)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user