Merge branch 'develop' into parse_drawings

This commit is contained in:
troosan 2018-07-14 03:30:11 +02:00 committed by GitHub
commit de83da2bbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 1322 additions and 517 deletions

21
.gitattributes vendored Normal file
View File

@ -0,0 +1,21 @@
# build config
/.scrutinizer.yml export-ignore
/.travis.yml export-ignore
/php_cs.dist export-ignore
/phpmd.xml.dist export-ignore
/phpstan.neon export-ignore
/composer.lock export-ignore
# git files
/.gitignore export-ignore
/.gitattributes export-ignore
# project directories
/build export-ignore
/docs export-ignore
/samples export-ignore
# tests
/phpunit.xml.dist export-ignore
/tests export-ignore

View File

@ -19,7 +19,7 @@ tools:
config:
ruleset: phpmd.xml.dist
external_code_coverage:
enabled: true
enabled: false
timeout: 1200
php_cpd: true
# php_sim: # Temporarily disabled to allow focus on things other than duplicates

View File

@ -37,7 +37,7 @@ before_script:
- composer self-update
- travis_wait composer install --prefer-source
## PHPDocumentor
- mkdir -p build/docs
##- mkdir -p build/docs
- mkdir -p build/coverage
script:
@ -52,10 +52,8 @@ script:
## PHPLOC
- if [ -z "$COVERAGE" ]; then ./vendor/bin/phploc src/ ; fi
## PHPDocumentor
- if [ -z "$COVERAGE" ]; then ./vendor/bin/phpdoc -q -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/*/*" --template="responsive-twig" ; fi
##- if [ -z "$COVERAGE" ]; then ./vendor/bin/phpdoc -q -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/*/*" --template="responsive-twig" ; fi
after_script:
## PHPDocumentor
- bash .travis_shell_after_success.sh
## Scrutinizer
- if [ -n "$COVERAGE" ]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml ; fi
after_success:
## Coveralls
- if [ -n "$COVERAGE" ]; then travis_retry php vendor/bin/php-coveralls -v ; fi

View File

@ -1,39 +0,0 @@
#!/bin/bash
echo "--DEBUG--"
echo "TRAVIS_REPO_SLUG: $TRAVIS_REPO_SLUG"
echo "TRAVIS_PHP_VERSION: $TRAVIS_PHP_VERSION"
echo "TRAVIS_PULL_REQUEST: $TRAVIS_PULL_REQUEST"
if [ "$TRAVIS_REPO_SLUG" == "PHPOffice/PHPWord" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.6" ]; then
echo -e "Publishing PHPDoc...\n"
cp -R build/docs $HOME/docs-latest
cp -R build/coverage $HOME/coverage-latest
cd $HOME
git config --global user.email "travis@travis-ci.org"
git config --global user.name "travis-ci"
git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/PHPOffice/PHPWord gh-pages > /dev/null
cd gh-pages
echo "--DEBUG : Suppression"
git rm -rf ./docs/$TRAVIS_BRANCH
echo "--DEBUG : Dossier"
mkdir -p docs/$TRAVIS_BRANCH
mkdir -p coverage/$TRAVIS_BRANCH
echo "--DEBUG : Copie"
cp -Rf $HOME/docs-latest/* ./docs/$TRAVIS_BRANCH/
cp -Rf $HOME/coverage-latest/* ./coverage/$TRAVIS_BRANCH/
echo "--DEBUG : Git"
git add -f .
git commit -m "PHPDocumentor (Travis Build: $TRAVIS_BUILD_NUMBER - Branch: $TRAVIS_BRANCH)"
git push -fq origin gh-pages > /dev/null
echo -e "Published PHPDoc to gh-pages.\n"
fi

View File

@ -20,6 +20,11 @@ v0.15.0 (?? ??? 2018)
- Added support for Image text wrapping distance @troosan #1310
- Added parsing of CSS line-height and text-indent in HTML reader @troosan #1316
- Added the ability to enable gridlines and axislabels on charts @FrankMeyer #576
- Add support for table indent (tblInd) @Trainmaster #1343
- Added parsing of internal links in HTML reader @lalop #1336
- Several improvements to charts @JAEK-S #1332
- Add parsing of html image in base64 format @jgpATs2w #1382
- Added Support for Indentation & Tabs on RTF Writer. @smaug1985 #1405
### Fixed
- Fix reading of docx default style - @troosan #1238
@ -33,10 +38,15 @@ v0.15.0 (?? ??? 2018)
- Fix parsing of Heading and Title formating @troosan @gthomas2 #465
- Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591
- Support reading of w:drawing for documents produced by word 2011+ @gthomas2 #464 #1324
- Fix missing column width in ODText writer @potofcoffee #413
- Disable entity loader before parsing XML to avoid XXE injection @Tom4t0 #1427
### Changed
- Remove zend-stdlib dependency @Trainmaster #1284
- The default unit for `\PhpOffice\PhpWord\Style\Image` changed from `px` to `pt`.
### Miscelaneous
- Drop GitHub pages, switch to coveralls for code coverage analysis @czosel #1360
v0.14.0 (29 Dec 2017)
----------------------

View File

@ -3,7 +3,7 @@
[![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v/stable.png)](https://packagist.org/packages/phpoffice/phpword)
[![Build Status](https://travis-ci.org/PHPOffice/PHPWord.svg?branch=master)](https://travis-ci.org/PHPOffice/PHPWord)
[![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/quality-score.png?s=b5997ce59ac2816b4514f3a38de9900f6d492c1d)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/)
[![Code Coverage](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/coverage.png?s=742a98745725c562955440edc8d2c39d7ff5ae25)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/)
[![Coverage Status](https://coveralls.io/repos/github/PHPOffice/PHPWord/badge.svg?branch=develop)](https://coveralls.io/github/PHPOffice/PHPWord?branch=develop)
[![Total Downloads](https://poser.pugx.org/phpoffice/phpword/downloads.png)](https://packagist.org/packages/phpoffice/phpword)
[![License](https://poser.pugx.org/phpoffice/phpword/license.png)](https://packagist.org/packages/phpoffice/phpword)
[![Join the chat at https://gitter.im/PHPOffice/PHPWord](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/PHPWord)

View File

@ -64,15 +64,17 @@
"phpoffice/common": "^0.2.9"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36 || ^5.0",
"phpdocumentor/phpdocumentor":"2.*",
"squizlabs/php_codesniffer": "^2.7",
"friendsofphp/php-cs-fixer": "^2.0",
"ext-zip": "*",
"ext-gd": "*",
"phpunit/phpunit": "^4.8.36 || ^7.0",
"squizlabs/php_codesniffer": "^2.9",
"friendsofphp/php-cs-fixer": "^2.2",
"phpmd/phpmd": "2.*",
"phploc/phploc": "2.* || 3.* || 4.*",
"dompdf/dompdf":"0.8.*",
"tecnickcom/tcpdf": "6.*",
"mpdf/mpdf": "5.* || 6.* || 7.*"
"mpdf/mpdf": "5.7.4 || 6.* || 7.*",
"php-coveralls/php-coveralls": "1.1.0 || ^2.0"
},
"suggest": {
"ext-zip": "Allows writing OOXML and ODF",

View File

@ -242,7 +242,7 @@ To add an image, use the ``addImage`` method to sections, headers, footers, text
$section->addImage($src, [$style]);
- ``$src``. String path to a local image, URL of a remote image or the image data, as a string.
- ``$src``. String path to a local image, URL of a remote image or the image data, as a string. Warning: Do not pass user-generated strings here, as that would allow an attacker to read arbitrary files or perform server-side request forgery by passing file paths or URLs instead of image data.
- ``$style``. See :ref:`image-style`.
Examples:
@ -435,8 +435,8 @@ Available line style attributes:
- ``dash``. Line types: dash, rounddot, squaredot, dashdot, longdash, longdashdot, longdashdotdot.
- ``beginArrow``. Start type of arrow: block, open, classic, diamond, oval.
- ``endArrow``. End type of arrow: block, open, classic, diamond, oval.
- ``width``. Line-object width in pt.
- ``height``. Line-object height in pt.
- ``width``. Line-object width in *pt*.
- ``height``. Line-object height in *pt*.
- ``flip``. Flip the line element: true, false.
Chart

View File

@ -54,7 +54,5 @@ Example:
Using samples
-------------
After installation, you can browse and use the samples that we've
provided, either by command line or using browser. If you can access
your PHPWord library folder using browser, point your browser to the
``samples`` folder, e.g. ``http://localhost/PhpWord/samples/``.
More examples are provided in the ``samples`` directory.
For an easy access to those samples launch ``php -S localhost:8000`` in the samples directory then browse to http://localhost:8000 to view the samples.

View File

@ -104,6 +104,7 @@ Available Table style options:
- ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'.
- ``border(Top|Right|Bottom|Left)Size``. Border size in *twip*.
- ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in *twip*.
- ``indent``. Table indent from leading margin. Must be an instance of ``\PhpOffice\PhpWord\ComplexType\TblWidth``.
- ``width``. Table width in percent.
- ``unit``. The unit to use for the width. One of ``\PhpOffice\PhpWord\SimpleType\TblWidth``. Defaults to *auto*.
- ``layout``. Table layout, either *fixed* or *autofit* See ``\PhpOffice\PhpWord\Style\Table`` for constants.
@ -149,10 +150,10 @@ Image
Available Image style options:
- ``alignment``. See ``\PhpOffice\PhpWord\SimpleType\Jc`` class for the details.
- ``height``. Height in pixels.
- ``height``. Height in *pt*.
- ``marginLeft``. Left margin in inches, can be negative.
- ``marginTop``. Top margin in inches, can be negative.
- ``width``. Width in pixels.
- ``width``. Width in *pt*.
- ``wrappingStyle``. Wrapping style, *inline*, *square*, *tight*, *behind*, or *infront*.
- ``wrapDistanceTop``. Top text wrapping in pixels.
- ``wrapDistanceBottom``. Bottom text wrapping in pixels.

View File

@ -1,7 +1,7 @@
includes:
- vendor/phpstan/phpstan/conf/config.level1.neon
parameters:
memory-limit: 200000
memory-limit: 20000000
autoload_directories:
- tests
autoload_files:

View File

@ -6,8 +6,7 @@
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
stopOnFailure="false">
<testsuites>
<testsuite name="PhpWord Test Suite">
<directory>./tests/PhpWord</directory>
@ -22,7 +21,7 @@
</whitelist>
</filter>
<logging>
<log type="coverage-html" target="./build/coverage" charset="UTF-8" highlight="true" />
<log type="coverage-html" target="./build/coverage" />
<log type="coverage-clover" target="./build/logs/clover.xml" />
</logging>
</phpunit>

View File

@ -1,6 +1,5 @@
<?php
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\Style\Paragraph;
include_once 'Sample_Header.php';

View File

@ -56,7 +56,7 @@ $templateProcessor->setValue('userPhone#3', '+1 428 889 775');
echo date('H:i:s'), ' Saving the result document...', EOL;
$templateProcessor->saveAs('results/Sample_07_TemplateCloneRow.docx');
echo getEndingNotes(array('Word2007' => 'docx'));
echo getEndingNotes(array('Word2007' => 'docx'), 'results/Sample_07_TemplateCloneRow.docx');
if (!CLI) {
include_once 'Sample_Footer.php';
}

View File

@ -14,7 +14,7 @@ $templateProcessor->deleteBlock('DELETEME');
echo date('H:i:s'), ' Saving the result document...', EOL;
$templateProcessor->saveAs('results/Sample_23_TemplateBlock.docx');
echo getEndingNotes(array('Word2007' => 'docx'));
echo getEndingNotes(array('Word2007' => 'docx'), 'results/Sample_23_TemplateBlock.docx');
if (!CLI) {
include_once 'Sample_Footer.php';
}

View File

@ -11,7 +11,7 @@ $html = '<h1>Adding element via HTML</h1>';
$html .= '<p>Some well-formed HTML snippet needs to be used</p>';
$html .= '<p>With for example <strong>some<sup>1</sup> <em>inline</em> formatting</strong><sub>1</sub></p>';
$html .= '<p>A link to <a href="http://phpword.readthedocs.io/">Read the docs</a></p>';
$html .= '<p>A link to <a href="http://phpword.readthedocs.io/" style="text-decoration: underline">Read the docs</a></p>';
$html .= '<p lang="he-IL" style="text-align: right; direction: rtl">היי, זה פסקה מימין לשמאל</p>';

View File

@ -6,15 +6,20 @@ include_once 'Sample_Header.php';
// New Word document
echo date('H:i:s'), ' Create new PhpWord object', EOL;
$phpWord = new \PhpOffice\PhpWord\PhpWord();
PhpOffice\PhpWord\Style::addTitleStyle(1, array('size' => 14));
// New section
$section = $phpWord->addSection();
$section->addTitle('This page demos fields');
// Add Field elements
// See Element/Field.php for all options
$section->addText('Date field:');
$section->addField('DATE', array('dateformat' => 'dddd d MMMM yyyy H:mm:ss'), array('PreserveFormat'));
$section->addText('Style Ref field:');
$section->addField('STYLEREF', array('StyleIdentifier' => 'Heading 1'));
$section->addText('Page field:');
$section->addField('PAGE', array('format' => 'Arabic'));

View File

@ -16,8 +16,8 @@ $section = $phpWord->addSection();
$section->addTitle('2D charts', 1);
$section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous'));
$chartTypes = array('pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar');
$twoSeries = array('bar', 'column', 'line', 'area', 'scatter', 'radar');
$chartTypes = array('pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column');
$twoSeries = array('bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column');
$threeSeries = array('bar', 'line');
$categories = array('A', 'B', 'C', 'D', 'E');
$series1 = array(1, 3, 2, 5, 4);

View File

@ -83,7 +83,7 @@ function write($phpWord, $filename, $writers)
$result .= EOL;
}
$result .= getEndingNotes($writers);
$result .= getEndingNotes($writers, $filename);
return $result;
}
@ -92,10 +92,10 @@ function write($phpWord, $filename, $writers)
* Get ending notes
*
* @param array $writers
*
* @param mixed $filename
* @return string
*/
function getEndingNotes($writers)
function getEndingNotes($writers, $filename)
{
$result = '';

View File

@ -11,5 +11,15 @@
<ul><li>Item 1</li><li>Item 2</li><ul><li>Item 2.1</li><li>Item 2.1</li></ul></ul>
<p>Ordered (numbered) list:</p>
<ol><li>Item 1</li><li>Item 2</li></ol>
<p style="line-height:2">Double height</p>
<h2>Includes images</h2>
<img src="https://phpword.readthedocs.io/en/latest/_images/phpword.png" alt=""/>
<img src="https://localhost/gev/desarrollo/actividades/pruebas_14/5b064503587f7.jpeg" name="Imagen 12" align="bottom" width="208" height="183" border="0"/>
<img src="http://localhost/gev/desarrollo/actividades/pruebas_14/5b064503589db.png" name="Imagen 13" align="bottom" width="143" height="202" border="0"/>
<img src="http://localhost/gev/desarrollo/actividades/pruebas_14/5b0645035aac8.jpeg" name="Imagen 14" align="bottom" width="194" height="188" border="0"/>
</body>
</html>

0
samples/results/.gitignore vendored Normal file → Executable file
View File

View File

@ -0,0 +1,59 @@
<?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\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;
}
}

