Merge pull request #1946 from liborm85/php80

Compatibility with PHP 7.4, PHP 8.0 and migrate to Laminas Escaper
This commit is contained in:
troosan 2020-12-29 22:42:02 +01:00 committed by GitHub
commit 7a97d24c77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 102 additions and 45 deletions

View File

@ -3,6 +3,12 @@ build:
analysis: analysis:
tests: tests:
override: [php-scrutinizer-run] override: [php-scrutinizer-run]
environment:
php:
version: '7.4'
pecl_extensions:
- zip
filter: filter:
excluded_paths: [ 'vendor/*', 'tests/*', 'samples/*', 'src/PhpWord/Shared/PCLZip/*' ] excluded_paths: [ 'vendor/*', 'tests/*', 'samples/*', 'src/PhpWord/Shared/PCLZip/*' ]

View File

@ -11,29 +11,30 @@ php:
- 7.1 - 7.1
- 7.2 - 7.2
- 7.3 - 7.3
- 7.4snapshot - 7.4
- 8.0
matrix: matrix:
include: include:
- php: 5.3 - php: 5.3
dist: precise dist: precise
env: COMPOSER_MEMORY_LIMIT=3G
- php: 5.4 - php: 5.4
dist: trusty dist: trusty
- php: 5.5 - php: 5.5
dist: trusty dist: trusty
- php: 7.0 - php: 7.0
env: COVERAGE=1 env: COVERAGE=1
- php: 7.3 - php: 8.0
env: DEPENDENCIES="--ignore-platform-reqs" env: DEPENDENCIES="--ignore-platform-reqs"
exclude: exclude:
- php: 5.3 - php: 5.3
dist: xenial
- php: 5.4 - php: 5.4
dist: xenial
- php: 5.5 - php: 5.5
- php: 7.0 dist: xenial
- php: 7.3
allow_failures: allow_failures:
- php: 7.4snapshot - php: 8.0
cache: cache:
directories: directories:
@ -55,7 +56,31 @@ before_script:
- if [ -z "$COVERAGE" ]; then phpenv config-rm xdebug.ini || echo "xdebug not available" ; fi - if [ -z "$COVERAGE" ]; then phpenv config-rm xdebug.ini || echo "xdebug not available" ; fi
## Composer ## Composer
- composer self-update - composer self-update
## Composer in PHP versions 5.x requires 3 GB memory
- if [ ${TRAVIS_PHP_VERSION:0:2} == "5." ]; then export COMPOSER_MEMORY_LIMIT=3G ; fi
## PHP 8 require PHPUnit 8 (ugly hack for support PHPUnit 7 and 8 together)
- |
if [[ ${TRAVIS_PHP_VERSION:0:2} == "8." ]] || [[ $TRAVIS_PHP_VERSION == "nightly" ]]; then
travis_wait composer remove phpunit/phpunit --dev --no-update --no-interaction
travis_wait composer require phpunit/phpunit ^8.0 --dev --no-update
fi
## Install composer packages
- travis_wait composer install --prefer-source $(if [ -n "$DEPENDENCIES" ]; then echo $DEPENDENCIES; fi) - travis_wait composer install --prefer-source $(if [ -n "$DEPENDENCIES" ]; then echo $DEPENDENCIES; fi)
## PHP 8 require PHPUnit 8 (ugly hack for support PHPUnit 7 and 8 together)
- |
if [[ ${TRAVIS_PHP_VERSION:0:2} == "8." ]] || [[ $TRAVIS_PHP_VERSION == "nightly" ]]; then
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function setUpBeforeClass()$/function setUpBeforeClass(): void/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function tearDownAfterClass()$/function tearDownAfterClass(): void/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function setUp()$/function setUp(): void/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/function tearDown()$/function tearDown(): void/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/->assertContains(/->assertStringContainsString(/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e 's/->assertNotContains(/->assertStringNotContainsString(/' {} \;
find ./tests/ -name "*.php" -type f -exec sed -i -e "s/->assertInternalType('array', /->assertIsArray(/" {} \;
sed -i "s/\$this->addWarning('The @expectedException,/\/\/\$this->addWarning('The @expectedException,/" ./vendor/phpunit/phpunit/src/Framework/TestCase.php
sed -i "s/self::createWarning('The optional \$delta/\/\/self::createWarning('The optional \$delta/" ./vendor/phpunit/phpunit/src/Framework/Assert.php
fi
## PHPDocumentor ## PHPDocumentor
##- mkdir -p build/docs ##- mkdir -p build/docs
- mkdir -p build/coverage - mkdir -p build/coverage

View File

@ -62,8 +62,7 @@ PHPWord requires the following:
- PHP 5.3.3+ - PHP 5.3.3+
- [XML Parser extension](http://www.php.net/manual/en/xml.installation.php) - [XML Parser extension](http://www.php.net/manual/en/xml.installation.php)
- [Zend\Escaper component](http://framework.zend.com/manual/current/en/modules/zend.escaper.introduction.html) - [Laminas Escaper component](https://docs.laminas.dev/laminas-escaper/intro/)
- [Zend\Stdlib component](http://framework.zend.com/manual/current/en/modules/zend.stdlib.hydrator.html)
- [Zip extension](http://php.net/manual/en/book.zip.php) (optional, used to write OOXML and ODF) - [Zip extension](http://php.net/manual/en/book.zip.php) (optional, used to write OOXML and ODF)
- [GD extension](http://php.net/manual/en/book.image.php) (optional, used to add images) - [GD extension](http://php.net/manual/en/book.image.php) (optional, used to add images)
- [XMLWriter extension](http://php.net/manual/en/book.xmlwriter.php) (optional, used to write OOXML and ODF) - [XMLWriter extension](http://php.net/manual/en/book.xmlwriter.php) (optional, used to write OOXML and ODF)

View File

@ -58,24 +58,27 @@
"fix": "Fixes issues found by PHP-CS" "fix": "Fixes issues found by PHP-CS"
}, },
"require": { "require": {
"php": "^5.3.3 || ^7.0", "php": "^5.3.3 || ^7.0 || ^8.0",
"ext-xml": "*", "ext-xml": "*",
"zendframework/zend-escaper": "^2.2", "laminas/laminas-escaper": "^2.2",
"phpoffice/common": "^0.2.9" "phpoffice/common": "^0.2.9"
}, },
"require-dev": { "require-dev": {
"ext-zip": "*", "ext-zip": "*",
"ext-gd": "*", "ext-gd": "*",
"phpunit/phpunit": "^4.8.36 || ^7.0", "phpunit/phpunit": "^4.8.36 || ^7.0",
"squizlabs/php_codesniffer": "^2.9", "squizlabs/php_codesniffer": "^2.9 || ^3.5",
"friendsofphp/php-cs-fixer": "^2.2", "friendsofphp/php-cs-fixer": "^2.2",
"phpmd/phpmd": "2.*", "phpmd/phpmd": "2.*",
"phploc/phploc": "2.* || 3.* || 4.*", "phploc/phploc": "2.* || 3.* || 4.* || 5.* || 6.* || 7.*",
"dompdf/dompdf":"0.8.*", "dompdf/dompdf":"0.8.*",
"tecnickcom/tcpdf": "6.*", "tecnickcom/tcpdf": "6.*",
"mpdf/mpdf": "5.7.4 || 6.* || 7.*", "mpdf/mpdf": "5.7.4 || 6.* || 7.* || 8.*",
"php-coveralls/php-coveralls": "1.1.0 || ^2.0" "php-coveralls/php-coveralls": "1.1.0 || ^2.0"
}, },
"replace": {
"laminas/laminas-zendframework-bridge": "*"
},
"suggest": { "suggest": {
"ext-zip": "Allows writing OOXML and ODF", "ext-zip": "Allows writing OOXML and ODF",
"ext-gd2": "Allows adding images", "ext-gd2": "Allows adding images",

View File

@ -10,9 +10,7 @@ Mandatory:
- PHP 5.3.3+ - PHP 5.3.3+
- `XML Parser <http://www.php.net/manual/en/xml.installation.php>`__ extension - `XML Parser <http://www.php.net/manual/en/xml.installation.php>`__ extension
- `Zend\\Escaper <http://framework.zend.com/manual/current/en/modules/zend.escaper.introduction.html>`__ component - `Laminas Escaper <https://docs.laminas.dev/laminas-escaper/intro/>`__ component
- Zend\\Stdlib component
- `Zend\\Validator <http://framework.zend.com/manual/current/en/modules/zend.validator.html>`__ component
Optional: Optional:

View File

@ -5,6 +5,8 @@
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"> xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<rule ref="rulesets/naming.xml"> <rule ref="rulesets/naming.xml">
<exclude name="ShortVariable" />
<exclude name="ShortClassName" />
<exclude name="LongVariable" /> <exclude name="LongVariable" />
</rule> </rule>
<rule ref="rulesets/naming.xml/LongVariable"> <rule ref="rulesets/naming.xml/LongVariable">

View File

@ -109,6 +109,7 @@ abstract class AbstractContainer extends AbstractElement
} else { } else {
// All other elements // All other elements
array_unshift($args, $element); // Prepend element name to the beginning of args array array_unshift($args, $element); // Prepend element name to the beginning of args array
return call_user_func_array(array($this, 'addElement'), $args); return call_user_func_array(array($this, 'addElement'), $args);
} }
} }

View File

@ -454,7 +454,7 @@ class Image extends AbstractElement
} else { } else {
$this->sourceType = self::SOURCE_GD; $this->sourceType = self::SOURCE_GD;
} }
} elseif (@file_exists($this->source)) { } elseif ((strpos($this->source, chr(0)) === false) && @file_exists($this->source)) {
$this->memoryImage = false; $this->memoryImage = false;
$this->sourceType = self::SOURCE_LOCAL; $this->sourceType = self::SOURCE_LOCAL;
} else { } else {

View File

@ -1581,7 +1581,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
// Variables // Variables
$sprmCPicLocation = null; $sprmCPicLocation = null;
$sprmCFData = null; $sprmCFData = null;
$sprmCFSpec = null; //$sprmCFSpec = null;
do { do {
// Variables // Variables
@ -1830,7 +1830,7 @@ class MsDoc extends AbstractReader implements ReaderInterface
break; break;
// sprmCFSpec // sprmCFSpec
case 0x55: case 0x55:
$sprmCFSpec = $operand; //$sprmCFSpec = $operand;
break; break;
// sprmCFtcBi // sprmCFtcBi
case 0x5E: case 0x5E:
@ -2094,11 +2094,11 @@ class MsDoc extends AbstractReader implements ReaderInterface
$sprmCPicLocation += 1; $sprmCPicLocation += 1;
// stPicName // stPicName
$stPicName = ''; //$stPicName = '';
for ($inc = 0; $inc <= $cchPicName; $inc++) { for ($inc = 0; $inc <= $cchPicName; $inc++) {
$chr = self::getInt1d($this->dataData, $sprmCPicLocation); //$chr = self::getInt1d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 1; $sprmCPicLocation += 1;
$stPicName .= chr($chr); //$stPicName .= chr($chr);
} }
} }
@ -2143,11 +2143,11 @@ class MsDoc extends AbstractReader implements ReaderInterface
$sprmCPicLocation += 1; $sprmCPicLocation += 1;
// nameData // nameData
if ($cbName > 0) { if ($cbName > 0) {
$nameData = ''; //$nameData = '';
for ($inc = 0; $inc <= ($cbName / 2); $inc++) { for ($inc = 0; $inc <= ($cbName / 2); $inc++) {
$chr = self::getInt2d($this->dataData, $sprmCPicLocation); //$chr = self::getInt2d($this->dataData, $sprmCPicLocation);
$sprmCPicLocation += 2; $sprmCPicLocation += 2;
$nameData .= chr($chr); //$nameData .= chr($chr);
} }
} }
// embeddedBlip // embeddedBlip

View File

@ -573,11 +573,11 @@ abstract class AbstractPart
* Returns the first child element found * Returns the first child element found
* *
* @param XMLReader $xmlReader * @param XMLReader $xmlReader
* @param \DOMElement $parentNode * @param \DOMElement|null $parentNode
* @param string|array $elements * @param string|array|null $elements
* @return string|null * @return string|null
*/ */
private function findPossibleElement(XMLReader $xmlReader, \DOMElement $parentNode = null, $elements) private function findPossibleElement(XMLReader $xmlReader, \DOMElement $parentNode = null, $elements = null)
{ {
if (is_array($elements)) { if (is_array($elements)) {
//if element is an array, we take the first element that exists in the XML //if element is an array, we take the first element that exists in the XML

View File

@ -338,9 +338,9 @@ class Converter
return false; return false;
} }
$red = hexdec($red); $red = ctype_xdigit($red) ? hexdec($red) : 0;
$green = hexdec($green); $green = ctype_xdigit($green) ? hexdec($green) : 0;
$blue = hexdec($blue); $blue = ctype_xdigit($blue) ? hexdec($blue) : 0;
return array($red, $green, $blue); return array($red, $green, $blue);
} }

View File

@ -72,7 +72,9 @@ class Html
} }
// Load DOM // Load DOM
if (\PHP_VERSION_ID < 80000) {
$orignalLibEntityLoader = libxml_disable_entity_loader(true); $orignalLibEntityLoader = libxml_disable_entity_loader(true);
}
$dom = new \DOMDocument(); $dom = new \DOMDocument();
$dom->preserveWhiteSpace = $preserveWhiteSpace; $dom->preserveWhiteSpace = $preserveWhiteSpace;
$dom->loadXML($html); $dom->loadXML($html);
@ -80,8 +82,10 @@ class Html
$node = $dom->getElementsByTagName('body'); $node = $dom->getElementsByTagName('body');
self::parseNode($node->item(0), $element); self::parseNode($node->item(0), $element);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($orignalLibEntityLoader); libxml_disable_entity_loader($orignalLibEntityLoader);
} }
}
/** /**
* parse Inline style of a node * parse Inline style of a node
@ -178,7 +182,7 @@ class Html
} }
} }
$method = "parse{$method}"; $method = "parse{$method}";
$newElement = call_user_func_array(array('PhpOffice\PhpWord\Shared\Html', $method), $arguments); $newElement = call_user_func_array(array('PhpOffice\PhpWord\Shared\Html', $method), array_values($arguments));
// Retrieve back variables from arguments // Retrieve back variables from arguments
foreach ($keys as $key) { foreach ($keys as $key) {

View File

@ -170,7 +170,9 @@ class TemplateProcessor
*/ */
protected function transformSingleXml($xml, $xsltProcessor) protected function transformSingleXml($xml, $xsltProcessor)
{ {
if (\PHP_VERSION_ID < 80000) {
$orignalLibEntityLoader = libxml_disable_entity_loader(true); $orignalLibEntityLoader = libxml_disable_entity_loader(true);
}
$domDocument = new \DOMDocument(); $domDocument = new \DOMDocument();
if (false === $domDocument->loadXML($xml)) { if (false === $domDocument->loadXML($xml)) {
throw new Exception('Could not load the given XML document.'); throw new Exception('Could not load the given XML document.');
@ -180,7 +182,9 @@ class TemplateProcessor
if (false === $transformedXml) { if (false === $transformedXml) {
throw new Exception('Could not transform the given XML document.'); throw new Exception('Could not transform the given XML document.');
} }
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($orignalLibEntityLoader); libxml_disable_entity_loader($orignalLibEntityLoader);
}
return $transformedXml; return $transformedXml;
} }

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Writer\HTML\Element; namespace PhpOffice\PhpWord\Writer\HTML\Element;
use Laminas\Escaper\Escaper;
use PhpOffice\PhpWord\Element\AbstractElement as Element; use PhpOffice\PhpWord\Element\AbstractElement as Element;
use PhpOffice\PhpWord\Writer\AbstractWriter; use PhpOffice\PhpWord\Writer\AbstractWriter;
use Zend\Escaper\Escaper;
/** /**
* Abstract HTML element writer * Abstract HTML element writer
@ -50,7 +50,7 @@ abstract class AbstractElement
protected $withoutP = false; protected $withoutP = false;
/** /**
* @var \Zend\Escaper\Escaper|\PhpOffice\PhpWord\Escaper\AbstractEscaper * @var \Laminas\Escaper\Escaper|\PhpOffice\PhpWord\Escaper\AbstractEscaper
*/ */
protected $escaper; protected $escaper;

View File

@ -17,9 +17,9 @@
namespace PhpOffice\PhpWord\Writer\HTML\Part; namespace PhpOffice\PhpWord\Writer\HTML\Part;
use Laminas\Escaper\Escaper;
use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\Writer\AbstractWriter; use PhpOffice\PhpWord\Writer\AbstractWriter;
use Zend\Escaper\Escaper;
/** /**
* @since 0.11.0 * @since 0.11.0
@ -32,7 +32,7 @@ abstract class AbstractPart
private $parentWriter; private $parentWriter;
/** /**
* @var \Zend\Escaper\Escaper * @var \Laminas\Escaper\Escaper
*/ */
protected $escaper; protected $escaper;

View File

@ -99,10 +99,10 @@ class TableTest extends \PHPUnit\Framework\TestCase
{ {
$oTable = new Table(); $oTable = new Table();
$oTable->addRow(); $oTable->addRow();
$element = $oTable->addCell(); $oTable->addCell();
$this->assertEquals($oTable->countColumns(), 1); $this->assertEquals($oTable->countColumns(), 1);
$element = $oTable->addCell(); $oTable->addCell();
$element = $oTable->addCell(); $oTable->addCell();
$this->assertEquals($oTable->countColumns(), 3); $this->assertEquals($oTable->countColumns(), 3);
} }
} }