View File

@ -347,7 +347,7 @@ abstract class AbstractElement
*
* @param \PhpOffice\PhpWord\Element\AbstractElement $container
*/
public function setParentContainer(AbstractElement $container)
public function setParentContainer(self $container)
{
$this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1);
$this->parent = $container;

View File

@ -61,11 +61,12 @@ class Chart extends AbstractElement
* @param array $categories
* @param array $values
* @param array $style
* @param null|mixed $seriesName
*/
public function __construct($type, $categories, $values, $style = null)
public function __construct($type, $categories, $values, $style = null, $seriesName = null)
{
$this->setType($type);
$this->addSeries($categories, $values);
$this->addSeries($categories, $values, $seriesName);
$this->style = $this->setNewStyle(new ChartStyle(), $style, true);
}
@ -86,7 +87,7 @@ class Chart extends AbstractElement
*/
public function setType($value)
{
$enum = array('pie', 'doughnut', 'line', 'bar', 'column', 'area', 'radar', 'scatter');
$enum = array('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');
}
@ -95,10 +96,15 @@ class Chart extends AbstractElement
*
* @param array $categories
* @param array $values
* @param null|mixed $name
*/
public function addSeries($categories, $values)
public function addSeries($categories, $values, $name = null)
{
$this->series[] = array('categories' => $categories, 'values' => $values);
$this->series[] = array(
'categories' => $categories,
'values' => $values,
'name' => $name,
);
}
/**

View File

@ -78,6 +78,10 @@ class Field extends AbstractElement
'properties' => array(),
'options' => array('PreserveFormat'),
),
'STYLEREF' => array(
'properties' => array('StyleIdentifier' => ''),
'options' => array('PreserveFormat'),
),
);
/**

View File

@ -83,7 +83,7 @@ class OLEObject extends AbstractElement
$this->style = $this->setNewStyle(new ImageStyle(), $style, true);
$this->icon = realpath(__DIR__ . "/../resources/{$ext}.png");
return $this;
return;
}
throw new InvalidObjectException();

View File

@ -29,7 +29,7 @@ class PreserveText extends AbstractElement
/**
* Text content
*
* @var string
* @var string|array
*/
private $text;
@ -64,8 +64,6 @@ class PreserveText extends AbstractElement
if (isset($matches[0])) {
$this->text = $matches;
}
return $this;
}
/**
@ -91,7 +89,7 @@ class PreserveText extends AbstractElement
/**
* Get Text content
*
* @return string
* @return string|array
*/
public function getText()
{

View File

@ -135,18 +135,40 @@ class Table extends AbstractElement
public function countColumns()
{
$columnCount = 0;
if (is_array($this->rows)) {
$rowCount = count($this->rows);
for ($i = 0; $i < $rowCount; $i++) {
/** @var \PhpOffice\PhpWord\Element\Row $row Type hint */
$row = $this->rows[$i];
$cellCount = count($row->getCells());
if ($columnCount < $cellCount) {
$columnCount = $cellCount;
}
$rowCount = count($this->rows);
for ($i = 0; $i < $rowCount; $i++) {
/** @var \PhpOffice\PhpWord\Element\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 = array();
foreach ($this->rows as $row) {
$cells = $row->getCells();
if (count($cells) <= count($cellWidths)) {
continue;
}
$cellWidths = array();
foreach ($cells as $cell) {
$cellWidths[] = $cell->getWidth();
}
}
return $cellWidths;
}
}

View File

@ -61,14 +61,12 @@ class Title extends AbstractElement
*/
public function __construct($text, $depth = 1)
{
if (isset($text)) {
if (is_string($text)) {
$this->text = CommonText::toUTF8($text);
} elseif ($text instanceof TextRun) {
$this->text = $text;
} else {
throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun');
}
if (is_string($text)) {
$this->text = CommonText::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;
@ -76,8 +74,6 @@ class Title extends AbstractElement
if (array_key_exists($styleName, Style::getStyles())) {
$this->style = str_replace('_', '', $styleName);
}
return $this;
}
/**

View File

@ -17,7 +17,7 @@
namespace PhpOffice\PhpWord\Metadata;
use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder;
use PhpOffice\Common\Microsoft\PasswordEncoder;
use PhpOffice\PhpWord\SimpleType\DocProtect;
/**
@ -113,7 +113,7 @@ class Protection
/**
* Set password
*
* @param $password
* @param string $password
* @return self
*/
public function setPassword($password)
@ -136,7 +136,7 @@ class Protection
/**
* Set count for hash iterations
*
* @param $spinCount
* @param int $spinCount
* @return self
*/
public function setSpinCount($spinCount)
@ -159,7 +159,7 @@ class Protection
/**
* Set algorithm
*
* @param $algorithm
* @param string $algorithm
* @return self
*/
public function setAlgorithm($algorithm)

View File

@ -35,10 +35,10 @@ use PhpOffice\PhpWord\Exception\Exception;
* @method int addChart(Element\Chart $chart)
* @method int addComment(Element\Comment $comment)
*
* @method Style\Paragraph addParagraphStyle(string $styleName, array $styles)
* @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(int $depth, mixed $fontStyle, mixed $paragraphStyle = null)
* @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)
*/

View File

@ -18,6 +18,7 @@
namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType;
use PhpOffice\PhpWord\Element\AbstractContainer;
use PhpOffice\PhpWord\Element\TextRun;
use PhpOffice\PhpWord\Element\TrackChange;
@ -486,6 +487,11 @@ abstract class AbstractPart
if ($tablePositionNode !== null) {
$style['position'] = $this->readTablePosition($xmlReader, $tablePositionNode);
}
$indentNode = $xmlReader->getElement('w:tblInd', $styleNode);
if ($indentNode !== null) {
$style['indent'] = $this->readTableIndent($xmlReader, $indentNode);
}
}
}
@ -517,6 +523,24 @@ abstract class AbstractPart
return $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
}
/**
* Read w:tblInd
*
* @param \PhpOffice\Common\XMLReader $xmlReader
* @param \DOMElement $domNode
* @return TblWidthComplexType
*/
private function readTableIndent(XMLReader $xmlReader, \DOMElement $domNode)
{
$styleDefs = array(
'value' => array(self::READ_VALUE, '.', 'w:w'),
'type' => array(self::READ_VALUE, '.', 'w:type'),
);
$styleDefs = $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
return new TblWidthComplexType((int) $styleDefs['value'], $styleDefs['type']);
}
/**
* Read w:tcPr
*

View File

@ -81,7 +81,7 @@ class Settings extends AbstractPart
*
* @param XMLReader $xmlReader
* @param PhpWord $phpWord
* @param \DOMNode $node
* @param \DOMElement $node
*/
protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
{
@ -102,14 +102,16 @@ class Settings extends AbstractPart
*
* @param XMLReader $xmlReader
* @param PhpWord $phpWord
* @param \DOMNode $node
* @param \DOMElement $node
*/
protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
{
$documentProtection = $phpWord->getSettings()->getDocumentProtection();
$edit = $xmlReader->getAttribute('w:edit', $node);
$documentProtection->setEditing($edit);
if ($edit !== null) {
$documentProtection->setEditing($edit);
}
}
/**
@ -117,7 +119,7 @@ class Settings extends AbstractPart
*
* @param XMLReader $xmlReader
* @param PhpWord $phpWord
* @param \DOMNode $node
* @param \DOMElement $node
*/
protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
{
@ -139,7 +141,7 @@ class Settings extends AbstractPart
*
* @param XMLReader $xmlReader
* @param PhpWord $phpWord
* @param \DOMNode $node
* @param \DOMElement $node
*/
protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
{
@ -156,7 +158,7 @@ class Settings extends AbstractPart
*
* @param XMLReader $xmlReader
* @param PhpWord $phpWord
* @param \DOMNode $node
* @param \DOMElement $node
*/
protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node)
{

View File

@ -20,6 +20,7 @@ namespace PhpOffice\PhpWord\Shared;
use PhpOffice\PhpWord\Element\AbstractContainer;
use PhpOffice\PhpWord\Element\Row;
use PhpOffice\PhpWord\Element\Table;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\SimpleType\Jc;
use PhpOffice\PhpWord\SimpleType\NumberFormat;
@ -32,23 +33,30 @@ class Html
{
private static $listIndex = 0;
private static $xpath;
private static $options;
/**
* Add HTML parts.
*
* Note: $stylesheet parameter is removed to avoid PHPMD error for unused parameter
* Warning: Do not pass user-generated HTML here, as that would allow an attacker to read arbitrary
* files or perform server-side request forgery by passing local file paths or URLs in <img>.
*
* @param \PhpOffice\PhpWord\Element\AbstractContainer $element Where the parts need to be added
* @param string $html The code to parse
* @param bool $fullHTML If it's a full HTML, no need to add 'body' tag
* @param bool $preserveWhiteSpace If false, the whitespaces between nodes will be removed
* @param array $options:
* + IMG_SRC_SEARCH: optional to speed up images loading from remote url when files can be found locally
* + IMG_SRC_REPLACE: optional to speed up images loading from remote url when files can be found locally
*/
public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true)
public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true, $options = null)
{
/*
* @todo parse $stylesheet for default styles. Should result in an array based on id, class and element,
* which could be applied when such an element occurs in the parseNode function.
*/
self::$options = $options;
// Preprocess: remove all line ends, decode HTML entity,
// fix ampersand and angle brackets and add body tag for HTML fragments
@ -63,10 +71,11 @@ class Html
}
// Load DOM
libxml_disable_entity_loader(true);
$dom = new \DOMDocument();
$dom->preserveWhiteSpace = $preserveWhiteSpace;
$dom->loadXML($html);
self::$xpath = new \DOMXpath($dom);
self::$xpath = new \DOMXPath($dom);
$node = $dom->getElementsByTagName('body');
self::parseNode($node->item(0), $element);
@ -139,6 +148,7 @@ class Html
'sup' => array('Property', null, null, $styles, null, 'superScript', true),
'sub' => array('Property', null, null, $styles, null, 'subScript', true),
'span' => array('Span', $node, null, $styles, null, null, null),
'font' => array('Span', $node, null, $styles, null, null, null),
'table' => array('Table', $node, $element, $styles, null, null, null),
'tr' => array('Row', $node, $element, $styles, null, null, null),
'td' => array('Cell', $node, $element, $styles, null, null, null),
@ -646,7 +656,52 @@ class Html
break;
}
}
$newElement = $element->addImage($src, $style);
$originSrc = $src;
if (strpos($src, 'data:image') !== false) {
$tmpDir = Settings::getTempDir() . '/';
$match = array();
preg_match('/data:image\/(\w+);base64,(.+)/', $src, $match);
$src = $imgFile = $tmpDir . uniqid() . '.' . $match[1];
$ifp = fopen($imgFile, 'wb');
if ($ifp !== false) {
fwrite($ifp, base64_decode($match[2]));
fclose($ifp);
}
}
$src = urldecode($src);
if (!is_file($src)
&& !is_null(self::$options)
&& isset(self::$options['IMG_SRC_SEARCH'])
&& isset(self::$options['IMG_SRC_REPLACE'])) {
$src = str_replace(self::$options['IMG_SRC_SEARCH'], self::$options['IMG_SRC_REPLACE'], $src);
}
if (!is_file($src)) {
if ($imgBlob = @file_get_contents($src)) {
$tmpDir = Settings::getTempDir() . '/';
$match = array();
preg_match('/.+\.(\w+)$/', $src, $match);
$src = $tmpDir . uniqid() . '.' . $match[1];
$ifp = fopen($src, 'wb');
if ($ifp !== false) {
fwrite($ifp, $imgBlob);
fclose($ifp);
}
}
}
if (is_file($src)) {
$newElement = $element->addImage($src, $style);
} else {
throw new \Exception("Could not load image $originSrc");
}
return $newElement;
}
@ -719,7 +774,11 @@ class Html
break;
}
}
self::parseInlineStyle($node, $styles['font']);
$styles['font'] = self::parseInlineStyle($node, $styles['font']);
if (strpos($target, '#') === 0) {
return $element->addLink(substr($target, 1), $node->textContent, $styles['font'], $styles['paragraph'], true);
}
return $element->addLink($target, $node->textContent, $styles['font'], $styles['paragraph']);
}

View File

@ -1,235 +0,0 @@
<?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\Microsoft;
/**
* 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';
/**
* 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 = array(
self::ALGORITHM_MD2 => array(1, 'md2'),
self::ALGORITHM_MD4 => array(2, 'md4'),
self::ALGORITHM_MD5 => array(3, 'md5'),
self::ALGORITHM_SHA_1 => array(4, 'sha1'),
self::ALGORITHM_MAC => array(5, ''), // 'mac' -> not possible with hash()
self::ALGORITHM_RIPEMD => array(6, 'ripemd'),
self::ALGORITHM_RIPEMD_160 => array(7, 'ripemd160'),
self::ALGORITHM_HMAC => array(9, ''), //'hmac' -> not possible with hash()
self::ALGORITHM_SHA_256 => array(12, 'sha256'),
self::ALGORITHM_SHA_384 => array(13, 'sha384'),
self::ALGORITHM_SHA_512 => array(14, 'sha512'),
);
private static $initialCodeArray = array(
0xE1F0,
0x1D0F,
0xCC9C,
0x84C0,
0x110C,
0x0E10,
0xF1CE,
0x313E,
0x1872,
0xE139,
0xD40F,
0x84F9,
0x280C,
0xA96A,
0x4EC3,
);
private static $encryptionMatrix = array(
array(0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09),
array(0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF),
array(0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0),
array(0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40),
array(0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5),
array(0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A),
array(0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9),
array(0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0),
array(0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC),
array(0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10),
array(0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168),
array(0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C),
array(0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD),
array(0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC),
array(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');
$byteChars = array();
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 & 0xFFFFFFFF)), 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 keys 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 & 0xFFFFFFFF);
if ($value & 0x80000000) {
$value = -((~$value & 0xFFFFFFFF) + 1);
}
return $value;
}
}

View File

@ -39,7 +39,7 @@ class Style
* Add paragraph style
*
* @param string $styleName
* @param array $styles
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles
* @return \PhpOffice\PhpWord\Style\Paragraph
*/
public static function addParagraphStyle($styleName, $styles)
@ -51,8 +51,8 @@ class Style
* Add font style
*
* @param string $styleName
* @param array $fontStyle
* @param array $paragraphStyle
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $fontStyle
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $paragraphStyle
* @return \PhpOffice\PhpWord\Style\Font
*/
public static function addFontStyle($styleName, $fontStyle, $paragraphStyle = null)
@ -64,7 +64,7 @@ class Style
* Add link style
*
* @param string $styleName
* @param array $styles
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles
* @return \PhpOffice\PhpWord\Style\Font
*/
public static function addLinkStyle($styleName, $styles)
@ -76,7 +76,7 @@ class Style
* Add numbering style
*
* @param string $styleName
* @param array $styleValues
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styleValues
* @return \PhpOffice\PhpWord\Style\Numbering
* @since 0.10.0
*/
@ -88,14 +88,14 @@ class Style
/**
* Add title style
*
* @param int $depth
* @param array $fontStyle
* @param array $paragraphStyle
* @param int|null $depth Provide null to set title font
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $fontStyle
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $paragraphStyle
* @return \PhpOffice\PhpWord\Style\Font
*/
public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null)
{
if ($depth == null) {
if (empty($depth)) {
$styleName = 'Title';
} else {
$styleName = "Heading_{$depth}";
@ -141,7 +141,7 @@ class Style
/**
* Set default paragraph style
*
* @param array $styles Paragraph style definition
* @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles Paragraph style definition
* @return \PhpOffice\PhpWord\Style\Paragraph
*/
public static function setDefaultParagraphStyle($styles)

View File

@ -46,6 +46,60 @@ class Chart extends AbstractStyle
private $is3d = false;
/**
* A list of colors to use in the chart
*
* @var array
*/
private $colors = array();
/**
* A list of display options for data labels
*
* @var array
*/
private $dataLabelOptions = array(
'showVal' => true, // value
'showCatName' => true, // category name
'showLegendKey' => false, //show the cart legend
'showSerName' => false, // series name
'showPercent' => false,
'showLeaderLines' => false,
'showBubbleSize' => false,
);
/**
* A string that tells the writer where to write chart labels or to skip
* "nextTo" - sets labels next to the axis (bar graphs on the left) (default)
* "low" - labels on the left side of the graph
* "high" - labels on the right side of the graph
*
* @var string
*/
private $categoryLabelPosition = 'nextTo';
/**
* A string that tells the writer where to write chart labels or to skip
* "nextTo" - sets labels next to the axis (bar graphs on the bottom) (default)
* "low" - labels are below the graph
* "high" - labels above the graph
*
* @var string
*/
private $valueLabelPosition = 'nextTo';
/**
* @var string
*/
private $categoryAxisTitle;
/**
* @var string
*/
private $valueAxisTitle;
private $majorTickMarkPos = 'none';
/*
* Show labels for axis
*
* @var bool
@ -146,6 +200,28 @@ class Chart extends AbstractStyle
}
/**
* Get the list of colors to use in a chart.
*
* @return array
*/
public function getColors()
{
return $this->colors;
}
/**
* Set the colors to use in a chart.
*
* @param array $value a list of colors to use in the chart
*/
public function setColors($value = array())
{
$this->colors = $value;
return $this;
}
/*
* Show labels for axis
*
* @return bool
@ -169,6 +245,31 @@ class Chart extends AbstractStyle
}
/**
* get the list of options for data labels
*
* @return array
*/
public function getDataLabelOptions()
{
return $this->dataLabelOptions;
}
/**
* Set values for data label options.
* This will only change values for options defined in $this->dataLabelOptions, and cannot create new ones.
*
* @param array $values [description]
*/
public function setDataLabelOptions($values = array())
{
foreach (array_keys($this->dataLabelOptions) as $option) {
if (isset($values[$option])) {
$this->dataLabelOptions[$option] = $this->setBoolVal($values[$option], $this->dataLabelOptions[$option]);
}
}
}
/*
* Show Gridlines for Y-Axis
*
* @return bool
@ -192,6 +293,117 @@ class Chart extends AbstractStyle
}
/**
* Get the categoryLabelPosition setting
*
* @return string
*/
public function getCategoryLabelPosition()
{
return $this->categoryLabelPosition;
}
/**
* Set the categoryLabelPosition setting
* "none" - skips writing labels
* "nextTo" - sets labels next to the (bar graphs on the left)
* "low" - labels on the left side of the graph
* "high" - labels on the right side of the graph
*
* @param mixed $labelPosition
* @return self
*/
public function setCategoryLabelPosition($labelPosition)
{
$enum = array('nextTo', 'low', 'high');
$this->categoryLabelPosition = $this->setEnumVal($labelPosition, $enum, $this->categoryLabelPosition);
return $this;
}
/**
* Get the valueAxisLabelPosition setting
*
* @return string
*/
public function getValueLabelPosition()
{
return $this->valueLabelPosition;
}
/**
* Set the valueLabelPosition setting
* "none" - skips writing labels
* "nextTo" - sets labels next to the value
* "low" - sets labels are below the graph
* "high" - sets labels above the graph
*
* @param string
* @param mixed $labelPosition
*/
public function setValueLabelPosition($labelPosition)
{
$enum = array('nextTo', 'low', 'high');
$this->valueLabelPosition = $this->setEnumVal($labelPosition, $enum, $this->valueLabelPosition);
return $this;
}
/**
* Get the categoryAxisTitle
* @return string
*/
public function getCategoryAxisTitle()
{
return $this->categoryAxisTitle;
}
/**
* Set the title that appears on the category side of the chart
* @param string $axisTitle
*/
public function setCategoryAxisTitle($axisTitle)
{
$this->categoryAxisTitle = $axisTitle;
return $this;
}
/**
* Get the valueAxisTitle
* @return string
*/
public function getValueAxisTitle()
{
return $this->valueAxisTitle;
}
/**
* Set the title that appears on the value side of the chart
* @param string $axisTitle
*/
public function setValueAxisTitle($axisTitle)
{
$this->valueAxisTitle = $axisTitle;
return $this;
}
public function getMajorTickPosition()
{
return $this->majorTickMarkPos;
}
/**
* set the position for major tick marks
* @param string $position [description]
*/
public function setMajorTickPosition($position)
{
$enum = array('in', 'out', 'cross', 'none');
$this->majorTickMarkPos = $this->setEnumVal($position, $enum, $this->majorTickMarkPos);
}
/*
* Show Gridlines for X-Axis
*
* @return bool

View File

@ -264,7 +264,7 @@ class Font extends AbstractStyle
* Create new font style
*
* @param string $type Type of font
* @param array $paragraph Paragraph styles definition
* @param array|string|\PhpOffice\PhpWord\Style\AbstractStyle $paragraph Paragraph styles definition
*/
public function __construct($type = 'text', $paragraph = null)
{

View File

@ -47,6 +47,9 @@ final class Language extends AbstractStyle
const HE_IL = 'he-IL';
const HE_IL_ID = 1037;
const IT_IT = 'it-IT';
const IT_IT_ID = 1040;
const JA_JP = 'ja-JP';
const JA_JP_ID = 1041;

View File

@ -17,6 +17,7 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType;
use PhpOffice\PhpWord\SimpleType\Jc;
use PhpOffice\PhpWord\SimpleType\JcTable;
use PhpOffice\PhpWord\SimpleType\TblWidth;
@ -159,6 +160,16 @@ class Table extends Border
*/
private $position;
/** @var TblWidthComplexType|null */
private $indent;
/**
* The width of each column, computed based on the max cell width of each column
*
* @var int[]
*/
private $columnWidths;
/**
* Create new table style
*
@ -724,4 +735,44 @@ class Table extends Border
return $this;
}
/**
* @return TblWidthComplexType
*/
public function getIndent()
{
return $this->indent;
}
/**
* @param TblWidthComplexType $indent
* @return self
* @see http://www.datypic.com/sc/ooxml/e-w_tblInd-1.html
*/
public function setIndent(TblWidthComplexType $indent)
{
$this->indent = $indent;
return $this;
}
/**
* Get the columnWidths
*
* @return number[]
*/
public function getColumnWidths()
{
return $this->columnWidths;
}
/**
* The column widths
*
* @param int[] $value
*/
public function setColumnWidths(array $value = null)
{
$this->columnWidths = $value;
}
}

View File

@ -113,6 +113,7 @@ class TemplateProcessor
*/
protected function transformSingleXml($xml, $xsltProcessor)
{
libxml_disable_entity_loader(true);
$domDocument = new \DOMDocument();
if (false === $domDocument->loadXML($xml)) {
throw new Exception('Could not load the given XML document.');

View File

@ -17,6 +17,10 @@
namespace PhpOffice\PhpWord\Writer\ODText\Element;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Element\Row as RowElement;
use PhpOffice\PhpWord\Element\Table as TableElement;
/**
* Table element writer
*
@ -36,32 +40,59 @@ class Table extends AbstractElement
}
$rows = $element->getRows();
$rowCount = count($rows);
$colCount = $element->countColumns();
if ($rowCount > 0) {
$xmlWriter->startElement('table:table');
$xmlWriter->writeAttribute('table:name', $element->getElementId());
$xmlWriter->writeAttribute('table:style', $element->getElementId());
$xmlWriter->startElement('table:table-column');
$xmlWriter->writeAttribute('table:number-columns-repeated', $colCount);
$xmlWriter->endElement(); // table:table-column
// Write columns
$this->writeColumns($xmlWriter, $element);
// Write rows
foreach ($rows as $row) {
$xmlWriter->startElement('table:table-row');
/** @var $row \PhpOffice\PhpWord\Element\Row Type hint */
foreach ($row->getCells() as $cell) {
$xmlWriter->startElement('table:table-cell');
$xmlWriter->writeAttribute('office:value-type', 'string');
$containerWriter = new Container($xmlWriter, $cell);
$containerWriter->write();
$xmlWriter->endElement(); // table:table-cell
}
$xmlWriter->endElement(); // table:table-row
$this->writeRow($xmlWriter, $row);
}
$xmlWriter->endElement(); // table:table
}
}
/**
* Write column.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Table $element
*/
private function writeColumns(XMLWriter $xmlWriter, TableElement $element)
{
$colCount = $element->countColumns();
for ($i = 0; $i < $colCount; $i++) {
$xmlWriter->startElement('table:table-column');
$xmlWriter->writeAttribute('table:style-name', $element->getElementId() . '.' . $i);
$xmlWriter->endElement();
}
}
/**
* Write row.
*
* @param \PhpOffice\Common\XMLWriter $xmlWriter
* @param \PhpOffice\PhpWord\Element\Row $row
*/
private function writeRow(XMLWriter $xmlWriter, RowElement $row)
{
$xmlWriter->startElement('table:table-row');
/** @var $row \PhpOffice\PhpWord\Element\Row Type hint */
foreach ($row->getCells() as $cell) {
$xmlWriter->startElement('table:table-cell');
$xmlWriter->writeAttribute('office:value-type', 'string');
$containerWriter = new Container($xmlWriter, $cell);
$containerWriter->write();
$xmlWriter->endElement(); // table:table-cell
}
$xmlWriter->endElement(); // table:table-row
}
}

View File

@ -239,6 +239,7 @@ class Content extends AbstractPart
$style->setStyleName('fr' . $element->getMediaIndex());
$this->autoStyles['Image'][] = $style;
} elseif ($element instanceof Table) {
/** @var \PhpOffice\PhpWord\Style\Table $style */
$style = $element->getStyle();
if ($style === null) {
$style = new TableStyle();
@ -246,6 +247,7 @@ class Content extends AbstractPart
$style = Style::getStyle($style);
}
$style->setStyleName($element->getElementId());
$style->setColumnWidths($element->findFirstDefinedCellWidths());
$this->autoStyles['Table'][] = $style;
}
}