View File

@ -140,6 +140,11 @@ final class TemplateProcessorTest extends \PHPUnit\Framework\TestCase
*/ */
final public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue() final public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue()
{ {
// Test is not needed for PHP 8.0, because internally validation throws TypeError exception.
if (\PHP_VERSION_ID >= 80000) {
$this->markTestSkipped('not needed for PHP 8.0');
}
$templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); $templateProcessor = new TemplateProcessor(__DIR__ . '/_files/templates/blank.docx');
$xslDomDocument = new \DOMDocument(); $xslDomDocument = new \DOMDocument();

View File

@ -33,6 +33,12 @@ class TCPDFTest extends \PHPUnit\Framework\TestCase
*/ */
public function testConstruct() public function testConstruct()
{ {
// TCPDF version 6.3.5 doesn't support PHP 5.3, fixed via https://github.com/tecnickcom/TCPDF/pull/197,
// pending new release.
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
return;
}
$file = __DIR__ . '/../../_files/tcpdf.pdf'; $file = __DIR__ . '/../../_files/tcpdf.pdf';
$phpWord = new PhpWord(); $phpWord = new PhpWord();

View File

@ -76,10 +76,14 @@ class XmlDocument
$this->file = $file; $this->file = $file;
$file = $this->path . '/' . $file; $file = $this->path . '/' . $file;
if (\PHP_VERSION_ID < 80000) {
$orignalLibEntityLoader = libxml_disable_entity_loader(false); $orignalLibEntityLoader = libxml_disable_entity_loader(false);
}
$this->dom = new \DOMDocument(); $this->dom = new \DOMDocument();
$this->dom->load($file); $this->dom->load($file);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($orignalLibEntityLoader); libxml_disable_entity_loader($orignalLibEntityLoader);
}
return $this->dom; return $this->dom;
} }