View File

@ -45,5 +45,19 @@ class Table extends AbstractStyle
$xmlWriter->writeAttribute('table:align', 'center');
$xmlWriter->endElement(); // style:table-properties
$xmlWriter->endElement(); // style:style
$cellWidths = $style->getColumnWidths();
$countCellWidths = count($cellWidths);
for ($i = 0; $i < $countCellWidths; $i++) {
$width = $cellWidths[$i];
$xmlWriter->startElement('style:style');
$xmlWriter->writeAttribute('style:name', $style->getStyleName() . '.' . $i);
$xmlWriter->writeAttribute('style:family', 'table-column');
$xmlWriter->startElement('style:table-column-properties');
$xmlWriter->writeAttribute('style:column-width', number_format($width * 0.0017638889, 2, '.', '') . 'cm');
$xmlWriter->endElement(); // style:table-column-properties
$xmlWriter->endElement(); // style:style
}
}
}

View File

@ -0,0 +1,45 @@
<?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\Writer\RTF\Style;
/**
* RTF indentation style writer
*
* @since 0.11.0
*/
class Indentation extends AbstractStyle
{
/**
* Write style
*
* @return string
*/
public function write()
{
$style = $this->getStyle();
if (!$style instanceof \PhpOffice\PhpWord\Style\Indentation) {
return '';
}
$content = '\fi' . $style->getFirstLine();
$content .= '\li' . $style->getLeft();
$content .= '\ri' . $style->getRight();
return $content . ' ';
}
}

View File

@ -64,9 +64,49 @@ class Paragraph extends AbstractStyle
if (isset($alignments[$style->getAlignment()])) {
$content .= $alignments[$style->getAlignment()];
}
$content .= $this->writeIndentation($style->getIndentation());
$content .= $this->getValueIf($spaceBefore !== null, '\sb' . $spaceBefore);
$content .= $this->getValueIf($spaceAfter !== null, '\sa' . $spaceAfter);
$styles = $style->getStyleValues();
$content .= $this->writeTabs($styles['tabs']);
return $content;
}
/**
* Writes an \PhpOffice\PhpWord\Style\Indentation
*
* @param null|\PhpOffice\PhpWord\Style\Indentation $indent
* @return string
*/
private function writeIndentation($indent = null)
{
if (isset($indent) && $indent instanceof \PhpOffice\PhpWord\Style\Indentation) {
$writer = new Indentation($indent);
return $writer->write();
}
return '';
}
/**
* Writes tabs
*
* @param \PhpOffice\PhpWord\Style\Tab[] $tabs
* @return string
*/
private function writeTabs($tabs = null)
{
$content = '';
if (!empty($tabs)) {
foreach ($tabs as $tab) {
$styleWriter = new Tab($tab);
$content .= $styleWriter->write();
}
}
return $content;
}

View File

@ -0,0 +1,49 @@
<?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\Writer\RTF\Style;
/**
* Line numbering style writer
*
* @since 0.10.0
*/
class Tab extends AbstractStyle
{
/**
* Write style.
*/
public function write()
{
$style = $this->getStyle();
if (!$style instanceof \PhpOffice\PhpWord\Style\Tab) {
return;
}
$tabs = array(
\PhpOffice\PhpWord\Style\Tab::TAB_STOP_RIGHT => '\tqr',
\PhpOffice\PhpWord\Style\Tab::TAB_STOP_CENTER => '\tqc',
\PhpOffice\PhpWord\Style\Tab::TAB_STOP_DECIMAL => '\tqdec',
);
$content = '';
if (isset($tabs[$style->getType()])) {
$content .= $tabs[$style->getType()];
}
$content .= '\tx' . $style->getPosition();
return $content;
}
}

View File

@ -177,6 +177,9 @@ class Field extends Text
case 'macroname':
$propertiesAndOptions .= $propval . ' ';
break;
default:
$propertiesAndOptions .= '"' . $propval . '" ';
break;
}
}

View File

@ -76,21 +76,7 @@ class Table extends AbstractElement
*/
private function writeColumns(XMLWriter $xmlWriter, TableElement $element)
{
$rows = $element->getRows();
$rowCount = count($rows);
$cellWidths = array();
for ($i = 0; $i < $rowCount; $i++) {
$row = $rows[$i];
$cells = $row->getCells();
if (count($cells) <= count($cellWidths)) {
continue;
}
$cellWidths = array();
foreach ($cells as $cell) {
$cellWidths[] = $cell->getWidth();
}
}
$cellWidths = $element->findFirstDefinedCellWidths();
$xmlWriter->startElement('w:tblGrid');
foreach ($cellWidths as $width) {

View File

@ -47,6 +47,7 @@ class Title extends AbstractElement
$xmlWriter->endElement();
}
$bookmarkRId = null;
if ($element->getDepth() !== 0) {
$rId = $element->getRelationId();
$bookmarkRId = $element->getPhpWord()->addBookmark();

View File

@ -41,14 +41,18 @@ class Chart extends AbstractPart
* @var array
*/
private $types = array(
'pie' => array('type' => 'pie', 'colors' => 1),
'doughnut' => array('type' => 'doughnut', 'colors' => 1, 'hole' => 75, 'no3d' => true),
'bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar'),
'column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col'),
'line' => array('type' => 'line', 'colors' => 0, 'axes' => true),
'area' => array('type' => 'area', 'colors' => 0, 'axes' => true),
'radar' => array('type' => 'radar', 'colors' => 0, 'axes' => true, 'radar' => 'standard', 'no3d' => true),
'scatter' => array('type' => 'scatter', 'colors' => 0, 'axes' => true, 'scatter' => 'marker', 'no3d' => true),
'pie' => array('type' => 'pie', 'colors' => 1),
'doughnut' => array('type' => 'doughnut', 'colors' => 1, 'hole' => 75, 'no3d' => true),
'bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar', 'grouping' => 'clustered'),
'stacked_bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar', 'grouping' => 'stacked'),
'percent_stacked_bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar', 'grouping' => 'percentStacked'),
'column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col', 'grouping' => 'clustered'),
'stacked_column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col', 'grouping' => 'stacked'),
'percent_stacked_column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col', 'grouping' => 'percentStacked'),
'line' => array('type' => 'line', 'colors' => 0, 'axes' => true),
'area' => array('type' => 'area', 'colors' => 0, 'axes' => true),
'radar' => array('type' => 'radar', 'colors' => 0, 'axes' => true, 'radar' => 'standard', 'no3d' => true),
'scatter' => array('type' => 'scatter', 'colors' => 0, 'axes' => true, 'scatter' => 'marker', 'no3d' => true),
);
/**
@ -145,7 +149,7 @@ class Chart extends AbstractPart
}
if (isset($this->options['bar'])) {
$xmlWriter->writeElementBlock('c:barDir', 'val', $this->options['bar']); // bar|col
$xmlWriter->writeElementBlock('c:grouping', 'val', 'clustered'); // 3d; standard = percentStacked
$xmlWriter->writeElementBlock('c:grouping', 'val', $this->options['grouping']); // 3d; standard = percentStacked
}
if (isset($this->options['radar'])) {
$xmlWriter->writeElementBlock('c:radarStyle', 'val', $this->options['radar']);
@ -157,6 +161,8 @@ class Chart extends AbstractPart
// Series
$this->writeSeries($xmlWriter, isset($this->options['scatter']));
$xmlWriter->writeElementBlock('c:overlap', 'val', '100');
// Axes
if (isset($this->options['axes'])) {
$xmlWriter->writeElementBlock('c:axId', 'val', 1);
@ -183,6 +189,8 @@ class Chart extends AbstractPart
private function writeSeries(XMLWriter $xmlWriter, $scatter = false)
{
$series = $this->element->getSeries();
$style = $this->element->getStyle();
$colors = $style->getColors();
$index = 0;
foreach ($series as $seriesItem) {
@ -194,6 +202,32 @@ class Chart extends AbstractPart
$xmlWriter->writeElementBlock('c:idx', 'val', $index);
$xmlWriter->writeElementBlock('c:order', 'val', $index);
if (!is_null($seriesItem['name']) && $seriesItem['name'] != '') {
$xmlWriter->startElement('c:tx');
$xmlWriter->startElement('c:strRef');
$xmlWriter->startElement('c:strCache');
$xmlWriter->writeElementBlock('c:ptCount', 'val', 1);
$xmlWriter->startElement('c:pt');
$xmlWriter->writeAttribute('idx', 0);
$xmlWriter->startElement('c:v');
$xmlWriter->writeRaw($seriesItem['name']);
$xmlWriter->endElement(); // c:v
$xmlWriter->endElement(); // c:pt
$xmlWriter->endElement(); // c:strCache
$xmlWriter->endElement(); // c:strRef
$xmlWriter->endElement(); // c:tx
}
// The c:dLbls was added to make word charts look more like the reports in SurveyGizmo
// This section needs to be made configurable before a pull request is made
$xmlWriter->startElement('c:dLbls');
foreach ($style->getDataLabelOptions() as $option => $val) {
$xmlWriter->writeElementBlock("c:{$option}", 'val', (int) $val);
}
$xmlWriter->endElement(); // c:dLbls
if (isset($this->options['scatter'])) {
$this->writeShape($xmlWriter);
}
@ -204,6 +238,26 @@ class Chart extends AbstractPart
} else {
$this->writeSeriesItem($xmlWriter, 'cat', $categories);
$this->writeSeriesItem($xmlWriter, 'val', $values);
// setting the chart colors was taken from https://github.com/PHPOffice/PHPWord/issues/494
if (is_array($colors) && count($colors)) {
// This is a workaround to make each series in a stack chart use a different color
if ($this->options['type'] == 'bar' && stristr($this->options['grouping'], 'stacked')) {
array_shift($colors);
}
$colorIndex = 0;
foreach ($colors as $color) {
$xmlWriter->startElement('c:dPt');
$xmlWriter->writeElementBlock('c:idx', 'val', $colorIndex);
$xmlWriter->startElement('c:spPr');
$xmlWriter->startElement('a:solidFill');
$xmlWriter->writeElementBlock('a:srgbClr', 'val', $color);
$xmlWriter->endElement(); // a:solidFill
$xmlWriter->endElement(); // c:spPr
$xmlWriter->endElement(); // c:dPt
$colorIndex++;
}
}
}
$xmlWriter->endElement(); // c:ser
@ -230,14 +284,19 @@ class Chart extends AbstractPart
$xmlWriter->startElement($itemType);
$xmlWriter->startElement($itemLit);
$xmlWriter->writeElementBlock('c:ptCount', 'val', count($values));
$index = 0;
foreach ($values as $value) {
$xmlWriter->startElement('c:pt');
$xmlWriter->writeAttribute('idx', $index);
$xmlWriter->startElement('c:v');
$xmlWriter->text($value);
$xmlWriter->endElement(); // c:v
if (\PhpOffice\PhpWord\Settings::isOutputEscapingEnabled()) {
$xmlWriter->writeElement('c:v', $value);
} else {
$xmlWriter->startElement('c:v');
$xmlWriter->writeRaw($value);
$xmlWriter->endElement(); // c:v
}
$xmlWriter->endElement(); // c:pt
$index++;
}
@ -266,15 +325,33 @@ class Chart extends AbstractPart
$xmlWriter->writeElementBlock('c:axId', 'val', $axisId);
$xmlWriter->writeElementBlock('c:axPos', 'val', $axisPos);
$categoryAxisTitle = $style->getCategoryAxisTitle();
$valueAxisTitle = $style->getValueAxisTitle();
if ($axisType == 'c:catAx') {
if (!is_null($categoryAxisTitle)) {
$this->writeAxisTitle($xmlWriter, $categoryAxisTitle);
}
} elseif ($axisType == 'c:valAx') {
if (!is_null($valueAxisTitle)) {
$this->writeAxisTitle($xmlWriter, $valueAxisTitle);
}
}
$xmlWriter->writeElementBlock('c:crossAx', 'val', $axisCross);
$xmlWriter->writeElementBlock('c:auto', 'val', 1);
if (isset($this->options['axes'])) {
$xmlWriter->writeElementBlock('c:delete', 'val', 0);
$xmlWriter->writeElementBlock('c:majorTickMark', 'val', 'none');
$xmlWriter->writeElementBlock('c:majorTickMark', 'val', $style->getMajorTickPosition());
$xmlWriter->writeElementBlock('c:minorTickMark', 'val', 'none');
if ($style->showAxisLabels()) {
$xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'nextTo');
if ($axisType == 'c:catAx') {
$xmlWriter->writeElementBlock('c:tickLblPos', 'val', $style->getCategoryLabelPosition());
} else {
$xmlWriter->writeElementBlock('c:tickLblPos', 'val', $style->getValueLabelPosition());
}
} else {
$xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none');
}
@ -312,4 +389,30 @@ class Chart extends AbstractPart
$xmlWriter->endElement(); // a:ln
$xmlWriter->endElement(); // c:spPr
}
private function writeAxisTitle(XMLWriter $xmlWriter, $title)
{
$xmlWriter->startElement('c:title'); //start c:title
$xmlWriter->startElement('c:tx'); //start c:tx
$xmlWriter->startElement('c:rich'); // start c:rich
$xmlWriter->writeElement('a:bodyPr');
$xmlWriter->writeElement('a:lstStyle');
$xmlWriter->startElement('a:p');
$xmlWriter->startElement('a:pPr');
$xmlWriter->writeElement('a:defRPr');
$xmlWriter->endElement(); // end a:pPr
$xmlWriter->startElement('a:r');
$xmlWriter->writeElementBlock('a:rPr', 'lang', 'en-US');
$xmlWriter->startElement('a:t');
$xmlWriter->writeRaw($title);
$xmlWriter->endElement(); //end a:t
$xmlWriter->endElement(); // end a:r
$xmlWriter->endElement(); //end a:p
$xmlWriter->endElement(); //end c:rich
$xmlWriter->endElement(); // end c:tx
$xmlWriter->writeElementBlock('c:overlay', 'val', '0');
$xmlWriter->endElement(); // end c:title
}
}

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
use PhpOffice\Common\Microsoft\PasswordEncoder;
use PhpOffice\PhpWord\ComplexType\ProofState;
use PhpOffice\PhpWord\ComplexType\TrackChangesView;
use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder;
use PhpOffice\PhpWord\Style\Language;
/**

View File

@ -79,6 +79,7 @@ class Table extends AbstractStyle
$this->writeTblWidth($xmlWriter, 'w:tblW', $style->getUnit(), $style->getWidth());
$this->writeTblWidth($xmlWriter, 'w:tblCellSpacing', TblWidth::TWIP, $style->getCellSpacing());
$this->writeIndent($xmlWriter, $style);
$this->writeLayout($xmlWriter, $style->getLayout());
// Position
@ -216,4 +217,19 @@ class Table extends AbstractStyle
{
$this->width = $value;
}
/**
* @param XMLWriter $xmlWriter
* @param TableStyle $style
*/
private function writeIndent(XMLWriter $xmlWriter, TableStyle $style)
{
$indent = $style->getIndent();
if ($indent === null) {
return;
}
$this->writeTblWidth($xmlWriter, 'w:tblInd', $indent->getType(), $indent->getValue());
}
}

View File

@ -126,4 +126,23 @@ class StyleTest extends AbstractTestReader
$fontStyle = $textRun->getElement(0)->getFontStyle();
$this->assertEquals(15, $fontStyle->getPosition());
}
public function testReadIndent()
{
$documentXml = '<w:tbl>
<w:tblPr>
<w:tblInd w:w="2160" w:type="dxa"/>
</w:tblPr>
</w:tbl>';
$phpWord = $this->getDocumentFromString(array('document' => $documentXml));
$elements = $phpWord->getSection(0)->getElements();
$this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]);
$this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle());
/** @var \PhpOffice\PhpWord\Style\Table $tableStyle */
$tableStyle = $elements[0]->getStyle();
$this->assertSame(TblWidth::TWIP, $tableStyle->getIndent()->getType());
$this->assertSame(2160, $tableStyle->getIndent()->getValue());
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,91 +0,0 @@
<?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\Shared\Microsoft\PasswordEncoder;
use PHPUnit\Framework\TestCase;
/**
* Test class for PhpOffice\PhpWord\Shared\Html
* @coversDefaultClass \PhpOffice\PhpWord\Shared\Html
*/
class PasswordEncoderTest extends \PHPUnit\Framework\TestCase
{
/**
* Test that a password can be hashed without specifying any additional parameters
*/
public function testEncodePassword()
{
//given
$password = 'test';
//when
$hashPassword = PasswordEncoder::hashPassword($password);
//then
TestCase::assertEquals('M795/MAlmGU8RIsY9Q9uDLHC7bk=', $hashPassword);
}
/**
* Test that a password can be hashed with a custom salt
*/
public function testEncodePasswordWithSalt()
{
//given
$password = 'test';
$salt = base64_decode('uq81pJRRGFIY5U+E9gt8tA==');
//when
$hashPassword = PasswordEncoder::hashPassword($password, PasswordEncoder::ALGORITHM_SHA_1, $salt);
//then
TestCase::assertEquals('QiDOcpia1YzSVJPiKPwWebl9p/0=', $hashPassword);
}
/**
* Test that the encoder falls back on SHA-1 if a non supported algorithm is given
*/
public function testDafaultsToSha1IfUnsupportedAlgorithm()
{
//given
$password = 'test';
$salt = base64_decode('uq81pJRRGFIY5U+E9gt8tA==');
//when
$hashPassword = PasswordEncoder::hashPassword($password, PasswordEncoder::ALGORITHM_MAC, $salt);
//then
TestCase::assertEquals('QiDOcpia1YzSVJPiKPwWebl9p/0=', $hashPassword);
}
/**
* Test that the encoder falls back on SHA-1 if a non supported algorithm is given
*/
public function testEncodePasswordWithNullAsciiCodeInPassword()
{
//given
$password = 'test' . chr(0);
$salt = base64_decode('uq81pJRRGFIY5U+E9gt8tA==');
//when
$hashPassword = PasswordEncoder::hashPassword($password, PasswordEncoder::ALGORITHM_MAC, $salt, 1);
//then
TestCase::assertEquals('rDV9sgdDsztoCQlvRCb1lF2wxNg=', $hashPassword);
}
}

View File

@ -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
* @copyright 2010-2017 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Style;
/**
* Test class for PhpOffice\PhpWord\Style\Chart
*
* @coversDefaultClass \PhpOffice\PhpWord\Style\Chart
* @runTestsInSeparateProcesses
*/
class ChartTest extends \PHPUnit\Framework\TestCase
{
/**
* Testing getter and setter for chart width
*/
public function testSetGetWidth()
{
$chart = new Chart();
$this->assertEquals($chart->getWidth(), 1000000);
$chart->setWidth(200);
$this->assertEquals($chart->getWidth(), 200);
}
/**
* Testing getter and setter for chart height
*/
public function testSetGetHeight()
{
$chart = new Chart();
$this->assertEquals($chart->getHeight(), 1000000);
$chart->setHeight(200);
$this->assertEquals($chart->getHeight(), 200);
}
/**
* Testing getter and setter for is3d
*/
public function testSetIs3d()
{
$chart = new Chart();
$this->assertEquals($chart->is3d(), false);
$chart->set3d(true);
$this->assertEquals($chart->is3d(), true);
}
/**
* Testing getter and setter for chart colors
*/
public function testSetGetColors()
{
$chart = new Chart();
$this->assertInternalType('array', $chart->getColors());
$this->assertEquals(count($chart->getColors()), 0);
$chart->setColors(array('FFFFFFFF', 'FF000000', 'FFFF0000'));
$this->assertEquals($chart->getColors(), array('FFFFFFFF', 'FF000000', 'FFFF0000'));
}
/**
* Testing getter and setter for dataLabelOptions
*/
public function testSetGetDataLabelOptions()
{
$chart = new Chart();
$originalDataLabelOptions = array(
'showVal' => true,
'showCatName' => true,
'showLegendKey' => false,
'showSerName' => false,
'showPercent' => false,
'showLeaderLines' => false,
'showBubbleSize' => false,
);
$this->assertEquals($chart->getDataLabelOptions(), $originalDataLabelOptions);
$changedDataLabelOptions = array(
'showVal' => false,
'showCatName' => false,
'showLegendKey' => true,
'showSerName' => true,
'showPercent' => true,
'showLeaderLines' => true,
'showBubbleSize' => true,
);
$chart->setDataLabelOptions(
array(
'showVal' => false,
'showCatName' => false,
'showLegendKey' => true,
'showSerName' => true,
'showPercent' => true,
'showLeaderLines' => true,
'showBubbleSize' => true,
)
);
$this->assertEquals($chart->getDataLabelOptions(), $changedDataLabelOptions);
}
/**
* Testing categoryLabelPosition getter and setter
*/
public function testSetGetCategoryLabelPosition()
{
$chart = new Chart();
$this->assertEquals($chart->getCategoryLabelPosition(), 'nextTo');
$chart->setCategoryLabelPosition('high');
$this->assertEquals($chart->getCategoryLabelPosition(), 'high');
}
/**
* Testing valueLabelPosition getter and setter
*/
public function testSetGetValueLabelPosition()
{
$chart = new Chart();
$this->assertEquals($chart->getValueLabelPosition(), 'nextTo');
$chart->setValueLabelPosition('low');
$this->assertEquals($chart->getValueLabelPosition(), 'low');
}
/**
* Testing categoryAxisTitle getter and setter
*/
public function testSetGetCategoryAxisTitle()
{
$chart = new Chart();
$chart->getCategoryAxisTitle();
$this->assertEquals($chart->getCategoryAxisTitle(), null);
$chart->setCategoryAxisTitle('Test Category Axis Title');
$this->assertEquals($chart->getCategoryAxisTitle(), 'Test Category Axis Title');
}
/**
* Testing valueAxisTitle getter and setter
*/
public function testSetGetValueAxisTitle()
{
$chart = new Chart();
$chart->getValueAxisTitle();
$this->assertEquals($chart->getValueAxisTitle(), null);
$chart->setValueAxisTitle('Test Value Axis Title');
$this->assertEquals($chart->getValueAxisTitle(), 'Test Value Axis Title');
}
}

View File

@ -17,7 +17,6 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\TestHelperDOCX;
/**

View File

@ -17,6 +17,7 @@
namespace PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType;
use PhpOffice\PhpWord\SimpleType\JcTable;
use PhpOffice\PhpWord\SimpleType\TblWidth;
@ -57,6 +58,7 @@ class TableTest extends \PHPUnit\Framework\TestCase
$this->assertNull($object->getBgColor());
$this->assertEquals(Table::LAYOUT_AUTO, $object->getLayout());
$this->assertEquals(TblWidth::AUTO, $object->getUnit());
$this->assertNull($object->getIndent());
}
/**
@ -208,4 +210,13 @@ class TableTest extends \PHPUnit\Framework\TestCase
$this->assertNotNull($object->getPosition());
$this->assertEquals(TablePosition::VANCHOR_PAGE, $object->getPosition()->getVertAnchor());
}
public function testIndent()
{
$indent = new TblWidthComplexType(100, TblWidth::TWIP);
$table = new Table(array('indent' => $indent));
$this->assertSame($indent, $table->getIndent());
}
}

View File

@ -70,7 +70,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase
$text2->setTrackChange(new TrackChange(TrackChange::DELETED, 'another author', new \DateTime()));
$dom = $this->getAsHTML($phpWord);
$xpath = new \DOMXpath($dom);
$xpath = new \DOMXPath($dom);
$this->assertTrue($xpath->query('/html/body/p[1]/ins')->length == 1);
$this->assertTrue($xpath->query('/html/body/p[2]/del')->length == 1);
@ -94,7 +94,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase
$cell22->addText('second cell');
$dom = $this->getAsHTML($phpWord);
$xpath = new \DOMXpath($dom);
$xpath = new \DOMXPath($dom);
$this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 1);
$this->assertEquals('2', $xpath->query('/html/body/table/tr/td[1]')->item(0)->attributes->getNamedItem('colspan')->textContent);
@ -123,7 +123,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase
$row3->addCell(500)->addText('third cell being spanned');
$dom = $this->getAsHTML($phpWord);
$xpath = new \DOMXpath($dom);
$xpath = new \DOMXPath($dom);
$this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 2);
$this->assertEquals('3', $xpath->query('/html/body/table/tr[1]/td[1]')->item(0)->attributes->getNamedItem('rowspan')->textContent);

View File

@ -17,7 +17,9 @@
namespace PhpOffice\PhpWord\Writer\RTF;
use PhpOffice\PhpWord\Writer\RTF;
use PhpOffice\PhpWord\Writer\RTF\Style\Border;
use PHPUnit\Framework\Assert;
/**
* Test class for PhpOffice\PhpWord\Writer\RTF\Style subnamespace
@ -29,7 +31,7 @@ class StyleTest extends \PHPUnit\Framework\TestCase
*/
public function testEmptyStyles()
{
$styles = array('Font', 'Paragraph', 'Section');
$styles = array('Font', 'Paragraph', 'Section', 'Tab', 'Indentation');
foreach ($styles as $style) {
$objectClass = 'PhpOffice\\PhpWord\\Writer\\RTF\\Style\\' . $style;
$object = new $objectClass();
@ -55,4 +57,55 @@ class StyleTest extends \PHPUnit\Framework\TestCase
$this->assertEquals($expected, $content);
}
public function testIndentation()
{
$indentation = new \PhpOffice\PhpWord\Style\Indentation();
$indentation->setLeft(1);
$indentation->setRight(2);
$indentation->setFirstLine(3);
$indentWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Indentation($indentation);
$indentWriter->setParentWriter(new RTF());
$result = $indentWriter->write();
Assert::assertEquals('\fi3\li1\ri2 ', $result);
}
public function testRightTab()
{
$tabRight = new \PhpOffice\PhpWord\Style\Tab();
$tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_RIGHT);
$tabRight->setPosition(5);
$tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight);
$tabWriter->setParentWriter(new RTF());
$result = $tabWriter->write();
Assert::assertEquals('\tqr\tx5', $result);
}
public function testCenterTab()
{
$tabRight = new \PhpOffice\PhpWord\Style\Tab();
$tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_CENTER);
$tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight);
$tabWriter->setParentWriter(new RTF());
$result = $tabWriter->write();
Assert::assertEquals('\tqc\tx0', $result);
}
public function testDecimalTab()
{
$tabRight = new \PhpOffice\PhpWord\Style\Tab();
$tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_DECIMAL);
$tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight);
$tabWriter->setParentWriter(new RTF());
$result = $tabWriter->write();
Assert::assertEquals('\tqdec\tx0', $result);
}
}

View File

@ -256,7 +256,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase
{
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$style = array('width' => 1000000, 'height' => 1000000);
$style = array('width' => 1000000, 'height' => 1000000, 'showAxisLabels' => true, 'showGridX' => true, 'showGridY' => true);
$chartTypes = array('pie', 'doughnut', 'bar', 'line', 'area', 'scatter', 'radar');
$categories = array('A', 'B', 'C', 'D', 'E');
@ -288,6 +288,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase
$section->addField('DATE', array(), array('LunarCalendar'));
$section->addField('DATE', array(), array('SakaEraCalendar'));
$section->addField('NUMPAGES', array('format' => 'roman', 'numformat' => '0,00'), array('SakaEraCalendar'));
$section->addField('STYLEREF', array('StyleIdentifier' => 'Heading 1'));
$doc = TestHelperDOCX::getDocument($phpWord);
$element = '/w:document/w:body/w:p/w:r/w:instrText';

View File

@ -17,11 +17,10 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
use PhpOffice\Common\Microsoft\PasswordEncoder;
use PhpOffice\PhpWord\ComplexType\ProofState;
use PhpOffice\PhpWord\ComplexType\TrackChangesView;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder;
use PhpOffice\PhpWord\SimpleType\Zoom;
use PhpOffice\PhpWord\Style\Language;
use PhpOffice\PhpWord\TestHelperDOCX;

View File

@ -43,7 +43,7 @@ class FontTest extends \PHPUnit\Framework\TestCase
$phpWord = new \PhpOffice\PhpWord\PhpWord();
$section = $phpWord->addSection();
$textrun = $section->addTextRun();
$textrun->addText('سلام این یک پاراگراف راست به چپ است', array('rtl' => true));
$textrun->addText('سلام این یک پاراگراف راست به چپ است', array('rtl' => true, 'lang' => 'ar-DZ'));
$doc = TestHelperDOCX::getDocument($phpWord, 'Word2007');
$file = 'word/document.xml';

View File

@ -17,6 +17,8 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Style;
use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType;
use PhpOffice\PhpWord\SimpleType\TblWidth;
use PhpOffice\PhpWord\Style\Table;
use PhpOffice\PhpWord\Style\TablePosition;
use PhpOffice\PhpWord\TestHelperDOCX;
@ -75,7 +77,7 @@ class TableTest extends \PHPUnit\Framework\TestCase
$path = '/w:document/w:body/w:tbl/w:tblPr/w:tblCellSpacing';
$this->assertTrue($doc->elementExists($path));
$this->assertEquals(10.3, $doc->getElementAttribute($path, 'w:w'));
$this->assertEquals(\PhpOffice\PhpWord\SimpleType\TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type'));
$this->assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type'));
}
/**
@ -118,4 +120,25 @@ class TableTest extends \PHPUnit\Framework\TestCase
$this->assertEquals(TablePosition::YALIGN_TOP, $doc->getElementAttribute($path, 'w:tblpYSpec'));
$this->assertEquals(60, $doc->getElementAttribute($path, 'w:tblpY'));
}
public function testIndent()
{
$value = 100;
$type = TblWidth::TWIP;
$tableStyle = new Table();
$tableStyle->setIndent(new TblWidthComplexType($value, $type));
$phpWord = new \PhpOffice\PhpWord\PhpWord();
$section = $phpWord->addSection();
$table = $section->addTable($tableStyle);
$table->addRow();
$doc = TestHelperDOCX::getDocument($phpWord, 'Word2007');
$path = '/w:document/w:body/w:tbl/w:tblPr/w:tblInd';
$this->assertTrue($doc->elementExists($path));
$this->assertSame($value, (int) $doc->getElementAttribute($path, 'w:w'));
$this->assertSame($type, $doc->getElementAttribute($path, 'w:type'));
}
}

View File

@ -37,9 +37,9 @@ class XmlDocument
private $dom;
/**
* DOMXpath object
* DOMXPath object
*
* @var \DOMXpath
* @var \DOMXPath
*/
private $xpath;
@ -76,8 +76,10 @@ class XmlDocument
$this->file = $file;
$file = $this->path . '/' . $file;
libxml_disable_entity_loader(false);
$this->dom = new \DOMDocument();
$this->dom->load($file);
libxml_disable_entity_loader(true);
return $this->dom;
}
@ -96,7 +98,7 @@ class XmlDocument
}
if (null === $this->xpath) {
$this->xpath = new \DOMXpath($this->dom);
$this->xpath = new \DOMXPath($this->dom);
$this->xpath->registerNamespace('w14', 'http://schemas.microsoft.com/office/word/2010/wordml');
}