diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ce201f8bb6..7b74162561 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,4 +9,4 @@ Fixes # (issue) - [ ] My CI is :green_circle: - [ ] I have covered by unit tests my new code (check build/coverage for coverage report) - [ ] I have updated the [documentation](https://github.com/PHPOffice/PHPWord/tree/master/docs) to describe the changes -- [ ] I have updated the [changelog](https://github.com/PHPOffice/PHPWord/blob/master/docs/changes/2.x/2.0.0.md) +- [ ] I have updated the [changelog](https://github.com/PHPOffice/PHPWord/blob/master/docs/changes/1.x/1.4.0.md) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index ed772171e7..0e2e9ea96d 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -1,165 +1,124 @@ -name: CI -on: - pull_request: - push: - branches: - - master +name: PHPWord +on: [push, pull_request] jobs: - test: + php-cs-fixer: + name: PHP CS Fixer runs-on: ubuntu-latest - strategy: - matrix: - php-version: - - "7.1.3" - - "7.2" - - "7.3" - - "7.4" - - "8.0" - - "8.1" - - "8.2" - - "8.3" - - name: PHP ${{ matrix.php-version }} - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup PHP, with composer and extensions + - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: ${{ matrix.php-version }} - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Remove lock for old EOL PHP versions - if: matrix.php-version == '7.1.3' || matrix.php-version == '7.2' || matrix.php-version == '7.3' || matrix.php-version == '7.4' - run: rm composer.lock && composer config platform.php ${{ matrix.php-version }} + php-version: '8.3' + extensions: mbstring, intl, gd, xml, dom, json, fileinfo, curl, zip, iconv + - uses: actions/checkout@v2 - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader + - name: Validate composer config + run: composer validate --strict - - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + - name: Composer Install + run: composer global require friendsofphp/php-cs-fixer - - name: Setup problem matchers for PHPUnit - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + - name: Add environment path + run: export PATH="$PATH:$HOME/.composer/vendor/bin" - - name: Configure matchers - uses: mheap/phpunit-matcher-action@v1 + - name: Run PHPCSFixer + run: php-cs-fixer fix --dry-run --diff - - name: Test with PHPUnit - run: ./vendor/bin/phpunit --no-coverage - - php-cs-fixer: + phpmd: + name: PHP Mess Detector runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + extensions: gd, xml, zip + - uses: actions/checkout@v2 - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.0 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - tools: cs2pr + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Code style with PHP-CS-Fixer - run: ./vendor/bin/php-cs-fixer fix --dry-run --diff + - name: Run phpmd + run: ./vendor/bin/phpmd src/,tests/ text ./phpmd.xml.dist --exclude "src/PhpWord/Shared/PCLZip/*" phpstan: + name: PHP Static Analysis runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Disabled PHPStan in '7.1' + php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] steps: - - name: Checkout - uses: actions/checkout@v3 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, xml, zip + - uses: actions/checkout@v2 - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.0 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - tools: cs2pr + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- + - name: Run phpstan + run: ./vendor/bin/phpstan analyse -c phpstan.neon.dist - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Static analysis with PHPStan - run: ./vendor/bin/phpstan analyse - - coverage: + phpunit: + name: PHPUnit ${{ matrix.php }} runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, xml, zip + coverage: ${{ (matrix.php == '7.3') && 'xdebug' || 'none' }} + + - uses: actions/checkout@v2 + + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress + + - name: Run phpunit + if: matrix.php != '7.3' + run: ./vendor/bin/phpunit -c phpunit.xml.dist --no-coverage + + - name: Run phpunit + if: matrix.php == '7.3' + run: ./vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover build/clover.xml + + - name: Upload coverage results to Coveralls + if: matrix.php == '7.3' + env: + COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.4.3/php-coveralls.phar + chmod +x php-coveralls.phar + php php-coveralls.phar --coverage_clover=build/clover.xml --json_path=build/coveralls-upload.json -vvv + + samples: + name: Check samples + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, xml, zip + coverage: xdebug - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.1 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: xdebug + - uses: actions/checkout@v2 - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress - - name: Cache composer dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Run phpunit - run: ./vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover build/clover.xml - - - name: Upload coverage results to Coveralls - env: - COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.4.3/php-coveralls.phar - chmod +x php-coveralls.phar - php php-coveralls.phar --coverage_clover=build/clover.xml --json_path=build/coveralls-upload.json -vvv + - name: Generate samples files + run: composer run samples diff --git a/.gitignore b/.gitignore index 3695438057..0b9d0608d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +/composer.lock + + .DS_Store ._* .Spotlight-V100 diff --git a/LICENSE b/LICENSE index 8a1acaeaba..aebd12b0ed 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ PHPWord, a pure PHP library for reading and writing word processing documents. -Copyright (c) 2010-2016 PHPWord. +Copyright (c) 2010-2025 PHPWord. PHPWord is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 as published by diff --git a/README.md b/README.md index 11bcd1525c..e080d32da8 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # ![PHPWord](https://rawgit.com/PHPOffice/PHPWord/develop/docs/images/phpword.svg "PHPWord") -[![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v/stable.png)](https://packagist.org/packages/phpoffice/phpword) +[![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v)](https://packagist.org/packages/phpoffice/phpword) [![Coverage Status](https://coveralls.io/repos/github/PHPOffice/PHPWord/badge.svg?branch=master)](https://coveralls.io/github/PHPOffice/PHPWord?branch=master) -[![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) -[![CI](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml/badge.svg)](https://github.com/PHPOffice/PHPWord/actions/workflows/ci.yml) -[![Join the chat at https://gitter.im/PHPOffice/PHPWord](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/PHPWord) +[![Total Downloads](https://poser.pugx.org/phpoffice/phpword/downloads)](https://packagist.org/packages/phpoffice/phpword) +[![License](https://poser.pugx.org/phpoffice/phpword/license)](https://packagist.org/packages/phpoffice/phpword) + +Branch Master : [![PHPWord](https://github.com/PHPOffice/PHPWord/actions/workflows/php.yml/badge.svg?branch=master)](https://github.com/PHPOffice/PHPWord/actions/workflows/php.yml) PHPWord is a library written in pure PHP that provides a set of classes to write to and read from different document file formats. The current version of PHPWord supports Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (RTF), HTML, and PDF. @@ -81,7 +81,6 @@ The following is a basic usage example of the PHPWord library. ```php =7.0", - "tecnickcom/tcpdf": "^6.5", "symfony/process": "^4.4 || ^5.0", - "friendsofphp/php-cs-fixer": "^3.3", - "phpstan/phpstan-phpunit": "@stable" + "tecnickcom/tcpdf": "^6.5" }, "suggest": { - "ext-zip": "Allows writing OOXML and ODF", - "ext-gd2": "Allows adding images", "ext-xmlwriter": "Allows writing OOXML and ODF", "ext-xsl": "Allows applying XSL style sheet to headers, to main document part, and to footers of an OOXML template", "dompdf/dompdf": "Allows writing PDF" diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 6eb3324ccb..0000000000 --- a/composer.lock +++ /dev/null @@ -1,5082 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "8d0272c1442e11290de55a7947fc849c", - "packages": [ - { - "name": "phpoffice/math", - "version": "0.1.0", - "source": { - "type": "git", - "url": "https://github.com/PHPOffice/Math.git", - "reference": "f0f8cad98624459c540cdd61d2a174d834471773" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/Math/zipball/f0f8cad98624459c540cdd61d2a174d834471773", - "reference": "f0f8cad98624459c540cdd61d2a174d834471773", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xml": "*", - "php": "^7.1|^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.88 || ^1.0.0", - "phpunit/phpunit": "^7.0 || ^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "PhpOffice\\Math\\": "src/Math/", - "Tests\\PhpOffice\\Math\\": "tests/Math/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Progi1984", - "homepage": "https://lefevre.dev" - } - ], - "description": "Math - Manipulate Math Formula", - "homepage": "https://phpoffice.github.io/Math/", - "keywords": [ - "MathML", - "officemathml", - "php" - ], - "support": { - "issues": "https://github.com/PHPOffice/Math/issues", - "source": "https://github.com/PHPOffice/Math/tree/0.1.0" - }, - "time": "2023-09-25T12:08:20+00:00" - } - ], - "packages-dev": [ - { - "name": "composer/pcre", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/1.0.1" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-21T20:24:37+00:00" - }, - { - "name": "composer/semver", - "version": "3.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-04-01T19:23:25+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "2.0.5", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", - "shasum": "" - }, - "require": { - "composer/pcre": "^1", - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-24T20:20:32+00:00" - }, - { - "name": "doctrine/annotations", - "version": "1.14.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", - "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^1 || ^2", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "~1.4.10 || ^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "vimeo/psalm": "^4.10" - }, - "suggest": { - "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.14.3" - }, - "time": "2023-02-01T09:20:38+00:00" - }, - { - "name": "doctrine/deprecations", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "8cffffb2218e01f3b370bf763e00e81697725259" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/8cffffb2218e01f3b370bf763e00e81697725259", - "reference": "8cffffb2218e01f3b370bf763e00e81697725259", - "shasum": "" - }, - "require": { - "php": "^7.1|^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.1.0" - }, - "time": "2023-05-29T18:55:17+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:15:36+00:00" - }, - { - "name": "doctrine/lexer", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^4.11 || ^5.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/2.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2022-12-14T08:49:07+00:00" - }, - { - "name": "dompdf/dompdf", - "version": "v2.0.4", - "source": { - "type": "git", - "url": "https://github.com/dompdf/dompdf.git", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/093f2d9739cec57428e39ddadedfd4f3ae862c0f", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "masterminds/html5": "^2.0", - "phenx/php-font-lib": ">=0.5.4 <1.0.0", - "phenx/php-svg-lib": ">=0.3.3 <1.0.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "ext-json": "*", - "ext-zip": "*", - "mockery/mockery": "^1.3", - "phpunit/phpunit": "^7.5 || ^8 || ^9", - "squizlabs/php_codesniffer": "^3.5" - }, - "suggest": { - "ext-gd": "Needed to process images", - "ext-gmagick": "Improves image processing performance", - "ext-imagick": "Improves image processing performance", - "ext-zlib": "Needed for pdf stream compression" - }, - "type": "library", - "autoload": { - "psr-4": { - "Dompdf\\": "src/" - }, - "classmap": [ - "lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1" - ], - "authors": [ - { - "name": "The Dompdf Community", - "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" - } - ], - "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", - "homepage": "https://github.com/dompdf/dompdf", - "support": { - "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v2.0.4" - }, - "time": "2023-12-12T20:19:39+00:00" - }, - { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.4.0", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", - "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", - "shasum": "" - }, - "require": { - "composer/semver": "^3.2", - "composer/xdebug-handler": "^2.0", - "doctrine/annotations": "^1.12", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.2.5 || ^8.0", - "php-cs-fixer/diff": "^2.0", - "symfony/console": "^4.4.20 || ^5.1.3 || ^6.0", - "symfony/event-dispatcher": "^4.4.20 || ^5.0 || ^6.0", - "symfony/filesystem": "^4.4.20 || ^5.0 || ^6.0", - "symfony/finder": "^4.4.20 || ^5.0 || ^6.0", - "symfony/options-resolver": "^4.4.20 || ^5.0 || ^6.0", - "symfony/polyfill-mbstring": "^1.23", - "symfony/polyfill-php80": "^1.23", - "symfony/polyfill-php81": "^1.23", - "symfony/process": "^4.4.20 || ^5.0 || ^6.0", - "symfony/stopwatch": "^4.4.20 || ^5.0 || ^6.0" - }, - "require-dev": { - "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^1.5", - "mikey179/vfsstream": "^1.6.8", - "php-coveralls/php-coveralls": "^2.5.2", - "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy": "^1.15", - "phpspec/prophecy-phpunit": "^1.1 || ^2.0", - "phpunit/phpunit": "^8.5.21 || ^9.5", - "phpunitgoodpractices/polyfill": "^1.5", - "phpunitgoodpractices/traits": "^1.9.1", - "symfony/phpunit-bridge": "^5.2.4 || ^6.0", - "symfony/yaml": "^4.4.20 || ^5.0 || ^6.0" - }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters." - }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", - "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - } - ], - "description": "A tool to automatically fix PHP code style", - "support": { - "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.4.0" - }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } - ], - "time": "2021-12-11T16:25:08+00:00" - }, - { - "name": "masterminds/html5", - "version": "2.8.1", - "source": { - "type": "git", - "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-4": { - "Masterminds\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Butcher", - "email": "technosophos@gmail.com" - }, - { - "name": "Matt Farina", - "email": "matt@mattfarina.com" - }, - { - "name": "Asmir Mustafic", - "email": "goetas@gmail.com" - } - ], - "description": "An HTML5 parser and serializer.", - "homepage": "http://masterminds.github.io/html5-php", - "keywords": [ - "HTML5", - "dom", - "html", - "parser", - "querypath", - "serializer", - "xml" - ], - "support": { - "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" - }, - "time": "2023-05-10T11:58:31+00:00" - }, - { - "name": "mpdf/mpdf", - "version": "v8.2.2", - "source": { - "type": "git", - "url": "https://github.com/mpdf/mpdf.git", - "reference": "596a87b876d7793be7be060a8ac13424de120dd5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/596a87b876d7793be7be060a8ac13424de120dd5", - "reference": "596a87b876d7793be7be060a8ac13424de120dd5", - "shasum": "" - }, - "require": { - "ext-gd": "*", - "ext-mbstring": "*", - "mpdf/psr-http-message-shim": "^1.0 || ^2.0", - "mpdf/psr-log-aware-trait": "^2.0 || ^3.0", - "myclabs/deep-copy": "^1.7", - "paragonie/random_compat": "^1.4|^2.0|^9.99.99", - "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "psr/http-message": "^1.0 || ^2.0", - "psr/log": "^1.0 || ^2.0 || ^3.0", - "setasign/fpdi": "^2.1" - }, - "require-dev": { - "mockery/mockery": "^1.3.0", - "mpdf/qrcode": "^1.1.0", - "squizlabs/php_codesniffer": "^3.5.0", - "tracy/tracy": "~2.5", - "yoast/phpunit-polyfills": "^1.0" - }, - "suggest": { - "ext-bcmath": "Needed for generation of some types of barcodes", - "ext-xml": "Needed mainly for SVG manipulation", - "ext-zlib": "Needed for compression of embedded resources, such as fonts" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Mpdf\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0-only" - ], - "authors": [ - { - "name": "Matěj Humpál", - "role": "Developer, maintainer" - }, - { - "name": "Ian Back", - "role": "Developer (retired)" - } - ], - "description": "PHP library generating PDF files from UTF-8 encoded HTML", - "homepage": "https://mpdf.github.io", - "keywords": [ - "pdf", - "php", - "utf-8" - ], - "support": { - "docs": "http://mpdf.github.io", - "issues": "https://github.com/mpdf/mpdf/issues", - "source": "https://github.com/mpdf/mpdf" - }, - "funding": [ - { - "url": "https://www.paypal.me/mpdf", - "type": "custom" - } - ], - "time": "2023-11-07T13:52:14+00:00" - }, - { - "name": "mpdf/psr-http-message-shim", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/mpdf/psr-http-message-shim.git", - "reference": "f25a0153d645e234f9db42e5433b16d9b113920f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mpdf/psr-http-message-shim/zipball/f25a0153d645e234f9db42e5433b16d9b113920f", - "reference": "f25a0153d645e234f9db42e5433b16d9b113920f", - "shasum": "" - }, - "require": { - "psr/http-message": "^2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Mpdf\\PsrHttpMessageShim\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mark Dorison", - "email": "mark@chromatichq.com" - }, - { - "name": "Kristofer Widholm", - "email": "kristofer@chromatichq.com" - }, - { - "name": "Nigel Cunningham", - "email": "nigel.cunningham@technocrat.com.au" - } - ], - "description": "Shim to allow support of different psr/message versions.", - "support": { - "issues": "https://github.com/mpdf/psr-http-message-shim/issues", - "source": "https://github.com/mpdf/psr-http-message-shim/tree/v2.0.1" - }, - "time": "2023-10-02T14:34:03+00:00" - }, - { - "name": "mpdf/psr-log-aware-trait", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/mpdf/psr-log-aware-trait.git", - "reference": "a633da6065e946cc491e1c962850344bb0bf3e78" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mpdf/psr-log-aware-trait/zipball/a633da6065e946cc491e1c962850344bb0bf3e78", - "reference": "a633da6065e946cc491e1c962850344bb0bf3e78", - "shasum": "" - }, - "require": { - "psr/log": "^3.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Mpdf\\PsrLogAwareTrait\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mark Dorison", - "email": "mark@chromatichq.com" - }, - { - "name": "Kristofer Widholm", - "email": "kristofer@chromatichq.com" - } - ], - "description": "Trait to allow support of different psr/log versions.", - "support": { - "issues": "https://github.com/mpdf/psr-log-aware-trait/issues", - "source": "https://github.com/mpdf/psr-log-aware-trait/tree/v3.0.0" - }, - "time": "2023-05-03T06:19:36+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.11.1", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2023-03-08T13:26:56+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.18.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" - }, - "time": "2023-12-10T21:03:43+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v9.99.100", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", - "shasum": "" - }, - "require": { - "php": ">= 7" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" - }, - "time": "2020-10-15T08:29:30+00:00" - }, - { - "name": "pdepend/pdepend", - "version": "2.16.2", - "source": { - "type": "git", - "url": "https://github.com/pdepend/pdepend.git", - "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/f942b208dc2a0868454d01b29f0c75bbcfc6ed58", - "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58", - "shasum": "" - }, - "require": { - "php": ">=5.3.7", - "symfony/config": "^2.3.0|^3|^4|^5|^6.0|^7.0", - "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0|^7.0", - "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0|^7.0", - "symfony/polyfill-mbstring": "^1.19" - }, - "require-dev": { - "easy-doc/easy-doc": "0.0.0|^1.2.3", - "gregwar/rst": "^1.0", - "squizlabs/php_codesniffer": "^2.0.0" - }, - "bin": [ - "src/bin/pdepend" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "PDepend\\": "src/main/php/PDepend" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Official version of pdepend to be handled with Composer", - "keywords": [ - "PHP Depend", - "PHP_Depend", - "dev", - "pdepend" - ], - "support": { - "issues": "https://github.com/pdepend/pdepend/issues", - "source": "https://github.com/pdepend/pdepend/tree/2.16.2" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/pdepend/pdepend", - "type": "tidelift" - } - ], - "time": "2023-12-17T18:09:59+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phenx/php-font-lib", - "version": "0.5.4", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/dd448ad1ce34c63d09baccd05415e361300c35b4", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4", - "shasum": "" - }, - "require": { - "ext-mbstring": "*" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5" - }, - "type": "library", - "autoload": { - "psr-4": { - "FontLib\\": "src/FontLib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0" - ], - "authors": [ - { - "name": "Fabien Ménager", - "email": "fabien.menager@gmail.com" - } - ], - "description": "A library to read, parse, export and make subsets of different types of font files.", - "homepage": "https://github.com/PhenX/php-font-lib", - "support": { - "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/0.5.4" - }, - "time": "2021-12-17T19:44:54+00:00" - }, - { - "name": "phenx/php-svg-lib", - "version": "0.5.1", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "8a8a1ebcf6aea861ef30197999f096f7bd4b4456" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8a8a1ebcf6aea861ef30197999f096f7bd4b4456", - "reference": "8a8a1ebcf6aea861ef30197999f096f7bd4b4456", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "^7.1 || ^8.0", - "sabberworm/php-css-parser": "^8.4" - }, - "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Svg\\": "src/Svg" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0" - ], - "authors": [ - { - "name": "Fabien Ménager", - "email": "fabien.menager@gmail.com" - } - ], - "description": "A library to read, parse and export to PDF SVG files.", - "homepage": "https://github.com/PhenX/php-svg-lib", - "support": { - "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.1" - }, - "time": "2023-12-11T20:56:08+00:00" - }, - { - "name": "php-cs-fixer/diff", - "version": "v2.0.2", - "source": { - "type": "git", - "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/29dc0d507e838c4580d018bd8b5cb412474f7ec3", - "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "symfony/process": "^3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "sebastian/diff v3 backport support for PHP 5.6+", - "homepage": "https://github.com/PHP-CS-Fixer", - "keywords": [ - "diff" - ], - "support": { - "issues": "https://github.com/PHP-CS-Fixer/diff/issues", - "source": "https://github.com/PHP-CS-Fixer/diff/tree/v2.0.2" - }, - "abandoned": true, - "time": "2020-10-14T08:32:19+00:00" - }, - { - "name": "phpmd/phpmd", - "version": "2.15.0", - "source": { - "type": "git", - "url": "https://github.com/phpmd/phpmd.git", - "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/74a1f56e33afad4128b886e334093e98e1b5e7c0", - "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0", - "shasum": "" - }, - "require": { - "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", - "ext-xml": "*", - "pdepend/pdepend": "^2.16.1", - "php": ">=5.3.9" - }, - "require-dev": { - "easy-doc/easy-doc": "0.0.0 || ^1.3.2", - "ext-json": "*", - "ext-simplexml": "*", - "gregwar/rst": "^1.0", - "mikey179/vfsstream": "^1.6.8", - "squizlabs/php_codesniffer": "^2.9.2 || ^3.7.2" - }, - "bin": [ - "src/bin/phpmd" - ], - "type": "library", - "autoload": { - "psr-0": { - "PHPMD\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Manuel Pichler", - "email": "github@manuel-pichler.de", - "homepage": "https://github.com/manuelpichler", - "role": "Project Founder" - }, - { - "name": "Marc Würth", - "email": "ravage@bluewin.ch", - "homepage": "https://github.com/ravage84", - "role": "Project Maintainer" - }, - { - "name": "Other contributors", - "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", - "role": "Contributors" - } - ], - "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", - "homepage": "https://phpmd.org/", - "keywords": [ - "dev", - "mess detection", - "mess detector", - "pdepend", - "phpmd", - "pmd" - ], - "support": { - "irc": "irc://irc.freenode.org/phpmd", - "issues": "https://github.com/phpmd/phpmd/issues", - "source": "https://github.com/phpmd/phpmd/tree/2.15.0" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/phpmd/phpmd", - "type": "tidelift" - } - ], - "time": "2023-12-11T08:22:20+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "1.10.40", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/93c84b5bf7669920d823631e39904d69b9c7dc5d", - "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" - } - ], - "time": "2023-10-30T14:48:31+00:00" - }, - { - "name": "phpstan/phpstan-phpunit", - "version": "1.3.15", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/70ecacc64fe8090d8d2a33db5a51fe8e88acd93a", - "reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.10" - }, - "conflict": { - "phpunit/phpunit": "<7.0" - }, - "require-dev": { - "nikic/php-parser": "^4.13.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^9.5" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPUnit extensions and rules for PHPStan", - "support": { - "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.15" - }, - "time": "2023-10-09T18:58:39+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.30", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:47:57+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.6.15", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1 || ^2", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", - "sebastian/version": "^3.0.2" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.6-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2023-12-01T16:55:19+00:00" - }, - { - "name": "psr/cache", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" - }, - "time": "2021-02-03T23:26:27+00:00" - }, - { - "name": "psr/container", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" - }, - "time": "2021-11-05T16:50:12+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/http-message", - "version": "2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" - }, - "time": "2023-04-04T09:54:51+00:00" - }, - { - "name": "psr/log", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" - }, - "time": "2021-07-14T16:46:02+00:00" - }, - { - "name": "sabberworm/php-css-parser", - "version": "8.4.0", - "source": { - "type": "git", - "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "php": ">=5.6.20" - }, - "require-dev": { - "codacy/coverage": "^1.4", - "phpunit/phpunit": "^4.8.36" - }, - "suggest": { - "ext-mbstring": "for parsing UTF-8 CSS" - }, - "type": "library", - "autoload": { - "psr-4": { - "Sabberworm\\CSS\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Raphael Schweikert" - } - ], - "description": "Parser for CSS Files written in PHP", - "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", - "keywords": [ - "css", - "parser", - "stylesheet" - ], - "support": { - "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", - "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0" - }, - "time": "2021-12-11T13:40:54+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-09-14T12:41:17+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:19:30+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-05-07T05:35:17+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:03:51+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-09-14T06:03:37+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-02T09:26:13+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:20:34+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:07:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:13:03+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "setasign/fpdi", - "version": "v2.6.0", - "source": { - "type": "git", - "url": "https://github.com/Setasign/FPDI.git", - "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Setasign/FPDI/zipball/a6db878129ec6c7e141316ee71872923e7f1b7ad", - "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad", - "shasum": "" - }, - "require": { - "ext-zlib": "*", - "php": "^5.6 || ^7.0 || ^8.0" - }, - "conflict": { - "setasign/tfpdf": "<1.31" - }, - "require-dev": { - "phpunit/phpunit": "~5.7", - "setasign/fpdf": "~1.8.6", - "setasign/tfpdf": "~1.33", - "squizlabs/php_codesniffer": "^3.5", - "tecnickcom/tcpdf": "~6.2" - }, - "suggest": { - "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured." - }, - "type": "library", - "autoload": { - "psr-4": { - "setasign\\Fpdi\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jan Slabon", - "email": "jan.slabon@setasign.com", - "homepage": "https://www.setasign.com" - }, - { - "name": "Maximilian Kresse", - "email": "maximilian.kresse@setasign.com", - "homepage": "https://www.setasign.com" - } - ], - "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.", - "homepage": "https://www.setasign.com/fpdi", - "keywords": [ - "fpdf", - "fpdi", - "pdf" - ], - "support": { - "issues": "https://github.com/Setasign/FPDI/issues", - "source": "https://github.com/Setasign/FPDI/tree/v2.6.0" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/setasign/fpdi", - "type": "tidelift" - } - ], - "time": "2023-12-11T16:03:32+00:00" - }, - { - "name": "symfony/config", - "version": "v5.4.31", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", - "reference": "dd5ea39de228813aba0c23c3a4153da2a4cf3cd9", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22" - }, - "conflict": { - "symfony/finder": "<4.4" - }, - "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/messenger": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/config/tree/v5.4.31" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-11-09T08:22:43+00:00" - }, - { - "name": "symfony/console", - "version": "v5.3.16", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "2e322c76cdccb302af6b275ea2207169c8355328" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2e322c76cdccb302af6b275ea2207169c8355328", - "reference": "2e322c76cdccb302af6b275ea2207169c8355328", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2", - "symfony/string": "^5.1" - }, - "conflict": { - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.3.16" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-03-01T08:24:05+00:00" - }, - { - "name": "symfony/dependency-injection", - "version": "v5.4.34", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "75d568165a65fa7d8124869ec7c3a90424352e6c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/75d568165a65fa7d8124869ec7c3a90424352e6c", - "reference": "75d568165a65fa7d8124869ec7c3a90424352e6c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22", - "symfony/service-contracts": "^1.1.6|^2" - }, - "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<5.3", - "symfony/finder": "<4.4", - "symfony/proxy-manager-bridge": "<4.4", - "symfony/yaml": "<4.4.26" - }, - "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0|2.0" - }, - "require-dev": { - "symfony/config": "^5.3|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4.26|^5.0|^6.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows you to standardize and centralize the way objects are constructed in your application", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.4.34" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-28T09:31:38+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v5.4.22", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1df20e45d56da29a4b1d8259dd6e950acbf1b13f", - "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.22" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-03-17T11:31:58+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v5.4.25", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", - "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.25" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-31T13:04:02+00:00" - }, - { - "name": "symfony/finder", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/078e9a5e1871fcfe6a5ce421b539344c21afef19", - "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-16T09:33:00+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-14T08:03:56+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-28T09:04:16+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.34", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "8fa22178dfc368911dbd513b431cd9b06f9afe7a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/8fa22178dfc368911dbd513b431cd9b06f9afe7a", - "reference": "8fa22178dfc368911dbd513b431cd9b06f9afe7a", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v5.4.34" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-12-02T08:41:43+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-30T19:17:29+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-14T08:03:56+00:00" - }, - { - "name": "symfony/string", - "version": "v5.4.22", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", - "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v5.4.22" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-03-14T06:11:53+00:00" - }, - { - "name": "tecnickcom/tcpdf", - "version": "6.6.5", - "source": { - "type": "git", - "url": "https://github.com/tecnickcom/TCPDF.git", - "reference": "5fce932fcee4371865314ab7f6c0d85423c5c7ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/5fce932fcee4371865314ab7f6c0d85423c5c7ce", - "reference": "5fce932fcee4371865314ab7f6c0d85423c5c7ce", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "config", - "include", - "tcpdf.php", - "tcpdf_parser.php", - "tcpdf_import.php", - "tcpdf_barcodes_1d.php", - "tcpdf_barcodes_2d.php", - "include/tcpdf_colors.php", - "include/tcpdf_filters.php", - "include/tcpdf_font_data.php", - "include/tcpdf_fonts.php", - "include/tcpdf_images.php", - "include/tcpdf_static.php", - "include/barcodes/datamatrix.php", - "include/barcodes/pdf417.php", - "include/barcodes/qrcode.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Nicola Asuni", - "email": "info@tecnick.com", - "role": "lead" - } - ], - "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", - "homepage": "http://www.tcpdf.org/", - "keywords": [ - "PDFD32000-2008", - "TCPDF", - "barcodes", - "datamatrix", - "pdf", - "pdf417", - "qrcode" - ], - "support": { - "issues": "https://github.com/tecnickcom/TCPDF/issues", - "source": "https://github.com/tecnickcom/TCPDF/tree/6.6.5" - }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_donations¤cy_code=GBP&business=paypal@tecnick.com&item_name=donation%20for%20tcpdf%20project", - "type": "custom" - } - ], - "time": "2023-09-06T15:09:26+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.2" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2023-11-20T00:12:19+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "phpstan/phpstan-phpunit": 0 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.1|^8.0", - "ext-dom": "*", - "ext-json": "*", - "ext-xml": "*" - }, - "platform-dev": { - "ext-zip": "*", - "ext-gd": "*", - "ext-libxml": "*" - }, - "platform-overrides": { - "php": "8.0" - }, - "plugin-api-version": "2.6.0" -} diff --git a/docs/changes/1.x/1.3.0.md b/docs/changes/1.x/1.3.0.md new file mode 100644 index 0000000000..4b2e1b25df --- /dev/null +++ b/docs/changes/1.x/1.3.0.md @@ -0,0 +1,53 @@ +# [1.3.0](https://github.com/PHPOffice/PHPWord/tree/1.3.0) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.2.0...1.3.0) + +## Enhancements + +- IOFactory : Added extractVariables method to extract variables from a document [@sibalonat](https://github.com/sibalonat) in [#2515](https://github.com/PHPOffice/PHPWord/pull/2515) +- PDF Writer : Documented how to specify a PDF renderer, when working with the PDF writer, as well as the three available choices by [@settermjd](https://github.com/settermjd) in [#2642](https://github.com/PHPOffice/PHPWord/pull/2642) +- Word2007 Reader: Support for Paragraph Border Style by [@damienfa](https://github.com/damienfa) in [#2651](https://github.com/PHPOffice/PHPWord/pull/2651) +- Word2007 Writer: Support for field REF by [@crystoline](https://github.com/crystoline) in [#2652](https://github.com/PHPOffice/PHPWord/pull/2652) +- Word2007 Reader : Support for FormFields by [@vincentKool](https://github.com/vincentKool) in [#2653](https://github.com/PHPOffice/PHPWord/pull/2653) +- RTF Writer : Support for Table Border Style fixing [#345](https://github.com/PHPOffice/PHPWord/issues/345) by [@Progi1984](https://github.com/Progi1984) in [#2656](https://github.com/PHPOffice/PHPWord/pull/2656) +- Word2007 Reader: Support the page break () by [@stanolacko](https://github.com/stanolacko) in [#2662](https://github.com/PHPOffice/PHPWord/pull/2662) +- MsDoc Reader: Support for UTF-8 characters by [@Progi1984] fixing [#881](https://github.com/PHPOffice/PHPWord/issues/881), [#1454](https://github.com/PHPOffice/PHPWord/issues/1454), [#1817](https://github.com/PHPOffice/PHPWord/issues/1817), [#1927](https://github.com/PHPOffice/PHPWord/issues/1927), [#2383](https://github.com/PHPOffice/PHPWord/issues/2383), [#2565](https://github.com/PHPOffice/PHPWord/issues/2565) in [#2664](https://github.com/PHPOffice/PHPWord/pull/2664) +- Word2007 Writer: Added support for multiples comment for the same text by [@rodrigoq](https://github.com/rodrigoq) fixing [#2109](https://github.com/PHPOffice/PHPWord/issues/2109) in [#2665](https://github.com/PHPOffice/PHPWord/pull/2665) + +### Bug fixes + +- MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) fixing [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) in [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) +- Html Reader : Process Titles as Headings not Paragraphs [@0b10011](https://github.com/0b10011) and [@oleibman](https://github.com/oleibman) Issue [#1692](https://github.com/PHPOffice/PHPWord/issues/1692) PR [#2533](https://github.com/PHPOffice/PHPWord/pull/2533) +- Generate Table Cell if Row Doesn't Have Any [@oleibman](https://github.com/oleibman) fixing [#2505](https://github.com/PHPOffice/PHPWord/issues/2505) in [#2516](https://github.com/PHPOffice/PHPWord/pull/2516) +- TemplateProcessor Persist File After Destruct [@oleibman](https://github.com/oleibman) fixing [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) in [#2545](https://github.com/PHPOffice/PHPWord/pull/2545) +- TemplateProcessor Destructor Problem with Php7 [@oleibman](https://github.com/oleibman) fixing [#2548](https://github.com/PHPOffice/PHPWord/issues/2548) in [#2554](https://github.com/PHPOffice/PHPWord/pull/2554) +- bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522) +- 32-bit Problem in PasswordEncoder [@oleibman](https://github.com/oleibman) fixing [#2550](https://github.com/PHPOffice/PHPWord/issues/2550) in [#2551](https://github.com/PHPOffice/PHPWord/pull/2551) +- Typo : Fix hardcoded macro chars in TemplateProcessor method [@glafarge](https://github.com/glafarge) in [#2618](https://github.com/PHPOffice/PHPWord/pull/2618) +- XML Reader : Prevent fatal errors when opening corrupt files or "doc" files [@mmcev106](https://github.com/mmcev106) in [#2626](https://github.com/PHPOffice/PHPWord/pull/2626) +- Documentation : Updated Comment element by [@laminga](https://github.com/laminga) in [#2650](https://github.com/PHPOffice/PHPWord/pull/2650) +- HTML Reader : Read width & height attributes in points fixing [#2589](https://github.com/PHPOffice/PHPWord/issues/2589) by [@Progi1984](https://github.com/Progi1984) in [#2654](https://github.com/PHPOffice/PHPWord/pull/2654) +- Template Processor : Fixed bad naming of variables fixing [#2586](https://github.com/PHPOffice/PHPWord/issues/2586) by [@Progi1984](https://github.com/Progi1984) in [#2655](https://github.com/PHPOffice/PHPWord/pull/2655) +- Word2007 Writer : Fix first footnote appearing as separator [#2634](https://github.com/PHPOffice/PHPWord/issues/2634) by [@jacksleight](https://github.com/jacksleight) in [#2635](https://github.com/PHPOffice/PHPWord/pull/2635) +- Template Processor : Fixed images with transparent backgrounds displaying a white background by [@ElwynVdb](https://github.com/ElwynVdb) in [#2638](https://github.com/PHPOffice/PHPWord/pull/2638) +- HTML Writer : Fixed rowspan for tables by [@andomiell](https://github.com/andomiell) in [#2659](https://github.com/PHPOffice/PHPWord/pull/2659) +- Word2007 Writer : Fixed StrikeThrough property by [@noec764](https://github.com/noec764) fixing [#1722](https://github.com/PHPOffice/PHPWord/issues/1722) & [#1693](https://github.com/PHPOffice/PHPWord/issues/1693) in [#2661](https://github.com/PHPOffice/PHPWord/pull/2661) +- HTML Reader : Fixed link without href by [@asmundstavdahl](https://github.com/asmundstavdahl) fixing [#1562](https://github.com/PHPOffice/PHPWord/issues/1562) in [#2663](https://github.com/PHPOffice/PHPWord/pull/2663) + +### Miscellaneous + +- Bump dompdf/dompdf from 2.0.3 to 2.0.4 by [@dependabot](https://github.com/dependabot) in [#2530](https://github.com/PHPOffice/PHPWord/pull/2530) +- Bump phpunit/phpunit from 9.6.13 to 9.6.14 by [@dependabot](https://github.com/dependabot) in [#2519](https://github.com/PHPOffice/PHPWord/pull/2519) +- Bump mpdf/mpdf from 8.2.0 to 8.2.2 by [@dependabot](https://github.com/dependabot) in [#2518](https://github.com/PHPOffice/PHPWord/pull/2518) +- Bump phpmd/phpmd from 2.14.1 to 2.15.0 by [@dependabot](https://github.com/dependabot) in [#2538](https://github.com/PHPOffice/PHPWord/pull/2538) +- Bump phpunit/phpunit from 9.6.14 to 9.6.15 by [@dependabot](https://github.com/dependabot) in [#2537](https://github.com/PHPOffice/PHPWord/pull/2537) +- Bump symfony/process from 5.4.28 to 5.4.34 by [@dependabot](https://github.com/dependabot) in [#2536](https://github.com/PHPOffice/PHPWord/pull/2536) +- Allow rgb() when converting Html by [@oleibman](https://github.com/oleibman) fixing [#2508](https://github.com/PHPOffice/PHPWord/issues/2508) in [#2512](https://github.com/PHPOffice/PHPWord/pull/2512) +- Improved Issue Template by [@Progi1984](https://github.com/Progi1984) in [#2609](https://github.com/PHPOffice/PHPWord/pull/2609) +- Bump phpoffice/math from 0.1.0 to 0.2.0 by [@Progi1984](https://github.com/Progi1984) fixing [#2559](https://github.com/PHPOffice/PHPWord/issues/2559) in [#2645](https://github.com/PHPOffice/PHPWord/pull/2645) +- Bump tecnickcom/tcpdf from 6.6.5 to 6.7.5 by [@dependabot](https://github.com/dependabot) in [#2646](https://github.com/PHPOffice/PHPWord/pull/2646) +- Bump mpdf/mpdf from 8.2.2 to 8.2.4 by [@dependabot](https://github.com/dependabot) in [#2647](https://github.com/PHPOffice/PHPWord/pull/2647) +- Bump phenx/php-svg-lib from 0.5.1 to 0.5.4 by [@dependabot](https://github.com/dependabot) in [#2649](https://github.com/PHPOffice/PHPWord/pull/2649) +- Bump phpstan/phpstan-phpunit from 1.3.15 to 1.4.0 by [@dependabot](https://github.com/dependabot) in [#2648](https://github.com/PHPOffice/PHPWord/pull/2648) + +### BC Breaks diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md new file mode 100644 index 0000000000..0a08848037 --- /dev/null +++ b/docs/changes/1.x/1.4.0.md @@ -0,0 +1,22 @@ +# [1.4.0](https://github.com/PHPOffice/PHPWord/tree/1.4.0) (WIP) + +[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.3.0...1.4.0) + +## Enhancements + +- Writer ODText: Support for ListItemRun by [@Progi1984](https://github.com/Progi1984) fixing [#2159](https://github.com/PHPOffice/PHPWord/issues/2159), [#2620](https://github.com/PHPOffice/PHPWord/issues/2620) in [#2669](https://github.com/PHPOffice/PHPWord/pull/2669) +- Writer HTML: Support for vAlign in Tables by [@SpraxDev](https://github.com/SpraxDev) in [#2675](https://github.com/PHPOffice/PHPWord/pull/2675) +- Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#2660](https://github.com/PHPOffice/PHPWord/pull/2660) +- Autoload : Allow to use PHPWord without Composer fixing [#2543](https://github.com/PHPOffice/PHPWord/issues/2543), [#2552](https://github.com/PHPOffice/PHPWord/issues/2552), [#2716](https://github.com/PHPOffice/PHPWord/issues/2716), [#2717](https://github.com/PHPOffice/PHPWord/issues/2717) in [#2722](https://github.com/PHPOffice/PHPWord/pull/2722) + +### Bug fixes + +- Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668) +- Allow vAlign and vMerge on Style\Cell to be set to null by [@SpraxDev](https://github.com/SpraxDev) fixing [#2673](https://github.com/PHPOffice/PHPWord/issues/2673) in [#2676](https://github.com/PHPOffice/PHPWord/pull/2676) + +### Miscellaneous + +- Bump dompdf/dompdf from 2.0.4 to 3.0.0 by [@dependabot](https://github.com/dependabot) fixing [#2621](https://github.com/PHPOffice/PHPWord/issues/2621) in [#2666](https://github.com/PHPOffice/PHPWord/pull/2666) +- Add test case to make sure vMerge defaults to 'continue' by [@SpraxDev](https://github.com/SpraxDev) in [#2677](https://github.com/PHPOffice/PHPWord/pull/2677) + +### BC Breaks diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md deleted file mode 100644 index c5fbaf4b52..0000000000 --- a/docs/changes/2.x/2.0.0.md +++ /dev/null @@ -1,28 +0,0 @@ -# [2.0.0](https://github.com/PHPOffice/PHPWord/tree/2.0.0) (WIP) - -[Full Changelog](https://github.com/PHPOffice/PHPWord/compare/1.2.0...2.0.0) - -## Enhancements - -- IOFactory : Added extractVariables method to extract variables from a document [@sibalonat](https://github.com/sibalonat) in [#2515](https://github.com/PHPOffice/PHPWord/pull/2515) - -### Bug fixes - -- MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) fixing [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) in [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) -- TemplateProcessor Persist File After Destruct [@oleibman](https://github.com/oleibman) fixing [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) in [#2545](https://github.com/PHPOffice/PHPWord/pull/2545) -- bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522) - -- 32-bit Problem in PasswordEncoder [@oleibman](https://github.com/oleibman) fixing [#2550](https://github.com/PHPOffice/PHPWord/issues/2550) in [#2551](https://github.com/PHPOffice/PHPWord/pull/2551) - -### Miscellaneous - -- Bump dompdf/dompdf from 2.0.3 to 2.0.4 by [@dependabot](https://github.com/dependabot) in [#2530](https://github.com/PHPOffice/PHPWord/pull/2530) -- Bump phpunit/phpunit from 9.6.13 to 9.6.14 by [@dependabot](https://github.com/dependabot) in [#2519](https://github.com/PHPOffice/PHPWord/pull/2519) -- Bump mpdf/mpdf from 8.2.0 to 8.2.2 by [@dependabot](https://github.com/dependabot) in [#2518](https://github.com/PHPOffice/PHPWord/pull/2518) -- Bump phpmd/phpmd from 2.14.1 to 2.15.0 by [@dependabot](https://github.com/dependabot) in [#2538](https://github.com/PHPOffice/PHPWord/pull/2538) -- Bump phpunit/phpunit from 9.6.14 to 9.6.15 by [@dependabot](https://github.com/dependabot) in [#2537](https://github.com/PHPOffice/PHPWord/pull/2537) -- Bump symfony/process from 5.4.28 to 5.4.34 by [@dependabot](https://github.com/dependabot) in [#2536](https://github.com/PHPOffice/PHPWord/pull/2536) -- Allow rgb() when converting Html by [@oleibman](https://github.com/oleibman) fixing [#2508](https://github.com/PHPOffice/PHPWord/issues/2508) in [#2512](https://github.com/PHPOffice/PHPWord/pull/2512) -- Improved Issue Template by [@Progi1984](https://github.com/Progi1984) in [#2609](https://github.com/PHPOffice/PHPWord/pull/2609) - -### BC Breaks diff --git a/docs/howto.md b/docs/howto.md index f53217f869..fd4c860682 100644 --- a/docs/howto.md +++ b/docs/howto.md @@ -15,7 +15,7 @@ $imageStyle = array( 'posHorizontalRel' => 'margin', 'posVerticalRel' => 'line', ); -$textrun->addImage('resources/_earth.jpg', $imageStyle); +$textrun->addImage(__DIR__ . '/resources/_earth.jpg', $imageStyle); ``` ## Download the produced file automatically diff --git a/docs/index.md b/docs/index.md index dd600689d7..211fc31a79 100644 --- a/docs/index.md +++ b/docs/index.md @@ -52,7 +52,7 @@ Below are the supported features for each file formats. | | Preserve Text | :material-check: | | | | | | | Text Break | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | | | Page Break | :material-check: | | :material-check: | | | -| | List | :material-check: | | | | | +| | List | :material-check: | :material-check: | | | | | | Table | :material-check: | :material-check: | :material-check: | :material-check: | :material-check: | | | Image | :material-check: | :material-check: | :material-check: | :material-check: | | | | Object | :material-check: | | | | | diff --git a/docs/install.md b/docs/install.md index 1b54a3173f..a4d61b104d 100644 --- a/docs/install.md +++ b/docs/install.md @@ -32,7 +32,6 @@ To install via Composer, add the following lines to your `composer.json`: To install manually: * [download PHPOffice\PHPWord package from GitHub](https://github.com/PHPOffice/PHPWord/archive/master.zip) -* [download PHPOffice\Common package from GitHub](https://github.com/PHPOffice/Common/archive/master.zip) * extract the package and put the contents to your machine. @@ -42,11 +41,10 @@ To install manually: require_once 'path/to/PHPWord/src/PhpWord/Autoloader.php'; \PhpOffice\PhpWord\Autoloader::register(); -require_once 'path/to/PhpOffice/Common/src/Common/Autoloader.php'; -\PhpOffice\Common\Autoloader::register(); - ``` +The preferred method is the Composer one. + ## 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/`. diff --git a/docs/usage/elements/comment.md b/docs/usage/elements/comment.md index 06a3866a3e..50813fa2a1 100644 --- a/docs/usage/elements/comment.md +++ b/docs/usage/elements/comment.md @@ -1,7 +1,7 @@ # Comment Comments can be added to a document by using ``addComment``. -The comment can contain formatted text. Once the comment has been added, it can be linked to any element with ``setCommentStart``. +The comment can contain formatted text. Once the comment has been added, it can be linked to any element with ``setCommentRangeStart``. ``` php addTextRun(); $textrun->addText('This '); $text = $textrun->addText('is'); // link the comment to the text you just created -$text->setCommentStart($comment); +$text->setCommentRangeStart($comment); +$textrun->addText(' a test'); ``` -If no end is set for a comment using the ``setCommentEnd``, the comment will be ended automatically at the end of the element it is started on. \ No newline at end of file +If no end is set for a comment using the ``setCommentRangeEnd``, the comment will be ended automatically at the end of the element it is started on. \ No newline at end of file diff --git a/docs/usage/elements/field.md b/docs/usage/elements/field.md index fe8e9756fc..1cafd18ef8 100644 --- a/docs/usage/elements/field.md +++ b/docs/usage/elements/field.md @@ -8,6 +8,7 @@ Currently the following fields are supported: - XE - INDEX - FILENAME +- REF ``` php addText('My '); $fieldText->addText('bold index', ['bold' => true]); $fieldText->addText(' entry'); $section->addField('XE', array(), array(), $fieldText); -//this actually adds the index +// this actually adds the index $section->addField('INDEX', array(), array('\\e " " \\h "A" \\c "3"'), 'right click to update index'); + +// Adding reference to a bookmark +$fieldText->addField('REF', [ + 'name' => 'bookmark' +], [ + 'InsertParagraphNumberRelativeContext', + 'CreateHyperLink', +]); ``` diff --git a/docs/usage/introduction.md b/docs/usage/introduction.md index b3a101ab0d..7a3d153d95 100644 --- a/docs/usage/introduction.md +++ b/docs/usage/introduction.md @@ -7,7 +7,6 @@ are provided in the [samples folder](https://github.com/PHPOffice/PHPWord/tree/m ``` php save(__DIR__ . '/sample.pdf'); ``` +#### Specify the PDF Renderer + +Before PHPWord can write a PDF, you **must** specify the renderer to use and the path to it. +Currently, three renderers are supported: + +- [DomPDF](https://github.com/dompdf/dompdf) +- [MPDF](https://mpdf.github.io/) +- [TCPDF](https://tcpdf.org/) + +To specify the renderer you use two static `Settings` functions: + +- `setPdfRendererName`: This sets the name of the renderer library to use. + Provide one of [`Settings`' three `PDF_` constants](https://github.com/PHPOffice/PHPWord/blob/master/src/PhpWord/Settings.php#L39-L41) to the function call. +- `setPdfRendererPath`: This sets the path to the renderer library. + This directory is the renderer's package directory within Composer's _vendor_ directory. + +In the code below, you can see an example of setting MPDF as the desired PDF renderer. + +```php +Settings::setPdfRendererName(Settings::PDF_RENDERER_MPDF); +Settings::setPdfRendererPath(__DIR__ . '/../vendor/mpdf/mpdf'); +``` + ## RTF The name of the writer is `RTF`. diff --git a/mkdocs.yml b/mkdocs.yml index 6eb4d42911..6b2c1b7fa6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -86,9 +86,9 @@ nav: - How to: 'howto.md' - Credits: 'credits.md' - Releases: - - '2.x': - - '2.0.0 (WIP)': 'changes/2.x/2.0.0.md' - '1.x': + - '1.4.0 (WIP)': 'changes/1.x/1.4.0.md' + - '1.3.0': 'changes/1.x/1.3.0.md' - '1.2.0': 'changes/1.x/1.2.0.md' - '1.1.0': 'changes/1.x/1.1.0.md' - '1.0.0': 'changes/1.x/1.0.0.md' diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 2e44745b3d..901888024d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -60,11 +60,6 @@ parameters: count: 1 path: src/PhpWord/Element/Image.php - - - message: "#^Parameter \\#2 \\$length of function fread expects int\\<0, max\\>, int\\<0, max\\>\\|false given\\.$#" - count: 1 - path: src/PhpWord/Element/Image.php - - message: "#^Property PhpOffice\\\\PhpWord\\\\Element\\\\Image\\:\\:\\$source \\(string\\) does not accept string\\|false\\.$#" count: 1 @@ -240,11 +235,6 @@ parameters: count: 1 path: src/PhpWord/Reader/Word2007/AbstractPart.php - - - message: "#^Parameter \\#1 \\$count of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:addTextBreak\\(\\) expects int, null given\\.$#" - count: 1 - path: src/PhpWord/Reader/Word2007/AbstractPart.php - - message: "#^Parameter \\#1 \\$depth of method PhpOffice\\\\PhpWord\\\\Element\\\\AbstractContainer\\:\\:addListItemRun\\(\\) expects int, string\\|null given\\.$#" count: 1 @@ -385,16 +375,6 @@ parameters: count: 1 path: src/PhpWord/Shared/Drawing.php - - - message: "#^Access to an undefined property DOMNode\\:\\:\\$value\\.$#" - count: 6 - path: src/PhpWord/Shared/Html.php - - - - message: "#^Binary operation \"\\*\" between string and 50 results in an error\\.$#" - count: 1 - path: src/PhpWord/Shared/Html.php - - message: "#^Call to an undefined method DOMNode\\:\\:getAttribute\\(\\)\\.$#" count: 1 @@ -520,16 +500,6 @@ parameters: count: 1 path: src/PhpWord/Shared/XMLWriter.php - - - message: "#^Parameter \\#1 \\$uri of method XMLWriter\\:\\:openUri\\(\\) expects string, string\\|false given\\.$#" - count: 1 - path: src/PhpWord/Shared/XMLWriter.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Shared\\\\XMLWriter\\:\\:\\$tempFileName \\(string\\) does not accept string\\|false\\.$#" - count: 1 - path: src/PhpWord/Shared/XMLWriter.php - - message: "#^Call to method add\\(\\) on an unknown class PclZip\\.$#" count: 2 @@ -710,11 +680,6 @@ parameters: count: 1 path: src/PhpWord/Style/Cell.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Cell\\:\\:\\$shading is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Cell.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\Chart\\:\\:getMajorTickPosition\\(\\) has no return type specified\\.$#" count: 1 @@ -785,41 +750,6 @@ parameters: count: 1 path: src/PhpWord/Style/Font.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$allCaps is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$doubleStrikethrough is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$lang is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$paragraph is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$shading is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$smallCaps is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Font\\:\\:\\$strikethrough is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Font.php - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Line\\:\\:\\$weight \\(int\\) does not accept float\\|int\\|null\\.$#" count: 1 @@ -840,21 +770,6 @@ parameters: count: 1 path: src/PhpWord/Style/Paragraph.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:\\$indentation is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Paragraph.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:\\$shading is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Paragraph.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Paragraph\\:\\:\\$spacing is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Paragraph.php - - message: "#^Result of && is always false\\.$#" count: 1 @@ -865,36 +780,6 @@ parameters: count: 1 path: src/PhpWord/Style/Section.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Section\\:\\:\\$lineNumbering is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Section.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$extrusion is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$fill is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$frame is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$outline is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - - - message: "#^Property PhpOffice\\\\PhpWord\\\\Style\\\\Shape\\:\\:\\$shadow is never written, only read\\.$#" - count: 1 - path: src/PhpWord/Style/Shape.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Style\\\\TOC\\:\\:setTabLeader\\(\\) should return PhpOffice\\\\PhpWord\\\\Style\\\\TOC but returns PhpOffice\\\\PhpWord\\\\Style\\\\Tab\\.$#" count: 1 @@ -1110,11 +995,6 @@ parameters: count: 1 path: src/PhpWord/TemplateProcessor.php - - - message: "#^Parameter \\#1 \\$str of function preg_quote expects string, int\\|string given\\.$#" - count: 1 - path: src/PhpWord/TemplateProcessor.php - - message: "#^Parameter \\#2 \\$array of function implode expects array\\|null, array\\\\|string given\\.$#" count: 1 @@ -1135,11 +1015,6 @@ parameters: count: 1 path: src/PhpWord/TemplateProcessor.php - - - message: "#^Property PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:\\$tempDocumentFilename \\(string\\) does not accept string\\|false\\.$#" - count: 1 - path: src/PhpWord/TemplateProcessor.php - - message: "#^Property PhpOffice\\\\PhpWord\\\\TemplateProcessor\\:\\:\\$tempDocumentFooters \\(array\\\\) does not accept string\\.$#" count: 1 @@ -1155,11 +1030,6 @@ parameters: count: 1 path: src/PhpWord/Writer/AbstractWriter.php - - - message: "#^PHPDoc tag @param has invalid value \\(\\\\PhpOffice\\\\PhpWord\\\\PhpWord\\)\\: Unexpected token \"\\\\n \\*\", expected variable at offset 78$#" - count: 1 - path: src/PhpWord/Writer/AbstractWriter.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\HTML\\\\Element\\\\AbstractElement\\:\\:write\\(\\) has no return type specified\\.$#" count: 1 @@ -1230,11 +1100,6 @@ parameters: count: 1 path: src/PhpWord/Writer/PDF.php - - - message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|false given\\.$#" - count: 1 - path: src/PhpWord/Writer/PDF.php - - message: "#^Property PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\:\\:\\$renderer \\(PhpOffice\\\\PhpWord\\\\Writer\\\\PDF\\\\AbstractRenderer\\) does not accept object\\.$#" count: 1 @@ -1355,11 +1220,6 @@ parameters: count: 1 path: src/PhpWord/Writer/RTF/Style/Border.php - - - message: "#^PHPDoc tag @param has invalid value \\(\\\\PhpOffice\\\\PhpWord\\\\PhpWord\\)\\: Unexpected token \"\\\\n \", expected variable at offset 86$#" - count: 1 - path: src/PhpWord/Writer/Word2007.php - - message: "#^Method PhpOffice\\\\PhpWord\\\\Writer\\\\Word2007\\\\Element\\\\AbstractElement\\:\\:write\\(\\) has no return type specified\\.$#" count: 1 @@ -1466,29 +1326,29 @@ parameters: path: tests/PhpWordTests/AbstractTestReader.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getBaseUrl\\(\\) has no return type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:getBaseUrl\\(\\) has no return type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getRemoteBmpImageUrl\\(\\) has no return type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:getRemoteBmpImageUrl\\(\\) has no return type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getRemoteGifImageUrl\\(\\) has no return type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:getRemoteGifImageUrl\\(\\) has no return type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:getRemoteImageUrl\\(\\) has no return type specified\\.$#" + message: "#^Method PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:getRemoteImageUrl\\(\\) has no return type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - - message: "#^Property PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbeddedTest\\:\\:\\$httpServer has no type specified\\.$#" + message: "#^Property PhpOffice\\\\PhpWordTests\\\\AbstractWebServerEmbedded\\:\\:\\$httpServer has no type specified\\.$#" count: 1 - path: tests/PhpWordTests/AbstractWebServerEmbeddedTest.php + path: tests/PhpWordTests/AbstractWebServerEmbedded.php - message: "#^Parameter \\#1 \\$width of class PhpOffice\\\\PhpWord\\\\Element\\\\Cell constructor expects int\\|null, string given\\.$#" @@ -1815,11 +1675,6 @@ parameters: count: 1 path: tests/PhpWordTests/TestHelperDOCX.php - - - message: "#^Static property PhpOffice\\\\PhpWordTests\\\\TestHelperDOCX\\:\\:\\$file \\(string\\) does not accept string\\|false\\.$#" - count: 1 - path: tests/PhpWordTests/TestHelperDOCX.php - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\TestableTemplateProcesor\\:\\:__construct\\(\\) has parameter \\$mainPart with no type specified\\.$#" count: 1 @@ -1832,17 +1687,12 @@ parameters: - message: "#^Cannot access property \\$length on DOMNodeList\\\\|false\\.$#" - count: 6 + count: 9 path: tests/PhpWordTests/Writer/HTML/ElementTest.php - message: "#^Cannot call method item\\(\\) on DOMNodeList\\\\|false\\.$#" - count: 8 - path: tests/PhpWordTests/Writer/HTML/ElementTest.php - - - - message: "#^Method PhpOffice\\\\PhpWordTests\\\\Writer\\\\HTML\\\\ElementTest\\:\\:getAsHTML\\(\\) has no return type specified\\.$#" - count: 1 + count: 11 path: tests/PhpWordTests/Writer/HTML/ElementTest.php - diff --git a/phpstan.neon b/phpstan.neon deleted file mode 100644 index e490e1b179..0000000000 --- a/phpstan.neon +++ /dev/null @@ -1,17 +0,0 @@ -includes: - - phpstan-baseline.neon - - vendor/phpstan/phpstan-phpunit/extension.neon - - vendor/phpstan/phpstan-phpunit/rules.neon -parameters: - level: 7 - paths: - - src/ - - tests/ - excludePaths: - - */pclzip.lib.php - - src/PhpWord/Shared/OLERead.php - - src/PhpWord/Reader/MsDoc.php - - src/PhpWord/Writer/PDF/MPDF.php - bootstrapFiles: - - tests/bootstrap.php - checkMissingIterableValueType: false diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000000..0cdf25ef21 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,44 @@ +includes: + - phpstan-baseline.neon + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon +parameters: + level: 7 + paths: + - src/ + - tests/ + excludePaths: + - */pclzip.lib.php + - src/PhpWord/Shared/OLERead.php + - src/PhpWord/Reader/MsDoc.php + - src/PhpWord/Writer/PDF/MPDF.php + bootstrapFiles: + - tests/bootstrap.php + ## <=PHP7.4 + reportUnmatchedIgnoredErrors: false + ignoreErrors: + - + identifier: missingType.iterableValue + + ## <=PHP7.4 + - + message: '#Parameter \#1 \$argument of class ReflectionClass constructor expects class-string\|T of object, string given.#' + path: src/PhpWord/Element/AbstractContainer.php + - + message: '#Parameter \#1 \$function of function call_user_func expects callable\(\): mixed, string given.#' + path: src/PhpWord/Element/Image.php + - + message: '#Parameter \#1 \$argument of class ReflectionClass constructor expects class-string\|T of object, string given.#' + path: src/PhpWord/IOFactory.php + - + message: '#Parameter \#1 \$function of function forward_static_call_array expects callable\(\): mixed, array{.+, string} given.#' + path: src/PhpWord/PhpWord.php + - + message: '#Parameter \#1 \$function of function call_user_func_array expects callable\(\): mixed, array{\$this\(PhpOffice\\PhpWord\\Shared\\ZipArchive\)\|PclZip\|ZipArchive, mixed} given.#' + path: src/PhpWord/Shared/ZipArchive.php + - + message: '#Parameter \#1 \$function of function call_user_func_array expects callable\(\): mixed, array{PhpOffice\\PhpWord\\Writer\\PDF\\AbstractRenderer, string} given.#' + path: src/PhpWord/Writer/PDF.php + - + message: '#Parameter \#1 \$argument of class ReflectionClass constructor expects class-string\|object, class-string\|false given.#' + path: tests/PhpWordTests/Style/AbstractStyleTest.php diff --git a/samples/Sample_01_SimpleText.php b/samples/Sample_01_SimpleText.php index e89f7323ba..07e0d05aa5 100644 --- a/samples/Sample_01_SimpleText.php +++ b/samples/Sample_01_SimpleText.php @@ -7,16 +7,16 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$languageEnGb = new \PhpOffice\PhpWord\Style\Language(\PhpOffice\PhpWord\Style\Language::EN_GB); +$languageEnGb = new PhpOffice\PhpWord\Style\Language(PhpOffice\PhpWord\Style\Language::EN_GB); -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->getSettings()->setThemeFontLang($languageEnGb); $fontStyleName = 'rStyle'; $phpWord->addFontStyle($fontStyleName, ['bold' => true, 'italic' => true, 'size' => 16, 'allCaps' => true, 'doubleStrikethrough' => true]); $paragraphStyleName = 'pStyle'; -$phpWord->addParagraphStyle($paragraphStyleName, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'spaceAfter' => 100]); +$phpWord->addParagraphStyle($paragraphStyleName, ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'spaceAfter' => 100]); $phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); @@ -29,7 +29,7 @@ // $pStyle = new Font(); // $pStyle->setLang() -$section->addText('Ce texte-ci est en français.', ['lang' => \PhpOffice\PhpWord\Style\Language::FR_BE]); +$section->addText('Ce texte-ci est en français.', ['lang' => PhpOffice\PhpWord\Style\Language::FR_BE]); // Two text break $section->addTextBreak(2); @@ -82,7 +82,7 @@ $section->addTextBreak(); // Image -$section->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); +$section->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_02_TabStops.php b/samples/Sample_02_TabStops.php index 74a0ed1fa3..ad99fe83f5 100644 --- a/samples/Sample_02_TabStops.php +++ b/samples/Sample_02_TabStops.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $multipleTabsStyleName = 'multipleTab'; @@ -12,18 +12,18 @@ $multipleTabsStyleName, [ 'tabs' => [ - new \PhpOffice\PhpWord\Style\Tab('left', 1550), - new \PhpOffice\PhpWord\Style\Tab('center', 3200), - new \PhpOffice\PhpWord\Style\Tab('right', 5300), + new PhpOffice\PhpWord\Style\Tab('left', 1550), + new PhpOffice\PhpWord\Style\Tab('center', 3200), + new PhpOffice\PhpWord\Style\Tab('right', 5300), ], ] ); $rightTabStyleName = 'rightTab'; -$phpWord->addParagraphStyle($rightTabStyleName, ['tabs' => [new \PhpOffice\PhpWord\Style\Tab('right', 9090)]]); +$phpWord->addParagraphStyle($rightTabStyleName, ['tabs' => [new PhpOffice\PhpWord\Style\Tab('right', 9090)]]); $leftTabStyleName = 'centerTab'; -$phpWord->addParagraphStyle($leftTabStyleName, ['tabs' => [new \PhpOffice\PhpWord\Style\Tab('center', 4680)]]); +$phpWord->addParagraphStyle($leftTabStyleName, ['tabs' => [new PhpOffice\PhpWord\Style\Tab('center', 4680)]]); // New portrait section $section = $phpWord->addSection(); diff --git a/samples/Sample_03_Sections.php b/samples/Sample_03_Sections.php index b02a277c43..b01726d81c 100644 --- a/samples/Sample_03_Sections.php +++ b/samples/Sample_03_Sections.php @@ -6,7 +6,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New portrait section $section = $phpWord->addSection(['borderColor' => '00FF00', 'borderSize' => 12]); diff --git a/samples/Sample_04_Textrun.php b/samples/Sample_04_Textrun.php index 33af08a5b4..6d50e285ec 100644 --- a/samples/Sample_04_Textrun.php +++ b/samples/Sample_04_Textrun.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $paragraphStyleName = 'pStyle'; @@ -17,7 +17,7 @@ $phpWord->addFontStyle($coloredFontStyleName, ['color' => 'FF8080', 'bgColor' => 'FFFFCC']); $linkFontStyleName = 'NLink'; -$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); +$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); // New portrait section $section = $phpWord->addSection(); @@ -35,9 +35,9 @@ $textrun->addText(' Sample Link: '); $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub', $linkFontStyleName); $textrun->addText(' Sample Image: '); -$textrun->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); +$textrun->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); $textrun->addText(' Sample Object: '); -$textrun->addObject('resources/_sheet.xls'); +$textrun->addObject(__DIR__ . '/resources/_sheet.xls'); $textrun->addText(' Here is some more text. '); $textrun = $section->addTextRun(); diff --git a/samples/Sample_05_Multicolumn.php b/samples/Sample_05_Multicolumn.php index 093dd60424..c4d1dd7280 100644 --- a/samples/Sample_05_Multicolumn.php +++ b/samples/Sample_05_Multicolumn.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $filler = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' . 'Nulla fermentum, tortor id adipiscing adipiscing, tortor turpis commodo. ' . 'Donec vulputate iaculis metus, vel luctus dolor hendrerit ac. ' diff --git a/samples/Sample_06_Footnote.php b/samples/Sample_06_Footnote.php index f3c369b342..035916ee09 100644 --- a/samples/Sample_06_Footnote.php +++ b/samples/Sample_06_Footnote.php @@ -7,8 +7,8 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); -\PhpOffice\PhpWord\Settings::setCompatibility(false); +$phpWord = new PhpOffice\PhpWord\PhpWord(); +PhpOffice\PhpWord\Settings::setCompatibility(false); // Define styles $paragraphStyleName = 'pStyle'; @@ -21,7 +21,7 @@ $phpWord->addFontStyle($coloredFontStyleName, ['color' => 'FF8080', 'bgColor' => 'FFFFCC']); $linkFontStyleName = 'NLink'; -$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); +$phpWord->addLinkStyle($linkFontStyleName, ['color' => '0000FF', 'underline' => PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE]); // New portrait section $section = $phpWord->addSection(); @@ -39,9 +39,9 @@ $footnote->addText('links like '); $footnote->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub', $linkFontStyleName); $footnote->addText(', image like '); -$footnote->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); +$footnote->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); $footnote->addText(', or object like '); -$footnote->addObject('resources/_sheet.xls'); +$footnote->addObject(__DIR__ . '/resources/_sheet.xls'); $footnote->addText('But you can only put footnote in section, not in header or footer.'); $section->addText( diff --git a/samples/Sample_07_TemplateCloneRow.php b/samples/Sample_07_TemplateCloneRow.php index a921569f64..0f1d165f19 100644 --- a/samples/Sample_07_TemplateCloneRow.php +++ b/samples/Sample_07_TemplateCloneRow.php @@ -4,7 +4,7 @@ // Template processor instance creation echo date('H:i:s'), ' Creating new TemplateProcessor instance...', EOL; -$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_07_TemplateCloneRow.docx'); +$templateProcessor = new PhpOffice\PhpWord\TemplateProcessor(__DIR__ . '/resources/Sample_07_TemplateCloneRow.docx'); // Variables on different parts of document $templateProcessor->setValue('weekday', date('l')); // On section/content @@ -79,9 +79,9 @@ // $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'); +$templateProcessor->saveAs(__DIR__ . '/results/Sample_07_TemplateCloneRow.docx'); -echo getEndingNotes(['Word2007' => 'docx'], 'results/Sample_07_TemplateCloneRow.docx'); +echo getEndingNotes(['Word2007' => 'docx'], __DIR__ . '/results/Sample_07_TemplateCloneRow.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_08_ParagraphPagination.php b/samples/Sample_08_ParagraphPagination.php index f343366a84..cac52e3baf 100644 --- a/samples/Sample_08_ParagraphPagination.php +++ b/samples/Sample_08_ParagraphPagination.php @@ -4,11 +4,11 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->setDefaultParagraphStyle( [ - 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::BOTH, - 'spaceAfter' => \PhpOffice\PhpWord\Shared\Converter::pointToTwip(12), + 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::BOTH, + 'spaceAfter' => PhpOffice\PhpWord\Shared\Converter::pointToTwip(12), 'spacing' => 120, ] ); diff --git a/samples/Sample_09_Tables.php b/samples/Sample_09_Tables.php index f1b67c9ecc..3a887468b0 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -7,7 +7,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $header = ['size' => 16, 'bold' => true]; @@ -31,10 +31,10 @@ $section->addText('Fancy table', $header); $fancyTableStyleName = 'Fancy Table'; -$fancyTableStyle = ['borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER, 'cellSpacing' => 50]; +$fancyTableStyle = ['borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80, 'alignment' => PhpOffice\PhpWord\SimpleType\JcTable::CENTER, 'cellSpacing' => 50]; $fancyTableFirstRowStyle = ['borderBottomSize' => 18, 'borderBottomColor' => '0000FF', 'bgColor' => '66BBFF']; $fancyTableCellStyle = ['valign' => 'center']; -$fancyTableCellBtlrStyle = ['valign' => 'center', 'textDirection' => \PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR]; +$fancyTableCellBtlrStyle = ['valign' => 'center', 'textDirection' => PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR]; $fancyTableFontStyle = ['bold' => true]; $phpWord->addTableStyle($fancyTableStyleName, $fancyTableStyle, $fancyTableFirstRowStyle); $table = $section->addTable($fancyTableStyleName); @@ -56,11 +56,13 @@ /* * 3. colspan (gridSpan) and rowspan (vMerge) - * --------------------- - * | | B | | - * | A |--------| E | - * | | C | D | | - * --------------------- + * ------------------------- + * | A | B | C | + * |-----|-----------| | + * | D | | + * ------|-----------| | + * | E | F | G | | + * ------------------------- */ $section->addPageBreak(); @@ -70,32 +72,27 @@ $cellRowSpan = ['vMerge' => 'restart', 'valign' => 'center', 'bgColor' => 'FFFF00']; $cellRowContinue = ['vMerge' => 'continue']; $cellColSpan = ['gridSpan' => 2, 'valign' => 'center']; -$cellHCentered = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]; +$cellHCentered = ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]; $cellVCentered = ['valign' => 'center']; $spanTableStyleName = 'Colspan Rowspan'; $phpWord->addTableStyle($spanTableStyleName, $fancyTableStyle); $table = $section->addTable($spanTableStyleName); -$table->addRow(); - -$cell1 = $table->addCell(2000, $cellRowSpan); -$textrun1 = $cell1->addTextRun($cellHCentered); -$textrun1->addText('A'); -$textrun1->addFootnote()->addText('Row span'); - -$cell2 = $table->addCell(4000, $cellColSpan); -$textrun2 = $cell2->addTextRun($cellHCentered); -$textrun2->addText('B'); -$textrun2->addFootnote()->addText('Column span'); +$row1 = $table->addRow(); +$row1->addCell(500)->addText('A'); +$row1->addCell(1000, ['gridSpan' => 2])->addText('B'); +$row1->addCell(500, ['vMerge' => 'restart'])->addText('C'); -$table->addCell(2000, $cellRowSpan)->addText('E', null, $cellHCentered); +$row2 = $table->addRow(); +$row2->addCell(1500, ['gridSpan' => 3])->addText('D'); +$row2->addCell(null, ['vMerge' => 'continue']); -$table->addRow(); -$table->addCell(null, $cellRowContinue); -$table->addCell(2000, $cellVCentered)->addText('C', null, $cellHCentered); -$table->addCell(2000, $cellVCentered)->addText('D', null, $cellHCentered); -$table->addCell(null, $cellRowContinue); +$row3 = $table->addRow(); +$row3->addCell(500)->addText('E'); +$row3->addCell(500)->addText('F'); +$row3->addCell(500)->addText('G'); +$row3->addCell(null, ['vMerge' => 'continue']); /* * 4. colspan (gridSpan) and rowspan (vMerge) @@ -137,10 +134,10 @@ $section->addTextBreak(2); $section->addText('Nested table in a centered and 50% width table.', $header); -$table = $section->addTable(['width' => 50 * 50, 'unit' => 'pct', 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER]); +$table = $section->addTable(['width' => 50 * 50, 'unit' => 'pct', 'alignment' => PhpOffice\PhpWord\SimpleType\JcTable::CENTER]); $cell = $table->addRow()->addCell(); $cell->addText('This cell contains nested table.'); -$innerCell = $cell->addTable(['alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER])->addRow()->addCell(); +$innerCell = $cell->addTable(['alignment' => PhpOffice\PhpWord\SimpleType\JcTable::CENTER])->addRow()->addCell(); $innerCell->addText('Inside nested table'); // 6. Table with floating position diff --git a/samples/Sample_10_EastAsianFontStyle.php b/samples/Sample_10_EastAsianFontStyle.php index c8a6ec3a5e..f730ab510f 100644 --- a/samples/Sample_10_EastAsianFontStyle.php +++ b/samples/Sample_10_EastAsianFontStyle.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $header = ['size' => 16, 'bold' => true]; //1.Use EastAisa FontStyle diff --git a/samples/Sample_11_ReadWord2007.php b/samples/Sample_11_ReadWord2007.php index 313cc00797..72cdfac625 100644 --- a/samples/Sample_11_ReadWord2007.php +++ b/samples/Sample_11_ReadWord2007.php @@ -7,7 +7,7 @@ $source = __DIR__ . "/resources/{$name}.docx"; echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_11_ReadWord97.php b/samples/Sample_11_ReadWord97.php index 4187baaef7..728df6210b 100644 --- a/samples/Sample_11_ReadWord97.php +++ b/samples/Sample_11_ReadWord97.php @@ -4,9 +4,9 @@ // Read contents $name = basename(__FILE__, '.php'); -$source = "resources/{$name}.doc"; +$source = __DIR__ . "/resources/{$name}.doc"; echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source, 'MsDoc'); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source, 'MsDoc'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_12_HeaderFooter.php b/samples/Sample_12_HeaderFooter.php index 081371863a..393e9d1032 100644 --- a/samples/Sample_12_HeaderFooter.php +++ b/samples/Sample_12_HeaderFooter.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New portrait section $section = $phpWord->addSection(); @@ -18,16 +18,16 @@ $textrun = $cell->addTextRun(); $textrun->addText('This is the header with '); $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); -$table->addCell(4500)->addImage('resources/PhpWord.png', ['width' => 80, 'height' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END]); +$table->addCell(4500)->addImage(__DIR__ . '/resources/PhpWord.png', ['width' => 80, 'height' => 80, 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::END]); // Add header for all other pages $subsequent = $section->addHeader(); $subsequent->addText('Subsequent pages in Section 1 will Have this!'); -$subsequent->addImage('resources/_mars.jpg', ['width' => 80, 'height' => 80]); +$subsequent->addImage(__DIR__ . '/resources/_mars.jpg', ['width' => 80, 'height' => 80]); // Add footer $footer = $section->addFooter(); -$footer->addPreserveText('Page {PAGE} of {NUMPAGES}.', null, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$footer->addPreserveText('Page {PAGE} of {NUMPAGES}.', null, ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $footer->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); // Write some text diff --git a/samples/Sample_13_Images.php b/samples/Sample_13_Images.php index 30b9cae949..a8ab87ce8c 100644 --- a/samples/Sample_13_Images.php +++ b/samples/Sample_13_Images.php @@ -1,22 +1,23 @@ addSection(); $section->addText('Local image without any styles:'); -$section->addImage('resources/_mars.jpg'); +$section->addImage(__DIR__ . '/resources/_mars.jpg'); printSeparator($section); $section->addText('Local image with styles:'); -$section->addImage('resources/_earth.jpg', ['width' => 210, 'height' => 210, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$section->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 210, 'height' => 210, 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); // Remote image printSeparator($section); @@ -26,7 +27,7 @@ // Image from string printSeparator($section); -$source = 'resources/_mars.jpg'; +$source = __DIR__ . '/resources/_mars.jpg'; $fileContent = file_get_contents($source); $section->addText('Image from string'); $section->addImage($fileContent); @@ -38,7 +39,7 @@ foreach ($wrappingStyles as $wrappingStyle) { $section->addText("Wrapping style {$wrappingStyle}"); $section->addImage( - 'resources/_earth.jpg', + __DIR__ . '/resources/_earth.jpg', [ 'positioning' => 'relative', 'marginTop' => -1, @@ -57,16 +58,16 @@ //Absolute positioning $section->addText('Absolute positioning: see top right corner of page'); $section->addImage( - 'resources/_mars.jpg', + __DIR__ . '/resources/_mars.jpg', [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_RIGHT, - 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, - 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15.5), - 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1.55), + 'width' => Converter::cmToPixel(3), + 'height' => Converter::cmToPixel(3), + 'positioning' => PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, + 'posHorizontal' => PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_RIGHT, + 'posHorizontalRel' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, + 'posVerticalRel' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_PAGE, + 'marginLeft' => Converter::cmToPixel(15.5), + 'marginTop' => Converter::cmToPixel(1.55), ] ); @@ -75,15 +76,15 @@ $section->addText('Relative positioning: Horizontal position center relative to column,'); $section->addText('Vertical position top relative to line'); $section->addImage( - 'resources/_mars.jpg', + __DIR__ . '/resources/_mars.jpg', [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(3), - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, - 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, - 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_LINE, + 'width' => Converter::cmToPixel(3), + 'height' => Converter::cmToPixel(3), + 'positioning' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE, + 'posHorizontal' => PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, + 'posHorizontalRel' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, + 'posVertical' => PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, + 'posVerticalRel' => PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_LINE, ] ); diff --git a/samples/Sample_14_ListItem.php b/samples/Sample_14_ListItem.php index 3b509f3577..f82c3ec064 100644 --- a/samples/Sample_14_ListItem.php +++ b/samples/Sample_14_ListItem.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $fontStyleName = 'myOwnStyle'; @@ -25,7 +25,7 @@ ] ); -$predefinedMultilevelStyle = ['listType' => \PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER_NESTED]; +$predefinedMultilevelStyle = ['listType' => PhpOffice\PhpWord\Style\ListItem::TYPE_NUMBER_NESTED]; // New section $section = $phpWord->addSection(); diff --git a/samples/Sample_15_Link.php b/samples/Sample_15_Link.php index faef305962..43994deaa2 100644 --- a/samples/Sample_15_Link.php +++ b/samples/Sample_15_Link.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $linkFontStyleName = 'myOwnLinStyle'; @@ -17,7 +17,7 @@ $section->addLink( 'https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub', - ['color' => '0000FF', 'underline' => \PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE] + ['color' => '0000FF', 'underline' => PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE] ); $section->addTextBreak(2); $section->addLink('http://www.bing.com', null, $linkFontStyleName); diff --git a/samples/Sample_16_Object.php b/samples/Sample_16_Object.php index b68fb1675b..d3912a6c50 100644 --- a/samples/Sample_16_Object.php +++ b/samples/Sample_16_Object.php @@ -4,13 +4,13 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Begin code $section = $phpWord->addSection(); $section->addText('You can open this OLE object by double clicking on the icon:'); $section->addTextBreak(2); -$section->addOLEObject('resources/_sheet.xls'); +$section->addOLEObject(__DIR__ . '/resources/_sheet.xls'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_17_TitleTOC.php b/samples/Sample_17_TitleTOC.php index dcf060b0e6..3102ebda83 100644 --- a/samples/Sample_17_TitleTOC.php +++ b/samples/Sample_17_TitleTOC.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->getSettings()->setUpdateFields(true); // New section diff --git a/samples/Sample_18_Watermark.php b/samples/Sample_18_Watermark.php index aebb369023..0b3ae34f83 100644 --- a/samples/Sample_18_Watermark.php +++ b/samples/Sample_18_Watermark.php @@ -4,12 +4,12 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Begin code $section = $phpWord->addSection(); $header = $section->addHeader(); -$header->addWatermark('resources/_earth.jpg', ['marginTop' => 200, 'marginLeft' => 55]); +$header->addWatermark(__DIR__ . '/resources/_earth.jpg', ['marginTop' => 200, 'marginLeft' => 55]); $section->addText('The header reference to the current section includes a watermark image.'); // Save file diff --git a/samples/Sample_19_TextBreak.php b/samples/Sample_19_TextBreak.php index 45c79beeb6..0b41110b18 100644 --- a/samples/Sample_19_TextBreak.php +++ b/samples/Sample_19_TextBreak.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $fontStyle24 = ['size' => 24]; diff --git a/samples/Sample_20_BGColor.php b/samples/Sample_20_BGColor.php index 915a824171..e0ce4d6436 100644 --- a/samples/Sample_20_BGColor.php +++ b/samples/Sample_20_BGColor.php @@ -4,14 +4,14 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); $section->addText( 'This is some text highlighted using fgColor (limited to 15 colors)', - ['fgColor' => \PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW] + ['fgColor' => PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW] ); $section->addText('This one uses bgColor and is using hex value (0xfbbb10)', ['bgColor' => 'fbbb10']); $section->addText('Compatible with font colors', ['color' => '0000ff', 'bgColor' => 'fbbb10']); diff --git a/samples/Sample_21_TableRowRules.php b/samples/Sample_21_TableRowRules.php index 42fc2d92a5..0ddaa08faf 100644 --- a/samples/Sample_21_TableRowRules.php +++ b/samples/Sample_21_TableRowRules.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); @@ -19,7 +19,7 @@ $table1 = $section->addTable(['cellMargin' => 0, 'cellMarginRight' => 0, 'cellMarginBottom' => 0, 'cellMarginLeft' => 0]); $table1->addRow(3750); $cell1 = $table1->addCell(null, ['valign' => 'top', 'borderSize' => 30, 'borderColor' => 'ff0000']); -$cell1->addImage('./resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$cell1->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $section->addTextBreak(); $section->addText("But if we set the rowStyle 'exactHeight' to true, the real row height is used, removing the textbreak:"); @@ -34,7 +34,7 @@ ); $table2->addRow(3750, ['exactHeight' => true]); $cell2 = $table2->addCell(null, ['valign' => 'top', 'borderSize' => 30, 'borderColor' => '00ff00']); -$cell2->addImage('./resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$cell2->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 250, 'height' => 250, 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $section->addTextBreak(); $section->addText('In this example, image is 250px height. Rows are calculated in twips, and 1px = 15twips.'); diff --git a/samples/Sample_22_CheckBox.php b/samples/Sample_22_CheckBox.php index 33d4e39c66..91685924b0 100644 --- a/samples/Sample_22_CheckBox.php +++ b/samples/Sample_22_CheckBox.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); diff --git a/samples/Sample_23_TemplateBlock.php b/samples/Sample_23_TemplateBlock.php index 6da66a72d4..4cc541ab3a 100644 --- a/samples/Sample_23_TemplateBlock.php +++ b/samples/Sample_23_TemplateBlock.php @@ -4,7 +4,7 @@ // Template processor instance creation echo date('H:i:s') , ' Creating new TemplateProcessor instance...' , EOL; -$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_23_TemplateBlock.docx'); +$templateProcessor = new PhpOffice\PhpWord\TemplateProcessor(__DIR__ . '/resources/Sample_23_TemplateBlock.docx'); // Will clone everything between ${tag} and ${/tag}, the number of times. By default, 1. $templateProcessor->cloneBlock('CLONEME', 3); @@ -13,9 +13,9 @@ $templateProcessor->deleteBlock('DELETEME'); echo date('H:i:s'), ' Saving the result document...', EOL; -$templateProcessor->saveAs('results/Sample_23_TemplateBlock.docx'); +$templateProcessor->saveAs(__DIR__ . '/results/Sample_23_TemplateBlock.docx'); -echo getEndingNotes(['Word2007' => 'docx'], 'Sample_23_TemplateBlock'); +echo getEndingNotes(['Word2007' => 'docx'], __DIR__ . '/results/Sample_23_TemplateBlock.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_24_ReadODText.php b/samples/Sample_24_ReadODText.php index 73c110203e..1b3a43cd57 100644 --- a/samples/Sample_24_ReadODText.php +++ b/samples/Sample_24_ReadODText.php @@ -7,7 +7,7 @@ $source = __DIR__ . "/resources/{$name}.odt"; echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source, 'ODText'); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source, 'ODText'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_25_TextBox.php b/samples/Sample_25_TextBox.php index a897a6269f..3516379d42 100644 --- a/samples/Sample_25_TextBox.php +++ b/samples/Sample_25_TextBox.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); @@ -12,7 +12,7 @@ // In section $textbox = $section->addTextBox( [ - 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER, + 'alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'width' => 400, 'height' => 150, 'borderSize' => 1, @@ -39,7 +39,7 @@ $textrun->addText(', '); $textrun->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); $textrun->addText(', and image '); -$textrun->addImage('resources/_earth.jpg', ['width' => 18, 'height' => 18]); +$textrun->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); $textrun->addText('.'); // Save file diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index daf109966c..971c317c43 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -4,7 +4,7 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->addParagraphStyle('Heading2', ['alignment' => 'center']); $section = $phpWord->addSection(); @@ -93,7 +93,7 @@ $html .= '

The text below is not visible, click on show/hide to reveil it:

'; $html .= '

This is hidden text

'; -\PhpOffice\PhpWord\Shared\Html::addHtml($section, $html, false, false); +PhpOffice\PhpWord\Shared\Html::addHtml($section, $html, false, false); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_27_Field.php b/samples/Sample_27_Field.php index fd441ba022..e1dbb4f258 100644 --- a/samples/Sample_27_Field.php +++ b/samples/Sample_27_Field.php @@ -6,7 +6,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); PhpOffice\PhpWord\Style::addTitleStyle(1, ['size' => 14]); // New section @@ -49,7 +49,7 @@ $section->addText('The actual index:'); $section->addField('INDEX', [], ['\\e " "'], 'right click to update the index'); -$textrun = $section->addTextRun(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); +$textrun = $section->addTextRun(['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]); $textrun->addText('This is the date of lunar calendar '); $textrun->addField('DATE', ['dateformat' => 'd-M-yyyy H:mm:ss'], ['PreserveFormat', 'LunarCalendar']); $textrun->addText(' written in a textrun.'); diff --git a/samples/Sample_28_ReadRTF.php b/samples/Sample_28_ReadRTF.php index 43b859ac28..52aa74a9a5 100644 --- a/samples/Sample_28_ReadRTF.php +++ b/samples/Sample_28_ReadRTF.php @@ -7,7 +7,7 @@ $source = __DIR__ . "/resources/{$name}.rtf"; echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source, 'RTF'); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source, 'RTF'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_29_Line.php b/samples/Sample_29_Line.php index e5f41b8340..2fdf33c30d 100644 --- a/samples/Sample_29_Line.php +++ b/samples/Sample_29_Line.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); @@ -14,16 +14,16 @@ $section->addText('Horizontal Line (Inline style):'); $section->addLine( [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + 'width' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), + 'height' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), 'positioning' => 'absolute', ] ); $section->addText('Vertical Line (Inline style):'); $section->addLine( [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), + 'width' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + 'height' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), 'positioning' => 'absolute', ] ); @@ -33,14 +33,14 @@ $section->addText('Positioned Line (red):'); $section->addLine( [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), + 'width' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(4), + 'height' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(1), 'positioning' => 'absolute', 'posHorizontalRel' => 'page', 'posVerticalRel' => 'page', - 'marginLeft' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(10), - 'marginTop' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(8), - 'wrappingStyle' => \PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE, + 'marginLeft' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(10), + 'marginTop' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(8), + 'wrappingStyle' => PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE, 'color' => 'red', ] ); @@ -48,12 +48,12 @@ $section->addText('Horizontal Formatted Line'); $section->addLine( [ - 'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(15), - 'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), + 'width' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(15), + 'height' => PhpOffice\PhpWord\Shared\Converter::cmToPixel(0), 'positioning' => 'absolute', - 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, - 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, - 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, + 'beginArrow' => PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, + 'endArrow' => PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, + 'dash' => PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, 'weight' => 10, ] ); diff --git a/samples/Sample_30_ReadHTML.php b/samples/Sample_30_ReadHTML.php index 8698fe639a..b6564eddc8 100644 --- a/samples/Sample_30_ReadHTML.php +++ b/samples/Sample_30_ReadHTML.php @@ -7,7 +7,7 @@ $source = realpath(__DIR__ . "/resources/{$name}.html"); echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$phpWord = \PhpOffice\PhpWord\IOFactory::load($source, 'HTML'); +$phpWord = PhpOffice\PhpWord\IOFactory::load($source, 'HTML'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_31_Shape.php b/samples/Sample_31_Shape.php index 90e364e7be..7f68f3fc2a 100644 --- a/samples/Sample_31_Shape.php +++ b/samples/Sample_31_Shape.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); diff --git a/samples/Sample_32_Chart.php b/samples/Sample_32_Chart.php index 7e99984e41..c8c65e989e 100644 --- a/samples/Sample_32_Chart.php +++ b/samples/Sample_32_Chart.php @@ -6,7 +6,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // Define styles $phpWord->addTitleStyle(1, ['size' => 14, 'bold' => true], ['keepNext' => true, 'spaceBefore' => 240]); diff --git a/samples/Sample_33_FormField.php b/samples/Sample_33_FormField.php index 24ef6ee947..223fdd2987 100644 --- a/samples/Sample_33_FormField.php +++ b/samples/Sample_33_FormField.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->getSettings()->getDocumentProtection()->setEditing('forms'); // New section diff --git a/samples/Sample_34_SDT.php b/samples/Sample_34_SDT.php index c1722b5b5c..4c8f588e81 100644 --- a/samples/Sample_34_SDT.php +++ b/samples/Sample_34_SDT.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New section $section = $phpWord->addSection(); diff --git a/samples/Sample_35_InternalLink.php b/samples/Sample_35_InternalLink.php index e59c353001..ef10c4b61f 100644 --- a/samples/Sample_35_InternalLink.php +++ b/samples/Sample_35_InternalLink.php @@ -4,7 +4,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $section->addTitle('This is page 1', 1); diff --git a/samples/Sample_36_RTL.php b/samples/Sample_36_RTL.php index b3baca90cb..e3cf84576a 100644 --- a/samples/Sample_36_RTL.php +++ b/samples/Sample_36_RTL.php @@ -6,7 +6,7 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $phpWord->setDefaultFontName('DejaVu Sans'); // for good rendition of PDF $rendererName = Settings::PDF_RENDERER_MPDF; $rendererLibraryPath = $vendorDirPath . '/mpdf/mpdf'; @@ -18,17 +18,17 @@ $textrun = $section->addTextRun(); $textrun->addText('This is a Left to Right paragraph.'); -$textrun = $section->addTextRun(['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END]); +$textrun = $section->addTextRun(['alignment' => PhpOffice\PhpWord\SimpleType\Jc::END]); $textrun->addText('سلام این یک پاراگراف راست به چپ است', ['rtl' => true]); $section->addText('Table visually presented as RTL'); $style = ['rtl' => true, 'size' => 12]; -$tableStyle = ['borderSize' => 6, 'borderColor' => '000000', 'width' => 5000, 'unit' => \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT, 'bidiVisual' => true]; +$tableStyle = ['borderSize' => 6, 'borderColor' => '000000', 'width' => 5000, 'unit' => PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT, 'bidiVisual' => true]; $table = $section->addTable($tableStyle); -$cellHCentered = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]; -$cellHEnd = ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::END]; -$cellVCentered = ['valign' => \PhpOffice\PhpWord\SimpleType\VerticalJc::CENTER]; +$cellHCentered = ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER]; +$cellHEnd = ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::END]; +$cellVCentered = ['valign' => PhpOffice\PhpWord\SimpleType\VerticalJc::CENTER]; //Vidually bidirectinal table $table->addRow(); diff --git a/samples/Sample_37_Comments.php b/samples/Sample_37_Comments.php index 79647478e8..ac03a699e4 100644 --- a/samples/Sample_37_Comments.php +++ b/samples/Sample_37_Comments.php @@ -4,10 +4,10 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // A comment -$comment = new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); +$comment = new PhpOffice\PhpWord\Element\Comment('Authors name', new DateTime(), 'my_initials'); $comment->addText('Test', ['bold' => true]); $phpWord->addComment($comment); @@ -22,7 +22,7 @@ $section->addTextBreak(2); // Let's create a comment that we will link to a start element and an end element -$commentWithStartAndEnd = new \PhpOffice\PhpWord\Element\Comment('Foo Bar', new \DateTime()); +$commentWithStartAndEnd = new PhpOffice\PhpWord\Element\Comment('Foo Bar', new DateTime()); $commentWithStartAndEnd->addText('A comment with a start and an end'); $phpWord->addComment($commentWithStartAndEnd); @@ -37,12 +37,12 @@ $section->addTextBreak(2); // Let's add a comment on an image -$commentOnImage = new \PhpOffice\PhpWord\Element\Comment('Mr Smart', new \DateTime()); +$commentOnImage = new PhpOffice\PhpWord\Element\Comment('Mr Smart', new DateTime()); $imageComment = $commentOnImage->addTextRun(); $imageComment->addText('Hey, Mars does look '); $imageComment->addText('red', ['color' => 'FF0000']); $phpWord->addComment($commentOnImage); -$image = $section->addImage('resources/_mars.jpg'); +$image = $section->addImage(__DIR__ . '/resources/_mars.jpg'); $image->setCommentRangeStart($commentOnImage); $section->addTextBreak(2); @@ -50,12 +50,27 @@ // We can also do things the other way round, link the comment to the element $anotherText = $section->addText('another text'); -$comment1 = new \PhpOffice\PhpWord\Element\Comment('Authors name', new \DateTime(), 'my_initials'); +$comment1 = new PhpOffice\PhpWord\Element\Comment('Authors name', new DateTime(), 'my_initials'); $comment1->addText('Test', ['bold' => true]); $comment1->setStartElement($anotherText); $comment1->setEndElement($anotherText); $phpWord->addComment($comment1); +// We can also do things the other way round, link the comment to the element +$lastText = $section->addText('with a last text and two comments'); + +$comment1 = new PhpOffice\PhpWord\Element\Comment('Authors name', new DateTime(), 'my_initials'); +$comment1->addText('Comment 1', ['bold' => true]); +$comment1->setStartElement($lastText); +$comment1->setEndElement($lastText); +$phpWord->addComment($comment1); + +$comment2 = new PhpOffice\PhpWord\Element\Comment('Authors name', new DateTime(), 'my_initials'); +$comment2->addText('Comment 2', ['bold' => true]); +$comment2->setStartElement($lastText); +$comment2->setEndElement($lastText); +$phpWord->addComment($comment2); + // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); if (!CLI) { diff --git a/samples/Sample_38_Protection.php b/samples/Sample_38_Protection.php index 9f61538096..737946d51a 100644 --- a/samples/Sample_38_Protection.php +++ b/samples/Sample_38_Protection.php @@ -6,7 +6,7 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); $documentProtection = $phpWord->getSettings()->getDocumentProtection(); $documentProtection->setEditing(DocProtect::READ_ONLY); diff --git a/samples/Sample_39_TrackChanges.php b/samples/Sample_39_TrackChanges.php index a95d98cb81..a2c2bcf61c 100644 --- a/samples/Sample_39_TrackChanges.php +++ b/samples/Sample_39_TrackChanges.php @@ -6,7 +6,7 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; -$phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord = new PhpOffice\PhpWord\PhpWord(); // New portrait section $section = $phpWord->addSection(); @@ -21,7 +21,7 @@ $text->setTrackChange(new TrackChange(TrackChange::INSERTED, 'Fred')); $text = $textRun->addText('go to sleep'); -$text->setChangeInfo(TrackChange::DELETED, 'Barney', new \DateTime('@' . (time() - 3600))); +$text->setChangeInfo(TrackChange::DELETED, 'Barney', new DateTime('@' . (time() - 3600))); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_40_TemplateSetComplexValue.php b/samples/Sample_40_TemplateSetComplexValue.php index 38ecb3f7ae..41cbab8950 100644 --- a/samples/Sample_40_TemplateSetComplexValue.php +++ b/samples/Sample_40_TemplateSetComplexValue.php @@ -9,7 +9,7 @@ // Template processor instance creation echo date('H:i:s'), ' Creating new TemplateProcessor instance...', EOL; -$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_40_TemplateSetComplexValue.docx'); +$templateProcessor = new PhpOffice\PhpWord\TemplateProcessor(__DIR__ . '/resources/Sample_40_TemplateSetComplexValue.docx'); $title = new TextRun(); $title->addText('This title has been set ', ['bold' => true, 'italic' => true, 'color' => 'blue']); @@ -38,9 +38,9 @@ // $templateProcessor->setComplexValue('link', $link); echo date('H:i:s'), ' Saving the result document...', EOL; -$templateProcessor->saveAs('results/Sample_40_TemplateSetComplexValue.docx'); +$templateProcessor->saveAs(__DIR__ . '/results/Sample_40_TemplateSetComplexValue.docx'); -echo getEndingNotes(['Word2007' => 'docx'], 'results/Sample_40_TemplateSetComplexValue.docx'); +echo getEndingNotes(['Word2007' => 'docx'], __DIR__ . '/results/Sample_40_TemplateSetComplexValue.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_41_TemplateSetChart.php b/samples/Sample_41_TemplateSetChart.php index 88eb2ccbd9..36be5888f7 100644 --- a/samples/Sample_41_TemplateSetChart.php +++ b/samples/Sample_41_TemplateSetChart.php @@ -7,7 +7,7 @@ // Template processor instance creation echo date('H:i:s'), ' Creating new TemplateProcessor instance...', EOL; -$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('resources/Sample_41_TemplateSetChart.docx'); +$templateProcessor = new PhpOffice\PhpWord\TemplateProcessor(__DIR__ . '/resources/Sample_41_TemplateSetChart.docx'); $chartTypes = ['pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column']; $twoSeries = ['bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column']; @@ -38,9 +38,9 @@ } echo date('H:i:s'), ' Saving the result document...', EOL; -$templateProcessor->saveAs('results/Sample_41_TemplateSetChart.docx'); +$templateProcessor->saveAs(__DIR__ . '/results/Sample_41_TemplateSetChart.docx'); -echo getEndingNotes(['Word2007' => 'docx'], 'results/Sample_41_TemplateSetChart.docx'); +echo getEndingNotes(['Word2007' => 'docx'], __DIR__ . '/results/Sample_41_TemplateSetChart.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_44_ExtractVariablesFromReaderWord2007.php b/samples/Sample_44_ExtractVariablesFromReaderWord2007.php index 24574e5fb7..8c1703499f 100644 --- a/samples/Sample_44_ExtractVariablesFromReaderWord2007.php +++ b/samples/Sample_44_ExtractVariablesFromReaderWord2007.php @@ -9,6 +9,6 @@ echo date('H:i:s'), " Reading contents from `{$source}`", EOL; -$variables = \PhpOffice\PhpWord\IOFactory::extractVariables($source); +$variables = PhpOffice\PhpWord\IOFactory::extractVariables($source); var_dump($variables); diff --git a/samples/Sample_45_Autoloader.php b/samples/Sample_45_Autoloader.php new file mode 100644 index 0000000000..71f443f770 --- /dev/null +++ b/samples/Sample_45_Autoloader.php @@ -0,0 +1,93 @@ +getSettings()->setThemeFontLang($languageEnGb); + +$fontStyleName = 'rStyle'; +$phpWord->addFontStyle($fontStyleName, ['bold' => true, 'italic' => true, 'size' => 16, 'allCaps' => true, 'doubleStrikethrough' => true]); + +$paragraphStyleName = 'pStyle'; +$phpWord->addParagraphStyle($paragraphStyleName, ['alignment' => PhpOffice\PhpWord\SimpleType\Jc::CENTER, 'spaceAfter' => 100]); + +$phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); + +// New portrait section +$section = $phpWord->addSection(); + +// Simple text +$section->addTitle('Welcome to PhpWord', 1); +$section->addText('Hello World!'); + +// $pStyle = new Font(); +// $pStyle->setLang() +$section->addText('Ce texte-ci est en français.', ['lang' => PhpOffice\PhpWord\Style\Language::FR_BE]); + +// Two text break +$section->addTextBreak(2); + +// Define styles +$section->addText('I am styled by a font style definition.', $fontStyleName); +$section->addText('I am styled by a paragraph style definition.', null, $paragraphStyleName); +$section->addText('I am styled by both font and paragraph style.', $fontStyleName, $paragraphStyleName); + +$section->addTextBreak(); + +// Inline font style +$fontStyle['name'] = 'Times New Roman'; +$fontStyle['size'] = 20; + +$textrun = $section->addTextRun(); +$textrun->addText('I am inline styled ', $fontStyle); +$textrun->addText('with '); +$textrun->addText('color', ['color' => '996699']); +$textrun->addText(', '); +$textrun->addText('bold', ['bold' => true]); +$textrun->addText(', '); +$textrun->addText('italic', ['italic' => true]); +$textrun->addText(', '); +$textrun->addText('underline', ['underline' => 'dash']); +$textrun->addText(', '); +$textrun->addText('strikethrough', ['strikethrough' => true]); +$textrun->addText(', '); +$textrun->addText('doubleStrikethrough', ['doubleStrikethrough' => true]); +$textrun->addText(', '); +$textrun->addText('superScript', ['superScript' => true]); +$textrun->addText(', '); +$textrun->addText('subScript', ['subScript' => true]); +$textrun->addText(', '); +$textrun->addText('smallCaps', ['smallCaps' => true]); +$textrun->addText(', '); +$textrun->addText('allCaps', ['allCaps' => true]); +$textrun->addText(', '); +$textrun->addText('fgColor', ['fgColor' => 'yellow']); +$textrun->addText(', '); +$textrun->addText('scale', ['scale' => 200]); +$textrun->addText(', '); +$textrun->addText('spacing', ['spacing' => 120]); +$textrun->addText(', '); +$textrun->addText('kerning', ['kerning' => 10]); +$textrun->addText('. '); + +// Link +$section->addLink('https://github.com/PHPOffice/PHPWord', 'PHPWord on GitHub'); +$section->addTextBreak(); + +// Image +$section->addImage(__DIR__ . '/resources/_earth.jpg', ['width' => 18, 'height' => 18]); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index 8d05a2a34e..eab7033275 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -1,5 +1,19 @@ items; } @@ -44,11 +47,9 @@ public function getItems() /** * Get item by index. * - * @param int $index - * - * @return ?\PhpOffice\PhpWord\Element\AbstractContainer + * @return ?T */ - public function getItem($index) + public function getItem(int $index) { if (array_key_exists($index, $this->items)) { return $this->items[$index]; @@ -60,10 +61,9 @@ public function getItem($index) /** * Set item. * - * @param int $index - * @param ?\PhpOffice\PhpWord\Element\AbstractContainer $item + * @param ?T $item */ - public function setItem($index, $item): void + public function setItem(int $index, $item): void { if (array_key_exists($index, $this->items)) { $this->items[$index] = $item; @@ -73,11 +73,9 @@ public function setItem($index, $item): void /** * Add new item. * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $item - * - * @return int + * @param T $item */ - public function addItem($item) + public function addItem($item): int { $index = $this->countItems(); $this->items[$index] = $item; @@ -87,10 +85,8 @@ public function addItem($item) /** * Get item count. - * - * @return int */ - public function countItems() + public function countItems(): int { return count($this->items); } diff --git a/src/PhpWord/Collection/Bookmarks.php b/src/PhpWord/Collection/Bookmarks.php index e7d9b4a384..0694bf7dd8 100644 --- a/src/PhpWord/Collection/Bookmarks.php +++ b/src/PhpWord/Collection/Bookmarks.php @@ -1,4 +1,5 @@ */ class Bookmarks extends AbstractCollection { diff --git a/src/PhpWord/Collection/Charts.php b/src/PhpWord/Collection/Charts.php index bb63a13962..ef1c6597ff 100644 --- a/src/PhpWord/Collection/Charts.php +++ b/src/PhpWord/Collection/Charts.php @@ -1,4 +1,5 @@ */ class Charts extends AbstractCollection { diff --git a/src/PhpWord/Collection/Comments.php b/src/PhpWord/Collection/Comments.php index 8c6b577d7e..4f1394359f 100644 --- a/src/PhpWord/Collection/Comments.php +++ b/src/PhpWord/Collection/Comments.php @@ -1,4 +1,5 @@ */ class Comments extends AbstractCollection { diff --git a/src/PhpWord/Collection/Endnotes.php b/src/PhpWord/Collection/Endnotes.php index 362b25881d..3de1ad22d5 100644 --- a/src/PhpWord/Collection/Endnotes.php +++ b/src/PhpWord/Collection/Endnotes.php @@ -1,4 +1,5 @@ */ class Endnotes extends AbstractCollection { diff --git a/src/PhpWord/Collection/Footnotes.php b/src/PhpWord/Collection/Footnotes.php index 76eae3eab3..804a45c873 100644 --- a/src/PhpWord/Collection/Footnotes.php +++ b/src/PhpWord/Collection/Footnotes.php @@ -1,4 +1,5 @@ */ class Footnotes extends AbstractCollection { diff --git a/src/PhpWord/Collection/Titles.php b/src/PhpWord/Collection/Titles.php index 7b795771e8..1a943697d2 100644 --- a/src/PhpWord/Collection/Titles.php +++ b/src/PhpWord/Collection/Titles.php @@ -1,4 +1,5 @@ */ class Titles extends AbstractCollection { diff --git a/src/PhpWord/ComplexType/FootnoteProperties.php b/src/PhpWord/ComplexType/FootnoteProperties.php index 2e7743ca08..10c426e84c 100644 --- a/src/PhpWord/ComplexType/FootnoteProperties.php +++ b/src/PhpWord/ComplexType/FootnoteProperties.php @@ -1,4 +1,5 @@ newInstanceArgs($elementArgs); // Set parent container @@ -165,7 +166,7 @@ protected function addElement($elementName) /** * Get all elements. * - * @return \PhpOffice\PhpWord\Element\AbstractElement[] + * @return AbstractElement[] */ public function getElements() { @@ -177,7 +178,7 @@ public function getElements() * * @param int $index * - * @return null|\PhpOffice\PhpWord\Element\AbstractElement + * @return null|AbstractElement */ public function getElement($index) { @@ -191,13 +192,13 @@ public function getElement($index) /** * Removes the element at requested index. * - * @param int|\PhpOffice\PhpWord\Element\AbstractElement $toRemove + * @param AbstractElement|int $toRemove */ public function removeElement($toRemove): void { if (is_int($toRemove) && array_key_exists($toRemove, $this->elements)) { unset($this->elements[$toRemove]); - } elseif ($toRemove instanceof \PhpOffice\PhpWord\Element\AbstractElement) { + } elseif ($toRemove instanceof AbstractElement) { foreach ($this->elements as $key => $element) { if ($element->getElementId() === $toRemove->getElementId()) { unset($this->elements[$key]); diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index 9f9c2e82aa..3a29b68673 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -1,4 +1,5 @@ phpWord; } @@ -254,7 +255,7 @@ public function getElementId() */ public function setElementId(): void { - $this->elementId = substr(md5(mt_rand()), 0, 6); + $this->elementId = substr(md5((string) mt_rand()), 0, 6); } /** @@ -287,14 +288,24 @@ public function getNestedLevel() return $this->nestedLevel; } + /** + * Get comments start. + */ + public function getCommentsRangeStart(): ?Comments + { + return $this->commentsRangeStart; + } + /** * Get comment start. - * - * @return Comment */ - public function getCommentRangeStart() + public function getCommentRangeStart(): ?Comment { - return $this->commentRangeStart; + if ($this->commentsRangeStart != null) { + return $this->commentsRangeStart->getItem($this->commentsRangeStart->countItems()); + } + + return null; } /** @@ -305,18 +316,40 @@ public function setCommentRangeStart(Comment $value): void if ($this instanceof Comment) { throw new InvalidArgumentException('Cannot set a Comment on a Comment'); } - $this->commentRangeStart = $value; - $this->commentRangeStart->setStartElement($this); + if ($this->commentsRangeStart == null) { + $this->commentsRangeStart = new Comments(); + } + // Set ID early to avoid duplicates. + if ($value->getElementId() == null) { + $value->setElementId(); + } + foreach ($this->commentsRangeStart->getItems() as $comment) { + if ($value->getElementId() == $comment->getElementId()) { + return; + } + } + $idxItem = $this->commentsRangeStart->addItem($value); + $this->commentsRangeStart->getItem($idxItem)->setStartElement($this); + } + + /** + * Get comments end. + */ + public function getCommentsRangeEnd(): ?Comments + { + return $this->commentsRangeEnd; } /** * Get comment end. - * - * @return Comment */ - public function getCommentRangeEnd() + public function getCommentRangeEnd(): ?Comment { - return $this->commentRangeEnd; + if ($this->commentsRangeEnd != null) { + return $this->commentsRangeEnd->getItem($this->commentsRangeEnd->countItems()); + } + + return null; } /** @@ -327,8 +360,20 @@ public function setCommentRangeEnd(Comment $value): void if ($this instanceof Comment) { throw new InvalidArgumentException('Cannot set a Comment on a Comment'); } - $this->commentRangeEnd = $value; - $this->commentRangeEnd->setEndElement($this); + if ($this->commentsRangeEnd == null) { + $this->commentsRangeEnd = new Comments(); + } + // Set ID early to avoid duplicates. + if ($value->getElementId() == null) { + $value->setElementId(); + } + foreach ($this->commentsRangeEnd->getItems() as $comment) { + if ($value->getElementId() == $comment->getElementId()) { + return; + } + } + $idxItem = $this->commentsRangeEnd->addItem($value); + $this->commentsRangeEnd->getItem($idxItem)->setEndElement($this); } /** @@ -428,7 +473,7 @@ public function isInSection() * Set new style value. * * @param mixed $styleObject Style object - * @param null|array|\PhpOffice\PhpWord\Style|string $styleValue Style value + * @param null|array|string|Style $styleValue Style value * @param bool $returnObject Always return object * * @return mixed diff --git a/src/PhpWord/Element/Bookmark.php b/src/PhpWord/Element/Bookmark.php index 4fe3d0f067..151d5a48bf 100644 --- a/src/PhpWord/Element/Bookmark.php +++ b/src/PhpWord/Element/Bookmark.php @@ -1,4 +1,5 @@ startElement = $value; - if ($value->getCommentRangeStart() == null) { - $value->setCommentRangeStart($this); - } + $value->setCommentRangeStart($this); } /** * Get the element where this comment starts. * - * @return \PhpOffice\PhpWord\Element\AbstractElement + * @return AbstractElement */ public function getStartElement() { @@ -104,15 +103,13 @@ public function getStartElement() public function setEndElement(AbstractElement $value): void { $this->endElement = $value; - if ($value->getCommentRangeEnd() == null) { - $value->setCommentRangeEnd($this); - } + $value->setCommentRangeEnd($this); } /** * Get the element where this comment ends. * - * @return \PhpOffice\PhpWord\Element\AbstractElement + * @return AbstractElement */ public function getEndElement() { diff --git a/src/PhpWord/Element/Endnote.php b/src/PhpWord/Element/Endnote.php index 2888fdebc3..d2f42eafd0 100644 --- a/src/PhpWord/Element/Endnote.php +++ b/src/PhpWord/Element/Endnote.php @@ -1,4 +1,5 @@ ['Path', 'PreserveFormat'], ], + 'REF' => [ + 'properties' => ['name' => ''], + 'options' => ['f', 'h', 'n', 'p', 'r', 't', 'w'], + ], ]; /** @@ -124,16 +129,16 @@ class Field extends AbstractElement /** * Font style. * - * @var \PhpOffice\PhpWord\Style\Font|string + * @var Font|string */ protected $fontStyle; /** * Set Font style. * - * @param array|\PhpOffice\PhpWord\Style\Font|string $style + * @param array|Font|string $style * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return Font|string */ public function setFontStyle($style = null) { @@ -154,7 +159,7 @@ public function setFontStyle($style = null) /** * Get Font style. * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return Font|string */ public function getFontStyle() { @@ -168,7 +173,7 @@ public function getFontStyle() * @param array $properties * @param array $options * @param null|string|TextRun $text - * @param array|\PhpOffice\PhpWord\Style\Font|string $fontStyle + * @param array|Font|string $fontStyle */ public function __construct($type = null, $properties = [], $options = [], $text = null, $fontStyle = null) { diff --git a/src/PhpWord/Element/Footer.php b/src/PhpWord/Element/Footer.php index a9c48f7714..d17db10a32 100644 --- a/src/PhpWord/Element/Footer.php +++ b/src/PhpWord/Element/Footer.php @@ -1,4 +1,5 @@ source; } else { $fileHandle = fopen($actualSource, 'rb', false); - if ($fileHandle !== false) { - $imageBinary = fread($fileHandle, filesize($actualSource)); + $fileSize = filesize($actualSource); + if ($fileHandle !== false && $fileSize > 0) { + $imageBinary = fread($fileHandle, $fileSize); fclose($fileHandle); } } diff --git a/src/PhpWord/Element/Line.php b/src/PhpWord/Element/Line.php index 40ad75c799..b3ad438197 100644 --- a/src/PhpWord/Element/Line.php +++ b/src/PhpWord/Element/Line.php @@ -1,4 +1,5 @@ $collectionArray; if (in_array($type, [Header::AUTO, Header::FIRST, Header::EVEN])) { $index = count($collection); - /** @var \PhpOffice\PhpWord\Element\AbstractContainer $container Type hint */ + /** @var AbstractContainer $container Type hint */ $container = new $containerClass($this->sectionId, ++$index, $type); $container->setPhpWord($this->phpWord); diff --git a/src/PhpWord/Element/Shape.php b/src/PhpWord/Element/Shape.php index 15161f892e..9ea221db3b 100644 --- a/src/PhpWord/Element/Shape.php +++ b/src/PhpWord/Element/Shape.php @@ -1,4 +1,5 @@ phpWord->getTitles()->getItems(); foreach ($titles as $i => $title) { - /** @var \PhpOffice\PhpWord\Element\Title $title Type hint */ + /** @var Title $title Type hint */ $depth = $title->getDepth(); if ($this->minDepth > $depth) { unset($titles[$i]); @@ -110,7 +111,7 @@ public function getTitles() /** * Get TOC Style. * - * @return \PhpOffice\PhpWord\Style\TOC + * @return TOCStyle */ public function getStyleTOC() { @@ -120,7 +121,7 @@ public function getStyleTOC() /** * Get Font Style. * - * @return \PhpOffice\PhpWord\Style\Font|string + * @return Font|string */ public function getStyleFont() { diff --git a/src/PhpWord/Element/Table.php b/src/PhpWord/Element/Table.php index 53a828a9ea..7fb1030638 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -1,4 +1,5 @@ rows); for ($i = 0; $i < $rowCount; ++$i) { - /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ + /** @var Row $row Type hint */ $row = $this->rows[$i]; $cellCount = count($row->getCells()); if ($columnCount < $cellCount) { diff --git a/src/PhpWord/Element/Text.php b/src/PhpWord/Element/Text.php index 9695395324..ea5f5f87a4 100644 --- a/src/PhpWord/Element/Text.php +++ b/src/PhpWord/Element/Text.php @@ -1,4 +1,5 @@ load($filename); @@ -100,7 +101,7 @@ public static function load($filename, $readerName = 'Word2007') */ public static function extractVariables(string $filename, string $readerName = 'Word2007'): array { - /** @var \PhpOffice\PhpWord\Reader\ReaderInterface $reader */ + /** @var ReaderInterface $reader */ $reader = self::createReader($readerName); $document = $reader->load($filename); $extractedVariables = []; diff --git a/src/PhpWord/Media.php b/src/PhpWord/Media.php index 31487a91fe..0a340a0a3c 100644 --- a/src/PhpWord/Media.php +++ b/src/PhpWord/Media.php @@ -1,4 +1,5 @@ collections[$key]; return $collectionObject->addItem($args[0] ?? null); @@ -152,7 +152,7 @@ public function __call($function, $args) /** * Get document properties object. * - * @return \PhpOffice\PhpWord\Metadata\DocInfo + * @return Metadata\DocInfo */ public function getDocInfo() { @@ -162,7 +162,7 @@ public function getDocInfo() /** * Get compatibility. * - * @return \PhpOffice\PhpWord\Metadata\Compatibility + * @return Metadata\Compatibility * * @since 0.12.0 */ @@ -174,7 +174,7 @@ public function getCompatibility() /** * Get compatibility. * - * @return \PhpOffice\PhpWord\Metadata\Settings + * @return Metadata\Settings * * @since 0.14.0 */ @@ -186,7 +186,7 @@ public function getSettings() /** * Get all sections. * - * @return \PhpOffice\PhpWord\Element\Section[] + * @return Section[] */ public function getSections() { @@ -198,7 +198,7 @@ public function getSections() * * @param int $index * - * @return null|\PhpOffice\PhpWord\Element\Section + * @return null|Section */ public function getSection($index) { @@ -214,7 +214,7 @@ public function getSection($index) * * @param null|array|string $style * - * @return \PhpOffice\PhpWord\Element\Section + * @return Section */ public function addSection($style = null) { @@ -282,7 +282,7 @@ public function setDefaultFontSize($fontSize): void * * @param array $styles Paragraph style definition * - * @return \PhpOffice\PhpWord\Style\Paragraph + * @return Style\Paragraph */ public function setDefaultParagraphStyle($styles) { @@ -334,7 +334,7 @@ public function save($filename, $format = 'Word2007', $download = false) * * @param array $settings * - * @return \PhpOffice\PhpWord\Element\Section + * @return Section * * @codeCoverageIgnore */ @@ -348,7 +348,7 @@ public function createSection($settings = null) * * @deprecated 0.12.0 * - * @return \PhpOffice\PhpWord\Metadata\DocInfo + * @return Metadata\DocInfo * * @codeCoverageIgnore */ @@ -362,7 +362,7 @@ public function getDocumentProperties() * * @deprecated 0.12.0 * - * @param \PhpOffice\PhpWord\Metadata\DocInfo $documentProperties + * @param Metadata\DocInfo $documentProperties * * @return self * diff --git a/src/PhpWord/Reader/AbstractReader.php b/src/PhpWord/Reader/AbstractReader.php index da5e6f6e19..3c70834d16 100644 --- a/src/PhpWord/Reader/AbstractReader.php +++ b/src/PhpWord/Reader/AbstractReader.php @@ -1,4 +1,5 @@ dataWorkDocument, $arrayRGFC[$key] + $inc); + for ($inc = 0; $inc < ($strLen * 2); ++$inc) { + $byte = self::getInt2d($this->dataWorkDocument, $arrayRGFC[$key] + ($inc * 2)); if ($byte > 0) { - $string .= chr($byte); + $string .= mb_chr($byte, 'UTF-8'); + } else { + break; } } } @@ -2331,7 +2334,7 @@ private function generatePhpWord(): void foreach ($this->arrayParagraphs as $itmParagraph) { $textPara = $itmParagraph; foreach ($this->arrayCharacters as $oCharacters) { - $subText = substr($textPara, $oCharacters->pos_start, $oCharacters->pos_len); + $subText = mb_substr($textPara, $oCharacters->pos_start, $oCharacters->pos_len); $subText = str_replace(chr(13), PHP_EOL, $subText); $arrayText = explode(PHP_EOL, $subText); if (end($arrayText) == '') { diff --git a/src/PhpWord/Reader/ODText.php b/src/PhpWord/Reader/ODText.php index d7f8344443..288bf9a0dd 100644 --- a/src/PhpWord/Reader/ODText.php +++ b/src/PhpWord/Reader/ODText.php @@ -1,4 +1,5 @@ setRels($relationships); $part->read($phpWord); diff --git a/src/PhpWord/Reader/ODText/AbstractPart.php b/src/PhpWord/Reader/ODText/AbstractPart.php index 4c89192edd..447c96f094 100644 --- a/src/PhpWord/Reader/ODText/AbstractPart.php +++ b/src/PhpWord/Reader/ODText/AbstractPart.php @@ -1,4 +1,5 @@ elementExists('w:pPr', $domNode) ? $this->readParagraphStyle($xmlReader, $domNode) : null; - // PreserveText - if ($xmlReader->elementExists('w:r/w:instrText', $domNode)) { + if ($xmlReader->elementExists('w:r/w:fldChar/w:ffData', $domNode)) { + // FormField + $partOfFormField = false; + $formNodes = []; + $formType = null; + $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag', $domNode); + if ($textRunContainers > 0) { + $nodes = $xmlReader->getElements('*', $domNode); + $paragraph = $parent->addTextRun($paragraphStyle); + foreach ($nodes as $node) { + if ($xmlReader->elementExists('w:fldChar/w:ffData', $node)) { + $partOfFormField = true; + $formNodes[] = $node; + if ($xmlReader->elementExists('w:fldChar/w:ffData/w:ddList', $node)) { + $formType = 'dropdown'; + } elseif ($xmlReader->elementExists('w:fldChar/w:ffData/w:textInput', $node)) { + $formType = 'textinput'; + } elseif ($xmlReader->elementExists('w:fldChar/w:ffData/w:checkBox', $node)) { + $formType = 'checkbox'; + } + } elseif ($partOfFormField && + $xmlReader->elementExists('w:fldChar', $node) && + 'end' == $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar') + ) { + $formNodes[] = $node; + $partOfFormField = false; + // Process the form fields + $this->readFormField($xmlReader, $formNodes, $paragraph, $paragraphStyle, $formType); + } elseif ($partOfFormField) { + $formNodes[] = $node; + } else { + // normal runs + $this->readRun($xmlReader, $node, $paragraph, $docPart, $paragraphStyle); + } + } + } + } elseif ($xmlReader->elementExists('w:r/w:instrText', $domNode)) { + // PreserveText $ignoreText = false; $textContent = ''; $fontStyle = $this->readFontStyle($xmlReader, $domNode); $nodes = $xmlReader->getElements('w:r', $domNode); foreach ($nodes as $node) { - $instrText = $xmlReader->getValue('w:instrText', $node); - if ($xmlReader->elementExists('w:fldChar', $node)) { - $fldCharType = $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar'); - if ('begin' == $fldCharType) { - $ignoreText = true; - } elseif ('end' == $fldCharType) { - $ignoreText = false; - } + if ($xmlReader->elementExists('w:lastRenderedPageBreak', $node)) { + $parent->addPageBreak(); } + $instrText = $xmlReader->getValue('w:instrText', $node); if (null !== $instrText) { $textContent .= '{' . $instrText . '}'; } else { + if ($xmlReader->elementExists('w:fldChar', $node)) { + $fldCharType = $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar'); + if ('begin' == $fldCharType) { + $ignoreText = true; + } elseif ('end' == $fldCharType) { + $ignoreText = false; + } + } if (false === $ignoreText) { $textContent .= $xmlReader->getValue('w:t', $node); } @@ -272,7 +313,7 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par // Text and TextRun $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag|w:commentReference|w:commentRangeStart|w:commentRangeEnd', $domNode); if (0 === $textRunContainers) { - $parent->addTextBreak(null, $paragraphStyle); + $parent->addTextBreak(1, $paragraphStyle); } else { $nodes = $xmlReader->getElements('*', $domNode); $paragraph = $parent->addTextRun($paragraphStyle); @@ -282,6 +323,109 @@ protected function readParagraph(XMLReader $xmlReader, DOMElement $domNode, $par } } + /** + * @param DOMElement[] $domNodes + * @param AbstractContainer $parent + * @param mixed $paragraphStyle + * @param string $formType + */ + private function readFormField(XMLReader $xmlReader, array $domNodes, $parent, $paragraphStyle, $formType): void + { + if (!in_array($formType, ['textinput', 'checkbox', 'dropdown'])) { + return; + } + + $formField = $parent->addFormField($formType, null, $paragraphStyle); + $ffData = $xmlReader->getElement('w:fldChar/w:ffData', $domNodes[0]); + + foreach ($xmlReader->getElements('*', $ffData) as $node) { + /** @var DOMElement $node */ + switch ($node->localName) { + case 'name': + $formField->setName($node->getAttribute('w:val')); + + break; + case 'ddList': + $listEntries = []; + foreach ($xmlReader->getElements('*', $node) as $ddListNode) { + switch ($ddListNode->localName) { + case 'result': + $formField->setValue($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'default': + $formField->setDefault($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'listEntry': + $listEntries[] = $xmlReader->getAttribute('w:val', $ddListNode); + + break; + } + } + $formField->setEntries($listEntries); + if (null !== $formField->getValue()) { + $formField->setText($listEntries[$formField->getValue()]); + } + + break; + case 'textInput': + foreach ($xmlReader->getElements('*', $node) as $ddListNode) { + switch ($ddListNode->localName) { + case 'default': + $formField->setDefault($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'format': + case 'maxLength': + break; + } + } + + break; + case 'checkBox': + foreach ($xmlReader->getElements('*', $node) as $ddListNode) { + switch ($ddListNode->localName) { + case 'default': + $formField->setDefault($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'checked': + $formField->setValue($xmlReader->getAttribute('w:val', $ddListNode)); + + break; + case 'size': + case 'sizeAuto': + break; + } + } + + break; + } + } + + if ('textinput' == $formType) { + $ignoreText = true; + $textContent = ''; + foreach ($domNodes as $node) { + if ($xmlReader->elementExists('w:fldChar', $node)) { + $fldCharType = $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar'); + if ('separate' == $fldCharType) { + $ignoreText = false; + } elseif ('end' == $fldCharType) { + $ignoreText = true; + } + } + + if (false === $ignoreText) { + $textContent .= $xmlReader->getValue('w:t', $node); + } + } + $formField->setValue(htmlspecialchars($textContent, ENT_QUOTES, 'UTF-8')); + $formField->setText(htmlspecialchars($textContent, ENT_QUOTES, 'UTF-8')); + } + } + /** * Returns the depth of the Heading, returns 0 for a Title. * @@ -307,7 +451,7 @@ private function getHeadingDepth(?array $paragraphStyle = null) /** * Read w:r. * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $parent + * @param AbstractContainer $parent * @param string $docPart * @param mixed $paragraphStyle * @@ -529,6 +673,18 @@ protected function readParagraphStyle(XMLReader $xmlReader, DOMElement $domNode) 'contextualSpacing' => [self::READ_TRUE, 'w:contextualSpacing'], 'bidi' => [self::READ_TRUE, 'w:bidi'], 'suppressAutoHyphens' => [self::READ_TRUE, 'w:suppressAutoHyphens'], + 'borderTopStyle' => [self::READ_VALUE, 'w:pBdr/w:top'], + 'borderTopColor' => [self::READ_VALUE, 'w:pBdr/w:top', 'w:color'], + 'borderTopSize' => [self::READ_VALUE, 'w:pBdr/w:top', 'w:sz'], + 'borderRightStyle' => [self::READ_VALUE, 'w:pBdr/w:right'], + 'borderRightColor' => [self::READ_VALUE, 'w:pBdr/w:right', 'w:color'], + 'borderRightSize' => [self::READ_VALUE, 'w:pBdr/w:right', 'w:sz'], + 'borderBottomStyle' => [self::READ_VALUE, 'w:pBdr/w:bottom'], + 'borderBottomColor' => [self::READ_VALUE, 'w:pBdr/w:bottom', 'w:color'], + 'borderBottomSize' => [self::READ_VALUE, 'w:pBdr/w:bottom', 'w:sz'], + 'borderLeftStyle' => [self::READ_VALUE, 'w:pBdr/w:left'], + 'borderLeftColor' => [self::READ_VALUE, 'w:pBdr/w:left', 'w:color'], + 'borderLeftSize' => [self::READ_VALUE, 'w:pBdr/w:left', 'w:sz'], ]; return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); diff --git a/src/PhpWord/Reader/Word2007/DocPropsApp.php b/src/PhpWord/Reader/Word2007/DocPropsApp.php index 9d6f3cbbe9..c7ecb007b3 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsApp.php +++ b/src/PhpWord/Reader/Word2007/DocPropsApp.php @@ -1,4 +1,5 @@ */ private function readWPNode(XMLReader $xmlReader, DOMElement $node, Section &$section): void { diff --git a/src/PhpWord/Reader/Word2007/Endnotes.php b/src/PhpWord/Reader/Word2007/Endnotes.php index 0c6b18db37..6ab4203579 100644 --- a/src/PhpWord/Reader/Word2007/Endnotes.php +++ b/src/PhpWord/Reader/Word2007/Endnotes.php @@ -1,4 +1,5 @@ cssContent); preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $cssContent, $cssExtracted); - // Check the number of extracted - if (count($cssExtracted) != 3) { - return; - } // Check if there are x selectors and x rules if (count($cssExtracted[1]) != count($cssExtracted[2])) { return; diff --git a/src/PhpWord/Shared/Drawing.php b/src/PhpWord/Shared/Drawing.php index df218108d9..8af7da2ffc 100644 --- a/src/PhpWord/Shared/Drawing.php +++ b/src/PhpWord/Shared/Drawing.php @@ -1,4 +1,5 @@ . * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element Where the parts need to be added + * @param 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 @@ -103,7 +104,7 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit * parse Inline style of a node. * * @param DOMNode $node Node to check on attributes and to compile a style array - * @param array $styles is supplied, the inline style attributes are added to the already existing style + * @param array $styles is supplied, the inline style attributes are added to the already existing style * * @return array */ @@ -112,7 +113,9 @@ protected static function parseInlineStyle($node, $styles = []) if (XML_ELEMENT_NODE == $node->nodeType) { $attributes = $node->attributes; // get all the attributes(eg: id, class) - $bidi = ($attributes['dir'] ?? '') === 'rtl'; + $attributeDir = $attributes->getNamedItem('dir'); + $attributeDirValue = $attributeDir ? $attributeDir->nodeValue : ''; + $bidi = $attributeDirValue === 'rtl'; foreach ($attributes as $attribute) { $val = $attribute->value; switch (strtolower($attribute->name)) { @@ -160,15 +163,15 @@ protected static function parseInlineStyle($node, $styles = []) $attributeIdentifier = $attributes->getNamedItem('id'); if ($attributeIdentifier && self::$css) { - $styles = self::parseStyleDeclarations(self::$css->getStyle('#' . $attributeIdentifier->value), $styles); + $styles = self::parseStyleDeclarations(self::$css->getStyle('#' . $attributeIdentifier->nodeValue), $styles); } $attributeClass = $attributes->getNamedItem('class'); if ($attributeClass) { if (self::$css) { - $styles = self::parseStyleDeclarations(self::$css->getStyle('.' . $attributeClass->value), $styles); + $styles = self::parseStyleDeclarations(self::$css->getStyle('.' . $attributeClass->nodeValue), $styles); } - $styles['className'] = $attributeClass->value; + $styles['className'] = $attributeClass->nodeValue; } $attributeStyle = $attributes->getNamedItem('style'); @@ -184,7 +187,7 @@ protected static function parseInlineStyle($node, $styles = []) * Parse a node and add a corresponding element to the parent element. * * @param DOMNode $node node to parse - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element object to add an element corresponding with the node + * @param AbstractContainer $element object to add an element corresponding with the node * @param array $styles Array with all styles * @param array $data Array to transport data to a next level in the DOM tree, for example level of listitems */ @@ -275,7 +278,7 @@ protected static function parseNode($node, $element, $styles = [], $data = []): * Parse child nodes. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer|Row|Table $element + * @param AbstractContainer|Row|Table $element * @param array $styles * @param array $data */ @@ -297,7 +300,7 @@ protected static function parseChildNodes($node, $element, $styles, $data): void * Parse paragraph node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles * * @return \PhpOffice\PhpWord\Element\PageBreak|\PhpOffice\PhpWord\Element\TextRun @@ -316,7 +319,7 @@ protected static function parseParagraph($node, $element, &$styles) * Parse input node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles */ protected static function parseInput($node, $element, &$styles): void @@ -326,10 +329,10 @@ protected static function parseInput($node, $element, &$styles): void return; } - $inputType = $attributes->getNamedItem('type')->value; + $inputType = $attributes->getNamedItem('type')->nodeValue; switch ($inputType) { case 'checkbox': - $checked = ($checked = $attributes->getNamedItem('checked')) && $checked->value === 'true' ? true : false; + $checked = ($checked = $attributes->getNamedItem('checked')) && $checked->nodeValue === 'true' ? true : false; $textrun = $element->addTextRun($styles['paragraph']); $textrun->addFormField('checkbox')->setValue($checked); @@ -362,7 +365,7 @@ protected static function parseHeading(DOMNode $node, AbstractContainer $element * Parse text node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles */ protected static function parseText($node, $element, &$styles): void @@ -406,7 +409,7 @@ protected static function parseSpan($node, &$styles): void * Parse table node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles * * @return Table $element @@ -425,8 +428,8 @@ protected static function parseTable($node, $element, &$styles) } $attributes = $node->attributes; - if ($attributes->getNamedItem('border') !== null) { - $border = (int) $attributes->getNamedItem('border')->value; + if ($attributes->getNamedItem('border')) { + $border = (int) $attributes->getNamedItem('border')->nodeValue; $newElement->getStyle()->setBorderSize(Converter::pixelToTwip($border)); } @@ -437,7 +440,7 @@ protected static function parseTable($node, $element, &$styles) * Parse a table row. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\Table $element + * @param Table $element * @param array &$styles * * @return Row $element @@ -460,7 +463,7 @@ protected static function parseRow($node, $element, &$styles) * Parse table cell. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\Table $element + * @param Table $element * @param array &$styles * * @return \PhpOffice\PhpWord\Element\Cell|\PhpOffice\PhpWord\Element\TextRun $element @@ -554,7 +557,7 @@ protected static function filterOutNonInheritedStyles(array $styles) * Parse list node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles * @param array &$data */ @@ -627,15 +630,15 @@ protected static function getListStyle($isOrderedList) return [ 'type' => 'hybridMultilevel', 'levels' => [ - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], - ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '◦', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '◦', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '◦', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'], + ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'], ], ]; } @@ -644,7 +647,7 @@ protected static function getListStyle($isOrderedList) * Parse list item node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array &$styles * @param array $data * @@ -886,7 +889,7 @@ protected static function parseStyleDeclarations(array $selectors, array $styles * Parse image node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * * @return \PhpOffice\PhpWord\Element\Image */ @@ -902,12 +905,34 @@ protected static function parseImage($node, $element) break; case 'width': $width = $attribute->value; + + // pt + if (false !== strpos($width, 'pt')) { + $width = Converter::pointToPixel((float) str_replace('pt', '', $width)); + } + + // px + if (false !== strpos($width, 'px')) { + $width = str_replace('px', '', $width); + } + $style['width'] = $width; $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; case 'height': $height = $attribute->value; + + // pt + if (false !== strpos($height, 'pt')) { + $height = Converter::pointToPixel((float) str_replace('pt', '', $height)); + } + + // px + if (false !== strpos($height, 'px')) { + $height = str_replace('px', '', $height); + } + $style['height'] = $height; $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; @@ -948,14 +973,15 @@ protected static function parseImage($node, $element) $match = []; preg_match('/data:image\/(\w+);base64,(.+)/', $src, $match); + if (!empty($match)) { + $src = $imgFile = $tmpDir . uniqid() . '.' . $match[1]; - $src = $imgFile = $tmpDir . uniqid() . '.' . $match[1]; + $ifp = fopen($imgFile, 'wb'); - $ifp = fopen($imgFile, 'wb'); - - if ($ifp !== false) { - fwrite($ifp, base64_decode($match[2])); - fclose($ifp); + if ($ifp !== false) { + fwrite($ifp, base64_decode($match[2])); + fclose($ifp); + } } } $src = urldecode($src); @@ -1107,7 +1133,7 @@ protected static function mapListType($cssListType) /** * Parse line break. * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element */ protected static function parseLineBreak($element): void { @@ -1118,7 +1144,7 @@ protected static function parseLineBreak($element): void * Parse link node. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element * @param array $styles */ protected static function parseLink($node, $element, &$styles) @@ -1134,7 +1160,11 @@ protected static function parseLink($node, $element, &$styles) } $styles['font'] = self::parseInlineStyle($node, $styles['font']); - if (strpos($target, '#') === 0) { + if (empty($target)) { + $target = '#'; + } + + if (strpos($target, '#') === 0 && strlen($target) > 1) { return $element->addLink(substr($target, 1), $node->textContent, $styles['font'], $styles['paragraph'], true); } @@ -1146,7 +1176,7 @@ protected static function parseLink($node, $element, &$styles) * Note: Word rule is not the same as HTML's
since it does not support width and thus neither alignment. * * @param DOMNode $node - * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param AbstractContainer $element */ protected static function parseHorizRule($node, $element): void { diff --git a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php index d6cf69fc6d..45f9a53632 100644 --- a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php +++ b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php @@ -1,4 +1,5 @@ open($zipFile); + $openStatus = $zip->open($zipFile); + if ($openStatus !== true) { + /** + * Throw an exception since making further calls on the ZipArchive would cause a fatal error. + * This prevents fatal errors on corrupt archives and attempts to open old "doc" files. + */ + throw new Exception("The archive failed to load with the following error code: $openStatus"); + } + $content = $zip->getFromName(ltrim($xmlFile, '/')); $zip->close(); diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index 9f51c0e514..8dc28e1184 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -1,4 +1,5 @@ usePclzip) { - if ($this->zip->close() === false) { + try { + $result = @$this->zip->close(); + } catch (Throwable $e) { + $result = false; + } + if ($result === false) { throw new Exception("Could not close zip file {$this->filename}: "); } } @@ -289,8 +294,10 @@ public function pclzipAddFromString($localname, $contents) // Write $contents to a temp file $handle = fopen($this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename'], 'wb'); - fwrite($handle, $contents); - fclose($handle); + if ($handle) { + fwrite($handle, $contents); + fclose($handle); + } // Add temp file to zip $filename = $this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename']; diff --git a/src/PhpWord/SimpleType/Border.php b/src/PhpWord/SimpleType/Border.php index 6cb42f0467..acd1c1a1b1 100644 --- a/src/PhpWord/SimpleType/Border.php +++ b/src/PhpWord/SimpleType/Border.php @@ -1,4 +1,5 @@ */ public function getBorderColor() { @@ -186,7 +187,7 @@ public function getBorderColor() /** * Set border color. * - * @param string $value + * @param null|string $value * * @return self */ @@ -259,7 +260,7 @@ public function setBorderTopSize($value = null) /** * Get border top color. * - * @return string + * @return null|string */ public function getBorderTopColor() { @@ -269,7 +270,7 @@ public function getBorderTopColor() /** * Set border top color. * - * @param string $value + * @param null|string $value * * @return self */ @@ -331,7 +332,7 @@ public function setBorderLeftSize($value = null) /** * Get border left color. * - * @return string + * @return null|string */ public function getBorderLeftColor() { @@ -341,7 +342,7 @@ public function getBorderLeftColor() /** * Set border left color. * - * @param string $value + * @param null|string $value * * @return self */ @@ -403,7 +404,7 @@ public function setBorderRightSize($value = null) /** * Get border right color. * - * @return string + * @return null|string */ public function getBorderRightColor() { @@ -413,7 +414,7 @@ public function getBorderRightColor() /** * Set border right color. * - * @param string $value + * @param null|string $value * * @return self */ @@ -475,7 +476,7 @@ public function setBorderBottomSize($value = null) /** * Get border bottom color. * - * @return string + * @return null|string */ public function getBorderBottomColor() { @@ -485,7 +486,7 @@ public function getBorderBottomColor() /** * Set border bottom color. * - * @param string $value + * @param null|string $value * * @return self */ diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 3246471fd5..f102bfa862 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -1,4 +1,5 @@ vAlign = null; + + return $this; + } + VerticalJc::validate($value); $this->vAlign = $this->setEnumVal($value, VerticalJc::values(), $this->vAlign); @@ -235,7 +242,7 @@ public function setGridSpan($value = null) /** * Get vertical merge (rowspan). * - * @return string + * @return null|string */ public function getVMerge() { @@ -245,12 +252,18 @@ public function getVMerge() /** * Set vertical merge (rowspan). * - * @param string $value + * @param null|string $value * * @return self */ public function setVMerge($value = null) { + if ($value === null) { + $this->vMerge = null; + + return $this; + } + $enum = [self::VMERGE_RESTART, self::VMERGE_CONTINUE]; $this->vMerge = $this->setEnumVal($value, $enum, $this->vMerge); @@ -260,7 +273,7 @@ public function setVMerge($value = null) /** * Get shading. * - * @return \PhpOffice\PhpWord\Style\Shading + * @return Shading */ public function getShading() { diff --git a/src/PhpWord/Style/Chart.php b/src/PhpWord/Style/Chart.php index 9dbc8db0a6..6cffc4d5b0 100644 --- a/src/PhpWord/Style/Chart.php +++ b/src/PhpWord/Style/Chart.php @@ -1,4 +1,5 @@ strikethrough; } @@ -577,20 +576,16 @@ public function isStrikethrough() * Set strikethrough. * * @param bool $value - * - * @return self */ - public function setStrikethrough($value = true) + public function setStrikethrough($value = true): self { return $this->setPairedVal($this->strikethrough, $this->doubleStrikethrough, $value); } /** * Get double strikethrough. - * - * @return bool */ - public function isDoubleStrikethrough() + public function isDoubleStrikethrough(): ?bool { return $this->doubleStrikethrough; } @@ -599,10 +594,8 @@ public function isDoubleStrikethrough() * Set double strikethrough. * * @param bool $value - * - * @return self */ - public function setDoubleStrikethrough($value = true) + public function setDoubleStrikethrough($value = true): self { return $this->setPairedVal($this->doubleStrikethrough, $this->strikethrough, $value); } @@ -690,7 +683,7 @@ public function getBgColor() * * @param string $value * - * @return \PhpOffice\PhpWord\Style\Table + * @return Table */ public function setBgColor($value = null) { @@ -820,7 +813,7 @@ public function setLineHeight($value) /** * Get paragraph style. * - * @return \PhpOffice\PhpWord\Style\Paragraph + * @return Paragraph */ public function getParagraph() { @@ -868,7 +861,7 @@ public function setRTL($value = true) /** * Get shading. * - * @return \PhpOffice\PhpWord\Style\Shading + * @return Shading */ public function getShading() { @@ -892,7 +885,7 @@ public function setShading($value = null) /** * Get language. * - * @return null|\PhpOffice\PhpWord\Style\Language + * @return null|Language */ public function getLang() { diff --git a/src/PhpWord/Style/Frame.php b/src/PhpWord/Style/Frame.php index 45fc583ed1..016722f36c 100644 --- a/src/PhpWord/Style/Frame.php +++ b/src/PhpWord/Style/Frame.php @@ -1,4 +1,5 @@ numId; } /** * Set Id. - * - * @param int $value - * - * @return self */ - public function setNumId($value) + public function setNumId(int $value): self { $this->numId = $this->setIntVal($value, $this->numId); @@ -78,22 +73,16 @@ public function setNumId($value) /** * Get multilevel type. - * - * @return string */ - public function getType() + public function getType(): ?string { return $this->type; } /** * Set multilevel type. - * - * @param string $value - * - * @return self */ - public function setType($value) + public function setType(string $value): self { $enum = ['singleLevel', 'multilevel', 'hybridMultilevel']; $this->type = $this->setEnumVal($value, $enum, $this->type); @@ -106,19 +95,15 @@ public function setType($value) * * @return NumberingLevel[] */ - public function getLevels() + public function getLevels(): array { return $this->levels; } /** * Set multilevel type. - * - * @param array $values - * - * @return self */ - public function setLevels($values) + public function setLevels(array $values): self { if (is_array($values)) { foreach ($values as $key => $value) { diff --git a/src/PhpWord/Style/NumberingLevel.php b/src/PhpWord/Style/NumberingLevel.php index 39c0d839d6..31ec3738c8 100644 --- a/src/PhpWord/Style/NumberingLevel.php +++ b/src/PhpWord/Style/NumberingLevel.php @@ -1,4 +1,5 @@ zip()->AddFromString("word/media/image1.jpg", file_get_contents($file));
* To read a file: $templateProcessor->zip()->getFromName("word/media/image1.jpg"); * - * @return \PhpOffice\PhpWord\Shared\ZipArchive + * @return ZipArchive */ public function zip() { @@ -281,7 +281,7 @@ public function setComplexValue($search, Element\AbstractElement $complexType): $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName; $xmlWriter = new XMLWriter(); - /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $elementWriter */ + /** @var Writer\Word2007\Element\AbstractElement $elementWriter */ $elementWriter = new $objectClass($xmlWriter, $complexType, true); $elementWriter->write(); @@ -308,7 +308,7 @@ public function setComplexBlock($search, Element\AbstractElement $complexType): $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName; $xmlWriter = new XMLWriter(); - /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $elementWriter */ + /** @var Writer\Word2007\Element\AbstractElement $elementWriter */ $elementWriter = new $objectClass($xmlWriter, $complexType, false); $elementWriter->write(); @@ -406,7 +406,7 @@ public function setChart($search, Element\AbstractElement $chart): void $filename = "charts/chart{$rId}.xml"; // Get the part writer - $writerPart = new \PhpOffice\PhpWord\Writer\Word2007\Part\Chart(); + $writerPart = new Writer\Word2007\Part\Chart(); $writerPart->setElement($chart); // ContentTypes.xml @@ -499,20 +499,22 @@ private function fixImageWidthHeightRatio(&$width, &$height, $actualWidth, $actu $widthFloat = $heightFloat * $imageRatio; $matches = []; preg_match('/\\d([a-z%]+)$/', $height, $matches); - $width = $widthFloat . $matches[1]; + $width = $widthFloat . (!empty($matches) ? $matches[1] : 'px'); } elseif ($height === '') { // defined height is empty $widthFloat = (float) $width; $heightFloat = $widthFloat / $imageRatio; $matches = []; preg_match('/\\d([a-z%]+)$/', $width, $matches); - $height = $heightFloat . $matches[1]; + $height = $heightFloat . (!empty($matches) ? $matches[1] : 'px'); } else { // we have defined size, but we need also check it aspect ratio $widthMatches = []; preg_match('/\\d([a-z%]+)$/', $width, $widthMatches); $heightMatches = []; preg_match('/\\d([a-z%]+)$/', $height, $heightMatches); // try to fix only if dimensions are same - if ($widthMatches[1] == $heightMatches[1]) { + if (!empty($widthMatches) + && !empty($heightMatches) + && $widthMatches[1] == $heightMatches[1]) { $dimention = $widthMatches[1]; $widthFloat = (float) $width; $heightFloat = (float) $height; @@ -662,13 +664,13 @@ public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEM foreach (array_keys($this->tempDocumentHeaders) as $headerIndex) { $searchParts[$this->getHeaderName($headerIndex)] = &$this->tempDocumentHeaders[$headerIndex]; } - foreach (array_keys($this->tempDocumentFooters) as $headerIndex) { - $searchParts[$this->getFooterName($headerIndex)] = &$this->tempDocumentFooters[$headerIndex]; + foreach (array_keys($this->tempDocumentFooters) as $footerIndex) { + $searchParts[$this->getFooterName($footerIndex)] = &$this->tempDocumentFooters[$footerIndex]; } // define templates // result can be verified via "Open XML SDK 2.5 Productivity Tool" (http://www.microsoft.com/en-us/download/details.aspx?id=30425) - $imgTpl = ''; + $imgTpl = ''; $i = 0; foreach ($searchParts as $partFileName => &$partContent) { @@ -805,8 +807,8 @@ public function cloneRow($search, $numberOfClones): void */ public function deleteRow(string $search): void { - if ('${' !== substr($search, 0, 2) && '}' !== substr($search, -1)) { - $search = '${' . $search . '}'; + if (self::$macroOpeningChars !== substr($search, 0, 2) && self::$macroClosingChars !== substr($search, -1)) { + $search = self::$macroOpeningChars . $search . self::$macroClosingChars; } $tagPos = strpos($this->tempDocumentMainPart, $search); @@ -1287,7 +1289,7 @@ protected function getSlice($startPosition, $endPosition = 0) * @param int $count * @param string $xmlBlock * - * @return string + * @return array */ protected function indexClonedVariables($count, $xmlBlock) { @@ -1339,7 +1341,7 @@ protected function replaceClonedVariables($variableReplacements, $xmlBlock) * @param string $block New block content * @param string $blockType XML tag type of block * - * @return \PhpOffice\PhpWord\TemplateProcessor Fluent interface + * @return TemplateProcessor Fluent interface */ public function replaceXmlBlock($macro, $block, $blockType = 'w:p') { diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php index 8ebf98c7b5..13859d8227 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -1,4 +1,5 @@ parts as $partName) { $partClass = 'PhpOffice\\PhpWord\\Writer\\HTML\\Part\\' . $partName; if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Writer\HTML\Part\AbstractPart $part Type hint */ + /** @var HTML\Part\AbstractPart $part Type hint */ $part = new $partClass(); $part->setParentWriter($this); $this->writerParts[strtolower($partName)] = $part; diff --git a/src/PhpWord/Writer/HTML/Element/AbstractElement.php b/src/PhpWord/Writer/HTML/Element/AbstractElement.php index 7c7bde3189..0e6a112eed 100644 --- a/src/PhpWord/Writer/HTML/Element/AbstractElement.php +++ b/src/PhpWord/Writer/HTML/Element/AbstractElement.php @@ -1,4 +1,5 @@ namespace, $elementClass); if (class_exists($writerClass)) { - /** @var \PhpOffice\PhpWord\Writer\HTML\Element\AbstractElement $writer Type hint */ + /** @var AbstractElement $writer Type hint */ $writer = new $writerClass($this->parentWriter, $element, $withoutP); $content .= $writer->write(); } diff --git a/src/PhpWord/Writer/HTML/Element/Endnote.php b/src/PhpWord/Writer/HTML/Element/Endnote.php index 1c35e8faa8..7e7f31d4fc 100644 --- a/src/PhpWord/Writer/HTML/Element/Endnote.php +++ b/src/PhpWord/Writer/HTML/Element/Endnote.php @@ -1,4 +1,5 @@ getGridSpan(); $cellRowSpan = 1; $cellVMerge = $cellStyle->getVMerge(); - // If this is the first cell of the vertical merge, find out how man rows it spans + // If this is the first cell of the vertical merge, find out how many rows it spans if ($cellVMerge === 'restart') { - for ($k = $i + 1; $k < $rowCount; ++$k) { - $kRowCells = $rows[$k]->getCells(); - if (isset($kRowCells[$j]) && $kRowCells[$j]->getStyle()->getVMerge() === 'continue') { - ++$cellRowSpan; - } else { - break; - } - } + $cellRowSpan = $this->calculateCellRowSpan($rows, $i, $j); } // Ignore cells that are merged vertically with previous rows if ($cellVMerge !== 'continue') { @@ -120,9 +114,7 @@ private function getTableStyle($tableStyle = null): string return ''; } if (is_string($tableStyle)) { - $style = ' class="' . $tableStyle; - - return $style . '"'; + return ' class="' . $tableStyle . '"'; } $styleWriter = new TableStyleWriter($tableStyle); @@ -133,4 +125,58 @@ private function getTableStyle($tableStyle = null): string return ' style="' . $style . '"'; } + + /** + * Calculates cell rowspan. + * + * @param \PhpOffice\PhpWord\Element\Row[] $rows + */ + private function calculateCellRowSpan(array $rows, int $rowIndex, int $colIndex): int + { + $currentRow = $rows[$rowIndex]; + $currentRowCells = $currentRow->getCells(); + $shiftedColIndex = 0; + + foreach ($currentRowCells as $cell) { + if ($cell === $currentRowCells[$colIndex]) { + break; + } + + $colSpan = 1; + + if ($cell->getStyle()->getGridSpan() !== null) { + $colSpan = $cell->getStyle()->getGridSpan(); + } + + $shiftedColIndex += $colSpan; + } + + $rowCount = count($rows); + $rowSpan = 1; + + for ($i = $rowIndex + 1; $i < $rowCount; ++$i) { + $rowCells = $rows[$i]->getCells(); + $colIndex = 0; + + foreach ($rowCells as $cell) { + if ($colIndex === $shiftedColIndex) { + if ($cell->getStyle()->getVMerge() === 'continue') { + ++$rowSpan; + } + + break; + } + + $colSpan = 1; + + if ($cell->getStyle()->getGridSpan() !== null) { + $colSpan = $cell->getStyle()->getGridSpan(); + } + + $colIndex += $colSpan; + } + } + + return $rowSpan; + } } diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index 5af9f2ab63..312d3a19c2 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -1,4 +1,5 @@ getVAlign(); + } foreach (['Top', 'Left', 'Bottom', 'Right'] as $direction) { $method = 'getBorder' . $direction . 'Style'; diff --git a/src/PhpWord/Writer/ODText.php b/src/PhpWord/Writer/ODText.php index 616119e5cc..c9a524e882 100644 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -1,4 +1,5 @@ parts) as $partName) { $partClass = static::class . '\\Part\\' . $partName; if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart $partObject Type hint */ + /** @var AbstractPart $partObject Type hint */ $partObject = new $partClass(); $partObject->setParentWriter($this); $this->writerParts[strtolower($partName)] = $partObject; diff --git a/src/PhpWord/Writer/ODText/Element/AbstractElement.php b/src/PhpWord/Writer/ODText/Element/AbstractElement.php index 5cd396aa51..ff3a6569de 100644 --- a/src/PhpWord/Writer/ODText/Element/AbstractElement.php +++ b/src/PhpWord/Writer/ODText/Element/AbstractElement.php @@ -1,4 +1,5 @@ + */ + protected $containerWithoutP = ['TextRun', 'Footnote', 'Endnote']; } diff --git a/src/PhpWord/Writer/ODText/Element/Field.php b/src/PhpWord/Writer/ODText/Element/Field.php index 46f62b0f02..6b54807869 100644 --- a/src/PhpWord/Writer/ODText/Element/Field.php +++ b/src/PhpWord/Writer/ODText/Element/Field.php @@ -1,4 +1,5 @@ getXmlWriter(); $element = $this->getElement(); - if (!$element instanceof \PhpOffice\PhpWord\Element\Image) { + if (!$element instanceof ElementImage) { return; } @@ -43,11 +44,16 @@ public function write(): void $width = Converter::pixelToCm($style->getWidth()); $height = Converter::pixelToCm($style->getHeight()); - $xmlWriter->startElement('text:p'); - $xmlWriter->writeAttribute('text:style-name', 'IM' . $mediaIndex); + $xmlWriter = $this->getXmlWriter(); + + if (!$this->withoutP) { + $xmlWriter->startElement('text:p'); + $xmlWriter->writeAttribute('text:style-name', 'IM' . $mediaIndex); + } $xmlWriter->startElement('draw:frame'); $xmlWriter->writeAttribute('draw:style-name', 'fr' . $mediaIndex); + $xmlWriter->writeAttributeIf($this->withoutP, 'draw:text-style-name', 'IM' . $mediaIndex); $xmlWriter->writeAttribute('draw:name', $element->getElementId()); $xmlWriter->writeAttribute('text:anchor-type', 'as-char'); $xmlWriter->writeAttribute('svg:width', $width . 'cm'); @@ -63,6 +69,8 @@ public function write(): void $xmlWriter->endElement(); // draw:frame - $xmlWriter->endElement(); // text:p + if (!$this->withoutP) { + $xmlWriter->endElement(); // text:p + } } } diff --git a/src/PhpWord/Writer/ODText/Element/Link.php b/src/PhpWord/Writer/ODText/Element/Link.php index 0375b11bc1..9ef35692c8 100644 --- a/src/PhpWord/Writer/ODText/Element/Link.php +++ b/src/PhpWord/Writer/ODText/Element/Link.php @@ -1,4 +1,5 @@ getElement(); + if (!$element instanceof ListItemRunElement) { + return; + } + $depth = $element->getDepth() + 1; + + $xmlWriter = $this->getXmlWriter(); + + for ($iDepth = 1; $iDepth <= $depth; ++$iDepth) { + $xmlWriter->startElement('text:list'); + $xmlWriter->writeAttribute('text:style-name', $element->getStyle()->getNumStyle()); + $xmlWriter->startElement('text:list-item'); + } + + $containerWriter = new Container($xmlWriter, $element, false); + $containerWriter->write(); + + for ($iDepth = 1; $iDepth <= $depth; ++$iDepth) { + $xmlWriter->endElement(); // text:list-item + $xmlWriter->endElement(); // text:list + } + } +} diff --git a/src/PhpWord/Writer/ODText/Element/PageBreak.php b/src/PhpWord/Writer/ODText/Element/PageBreak.php index 367106c0fd..ca9e53f4a6 100644 --- a/src/PhpWord/Writer/ODText/Element/PageBreak.php +++ b/src/PhpWord/Writer/ODText/Element/PageBreak.php @@ -1,4 +1,5 @@ getXmlWriter(); $element = $this->getElement(); - if (!$element instanceof \PhpOffice\PhpWord\Element\Table) { + if (!$element instanceof TableElement) { return; } $rows = $element->getRows(); @@ -77,7 +78,7 @@ private function writeColumns(XMLWriter $xmlWriter, TableElement $element): void private function writeRow(XMLWriter $xmlWriter, RowElement $row): void { $xmlWriter->startElement('table:table-row'); - /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ + /** @var RowElement $row Type hint */ foreach ($row->getCells() as $cell) { $xmlWriter->startElement('table:table-cell'); $xmlWriter->writeAttribute('office:value-type', 'string'); diff --git a/src/PhpWord/Writer/ODText/Element/Text.php b/src/PhpWord/Writer/ODText/Element/Text.php index 75fb930856..65909fce0c 100644 --- a/src/PhpWord/Writer/ODText/Element/Text.php +++ b/src/PhpWord/Writer/ODText/Element/Text.php @@ -1,4 +1,5 @@ writeAttribute('text:change-id', $element->getTrackChange()->getElementId()); $xmlWriter->endElement(); } else { - if (empty($fontStyle)) { - if (empty($paragraphStyle)) { - if (!$this->withoutP) { - $xmlWriter->writeAttribute('text:style-name', 'Normal'); - } - } elseif (is_string($paragraphStyle)) { - if (!$this->withoutP) { - $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); - } + if (empty($paragraphStyle)) { + if (!$this->withoutP) { + $xmlWriter->writeAttribute('text:style-name', 'Normal'); } - $this->writeChangeInsertion(true, $element->getTrackChange()); - $this->replaceTabs($element->getText(), $xmlWriter); - $this->writeChangeInsertion(false, $element->getTrackChange()); - } else { - if (empty($paragraphStyle)) { - if (!$this->withoutP) { - $xmlWriter->writeAttribute('text:style-name', 'Normal'); - } - } elseif (is_string($paragraphStyle)) { - if (!$this->withoutP) { - $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); - } + } elseif (is_string($paragraphStyle)) { + if (!$this->withoutP) { + $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); } + } + + if (!empty($fontStyle)) { // text:span $xmlWriter->startElement('text:span'); if (is_string($fontStyle)) { $xmlWriter->writeAttribute('text:style-name', $fontStyle); } - $this->writeChangeInsertion(true, $element->getTrackChange()); - $this->replaceTabs($element->getText(), $xmlWriter); - $this->writeChangeInsertion(false, $element->getTrackChange()); + } + + $this->writeChangeInsertion(true, $element->getTrackChange()); + $this->replaceTabs($element->getText(), $xmlWriter); + $this->writeChangeInsertion(false, $element->getTrackChange()); + + if (!empty($fontStyle)) { $xmlWriter->endElement(); } } diff --git a/src/PhpWord/Writer/ODText/Element/TextBreak.php b/src/PhpWord/Writer/ODText/Element/TextBreak.php index 1bfe398857..1a69700792 100644 --- a/src/PhpWord/Writer/ODText/Element/TextBreak.php +++ b/src/PhpWord/Writer/ODText/Element/TextBreak.php @@ -1,4 +1,5 @@ imageParagraphStyles as $style) { - $styleWriter = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $style); + $styleWriter = new ParagraphStyleWriter($xmlWriter, $style); $styleWriter->write(); } } @@ -256,7 +257,7 @@ private function getAutoStyles(PhpWord $phpWord): void * * Table style can be null or string of the style name * - * @param \PhpOffice\PhpWord\Element\AbstractContainer $container + * @param AbstractContainer $container * @param int $paragraphStyleCount * @param int $fontStyleCount * @@ -277,7 +278,7 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl $style = $element->getStyle(); $style->setStyleName('fr' . $element->getMediaIndex()); $this->autoStyles['Image'][] = $style; - $sty = new \PhpOffice\PhpWord\Style\Paragraph(); + $sty = new Paragraph(); $sty->setStyleName('IM' . $element->getMediaIndex()); $sty->setAuto(); $sty->setAlignment($style->getAlignment()); @@ -300,7 +301,7 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl /** * Get style of individual element. * - * @param \PhpOffice\PhpWord\Element\Text $element + * @param Text $element * @param int $paragraphStyleCount * @param int $fontStyleCount */ @@ -346,7 +347,7 @@ private function getElementStyle($element, &$paragraphStyleCount, &$fontStyleCou /** * Get font style of individual field element. * - * @param \PhpOffice\PhpWord\Element\Field $element + * @param Field $element * @param int $fontStyleCount */ private function getElementStyleField($element, &$fontStyleCount): void @@ -371,7 +372,7 @@ private function getElementStyleField($element, &$fontStyleCount): void /** * Get style of individual element. * - * @param \PhpOffice\PhpWord\Element\TextRun $element + * @param TextRun $element * @param int $paragraphStyleCount */ private function getElementStyleTextRun($element, &$paragraphStyleCount): void diff --git a/src/PhpWord/Writer/ODText/Part/Manifest.php b/src/PhpWord/Writer/ODText/Part/Manifest.php index 37fb797935..200da15836 100644 --- a/src/PhpWord/Writer/ODText/Part/Manifest.php +++ b/src/PhpWord/Writer/ODText/Part/Manifest.php @@ -1,4 +1,5 @@ setStyleName($style->getStyleName()); - $temp2 = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $temp1); + $temp2 = new Paragraph($xmlWriter, $temp1); $temp2->write(); } diff --git a/src/PhpWord/Writer/ODText/Style/Image.php b/src/PhpWord/Writer/ODText/Style/Image.php index 79ddfc502e..56c4f57a5b 100644 --- a/src/PhpWord/Writer/ODText/Style/Image.php +++ b/src/PhpWord/Writer/ODText/Style/Image.php @@ -1,4 +1,5 @@ getStyle(); + if (!$style instanceof StyleNumbering) { + return; + } + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startElement('text:list-style'); + $xmlWriter->writeAttribute('style:name', $style->getStyleName()); + + foreach ($style->getLevels() as $styleLevel) { + $numLevel = $styleLevel->getLevel() + 1; + + // In Twips + $tabPos = $styleLevel->getTabPos(); + // In Inches + $tabPos /= Converter::INCH_TO_TWIP; + // In Centimeters + $tabPos *= Converter::INCH_TO_CM; + + // In Twips + $hanging = $styleLevel->getHanging(); + // In Inches + $hanging /= Converter::INCH_TO_TWIP; + // In Centimeters + $hanging *= Converter::INCH_TO_CM; + + $xmlWriter->startElement('text:list-level-style-bullet'); + $xmlWriter->writeAttribute('text:level', $numLevel); + $xmlWriter->writeAttribute('text:style-name', $style->getStyleName() . '_' . $numLevel); + $xmlWriter->writeAttribute('text:bullet-char', $styleLevel->getText()); + + $xmlWriter->startElement('style:list-level-properties'); + $xmlWriter->writeAttribute('text:list-level-position-and-space-mode', 'label-alignment'); + + $xmlWriter->startElement('style:list-level-label-alignment'); + $xmlWriter->writeAttribute('text:label-followed-by', 'listtab'); + $xmlWriter->writeAttribute('text:list-tab-stop-position', number_format($tabPos, 2, '.', '') . 'cm'); + $xmlWriter->writeAttribute('fo:text-indent', '-' . number_format($hanging, 2, '.', '') . 'cm'); + $xmlWriter->writeAttribute('fo:margin-left', number_format($tabPos, 2, '.', '') . 'cm'); + + $xmlWriter->endElement(); // style:list-level-label-alignment + $xmlWriter->endElement(); // style:list-level-properties + + $xmlWriter->startElement('style:text-properties'); + $xmlWriter->writeAttribute('style:font-name', $styleLevel->getFont()); + $xmlWriter->endElement(); // style:text-properties + + $xmlWriter->endElement(); // text:list-level-style-bullet + } + + $xmlWriter->endElement(); // text:list-style + } +} diff --git a/src/PhpWord/Writer/ODText/Style/Paragraph.php b/src/PhpWord/Writer/ODText/Style/Paragraph.php index 4459c76c01..99963bd4a3 100644 --- a/src/PhpWord/Writer/ODText/Style/Paragraph.php +++ b/src/PhpWord/Writer/ODText/Style/Paragraph.php @@ -1,4 +1,5 @@ getStyle(); - if (!$style instanceof \PhpOffice\PhpWord\Style\Paragraph) { + if (!$style instanceof Style\Paragraph) { return; } $xmlWriter = $this->getXmlWriter(); @@ -73,13 +74,13 @@ public function write(): void } elseif (substr($styleName, 0, 2) === 'HD') { $styleAuto = true; $psm = 'Heading_' . substr($styleName, 2); - $stylep = \PhpOffice\PhpWord\Style::getStyle($psm); - if ($stylep instanceof \PhpOffice\PhpWord\Style\Font) { + $stylep = Style::getStyle($psm); + if ($stylep instanceof Style\Font) { if (method_exists($stylep, 'getParagraph')) { $stylep = $stylep->getParagraph(); } } - if ($stylep instanceof \PhpOffice\PhpWord\Style\Paragraph) { + if ($stylep instanceof Style\Paragraph) { if ($stylep->hasPageBreakBefore()) { $breakbefore = true; } diff --git a/src/PhpWord/Writer/ODText/Style/Section.php b/src/PhpWord/Writer/ODText/Style/Section.php index 0a250194fd..05152a3944 100644 --- a/src/PhpWord/Writer/ODText/Style/Section.php +++ b/src/PhpWord/Writer/ODText/Style/Section.php @@ -1,4 +1,5 @@ parts as $partName) { $partClass = static::class . '\\Part\\' . $partName; if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Writer\RTF\Part\AbstractPart $part Type hint */ + /** @var RTF\Part\AbstractPart $part Type hint */ $part = new $partClass(); $part->setParentWriter($this); $this->writerParts[strtolower($partName)] = $part; diff --git a/src/PhpWord/Writer/RTF/Element/AbstractElement.php b/src/PhpWord/Writer/RTF/Element/AbstractElement.php index dedbc8bfa1..e007e6aa26 100644 --- a/src/PhpWord/Writer/RTF/Element/AbstractElement.php +++ b/src/PhpWord/Writer/RTF/Element/AbstractElement.php @@ -1,4 +1,5 @@ parentWriter = $parentWriter; $this->element = $element; @@ -95,7 +96,7 @@ public function __construct(AbstractWriter $parentWriter, Element $element, bool */ protected function getStyles(): void { - /** @var \PhpOffice\PhpWord\Writer\RTF $parentWriter Type hint */ + /** @var WriterRTF $parentWriter Type hint */ $parentWriter = $this->parentWriter; /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ @@ -188,7 +189,7 @@ protected function writeFontStyle() return ''; } - /** @var \PhpOffice\PhpWord\Writer\RTF $parentWriter Type hint */ + /** @var WriterRTF $parentWriter Type hint */ $parentWriter = $this->parentWriter; // Create style writer and set color/name index diff --git a/src/PhpWord/Writer/RTF/Element/Container.php b/src/PhpWord/Writer/RTF/Element/Container.php index 5e198aec86..dcac8ec071 100644 --- a/src/PhpWord/Writer/RTF/Element/Container.php +++ b/src/PhpWord/Writer/RTF/Element/Container.php @@ -1,4 +1,5 @@ element->getStyle(); + if (is_string($tableStyle)) { + $tableStyle = Style::getStyle($tableStyle); + if (!($tableStyle instanceof TableStyle)) { + $tableStyle = null; + } + } $rightMargin = 0; foreach ($row->getCells() as $cell) { + $content .= $this->writeCellStyle($cell->getStyle(), $tableStyle); + $width = $cell->getWidth(); $vMerge = $this->getVMerge($cell->getStyle()->getVMerge()); if ($width === null) { @@ -127,6 +145,103 @@ private function writeCell(CellElement $cell) return $content; } + private function writeCellStyle(CellStyle $cell, ?TableStyle $table): string + { + $content = $this->writeCellBorder( + 't', + $cell->getBorderTopStyle() ?: ($table ? $table->getBorderTopStyle() : null), + (int) round($cell->getBorderTopSize() ?: ($table ? ($table->getBorderTopSize() ?: 0) : 0)), + $cell->getBorderTopColor() ?? ($table ? $table->getBorderTopColor() : null) + ); + $content .= $this->writeCellBorder( + 'l', + $cell->getBorderLeftStyle() ?: ($table ? $table->getBorderLeftStyle() : null), + (int) round($cell->getBorderLeftSize() ?: ($table ? ($table->getBorderLeftSize() ?: 0) : 0)), + $cell->getBorderLeftColor() ?? ($table ? $table->getBorderLeftColor() : null) + ); + $content .= $this->writeCellBorder( + 'b', + $cell->getBorderBottomStyle() ?: ($table ? $table->getBorderBottomStyle() : null), + (int) round($cell->getBorderBottomSize() ?: ($table ? ($table->getBorderBottomSize() ?: 0) : 0)), + $cell->getBorderBottomColor() ?? ($table ? $table->getBorderBottomColor() : null) + ); + $content .= $this->writeCellBorder( + 'r', + $cell->getBorderRightStyle() ?: ($table ? $table->getBorderRightStyle() : null), + (int) round($cell->getBorderRightSize() ?: ($table ? ($table->getBorderRightSize() ?: 0) : 0)), + $cell->getBorderRightColor() ?? ($table ? $table->getBorderRightColor() : null) + ); + + return $content; + } + + private function writeCellBorder(string $prefix, ?string $borderStyle, int $borderSize, ?string $borderColor): string + { + if ($borderSize == 0) { + return ''; + } + + $content = '\clbrdr' . $prefix; + /** + * \brdrs Single-thickness border. + * \brdrth Double-thickness border. + * \brdrsh Shadowed border. + * \brdrdb Double border. + * \brdrdot Dotted border. + * \brdrdash Dashed border. + * \brdrhair Hairline border. + * \brdrinset Inset border. + * \brdrdashsm Dash border (small). + * \brdrdashd Dot dash border. + * \brdrdashdd Dot dot dash border. + * \brdroutset Outset border. + * \brdrtriple Triple border. + * \brdrtnthsg Thick thin border (small). + * \brdrthtnsg Thin thick border (small). + * \brdrtnthtnsg Thin thick thin border (small). + * \brdrtnthmg Thick thin border (medium). + * \brdrthtnmg Thin thick border (medium). + * \brdrtnthtnmg Thin thick thin border (medium). + * \brdrtnthlg Thick thin border (large). + * \brdrthtnlg Thin thick border (large). + * \brdrtnthtnlg Thin thick thin border (large). + * \brdrwavy Wavy border. + * \brdrwavydb Double wavy border. + * \brdrdashdotstr Striped border. + * \brdremboss Emboss border. + * \brdrengrave Engrave border. + */ + switch ($borderStyle) { + case Border::DOTTED: + $content .= '\brdrdot'; + + break; + case Border::SINGLE: + default: + $content .= '\brdrs'; + + break; + } + + // \brdrwN N is the width in twips (1/20 pt) of the pen used to draw the paragraph border line. + // N cannot be greater than 75. + // To obtain a larger border width, the \brdth control word can be used to obtain a width double that of N. + // $borderSize is in eights of a point, i.e. 4 / 8 = .5pt + // 1/20 pt => 1/8 / 2.5 + $content .= '\brdrw' . (int) ($borderSize / 2.5); + + // \brdrcfN N is the color of the paragraph border, specified as an index into the color table in the RTF header. + $colorIndex = 0; + $index = array_search($borderColor, $this->parentWriter->getColorTable()); + if ($index !== false) { + $colorIndex = (int) $index + 1; + } + $content .= '\brdrcf' . $colorIndex; + $content .= PHP_EOL; + + return $content; + } + /** * Get vertical merge style. * diff --git a/src/PhpWord/Writer/RTF/Element/Text.php b/src/PhpWord/Writer/RTF/Element/Text.php index bd8cbae5ca..71d3a27ce8 100644 --- a/src/PhpWord/Writer/RTF/Element/Text.php +++ b/src/PhpWord/Writer/RTF/Element/Text.php @@ -1,4 +1,5 @@ getHeaders() as $header) { $type = $header->getType(); - if ($evenOdd || $type !== FOOTER::EVEN) { + if ($evenOdd || $type !== Footer::EVEN) { $content .= '{\\header'; if ($type === Footer::FIRST) { $content .= 'f'; } elseif ($evenOdd) { - $content .= ($type === FOOTER::EVEN) ? 'l' : 'r'; + $content .= ($type === Footer::EVEN) ? 'l' : 'r'; } foreach ($header->getElements() as $element) { $cl = get_class($element); @@ -182,12 +183,12 @@ private function writeSections() } foreach ($section->getFooters() as $footer) { $type = $footer->getType(); - if ($evenOdd || $type !== FOOTER::EVEN) { + if ($evenOdd || $type !== Footer::EVEN) { $content .= '{\\footer'; if ($type === Footer::FIRST) { $content .= 'f'; } elseif ($evenOdd) { - $content .= ($type === FOOTER::EVEN) ? 'l' : 'r'; + $content .= ($type === Footer::EVEN) ? 'l' : 'r'; } foreach ($footer->getElements() as $element) { $cl = get_class($element); diff --git a/src/PhpWord/Writer/RTF/Part/Header.php b/src/PhpWord/Writer/RTF/Part/Header.php index e4ad4bee0b..97644fe4ac 100644 --- a/src/PhpWord/Writer/RTF/Part/Header.php +++ b/src/PhpWord/Writer/RTF/Part/Header.php @@ -1,4 +1,5 @@ registerTableItem($this->fontTable, $style->getName(), $defaultFont); $this->registerTableItem($this->colorTable, $style->getColor(), $defaultColor); $this->registerTableItem($this->colorTable, $style->getFgColor(), $defaultColor); + + return; + } + if ($style instanceof Table) { + $this->registerTableItem($this->colorTable, $style->getBorderTopColor(), $defaultColor); + $this->registerTableItem($this->colorTable, $style->getBorderRightColor(), $defaultColor); + $this->registerTableItem($this->colorTable, $style->getBorderLeftColor(), $defaultColor); + $this->registerTableItem($this->colorTable, $style->getBorderBottomColor(), $defaultColor); } } diff --git a/src/PhpWord/Writer/RTF/Style/AbstractStyle.php b/src/PhpWord/Writer/RTF/Style/AbstractStyle.php index 355e384440..00e148dfe9 100644 --- a/src/PhpWord/Writer/RTF/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/RTF/Style/AbstractStyle.php @@ -1,4 +1,5 @@ parts) as $partName) { $partClass = static::class . '\\Part\\' . $partName; if (class_exists($partClass)) { - /** @var \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart $part Type hint */ + /** @var Word2007\Part\AbstractPart $part Type hint */ $part = new $partClass(); $part->setParentWriter($this); $this->writerParts[strtolower($partName)] = $part; @@ -179,7 +178,7 @@ private function addHeaderFooterMedia(ZipArchive $zip, $docPart): void $this->registerContentTypes($media); } - /** @var \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart $writerPart Type hint */ + /** @var Word2007\Part\AbstractPart $writerPart Type hint */ $writerPart = $this->getWriterPart('relspart')->setMedia($media); $zip->addFromString("word/_rels/{$file}.xml.rels", $writerPart->write()); } @@ -206,7 +205,7 @@ private function addHeaderFooterContent(Section &$section, ZipArchive $zip, $elm $this->contentTypes['override']["/word/$elmFile"] = $elmType; $this->relationships[] = ['target' => $elmFile, 'type' => $elmType, 'rID' => $rId]; - /** @var \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart $writerPart Type hint */ + /** @var Word2007\Part\AbstractPart $writerPart Type hint */ $writerPart = $this->getWriterPart($elmType)->setElement($element); $zip->addFromString("word/$elmFile", $writerPart->write()); } @@ -227,7 +226,6 @@ private function addNotes(ZipArchive $zip, &$rId, $noteType = 'footnote'): void $collection = $phpWord->$method(); // Add footnotes media files, relations, and contents - /** @var \PhpOffice\PhpWord\Collection\AbstractCollection $collection Type hint */ if ($collection->countItems() > 0) { $media = Media::getElements($noteType); $this->addFilesToPackage($zip, $media); @@ -237,7 +235,7 @@ private function addNotes(ZipArchive $zip, &$rId, $noteType = 'footnote'): void // Write relationships file, e.g. word/_rels/footnotes.xml if (!empty($media)) { - /** @var \PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart $writerPart Type hint */ + /** @var Word2007\Part\AbstractPart $writerPart Type hint */ $writerPart = $this->getWriterPart('relspart')->setMedia($media); $zip->addFromString("word/_rels/{$partName}.xml.rels", $writerPart->write()); } @@ -260,7 +258,6 @@ private function addComments(ZipArchive $zip, &$rId): void $partName = 'comments'; // Add comment relations and contents - /** @var \PhpOffice\PhpWord\Collection\AbstractCollection $collection Type hint */ if ($collection->countItems() > 0) { $this->relationships[] = ['target' => "{$partName}.xml", 'type' => $partName, 'rID' => ++$rId]; diff --git a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php index abd1324aad..5743c8c7c7 100644 --- a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php +++ b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php @@ -1,4 +1,5 @@ xmlWriter = $xmlWriter; $this->element = $element; @@ -76,7 +75,7 @@ public function __construct(XMLWriter $xmlWriter, Element $element, $withoutP = /** * Get XML Writer. * - * @return \PhpOffice\PhpWord\Shared\XMLWriter + * @return XMLWriter */ protected function getXmlWriter() { @@ -86,7 +85,7 @@ protected function getXmlWriter() /** * Get element. * - * @return \PhpOffice\PhpWord\Element\AbstractElement + * @return Element */ protected function getElement() { @@ -126,14 +125,10 @@ protected function endElementP(): void */ protected function writeCommentRangeStart(): void { - if ($this->element->getCommentRangeStart() != null) { - $comment = $this->element->getCommentRangeStart(); - //only set the ID if it is not yet set, otherwise it will overwrite it - if ($comment->getElementId() == null) { - $comment->setElementId(); + if ($this->element->getCommentsRangeStart() != null) { + foreach ($this->element->getCommentsRangeStart()->getItems() as $comment) { + $this->xmlWriter->writeElementBlock('w:commentRangeStart', ['w:id' => $comment->getElementId()]); } - - $this->xmlWriter->writeElementBlock('w:commentRangeStart', ['w:id' => $comment->getElementId()]); } } @@ -142,28 +137,23 @@ protected function writeCommentRangeStart(): void */ protected function writeCommentRangeEnd(): void { - if ($this->element->getCommentRangeEnd() != null) { - $comment = $this->element->getCommentRangeEnd(); - //only set the ID if it is not yet set, otherwise it will overwrite it, this should normally not happen - if ($comment->getElementId() == null) { - $comment->setElementId(); // @codeCoverageIgnore - } // @codeCoverageIgnore - - $this->xmlWriter->writeElementBlock('w:commentRangeEnd', ['w:id' => $comment->getElementId()]); - $this->xmlWriter->startElement('w:r'); - $this->xmlWriter->writeElementBlock('w:commentReference', ['w:id' => $comment->getElementId()]); - $this->xmlWriter->endElement(); - } elseif ($this->element->getCommentRangeStart() != null && $this->element->getCommentRangeStart()->getEndElement() == null) { - $comment = $this->element->getCommentRangeStart(); - //only set the ID if it is not yet set, otherwise it will overwrite it, this should normally not happen - if ($comment->getElementId() == null) { - $comment->setElementId(); // @codeCoverageIgnore - } // @codeCoverageIgnore - - $this->xmlWriter->writeElementBlock('w:commentRangeEnd', ['w:id' => $comment->getElementId()]); - $this->xmlWriter->startElement('w:r'); - $this->xmlWriter->writeElementBlock('w:commentReference', ['w:id' => $comment->getElementId()]); - $this->xmlWriter->endElement(); + if ($this->element->getCommentsRangeEnd() != null) { + foreach ($this->element->getCommentsRangeEnd()->getItems() as $comment) { + $this->xmlWriter->writeElementBlock('w:commentRangeEnd', ['w:id' => $comment->getElementId()]); + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->writeElementBlock('w:commentReference', ['w:id' => $comment->getElementId()]); + $this->xmlWriter->endElement(); + } + } + if ($this->element->getCommentsRangeStart() != null) { + foreach ($this->element->getCommentsRangeStart()->getItems() as $comment) { + if ($comment->getEndElement() == null) { + $this->xmlWriter->writeElementBlock('w:commentRangeEnd', ['w:id' => $comment->getElementId()]); + $this->xmlWriter->startElement('w:r'); + $this->xmlWriter->writeElementBlock('w:commentReference', ['w:id' => $comment->getElementId()]); + $this->xmlWriter->endElement(); + } + } } } diff --git a/src/PhpWord/Writer/Word2007/Element/Bookmark.php b/src/PhpWord/Writer/Word2007/Element/Bookmark.php index 1e618af987..ba61ad69fd 100644 --- a/src/PhpWord/Writer/Word2007/Element/Bookmark.php +++ b/src/PhpWord/Writer/Word2007/Element/Bookmark.php @@ -1,4 +1,5 @@ + */ + protected $containerWithoutP = ['TextRun', 'Footnote', 'Endnote', 'ListItemRun']; + /** * Write element. */ @@ -46,7 +52,7 @@ public function write(): void return; } $containerClass = substr(get_class($container), strrpos(get_class($container), '\\') + 1); - $withoutP = in_array($containerClass, ['TextRun', 'Footnote', 'Endnote', 'ListItemRun']); + $withoutP = in_array($containerClass, $this->containerWithoutP); $xmlWriter = $this->getXmlWriter(); // Loop through elements @@ -62,7 +68,7 @@ public function write(): void $writeLastTextBreak = ($containerClass == 'Cell') && ($elementClass == '' || $elementClass == 'Table'); if ($writeLastTextBreak) { $writerClass = $this->namespace . '\\TextBreak'; - /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $writer Type hint */ + /** @var AbstractElement $writer Type hint */ $writer = new $writerClass($xmlWriter, new TextBreakElement(), $withoutP); $writer->write(); } @@ -70,18 +76,14 @@ public function write(): void /** * Write individual element. - * - * @param bool $withoutP - * - * @return string */ - private function writeElement(XMLWriter $xmlWriter, Element $element, $withoutP) + private function writeElement(XMLWriter $xmlWriter, Element $element, bool $withoutP): string { $elementClass = substr(get_class($element), strrpos(get_class($element), '\\') + 1); $writerClass = $this->namespace . '\\' . $elementClass; if (class_exists($writerClass)) { - /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $writer Type hint */ + /** @var AbstractElement $writer Type hint */ $writer = new $writerClass($xmlWriter, $element, $withoutP); $writer->setPart($this->getPart()); $writer->write(); diff --git a/src/PhpWord/Writer/Word2007/Element/Endnote.php b/src/PhpWord/Writer/Word2007/Element/Endnote.php index f96ac7977f..6a00ed5b3b 100644 --- a/src/PhpWord/Writer/Word2007/Element/Endnote.php +++ b/src/PhpWord/Writer/Word2007/Element/Endnote.php @@ -1,4 +1,5 @@ getElement(); - if (!$element instanceof \PhpOffice\PhpWord\Element\Field) { + if (!$element instanceof ElementField) { return; } @@ -42,7 +46,7 @@ public function write(): void } } - private function writeDefault(\PhpOffice\PhpWord\Element\Field $element): void + private function writeDefault(ElementField $element): void { $xmlWriter = $this->getXmlWriter(); $this->startElementP(); @@ -73,7 +77,7 @@ private function writeDefault(\PhpOffice\PhpWord\Element\Field $element): void $xmlWriter->endElement(); // w:r if ($element->getText() != null) { - if ($element->getText() instanceof \PhpOffice\PhpWord\Element\TextRun) { + if ($element->getText() instanceof TextRun) { $containerWriter = new Container($xmlWriter, $element->getText(), true); $containerWriter->write(); @@ -120,7 +124,7 @@ private function writeDefault(\PhpOffice\PhpWord\Element\Field $element): void * * //TODO A lot of code duplication with general method, should maybe be refactored */ - protected function writeMacrobutton(\PhpOffice\PhpWord\Element\Field $element): void + protected function writeMacrobutton(ElementField $element): void { $xmlWriter = $this->getXmlWriter(); $this->startElementP(); @@ -144,7 +148,7 @@ protected function writeMacrobutton(\PhpOffice\PhpWord\Element\Field $element): $xmlWriter->endElement(); // w:r if ($element->getText() != null) { - if ($element->getText() instanceof \PhpOffice\PhpWord\Element\TextRun) { + if ($element->getText() instanceof TextRun) { $containerWriter = new Container($xmlWriter, $element->getText(), true); $containerWriter->write(); } @@ -159,7 +163,7 @@ protected function writeMacrobutton(\PhpOffice\PhpWord\Element\Field $element): $this->endElementP(); // w:p } - private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $element) + private function buildPropertiesAndOptions(ElementField $element) { $propertiesAndOptions = ''; $properties = $element->getProperties(); @@ -226,4 +230,104 @@ private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $ele return $propertiesAndOptions; } + + /** + * Writes a REF field. + */ + protected function writeRef(ElementField $element): void + { + $xmlWriter = $this->getXmlWriter(); + $this->startElementP(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $xmlWriter->endElement(); // w:fldChar + $xmlWriter->endElement(); // w:r + + $instruction = ' ' . $element->getType() . ' '; + + foreach ($element->getProperties() as $property) { + $instruction .= $property . ' '; + } + foreach ($element->getOptions() as $optionKey => $optionValue) { + $instruction .= $this->convertRefOption($optionKey, $optionValue) . ' '; + } + + $xmlWriter->startElement('w:r'); + $this->writeFontStyle(); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->text($instruction); + $xmlWriter->endElement(); // w:instrText + $xmlWriter->endElement(); // w:r + + if ($element->getText() != null) { + if ($element->getText() instanceof TextRun) { + $containerWriter = new Container($xmlWriter, $element->getText(), true); + $containerWriter->write(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->text('"' . $this->buildPropertiesAndOptions($element)); + $xmlWriter->endElement(); // w:instrText + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->text(' '); + $xmlWriter->endElement(); // w:instrText + $xmlWriter->endElement(); // w:r + } + } + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'separate'); + $xmlWriter->endElement(); // w:fldChar + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:rPr'); + $xmlWriter->startElement('w:noProof'); + $xmlWriter->endElement(); // w:noProof + $xmlWriter->endElement(); // w:rPr + $xmlWriter->writeElement('w:t', $element->getText() != null && is_string($element->getText()) ? $element->getText() : '1'); + $xmlWriter->endElement(); // w:r + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'end'); + $xmlWriter->endElement(); // w:fldChar + $xmlWriter->endElement(); // w:r + + $this->endElementP(); // w:p + } + + private function convertRefOption(string $optionKey, string $optionValue): string + { + if ($optionKey === 'NumberSeperatorSequence') { + return '\\d ' . $optionValue; + } + + switch ($optionValue) { + case 'IncrementAndInsertText': + return '\\f'; + case 'CreateHyperLink': + return '\\h'; + case 'NoTrailingPeriod': + return '\\n'; + case 'IncludeAboveOrBelow': + return '\\p'; + case 'InsertParagraphNumberRelativeContext': + return '\\r'; + case 'SuppressNonDelimiterNonNumericalText': + return '\\t'; + case 'InsertParagraphNumberFullContext': + return '\\w'; + default: + return ''; + } + } } diff --git a/src/PhpWord/Writer/Word2007/Element/Footnote.php b/src/PhpWord/Writer/Word2007/Element/Footnote.php index b59fc5e1cc..68f998e390 100644 --- a/src/PhpWord/Writer/Word2007/Element/Footnote.php +++ b/src/PhpWord/Writer/Word2007/Element/Footnote.php @@ -1,4 +1,5 @@ endElement(); // w:rStyle $xmlWriter->endElement(); // w:rPr $xmlWriter->startElement("w:{$this->referenceType}"); - $xmlWriter->writeAttribute('w:id', $element->getRelationId()); + $xmlWriter->writeAttribute('w:id', $element->getRelationId() + 1); $xmlWriter->endElement(); // w:$referenceType $xmlWriter->endElement(); // w:r diff --git a/src/PhpWord/Writer/Word2007/Element/FormField.php b/src/PhpWord/Writer/Word2007/Element/FormField.php index 5bfc8cab45..c5d59a4497 100644 --- a/src/PhpWord/Writer/Word2007/Element/FormField.php +++ b/src/PhpWord/Writer/Word2007/Element/FormField.php @@ -1,4 +1,5 @@ getCells() as $cell) { - $this->writeCell($xmlWriter, $cell); + $cells = $row->getCells(); + if (count($cells) === 0) { + // issue 2505 - Word treats doc as corrupt if row without cell + $this->writeCell($xmlWriter, new CellElement()); + } else { + foreach ($cells as $cell) { + $this->writeCell($xmlWriter, $cell); + } } $xmlWriter->endElement(); // w:tr diff --git a/src/PhpWord/Writer/Word2007/Element/TableAlignment.php b/src/PhpWord/Writer/Word2007/Element/TableAlignment.php index c8b48644da..9c0977b8fd 100644 --- a/src/PhpWord/Writer/Word2007/Element/TableAlignment.php +++ b/src/PhpWord/Writer/Word2007/Element/TableAlignment.php @@ -1,4 +1,5 @@ startElement($this->elementNode); - $xmlWriter->writeAttribute('w:id', $element->getRelationId()); + $xmlWriter->writeAttribute('w:id', $element->getRelationId() + 1); $xmlWriter->startElement('w:p'); // Paragraph style diff --git a/src/PhpWord/Writer/Word2007/Part/Header.php b/src/PhpWord/Writer/Word2007/Part/Header.php index 36abd06040..1fafc79129 100644 --- a/src/PhpWord/Writer/Word2007/Part/Header.php +++ b/src/PhpWord/Writer/Word2007/Part/Header.php @@ -1,4 +1,5 @@ getSalt() == null) { - $documentProtection->setSalt(openssl_random_pseudo_bytes(16)); + $documentProtection->setSalt((string) openssl_random_pseudo_bytes(16)); } $passwordHash = PasswordEncoder::hashPassword($documentProtection->getPassword(), $documentProtection->getAlgorithm(), $documentProtection->getSalt(), $documentProtection->getSpinCount()); $this->settings['w:documentProtection'] = [ diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index 2112fd3ce6..bda1e653b7 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -1,4 +1,5 @@ getParagraph() != null) { + if ($normalStyle instanceof FontStyle && $normalStyle->getParagraph() != null) { $styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle->getParagraph()); $styleWriter->write(); } elseif ($normalStyle instanceof ParagraphStyle) { diff --git a/src/PhpWord/Writer/Word2007/Part/Theme.php b/src/PhpWord/Writer/Word2007/Part/Theme.php index ad57d66493..a70c248da6 100644 --- a/src/PhpWord/Writer/Word2007/Part/Theme.php +++ b/src/PhpWord/Writer/Word2007/Part/Theme.php @@ -1,4 +1,5 @@ write(); } diff --git a/src/PhpWord/Writer/Word2007/Style/Cell.php b/src/PhpWord/Writer/Word2007/Style/Cell.php index 6e22597dd3..ea6fba6d7c 100644 --- a/src/PhpWord/Writer/Word2007/Style/Cell.php +++ b/src/PhpWord/Writer/Word2007/Style/Cell.php @@ -1,4 +1,5 @@ writeElementIf($style->isItalic() !== null, 'w:iCs', 'w:val', $this->writeOnOf($style->isItalic())); // Strikethrough, double strikethrough - $xmlWriter->writeElementIf($style->isStrikethrough() !== null, 'w:strike', 'w:val', $this->writeOnOf($style->isStrikethrough())); - $xmlWriter->writeElementIf($style->isDoubleStrikethrough() !== null, 'w:dstrike', 'w:val', $this->writeOnOf($style->isDoubleStrikethrough())); + $xmlWriter->writeElementIf($style->isStrikethrough(), 'w:strike', 'w:val', $this->writeOnOf($style->isStrikethrough())); + $xmlWriter->writeElementIf($style->isDoubleStrikethrough(), 'w:dstrike', 'w:val', $this->writeOnOf($style->isDoubleStrikethrough())); // Small caps, all caps $xmlWriter->writeElementIf($style->isSmallCaps() !== null, 'w:smallCaps', 'w:val', $this->writeOnOf($style->isSmallCaps())); diff --git a/src/PhpWord/Writer/Word2007/Style/Frame.php b/src/PhpWord/Writer/Word2007/Style/Frame.php index 0ba52ec5ab..a7aab43e61 100644 --- a/src/PhpWord/Writer/Word2007/Style/Frame.php +++ b/src/PhpWord/Writer/Word2007/Style/Frame.php @@ -1,4 +1,5 @@ $value */ public function setColors($value): void { diff --git a/src/PhpWord/Writer/Word2007/Style/Outline.php b/src/PhpWord/Writer/Word2007/Style/Outline.php index 63ea6dee78..45f37cc61e 100644 --- a/src/PhpWord/Writer/Word2007/Style/Outline.php +++ b/src/PhpWord/Writer/Word2007/Style/Outline.php @@ -1,4 +1,5 @@ startElement('w:numPr'); diff --git a/src/PhpWord/Writer/Word2007/Style/Row.php b/src/PhpWord/Writer/Word2007/Style/Row.php index 7e1468e87b..2b9d804f39 100644 --- a/src/PhpWord/Writer/Word2007/Style/Row.php +++ b/src/PhpWord/Writer/Word2007/Style/Row.php @@ -1,4 +1,5 @@ getEndElement()); } + /** + * Two comments on same text. + */ + public function testTwoCommentsOnSameText(): void + { + $section = new Section(0); + $text = $section->addText('Text'); + + $comment1 = new Comment('Author1', new DateTime(), 'A1'); + $comment1->addText('Comment1'); + + $comment2 = new Comment('Author2', new DateTime(), 'A2'); + $comment2->addText('Comment2'); + + $comment1->setStartElement($text); + $comment2->setStartElement($text); + + $text->setCommentRangeStart($comment1); + $text->setCommentRangeEnd($comment1); + + $text->setCommentRangeStart($comment2); + $text->setCommentRangeEnd($comment2); + + self::assertEquals(2, $text->getCommentsRangeStart()->countItems()); + self::assertEquals(2, $text->getCommentsRangeEnd()->countItems()); + + self::assertEquals($text->getCommentsRangeStart()->getItem(0)->getElementId(), $comment1->getElementId()); + self::assertEquals($text->getCommentsRangeEnd()->getItem(0)->getElementId(), $comment1->getElementId()); + + self::assertEquals($text->getCommentsRangeStart()->getItem(1)->getElementId(), $comment2->getElementId()); + self::assertEquals($text->getCommentsRangeEnd()->getItem(1)->getElementId(), $comment2->getElementId()); + } + /** * Add text. */ diff --git a/tests/PhpWordTests/Element/FieldTest.php b/tests/PhpWordTests/Element/FieldTest.php index 06f7c6841b..f3accf8789 100644 --- a/tests/PhpWordTests/Element/FieldTest.php +++ b/tests/PhpWordTests/Element/FieldTest.php @@ -1,4 +1,5 @@ getSource()); - self::assertEquals(md5($source), $image->getMediaId()); + self::assertEquals(md5((string) $source), $image->getMediaId()); self::assertEquals('image/jpeg', $image->getImageType()); self::assertEquals('jpg', $image->getImageExtension()); self::assertEquals('imagecreatefromstring', $image->getImageCreateFunction()); diff --git a/tests/PhpWordTests/Element/LineTest.php b/tests/PhpWordTests/Element/LineTest.php index 101c7309fb..98298fc76c 100644 --- a/tests/PhpWordTests/Element/LineTest.php +++ b/tests/PhpWordTests/Element/LineTest.php @@ -1,4 +1,5 @@ expectException(\PhpOffice\PhpWord\Exception\CopyFileException::class); + $this->expectException(CopyFileException::class); throw new CopyFileException('C:\source\dummy.txt', 'C:\destination\dummy.txt'); } diff --git a/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php b/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php index 834a1c09fc..dd8f395318 100644 --- a/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php +++ b/tests/PhpWordTests/Exception/CreateTemporaryFileExceptionTest.php @@ -1,4 +1,5 @@ expectException(\PhpOffice\PhpWord\Exception\CreateTemporaryFileException::class); + $this->expectException(CreateTemporaryFileException::class); throw new CreateTemporaryFileException(); } diff --git a/tests/PhpWordTests/Exception/ExceptionTest.php b/tests/PhpWordTests/Exception/ExceptionTest.php index e186e94fad..09ee933c86 100644 --- a/tests/PhpWordTests/Exception/ExceptionTest.php +++ b/tests/PhpWordTests/Exception/ExceptionTest.php @@ -1,4 +1,5 @@ expectException(\PhpOffice\PhpWord\Exception\InvalidImageException::class); + $this->expectException(InvalidImageException::class); throw new InvalidImageException(); } diff --git a/tests/PhpWordTests/Exception/InvalidStyleExceptionTest.php b/tests/PhpWordTests/Exception/InvalidStyleExceptionTest.php index d1da3b2a85..7f2a1650e4 100644 --- a/tests/PhpWordTests/Exception/InvalidStyleExceptionTest.php +++ b/tests/PhpWordTests/Exception/InvalidStyleExceptionTest.php @@ -1,4 +1,5 @@ expectException(\PhpOffice\PhpWord\Exception\InvalidStyleException::class); + $this->expectException(InvalidStyleException::class); throw new InvalidStyleException(); } diff --git a/tests/PhpWordTests/Exception/UnsupportedImageTypeExceptionTest.php b/tests/PhpWordTests/Exception/UnsupportedImageTypeExceptionTest.php index e978b97254..2252b874ef 100644 --- a/tests/PhpWordTests/Exception/UnsupportedImageTypeExceptionTest.php +++ b/tests/PhpWordTests/Exception/UnsupportedImageTypeExceptionTest.php @@ -1,4 +1,5 @@ expectException(\PhpOffice\PhpWord\Exception\UnsupportedImageTypeException::class); + $this->expectException(UnsupportedImageTypeException::class); throw new UnsupportedImageTypeException(); } diff --git a/tests/PhpWordTests/IOFactoryTest.php b/tests/PhpWordTests/IOFactoryTest.php index 79f0fd0c76..6a8d746bd0 100644 --- a/tests/PhpWordTests/IOFactoryTest.php +++ b/tests/PhpWordTests/IOFactoryTest.php @@ -1,4 +1,5 @@ canRead($filename)); } - /** - * Load. - */ - public function testLoad(): void + public function testLoadBasic(): void { $filename = __DIR__ . '/../_files/documents/reader.doc'; $phpWord = IOFactory::load($filename, 'MsDoc'); - self::assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $elements = $sections[0]->getElements(); + self::assertArrayHasKey(0, $elements); + /** @var Text $element0 */ + $element0 = $elements[0]; + self::assertInstanceOf(Text::class, $element0); + self::assertEquals('Welcome to PhpWord', $element0->getText()); } public function testLoadHalfPointFont(): void @@ -76,6 +85,54 @@ public function testLoadHalfPointFont(): void } } + public function testLoadChinese(): void + { + $filename = __DIR__ . '/../_files/documents/docChinese.doc'; + $phpWord = IOFactory::load($filename, 'MsDoc'); + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $elements = $sections[0]->getElements(); + self::assertArrayHasKey(0, $elements); + /** @var Text $element0 */ + $element0 = $elements[0]; + self::assertInstanceOf(Text::class, $element0); + self::assertEquals('OKKI AI 客户案例', $element0->getText()); + } + + public function testLoadCzech(): void + { + $filename = __DIR__ . '/../_files/documents/docCzech.doc'; + $phpWord = IOFactory::load($filename, 'MsDoc'); + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $elements = $sections[0]->getElements(); + self::assertArrayHasKey(0, $elements); + /** @var Text $element0 */ + $element0 = $elements[0]; + self::assertInstanceOf(Text::class, $element0); + self::assertEquals('Příliš žluťoučký kůň pěl ďábelské ódy', $element0->getText()); + } + + public function testLoadSlovak(): void + { + $filename = __DIR__ . '/../_files/documents/docSlovak.doc'; + $phpWord = IOFactory::load($filename, 'MsDoc'); + self::assertInstanceOf(PhpWord::class, $phpWord); + + $sections = $phpWord->getSections(); + self::assertCount(1, $sections); + $elements = $sections[0]->getElements(); + self::assertArrayHasKey(0, $elements); + /** @var Text $element0 */ + $element0 = $elements[0]; + self::assertInstanceOf(Text::class, $element0); + self::assertEquals('Pondelok', $element0->getText()); + } + /** * Test exception on not existing file. */ diff --git a/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php b/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php index 0a1a4512db..8567dbcbea 100644 --- a/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php +++ b/tests/PhpWordTests/Reader/ODText/ODTextSectionTest.php @@ -1,4 +1,5 @@ getElement(1)->getText()); self::assertNotNull($textRun->getElement(1)->getTrackChange()); - /** @var \PhpOffice\PhpWord\Element\TrackChange $trackChange */ + /** @var TrackChange $trackChange */ $trackChange = $textRun->getElement(1)->getTrackChange(); self::assertEquals(TrackChange::DELETED, $trackChange->getChangeType()); self::assertEquals('three', $textRun->getElement(2)->getText()); self::assertNotNull($textRun->getElement(2)->getTrackChange()); - /** @var \PhpOffice\PhpWord\Element\TrackChange $trackChange */ + /** @var TrackChange $trackChange */ $trackChange = $textRun->getElement(2)->getTrackChange(); self::assertEquals(TrackChange::INSERTED, $trackChange->getChangeType()); } @@ -355,4 +356,192 @@ public function testReadDrawing(): void $elements = $phpWord->getSection(0)->getElements(); self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); } + + /** + * Test reading FormField - DROPDOWN. + */ + public function testReadFormFieldDropdown(): void + { + $documentXml = ' + + Reference + + + + + + + + + + + + + + + + + + + + FORMDROPDOWN + + + + + + + + + + + + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + + $subElements = $elements[0]->getElements(); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $subElements[0]); + self::assertEquals('Reference', $subElements[0]->getText()); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\FormField', $subElements[1]); + self::assertEquals('dropdown', $subElements[1]->getType()); + self::assertEquals('DropDownList1', $subElements[1]->getName()); + self::assertEquals('2', $subElements[1]->getValue()); + self::assertEquals('Option Two', $subElements[1]->getText()); + self::assertEquals(['TBD', 'Option One', 'Option Two', 'Option Three', 'Other'], $subElements[1]->getEntries()); + } + + /** + * Test reading FormField - textinput. + */ + public function testReadFormFieldTextinput(): void + { + $documentXml = ' + + Fieldname + + + + + + + + + + + + + + + + FORMTEXT + + + + + + + + + + + + + + + + + + This is some sample text + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + + $subElements = $elements[0]->getElements(); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $subElements[0]); + self::assertEquals('Fieldname', $subElements[0]->getText()); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\FormField', $subElements[1]); + self::assertEquals('textinput', $subElements[1]->getType()); + self::assertEquals('TextInput2', $subElements[1]->getName()); + self::assertEquals('This is some sample text', $subElements[1]->getValue()); + self::assertEquals('This is some sample text', $subElements[1]->getText()); + } + + /** + * Test reading FormField - checkbox. + */ + public function testReadFormFieldCheckbox(): void + { + $documentXml = ' + + + + + + + + + + + + + + + + + + FORMCHECKBOX + + + + + + + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + + $subElements = $elements[0]->getElements(); + +// $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $subElements[0]); +// $this->assertEquals('Fieldname', $subElements[0]->getText()); + + self::assertInstanceOf('PhpOffice\PhpWord\Element\FormField', $subElements[0]); + self::assertEquals('checkbox', $subElements[0]->getType()); + self::assertEquals('SomeCheckbox', $subElements[0]->getName()); + } } diff --git a/tests/PhpWordTests/Reader/Word2007/PartTest.php b/tests/PhpWordTests/Reader/Word2007/PartTest.php index 46089e8f02..4f19f8b91f 100644 --- a/tests/PhpWordTests/Reader/Word2007/PartTest.php +++ b/tests/PhpWordTests/Reader/Word2007/PartTest.php @@ -1,4 +1,5 @@ getStyle()); self::assertNotNull($elements[0]->getStyle()->getPosition()); self::assertInstanceOf('PhpOffice\PhpWord\Style\TablePosition', $elements[0]->getStyle()->getPosition()); - /** @var \PhpOffice\PhpWord\Style\TablePosition $tableStyle */ + /** @var TablePosition $tableStyle */ $tableStyle = $elements[0]->getStyle()->getPosition(); self::assertEquals(10, $tableStyle->getLeftFromText()); self::assertEquals(20, $tableStyle->getRightFromText()); @@ -118,7 +119,7 @@ public function testReadTableCellSpacing(): void $elements = $phpWord->getSection(0)->getElements(); self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); - /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + /** @var Table $tableStyle */ $tableStyle = $elements[0]->getStyle(); self::assertEquals(TblWidth::AUTO, $tableStyle->getUnit()); self::assertEquals(10.5, $tableStyle->getCellSpacing()); @@ -165,6 +166,44 @@ public function testReadTableCellStyle(): void self::assertEquals('auto', $styleCell->getBorderBottomColor()); } + public function testReadTableCellsWithVerticalMerge(): void + { + $documentXml = ' + + + + + + + + + + + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $table = $phpWord->getSection(0)->getElements()[0]; + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $table); + + $rows = $table->getRows(); + self::assertCount(3, $rows); + foreach ($rows as $row) { + self::assertCount(1, $row->getCells()); + } + + self::assertSame('restart', $rows[0]->getCells()[0]->getStyle()->getVMerge()); + self::assertSame('continue', $rows[1]->getCells()[0]->getStyle()->getVMerge()); + self::assertNull($rows[2]->getCells()[0]->getStyle()->getVMerge()); + } + /** * Test reading of position. */ @@ -187,7 +226,7 @@ public function testReadPosition(): void self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $textRun); self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); self::assertInstanceOf('PhpOffice\PhpWord\Style\Font', $textRun->getElement(0)->getFontStyle()); - /** @var \PhpOffice\PhpWord\Style\Font $fontStyle */ + /** @var Style\Font $fontStyle */ $fontStyle = $textRun->getElement(0)->getFontStyle(); self::assertEquals(15, $fontStyle->getPosition()); } @@ -205,7 +244,7 @@ public function testReadIndent(): void $elements = $phpWord->getSection(0)->getElements(); self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); - /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + /** @var Table $tableStyle */ $tableStyle = $elements[0]->getStyle(); self::assertSame(TblWidth::TWIP, $tableStyle->getIndent()->getType()); self::assertSame(2160, $tableStyle->getIndent()->getValue()); @@ -224,7 +263,7 @@ public function testReadTableRTL(): void $elements = $phpWord->getSection(0)->getElements(); self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); - /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + /** @var Table $tableStyle */ $tableStyle = $elements[0]->getStyle(); self::assertTrue($tableStyle->isBidiVisual()); } @@ -248,7 +287,7 @@ public function testReadHidden(): void self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $textRun); self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); self::assertInstanceOf('PhpOffice\PhpWord\Style\Font', $textRun->getElement(0)->getFontStyle()); - /** @var \PhpOffice\PhpWord\Style\Font $fontStyle */ + /** @var Style\Font $fontStyle */ $fontStyle = $textRun->getElement(0)->getFontStyle(); self::assertTrue($fontStyle->isHidden()); } diff --git a/tests/PhpWordTests/Reader/Word2007Test.php b/tests/PhpWordTests/Reader/Word2007Test.php index fac5b6b59a..65c8a4a71b 100644 --- a/tests/PhpWordTests/Reader/Word2007Test.php +++ b/tests/PhpWordTests/Reader/Word2007Test.php @@ -1,4 +1,5 @@ getElementAttribute('/w:document/w:body/w:p/w:r[w:t/node()="italics"]/w:rPr/w:b', 'w:val')); } + public function testLoadStyles(): void + { + $phpWord = IOFactory::load(dirname(__DIR__, 1) . '/_files/documents/reader-styles.docx', 'Word2007'); + + self::assertInstanceOf(PhpWord::class, $phpWord); + + $section2 = $phpWord->getSection(2); + self::assertInstanceOf(Section::class, $section2); + + $element2e31 = $section2->getElement(31); + self::assertInstanceOf(TextRun::class, $element2e31); + self::assertEquals('This is a paragraph with border differents', $element2e31->getText()); + + /** @var Paragraph $element2e31pStyle */ + $element2e31pStyle = $element2e31->getParagraphStyle(); + self::assertInstanceOf(Paragraph::class, $element2e31pStyle); + + // Top + self::assertEquals('FFFF00', $element2e31pStyle->getBorderTopColor()); + self::assertEquals('10', $element2e31pStyle->getBorderTopSize()); + self::assertEquals('dotted', $element2e31pStyle->getBorderTopStyle()); + // Right + self::assertEquals('00A933', $element2e31pStyle->getBorderRightColor()); + self::assertEquals('4', $element2e31pStyle->getBorderRightSize()); + self::assertEquals('dashed', $element2e31pStyle->getBorderRightStyle()); + // Bottom + self::assertEquals('F10D0C', $element2e31pStyle->getBorderBottomColor()); + self::assertEquals('8', $element2e31pStyle->getBorderBottomSize()); + self::assertEquals('dashSmallGap', $element2e31pStyle->getBorderBottomStyle()); + // Left + self::assertEquals('3465A4', $element2e31pStyle->getBorderLeftColor()); + self::assertEquals('8', $element2e31pStyle->getBorderLeftSize()); + self::assertEquals('dashed', $element2e31pStyle->getBorderLeftStyle()); + } + /** * Load a Word 2011 file. */ @@ -126,7 +163,7 @@ public function testLoadWord2011SettingsImageLoading(bool $hasImageLoading): voi } } - public function providerSettingsImageLoading(): iterable + public static function providerSettingsImageLoading(): iterable { return [ [true], diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index 46c72eab28..67099650aa 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -1,4 +1,5 @@ getElementAttribute($baseXpath . '[2]/w:pict/v:shape', 'style')); } + /** + * Test parsing of img. + */ + public function testParseImageSizeInPixels(): void + { + $src = __DIR__ . '/../_files/images/firefox.png'; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $html = '

'; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + self::assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + self::assertStringMatchesFormat('%Swidth:150px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + self::assertStringMatchesFormat('%Sheight:200px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + } + + /** + * Test parsing of img. + */ + public function testParseImageSizeInPoints(): void + { + $src = __DIR__ . '/../_files/images/firefox.png'; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $html = '

'; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + self::assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + self::assertStringMatchesFormat('%Swidth:200px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + self::assertStringMatchesFormat('%Sheight:266.66666666667%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + } + + /** + * Test parsing of img. + */ + public function testParseImageSizeWithoutUnits(): void + { + $src = __DIR__ . '/../_files/images/firefox.png'; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $html = '

'; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + self::assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + self::assertStringMatchesFormat('%Swidth:150px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + self::assertStringMatchesFormat('%Sheight:200px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + } + /** * Test parsing of remote img. */ @@ -924,6 +985,27 @@ public function testParseLink2(): void self::assertEquals('bookmark', $doc->getElement('/w:document/w:body/w:p/w:hyperlink')->getAttribute('w:anchor')); } + public function testParseLinkAllowsAbsenceOfHref(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $html = '

text of href-less link

'; + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); + self::assertEquals('text of href-less link', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $html = '

text of empty-href link

'; + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); + self::assertEquals('text of empty-href link', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); + } + public function testParseMalformedStyleIsIgnored(): void { $phpWord = new PhpWord(); diff --git a/tests/PhpWordTests/Shared/Microsoft/PasswordEncoderTest.php b/tests/PhpWordTests/Shared/Microsoft/PasswordEncoderTest.php index 9389c97411..d3c13bf8b4 100644 --- a/tests/PhpWordTests/Shared/Microsoft/PasswordEncoderTest.php +++ b/tests/PhpWordTests/Shared/Microsoft/PasswordEncoderTest.php @@ -1,4 +1,5 @@ getDomFromZip($archiveFile, 'test.xml'); } + /** + * Test that read from invalid archive throws exception. + */ + public function testThrowsExceptionOnZipArchiveOpenErrors(): void + { + /** + * @var string + */ + $tempPath = tempnam(sys_get_temp_dir(), 'PhpWord'); + + // Simulate a corrupt archive + file_put_contents($tempPath, mt_rand()); + + $exceptionMessage = null; + + try { + $reader = new XMLReader(); + $reader->getDomFromZip($tempPath, 'test.xml'); + } catch (Exception $e) { + $exceptionMessage = $e->getMessage(); + } + + self::assertNotNull($exceptionMessage); + + unlink($tempPath); + } + /** * Test elements count. */ diff --git a/tests/PhpWordTests/Shared/XMLWriterTest.php b/tests/PhpWordTests/Shared/XMLWriterTest.php index ccb07c1a3d..476b8b3ba9 100644 --- a/tests/PhpWordTests/Shared/XMLWriterTest.php +++ b/tests/PhpWordTests/Shared/XMLWriterTest.php @@ -1,4 +1,5 @@ */ public function testZipArchive($zipClass = 'ZipArchive'): void { @@ -107,8 +106,6 @@ public function testZipArchive($zipClass = 'ZipArchive'): void /** * Test PclZip. - * - * @covers :: */ public function testPCLZip(): void { diff --git a/tests/PhpWordTests/Style/AbstractStyleTest.php b/tests/PhpWordTests/Style/AbstractStyleTest.php index 47c265738a..2f1585fd5a 100644 --- a/tests/PhpWordTests/Style/AbstractStyleTest.php +++ b/tests/PhpWordTests/Style/AbstractStyleTest.php @@ -1,4 +1,5 @@ 240, 'marginLeft' => 240, 'position' => 10, - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, - 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, - 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_IMARGIN, + 'positioning' => Image::POSITION_ABSOLUTE, + 'posHorizontal' => Image::POSITION_HORIZONTAL_CENTER, + 'posVertical' => Image::POSITION_VERTICAL_TOP, + 'posHorizontalRel' => Image::POSITION_RELATIVE_TO_COLUMN, + 'posVerticalRel' => Image::POSITION_RELATIVE_TO_IMARGIN, 'wrapDistanceLeft' => 10, 'wrapDistanceRight' => 20, 'wrapDistanceTop' => 30, diff --git a/tests/PhpWordTests/Style/IndentationTest.php b/tests/PhpWordTests/Style/IndentationTest.php index 4de664477a..db13407ff3 100644 --- a/tests/PhpWordTests/Style/IndentationTest.php +++ b/tests/PhpWordTests/Style/IndentationTest.php @@ -1,4 +1,5 @@ \PhpOffice\PhpWord\Style\Line::CONNECTOR_TYPE_STRAIGHT, - 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, - 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, - 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, + 'connectorType' => Line::CONNECTOR_TYPE_STRAIGHT, + 'beginArrow' => Line::ARROW_STYLE_BLOCK, + 'endArrow' => Line::ARROW_STYLE_OVAL, + 'dash' => Line::DASH_STYLE_LONG_DASH_DOT_DOT, 'weight' => 10, 'color' => 'red', ]; @@ -59,10 +60,10 @@ public function testSetStyleValue(): void $object = new Line(); $properties = [ - 'connectorType' => \PhpOffice\PhpWord\Style\Line::CONNECTOR_TYPE_STRAIGHT, - 'beginArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK, - 'endArrow' => \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_OVAL, - 'dash' => \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT, + 'connectorType' => Line::CONNECTOR_TYPE_STRAIGHT, + 'beginArrow' => Line::ARROW_STYLE_BLOCK, + 'endArrow' => Line::ARROW_STYLE_OVAL, + 'dash' => Line::DASH_STYLE_LONG_DASH_DOT_DOT, 'weight' => 10, 'color' => 'red', ]; @@ -89,7 +90,7 @@ public function testSetGetFlip(): void */ public function testSetGetConnectorType(): void { - $expected = \PhpOffice\PhpWord\Style\Line::CONNECTOR_TYPE_STRAIGHT; + $expected = Line::CONNECTOR_TYPE_STRAIGHT; $object = new Line(); $object->setConnectorType($expected); self::assertEquals($expected, $object->getConnectorType()); @@ -122,7 +123,7 @@ public function testSetGetColor(): void */ public function testSetGetDash(): void { - $expected = \PhpOffice\PhpWord\Style\Line::DASH_STYLE_LONG_DASH_DOT_DOT; + $expected = Line::DASH_STYLE_LONG_DASH_DOT_DOT; $object = new Line(); $object->setDash($expected); self::assertEquals($expected, $object->getDash()); @@ -133,7 +134,7 @@ public function testSetGetDash(): void */ public function testSetGetBeginArrow(): void { - $expected = \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_BLOCK; + $expected = Line::ARROW_STYLE_BLOCK; $object = new Line(); $object->setBeginArrow($expected); self::assertEquals($expected, $object->getBeginArrow()); @@ -144,7 +145,7 @@ public function testSetGetBeginArrow(): void */ public function testSetGetEndArrow(): void { - $expected = \PhpOffice\PhpWord\Style\Line::ARROW_STYLE_CLASSIC; + $expected = Line::ARROW_STYLE_CLASSIC; $object = new Line(); $object->setEndArrow($expected); self::assertEquals($expected, $object->getEndArrow()); diff --git a/tests/PhpWordTests/Style/ListItemTest.php b/tests/PhpWordTests/Style/ListItemTest.php index bc1ad67014..59cdfeeda1 100644 --- a/tests/PhpWordTests/Style/ListItemTest.php +++ b/tests/PhpWordTests/Style/ListItemTest.php @@ -1,4 +1,5 @@ getTemplateProcessor(__DIR__ . '/_files/templates/blank.docx'); self::assertInstanceOf('PhpOffice\\PhpWord\\TemplateProcessor', $object); self::assertEquals([], $object->getVariables()); + $object->save(); + + try { + $object->zip()->close(); + self::fail('Expected exception for double close'); + } catch (Throwable $e) { + // nothing to do here + } } /** @@ -853,15 +864,15 @@ public function testSetImageValue(): void // dynamic generated doc $testFileName = 'images-test-sample.docx'; - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addText('${Test:width=100:ratio=true}'); - $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); + $objWriter = IOFactory::createWriter($phpWord, 'Word2007'); $objWriter->save($testFileName); self::assertFileExists($testFileName, "Generated file '{$testFileName}' not found!"); $resultFileName = 'images-test-result.docx'; - $templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($testFileName); + $templateProcessor = new TemplateProcessor($testFileName); unlink($testFileName); $templateProcessor->setImageValue('Test', $imagePath); $templateProcessor->setImageValue('Test1', $imagePath); @@ -1015,7 +1026,7 @@ public function testCloneBlockCanCloneABlockTwice(): void // and the placeholders have been replaced correctly $phpWord = IOFactory::load($templatePath); $sections = $phpWord->getSections(); - /** @var \PhpOffice\PhpWord\Element\TextRun[] $actualElements */ + /** @var TextRun[] $actualElements */ $actualElements = $sections[0]->getElements(); unlink($templatePath); $expectedElements = [ @@ -1069,7 +1080,7 @@ public function testCloneBlockCanCloneABlockTwiceWithCustomMacro(): void // and the placeholders have been replaced correctly $phpWord = IOFactory::load($templatePath); $sections = $phpWord->getSections(); - /** @var \PhpOffice\PhpWord\Element\TextRun[] $actualElements */ + /** @var TextRun[] $actualElements */ $actualElements = $sections[0]->getElements(); unlink($templatePath); diff --git a/tests/PhpWordTests/TestHelperDOCX.php b/tests/PhpWordTests/TestHelperDOCX.php index de9f1a81b7..2a6fbabae0 100644 --- a/tests/PhpWordTests/TestHelperDOCX.php +++ b/tests/PhpWordTests/TestHelperDOCX.php @@ -1,4 +1,5 @@ addSection(); + + $table = $section->addTable(); + $row = $table->addRow(); + + $cell = $row->addCell(); + $cell->addText('top text'); + $cell->getStyle()->setVAlign(VerticalJc::TOP); + + $cell = $row->addCell(); + $cell->addText('bottom text'); + $cell->getStyle()->setVAlign(VerticalJc::BOTTOM); + + $cell = $row->addCell(); + $cell->addText('no vAlign'); + $cell->getStyle()->setVAlign(VerticalJc::BOTTOM); + $cell->getStyle()->setVAlign(); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + $cell1Style = Helper::getTextContent($xpath, '//table/tr/td[1]', 'style'); + $cell2Style = Helper::getTextContent($xpath, '//table/tr/td[2]', 'style'); + self::assertSame('vertical-align: top;', $cell1Style); + self::assertSame('vertical-align: bottom;', $cell2Style); + + $cell3Query = $xpath->query('//table/tr/td[3]'); + self::assertNotFalse($cell3Query); + self::assertCount(1, $cell3Query); + + $cell3Style = $cell3Query->item(0)->attributes->getNamedItem('style'); + self::assertNull($cell3Style); + } + + public function testWriteTableCellVMerge(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $table = $section->addTable(); + + $cell = $table->addRow()->addCell(); + $cell->addText('text'); + $cell->getStyle()->setVMerge(Style\Cell::VMERGE_RESTART); + + $cell = $table->addRow()->addCell(); + $cell->getStyle()->setVMerge(Style\Cell::VMERGE_CONTINUE); + + $cell = $table->addRow()->addCell(); + $cell->addText('no vMerge'); + $cell->getStyle()->setVMerge(Style\Cell::VMERGE_CONTINUE); + $cell->getStyle()->setVMerge(); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + $cell1Style = Helper::getTextContent($xpath, '//table/tr[1]/td[1]', 'rowspan'); + self::assertSame('2', $cell1Style); + + $cell3Query = $xpath->query('//table/tr[3]/td[1]'); + self::assertNotFalse($cell3Query); + self::assertCount(1, $cell3Query); + self::assertNull($cell3Query->item(0)->attributes->getNamedItem('rowspan')); + } } diff --git a/tests/PhpWordTests/Writer/HTML/ElementTest.php b/tests/PhpWordTests/Writer/HTML/ElementTest.php index 64fa5a31ff..3b2580381f 100644 --- a/tests/PhpWordTests/Writer/HTML/ElementTest.php +++ b/tests/PhpWordTests/Writer/HTML/ElementTest.php @@ -1,4 +1,5 @@ addText('my other text'); $text2->setTrackChange(new TrackChange(TrackChange::DELETED, 'another author', new DateTime())); - $dom = $this->getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord); $xpath = new DOMXPath($dom); self::assertEquals(1, $xpath->query('/html/body/div/p[1]/ins')->length); @@ -97,7 +98,7 @@ public function testWriteColSpan(): void $cell22 = $row2->addCell(500); $cell22->addText('second cell'); - $dom = $this->getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord); $xpath = new DOMXPath($dom); self::assertEquals(1, $xpath->query('/html/body/div/table/tr[1]/td')->length); @@ -131,7 +132,7 @@ public function testWriteRowSpan(): void $row3->addCell(null, ['vMerge' => 'continue']); $row3->addCell(500)->addText('third cell being spanned'); - $dom = $this->getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord); $xpath = new DOMXPath($dom); self::assertEquals(2, $xpath->query('/html/body/div/table/tr[1]/td')->length); @@ -139,13 +140,41 @@ public function testWriteRowSpan(): void self::assertEquals(1, $xpath->query('/html/body/div/table/tr[2]/td')->length); } - private function getAsHTML(PhpWord $phpWord) + /** + * Tests writing table with rowspan and colspan. + */ + public function testWriteRowSpanAndColSpan(): void { - $htmlWriter = new HTML($phpWord); - $dom = new DOMDocument(); - $dom->loadHTML($htmlWriter->getContent()); + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $table = $section->addTable(); + + $row1 = $table->addRow(); + $row1->addCell(500)->addText('A'); + $row1->addCell(1000, ['gridSpan' => 2])->addText('B'); + $row1->addCell(500, ['vMerge' => 'restart'])->addText('C'); + + $row2 = $table->addRow(); + $row2->addCell(1500, ['gridSpan' => 3])->addText('D'); + $row2->addCell(null, ['vMerge' => 'continue']); + + $row3 = $table->addRow(); + $row3->addCell(500)->addText('E'); + $row3->addCell(500)->addText('F'); + $row3->addCell(500)->addText('G'); + $row3->addCell(null, ['vMerge' => 'continue']); + + $dom = Helper::getAsHTML($phpWord); + $xpath = new DOMXPath($dom); + + self::assertEquals(3, $xpath->query('/html/body/div/table/tr[1]/td')->length); + self::assertEquals('2', $xpath->query('/html/body/div/table/tr[1]/td[2]')->item(0)->attributes->getNamedItem('colspan')->textContent); + self::assertEquals('3', $xpath->query('/html/body/div/table/tr[1]/td[3]')->item(0)->attributes->getNamedItem('rowspan')->textContent); + + self::assertEquals(1, $xpath->query('/html/body/div/table/tr[2]/td')->length); + self::assertEquals('3', $xpath->query('/html/body/div/table/tr[2]/td[1]')->item(0)->attributes->getNamedItem('colspan')->textContent); - return $dom; + self::assertEquals(3, $xpath->query('/html/body/div/table/tr[3]/td')->length); } public function testWriteTitleTextRun(): void @@ -208,7 +237,7 @@ public function testWriteTableLayout(): void $row2 = $table2->addRow(); $row2->addCell()->addText('auto layout table'); - $dom = $this->getAsHTML($phpWord); + $dom = Helper::getAsHTML($phpWord); $xpath = new DOMXPath($dom); self::assertEquals('table-layout: fixed;', $xpath->query('/html/body/div/table[1]')->item(0)->attributes->getNamedItem('style')->textContent); diff --git a/tests/PhpWordTests/Writer/HTML/FontTest.php b/tests/PhpWordTests/Writer/HTML/FontTest.php index 08a8fca6a4..e9f89e2ad4 100644 --- a/tests/PhpWordTests/Writer/HTML/FontTest.php +++ b/tests/PhpWordTests/Writer/HTML/FontTest.php @@ -1,4 +1,5 @@ addSection(); $section->addImage(__DIR__ . '/../../../_files/images/earth.jpg'); $section->addImage(__DIR__ . '/../../../_files/images/mario.gif', ['align' => 'end']); @@ -59,9 +61,11 @@ public function testImage1(): void $path = '/office:document-content/office:body/office:text/text:section/text:p[2]'; self::assertTrue($doc->elementExists($path)); + self::assertFalse($doc->hasElementAttribute($path, 'draw:text-style-name')); self::assertEquals('IM1', $doc->getElementAttribute($path, 'text:style-name')); $path = '/office:document-content/office:body/office:text/text:section/text:p[3]'; self::assertTrue($doc->elementExists($path)); + self::assertFalse($doc->hasElementAttribute($path, 'draw:text-style-name')); self::assertEquals('IM2', $doc->getElementAttribute($path, 'text:style-name')); } @@ -70,7 +74,7 @@ public function testImage1(): void */ public function testImage2(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); Settings::setDefaultRtl(false); $section = $phpWord->addSection(); $section->addImage(__DIR__ . '/../../../_files/images/earth.jpg'); @@ -89,8 +93,36 @@ public function testImage2(): void $path = '/office:document-content/office:body/office:text/text:section/text:p[2]'; self::assertTrue($doc->elementExists($path)); self::assertEquals('IM1', $doc->getElementAttribute($path, 'text:style-name')); + self::assertFalse($doc->hasElementAttribute($path, 'draw:text-style-name')); $path = '/office:document-content/office:body/office:text/text:section/text:p[3]'; self::assertTrue($doc->elementExists($path)); self::assertEquals('IM2', $doc->getElementAttribute($path, 'text:style-name')); + self::assertFalse($doc->hasElementAttribute($path, 'draw:text-style-name')); + } + + /** + * Test writing image not in a section. + */ + public function testImageInTextRun(): void + { + $phpWord = new PhpWord(); + Settings::setDefaultRtl(false); + $section = $phpWord->addSection(); + $textRun = $section->addTextRun(); + $textRun->addImage(__DIR__ . '/../../../_files/images/earth.jpg'); + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + $s2a = '/office:document-content/office:automatic-styles'; + $element = "$s2a/style:style[4]"; + self::assertEquals('IM1', $doc->getElementAttribute($element, 'style:name')); + $element .= '/style:paragraph-properties'; + self::assertEquals('left', $doc->getElementAttribute($element, 'fo:text-align')); + + $path = '/office:document-content/office:body/office:text/text:section/text:p[2]'; + self::assertTrue($doc->elementExists($path)); + self::assertEquals('P1', $doc->getElementAttribute($path, 'text:style-name')); + $path = '/office:document-content/office:body/office:text/text:section/text:p[2]/draw:frame'; + self::assertTrue($doc->elementExists($path)); + self::assertTrue($doc->hasElementAttribute($path, 'draw:text-style-name')); + self::assertEquals('IM1', $doc->getElementAttribute($path, 'draw:text-style-name')); } } diff --git a/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php b/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php new file mode 100644 index 0000000000..9f531255fc --- /dev/null +++ b/tests/PhpWordTests/Writer/ODText/Element/ListItemRunTest.php @@ -0,0 +1,83 @@ +addSection() + ->addListItemRun() + ->addText($expected); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + $xPath = '/office:document-content/office:body/office:text/text:section/text:list'; + + self::assertTrue($doc->elementExists($xPath)); + self::assertTrue($doc->hasElementAttribute($xPath, 'text:style-name')); + self::assertEquals('PHPWordListType3', $doc->getElementAttribute($xPath, 'text:style-name')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:p')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:p/text:span')); + self::assertEquals($expected, $doc->getElement($xPath . '/text:list-item/text:p/text:span')->nodeValue); + } + + public function testAddListItemRunLevels(): void + { + $expected = 'List item run : '; + + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addListItemRun(0)->addText($expected . '1'); + $section->addListItemRun(1)->addText($expected . '2'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + + $xPath = '/office:document-content/office:body/office:text/text:section/text:list'; + + self::assertTrue($doc->elementExists($xPath)); + self::assertTrue($doc->hasElementAttribute($xPath, 'text:style-name')); + self::assertEquals('PHPWordListType3', $doc->getElementAttribute($xPath, 'text:style-name')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:p')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:p/text:span')); + self::assertEquals($expected . '1', $doc->getElement($xPath . '/text:list-item/text:p/text:span')->nodeValue); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:list/text:list-item')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:list/text:list-item/text:p')); + self::assertTrue($doc->elementExists($xPath . '/text:list-item/text:list/text:list-item/text:p/text:span')); + self::assertEquals($expected . '2', $doc->getElement($xPath . '/text:list-item/text:list/text:list-item/text:p/text:span')->nodeValue); + } +} diff --git a/tests/PhpWordTests/Writer/ODText/ElementTest.php b/tests/PhpWordTests/Writer/ODText/ElementTest.php index 0ad0325656..56bbf025ed 100644 --- a/tests/PhpWordTests/Writer/ODText/ElementTest.php +++ b/tests/PhpWordTests/Writer/ODText/ElementTest.php @@ -1,4 +1,5 @@ addTitleStyle(1, ['name' => 'Times New Roman', 'size' => 18, 'bold' => true]); $section = $phpWord->addSection(); $section->addTitle('Text Title', 1); @@ -275,7 +276,7 @@ public function testPageBreak(): void */ public function testTrackedChanges(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); // New portrait section $section = $phpWord->addSection(); diff --git a/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php b/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php index 3ebc534b21..6742b20ad5 100644 --- a/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php +++ b/tests/PhpWordTests/Writer/ODText/Part/AbstractPartTest.php @@ -1,4 +1,5 @@ getMockForAbstractClass(\PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart::class); + $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); $object->setParentWriter(new ODText()); self::assertEquals(new ODText(), $object->getParentWriter()); } @@ -45,7 +46,7 @@ public function testSetGetParentWriterNull(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('No parent WriterInterface assigned.'); - $object = $this->getMockForAbstractClass(\PhpOffice\PhpWord\Writer\ODText\Part\AbstractPart::class); + $object = $this->getMockForAbstractClass(ODText\Part\AbstractPart::class); $object->getParentWriter(); } } diff --git a/tests/PhpWordTests/Writer/ODText/Part/ContentTest.php b/tests/PhpWordTests/Writer/ODText/Part/ContentTest.php index f86507ce06..e1dc78a32b 100644 --- a/tests/PhpWordTests/Writer/ODText/Part/ContentTest.php +++ b/tests/PhpWordTests/Writer/ODText/Part/ContentTest.php @@ -1,4 +1,5 @@ addSection(); $section->addText('This is red (800) in rtf/html, default in docx/odt', ['color' => '800']); $section->addText('This should be cyanish (008787)', ['color' => '008787']); - $section->addText('This should be dark green (FGCOLOR_DARKGREEN)', ['color' => \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKGREEN]); + $section->addText('This should be dark green (FGCOLOR_DARKGREEN)', ['color' => Font::FGCOLOR_DARKGREEN]); $section->addText('This color is default (unknow)', ['color' => 'unknow']); $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); @@ -219,7 +220,7 @@ public function testFieldStyles(): void $fld->setFontStyle(['color' => '008000']); $textrun = $section->addTextRun(); $fld = $textrun->addField('DATE'); - $font = new \PhpOffice\PhpWord\Style\Font(); + $font = new Font(); $font->setColor('000080'); $fld->setFontStyle($font); $textrun = $section->addTextRun(); diff --git a/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php b/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php new file mode 100644 index 0000000000..b06242706d --- /dev/null +++ b/tests/PhpWordTests/Writer/ODText/Style/NumberingTest.php @@ -0,0 +1,70 @@ +addNumberingStyle($expected, [ + 'type' => 'multilevel', + 'levels' => [ + [ + 'start' => 1, + 'format' => 'decimal', + 'restart' => 1, + 'suffix' => 'space', + 'text' => '%1.', + 'alignment' => Jc::START, + ], + ], + ]); + $phpWord->addSection() + ->addListItemRun(0, $expected) + ->addText('List item run 1'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'ODText'); + $doc->setDefaultFile('styles.xml'); + + $xPath = '/office:document-styles/office:styles'; + self::assertTrue($doc->elementExists($xPath)); + self::assertTrue($doc->elementExists($xPath . '/text:list-style')); + self::assertTrue($doc->hasElementAttribute($xPath . '/text:list-style', 'style:name')); + self::assertEquals($expected, $doc->getElementAttribute($xPath . '/text:list-style', 'style:name')); + self::assertTrue($doc->elementExists($xPath . '/text:list-style/text:list-level-style-bullet')); + self::assertTrue($doc->elementExists($xPath . '/text:list-style/text:list-level-style-bullet/style:list-level-properties')); + self::assertTrue($doc->elementExists($xPath . '/text:list-style/text:list-level-style-bullet/style:list-level-properties/style:list-level-label-alignment')); + self::assertTrue($doc->elementExists($xPath . '/text:list-style/text:list-level-style-bullet/style:text-properties')); + } +} diff --git a/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php b/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php index b638b380b6..bc02ca8ea0 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php +++ b/tests/PhpWordTests/Writer/ODText/Style/Paragraph2Test.php @@ -1,4 +1,5 @@ addParagraphStyle('parstyle1', ['align' => 'start']); $phpWord->addParagraphStyle('parstyle2', ['align' => 'end']); $section = $phpWord->addSection(); @@ -403,7 +404,7 @@ public function testTextRun(): void */ public function testTextRunUnnamed(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $parstyle1 = ['align' => 'start']; $parstyle2 = ['align' => 'end']; $section = $phpWord->addSection(); @@ -437,7 +438,7 @@ public function testTextRunUnnamed(): void */ public function testEmptyFontAndParagraphStyles(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $phpWord->addFontStyle('namedfont', ['name' => 'Courier New', 'size' => 8]); $phpWord->addParagraphStyle('namedpar', ['lineHeight' => 1.08]); diff --git a/tests/PhpWordTests/Writer/ODText/Style/SectionTest.php b/tests/PhpWordTests/Writer/ODText/Style/SectionTest.php index cbd58da455..83f5962944 100644 --- a/tests/PhpWordTests/Writer/ODText/Style/SectionTest.php +++ b/tests/PhpWordTests/Writer/ODText/Style/SectionTest.php @@ -1,4 +1,5 @@ addFontStyle('hdrstyle1', ['name' => 'Courier New', 'size' => 8]); $section = $phpWord->addSection(['paperSize' => 'Letter', 'marginTop' => $margins, 'marginBottom' => $margins]); diff --git a/tests/PhpWordTests/Writer/ODText/StyleTest.php b/tests/PhpWordTests/Writer/ODText/StyleTest.php index 0d36b4899c..21d4c8bb53 100644 --- a/tests/PhpWordTests/Writer/ODText/StyleTest.php +++ b/tests/PhpWordTests/Writer/ODText/StyleTest.php @@ -1,4 +1,5 @@ write()); + } + + public function testTable(): void + { + Settings::setDefaultRtl(false); + $parentWriter = new RTF(); + $element = new Table(); + $width = 100; + $width2 = 2 * $width; + $element->addRow(); + $tce = $element->addCell($width); + $tce->addText('1'); + $tce = $element->addCell($width); + $tce->addText('2'); + $element->addRow(); + $tce = $element->addCell($width); + $tce->addText('3'); + $tce = $element->addCell($width); + $tce->addText('4'); + $table = new WriterTable($parentWriter, $element); + $expect = implode("\n", [ + '\\pard', + "\\trowd \\cellx$width \\cellx$width2 ", + '\\intbl', + '\\ql{\\cf0\\f0 1}\\par', + '\\cell', + '\\intbl', + '{\\cf0\\f0 2}\\par', + '\\cell', + '\\row', + "\\trowd \\cellx$width \\cellx$width2 ", + '\\intbl', + '\\ql{\\cf0\\f0 3}\\par', + '\\cell', + '\\intbl', + '{\\cf0\\f0 4}\par', + '\\cell', + '\\row', + '\\pard', + '', + ]); + + self::assertEquals($expect, $this->removeCr($table)); + } + + public function testTableStyle(): void + { + $width = 100; + + Settings::setDefaultRtl(false); + $parentWriter = new RTF(); + + Style::addTableStyle('TableStyle', ['borderSize' => 6, 'borderColor' => '006699']); + + $element = new Table('TableStyle'); + $element->addRow(); + $elementCell = $element->addCell($width); + $elementCell->addText('1'); + + $expect = implode("\n", [ + '\\pard', + '\\trowd \\clbrdrt\\brdrs\\brdrw2\\brdrcf0', + '\\clbrdrl\\brdrs\\brdrw2\\brdrcf0', + '\\clbrdrb\\brdrs\\brdrw2\\brdrcf0', + '\\clbrdrr\\brdrs\\brdrw2\\brdrcf0', + "\\cellx$width ", + '\\intbl', + '\\ql{\\cf0\\f0 1}\\par', + '\\cell', + '\\row', + '\\pard', + '', + ]); + + self::assertEquals($expect, $this->removeCr(new WriterTable($parentWriter, $element))); + } + + public function testTableStyleNotExisting(): void + { + $width = 100; + + Settings::setDefaultRtl(false); + $parentWriter = new RTF(); + + $element = new Table('TableStyleNotExisting'); + $element->addRow(); + $elementCell = $element->addCell($width); + $elementCell->addText('1'); + + $expect = implode("\n", [ + '\\pard', + "\\trowd \\cellx$width ", + '\\intbl', + '\\ql{\\cf0\\f0 1}\\par', + '\\cell', + '\\row', + '\\pard', + '', + ]); + + self::assertEquals($expect, $this->removeCr(new WriterTable($parentWriter, $element))); + } + + public function testTableCellStyle(): void + { + $width = 100; + + Settings::setDefaultRtl(false); + $parentWriter = new RTF(); + + $element = new Table(); + $element->addRow(); + $elementCell = $element->addCell($width, ['borderSize' => 6, 'borderColor' => '006699', 'borderStyle' => Border::DOTTED]); + $elementCell->addText('1'); + + $expect = implode("\n", [ + '\\pard', + '\\trowd \\clbrdrt\\brdrdot\\brdrw2\\brdrcf0', + '\\clbrdrl\\brdrdot\\brdrw2\\brdrcf0', + '\\clbrdrb\\brdrdot\\brdrw2\\brdrcf0', + '\\clbrdrr\\brdrdot\\brdrw2\\brdrcf0', + "\\cellx$width ", + '\\intbl', + '\\ql{\\cf0\\f0 1}\\par', + '\\cell', + '\\row', + '\\pard', + '', + ]); + + self::assertEquals($expect, $this->removeCr(new WriterTable($parentWriter, $element))); + } +} diff --git a/tests/PhpWordTests/Writer/RTF/Element2Test.php b/tests/PhpWordTests/Writer/RTF/Element2Test.php index d82a3095d7..2220d93b68 100644 --- a/tests/PhpWordTests/Writer/RTF/Element2Test.php +++ b/tests/PhpWordTests/Writer/RTF/Element2Test.php @@ -1,4 +1,5 @@ write()); } - public function testTable(): void - { - Settings::setDefaultRtl(false); - $parentWriter = new RTF(); - $element = new \PhpOffice\PhpWord\Element\Table(); - $width = 100; - $width2 = 2 * $width; - $element->addRow(); - $tce = $element->addCell($width); - $tce->addText('1'); - $tce = $element->addCell($width); - $tce->addText('2'); - $element->addRow(); - $tce = $element->addCell($width); - $tce->addText('3'); - $tce = $element->addCell($width); - $tce->addText('4'); - $table = new WriterTable($parentWriter, $element); - $expect = implode("\n", [ - '\\pard', - "\\trowd \\cellx$width \\cellx$width2 ", - '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', - '\\cell', - '\\intbl', - '{\\cf0\\f0 2}\\par', - '\\cell', - '\\row', - "\\trowd \\cellx$width \\cellx$width2 ", - '\\intbl', - '\\ql{\\cf0\\f0 3}\\par', - '\\cell', - '\\intbl', - '{\\cf0\\f0 4}\par', - '\\cell', - '\\row', - '\\pard', - '', - ]); - - self::assertEquals($expect, $this->removeCr($table)); - } - public function testTextRun(): void { Settings::setDefaultRtl(false); diff --git a/tests/PhpWordTests/Writer/RTF/ElementTest.php b/tests/PhpWordTests/Writer/RTF/ElementTest.php index fd0842cd6c..dbd937bc0d 100644 --- a/tests/PhpWordTests/Writer/RTF/ElementTest.php +++ b/tests/PhpWordTests/Writer/RTF/ElementTest.php @@ -1,4 +1,5 @@ removeCr($field)); } @@ -58,7 +59,7 @@ public function testFilenameFieldOptionsPath(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('FILENAME', [], ['Path']); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{\\field{\\*\\fldinst FILENAME \\\\p}{\\fldrslt}}\\par\n", $this->removeCr($field)); } @@ -67,7 +68,7 @@ public function testPageField(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('PAGE'); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{\\field{\\*\\fldinst PAGE}{\\fldrslt}}\\par\n", $this->removeCr($field)); } @@ -76,7 +77,7 @@ public function testNumpageField(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('NUMPAGES'); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{\\field{\\*\\fldinst NUMPAGES}{\\fldrslt}}\\par\n", $this->removeCr($field)); } @@ -85,7 +86,7 @@ public function testDateField(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('DATE', ['dateformat' => 'd MM yyyy H:mm:ss']); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{\\field{\\*\\fldinst DATE \\\\@ \"d MM yyyy H:mm:ss\"}{\\fldrslt}}\\par\n", $this->removeCr($field)); } @@ -94,7 +95,7 @@ public function testIndexField(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Field('INDEX'); - $field = new \PhpOffice\PhpWord\Writer\RTF\Element\Field($parentWriter, $element); + $field = new RTF\Element\Field($parentWriter, $element); self::assertEquals("{}\\par\n", $this->removeCr($field)); } @@ -115,7 +116,7 @@ public function testTable(): void $tce->addText('3'); $tce = $element->addCell($width); $tce->addText('4'); - $table = new \PhpOffice\PhpWord\Writer\RTF\Element\Table($parentWriter, $element); + $table = new RTF\Element\Table($parentWriter, $element); $expect = implode("\n", [ '\\pard', "\\trowd \\cellx$width \\cellx$width2 ", @@ -147,7 +148,7 @@ public function testTextRun(): void $element = new \PhpOffice\PhpWord\Element\TextRun(); $element->addText('Hello '); $element->addText('there.'); - $textrun = new \PhpOffice\PhpWord\Writer\RTF\Element\TextRun($parentWriter, $element); + $textrun = new RTF\Element\TextRun($parentWriter, $element); $expect = "\\pard\\nowidctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -158,7 +159,7 @@ public function testTextRunParagraphStyle(): void $element = new \PhpOffice\PhpWord\Element\TextRun(['spaceBefore' => 0, 'spaceAfter' => 0]); $element->addText('Hello '); $element->addText('there.'); - $textrun = new \PhpOffice\PhpWord\Writer\RTF\Element\TextRun($parentWriter, $element); + $textrun = new RTF\Element\TextRun($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -170,7 +171,7 @@ public function testTitle(): void $phpWord->addTitleStyle(1, [], ['spaceBefore' => 0, 'spaceAfter' => 0]); $section = $phpWord->addSection(); $element = $section->addTitle('First Heading', 1); - $elwrite = new \PhpOffice\PhpWord\Writer\RTF\Element\Title($parentWriter, $element); + $elwrite = new RTF\Element\Title($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); } diff --git a/tests/PhpWordTests/Writer/RTF/HeaderFooterTest.php b/tests/PhpWordTests/Writer/RTF/HeaderFooterTest.php index ec71b2f078..3b4f86c7d7 100644 --- a/tests/PhpWordTests/Writer/RTF/HeaderFooterTest.php +++ b/tests/PhpWordTests/Writer/RTF/HeaderFooterTest.php @@ -1,4 +1,5 @@ setRight(2); $indentation->setFirstLine(3); - $indentWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Indentation($indentation); + $indentWriter = new RTF\Style\Indentation($indentation); $indentWriter->setParentWriter(new RTF()); $result = $indentWriter->write(); @@ -89,7 +90,7 @@ public function testRightTab(): void $tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_RIGHT); $tabRight->setPosition(5); - $tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight); + $tabWriter = new RTF\Style\Tab($tabRight); $tabWriter->setParentWriter(new RTF()); $result = $tabWriter->write(); @@ -101,7 +102,7 @@ public function testCenterTab(): void $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 = new RTF\Style\Tab($tabRight); $tabWriter->setParentWriter(new RTF()); $result = $tabWriter->write(); @@ -113,7 +114,7 @@ public function testDecimalTab(): void $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 = new RTF\Style\Tab($tabRight); $tabWriter->setParentWriter(new RTF()); $result = $tabWriter->write(); @@ -124,7 +125,7 @@ public function testRTL(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד', ['RTL' => true]); - $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $text = new RTF\Element\Text($parentWriter, $element); $expect = "\\pard\\nowidctlpar {\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -134,7 +135,7 @@ public function testRTL2(): void Settings::setDefaultRtl(true); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד'); - $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $text = new RTF\Element\Text($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\qr{\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -143,7 +144,7 @@ public function testPageBreakLineHeight(): void { $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); - $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $text = new RTF\Element\Text($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -153,7 +154,7 @@ public function testPageBreakLineHeight2(): void Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); - $text = new \PhpOffice\PhpWord\Writer\RTF\Element\Text($parentWriter, $element); + $text = new RTF\Element\Text($parentWriter, $element); $expect = "\\pard\\nowidctlpar \\ql\\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -163,7 +164,7 @@ public function testPageNumberRestart(): void //$parentWriter = new RTF(); $phpword = new \PhpOffice\PhpWord\PhpWord(); $section = $phpword->addSection(['pageNumberingStart' => 5]); - $styleWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Section($section->getStyle()); + $styleWriter = new RTF\Style\Section($section->getStyle()); $wstyle = $this->removeCr($styleWriter); // following have default values which might change so don't use them $wstyle = preg_replace('/\\\\pgwsxn\\d+/', '', $wstyle); diff --git a/tests/PhpWordTests/Writer/RTFTest.php b/tests/PhpWordTests/Writer/RTFTest.php index c56bc9f3dc..4f9f8944ac 100644 --- a/tests/PhpWordTests/Writer/RTFTest.php +++ b/tests/PhpWordTests/Writer/RTFTest.php @@ -1,4 +1,5 @@ addSection(); + $section->addField( + 'REF', + [ + 'name' => 'my-bookmark', + ], + [ + 'InsertParagraphNumberRelativeContext', + 'CreateHyperLink', + ] + ); + + $section->addListItem('line one item'); + $section->addListItem('line two item'); + $section->addBookmark('my-bookmark'); + $section->addListItem('line three item'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $refFieldPath = '/w:document/w:body/w:p[1]/w:r[2]/w:instrText'; + self::assertTrue($doc->elementExists($refFieldPath)); + + $bookMarkElement = $doc->getElement($refFieldPath); + self::assertNotNull($bookMarkElement); + self::assertEquals(' REF my-bookmark \r \h ', $bookMarkElement->textContent); + + $bookmarkPath = '/w:document/w:body/w:bookmarkStart'; + self::assertTrue($doc->elementExists($bookmarkPath)); + self::assertEquals('my-bookmark', $doc->getElementAttribute("$bookmarkPath", 'w:name')); + } +} diff --git a/tests/PhpWordTests/Writer/Word2007/Element/FormFieldTest.php b/tests/PhpWordTests/Writer/Word2007/Element/FormFieldTest.php index 14e30d552d..52861900e7 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/FormFieldTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/FormFieldTest.php @@ -1,4 +1,5 @@ addSection(); + $section->addText('Before table (normal).'); + $table = $section->addTable(['width' => 5000, 'unit' => TblWidth::PERCENT]); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R1C1'); + $tc = $table->addCell(); + $tc->addText('R1C2'); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R2C1'); + $tc = $table->addCell(); + $tc->addText('R2C2'); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R3C1'); + $tc = $table->addCell(); + $tc->addText('R3C2'); + $section->addText('After table.'); + + $doc = TestHelperDOCX::getDocument($phpWord); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl[2]'), 'should be only 1 table'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[3]')); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc[3]')); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc[3]')); + } + + public static function testSomeRowWithNoCells(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Before table (row 2 has no cells).'); + $table = $section->addTable(['width' => 5000, 'unit' => TblWidth::PERCENT]); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R1C1'); + $tc = $table->addCell(); + $tc->addText('R1C2'); + $row = $table->addRow(); + $row = $table->addRow(); + $tc = $table->addCell(); + $tc->addText('R3C1'); + $tc = $table->addCell(); + $tc->addText('R3C2'); + $section->addText('After table.'); + + $doc = TestHelperDOCX::getDocument($phpWord); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl[2]'), 'should be only 1 table'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[3]')); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]/w:tc[2]')); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc[2]')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[3]/w:tc[3]')); + } + + public static function testOnly1RowWithNoCells(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Before table (only 1 row and it has no cells).'); + $table = $section->addTable(['width' => 5000, 'unit' => TblWidth::PERCENT]); + $row = $table->addRow(); + $section->addText('After table.'); + + $doc = TestHelperDOCX::getDocument($phpWord); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl[2]'), 'only 1 table should be written'); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc')); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[1]/w:tc[2]')); + + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl/w:tr[2]')); + } + + public static function testNoRows(): void + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $section->addText('Before table (no rows therefore omitted).'); + $table = $section->addTable(['width' => 5000, 'unit' => TblWidth::PERCENT]); + $section->addText('After table.'); + + $doc = TestHelperDOCX::getDocument($phpWord); + self::assertFalse($doc->elementExists('/w:document/w:body/w:tbl[1]'), 'no table should be written'); + } +} diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php index 180a319eb1..1d62ffa964 100644 --- a/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php @@ -1,4 +1,5 @@ getMockForAbstractClass(\PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart::class); + $object = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); $object->setParentWriter(new Word2007()); self::assertEquals(new Word2007(), $object->getParentWriter()); } @@ -43,7 +44,7 @@ public function testSetGetParentWriterNull(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('No parent WriterInterface assigned.'); - $object = $this->getMockForAbstractClass(\PhpOffice\PhpWord\Writer\Word2007\Part\AbstractPart::class); + $object = $this->getMockForAbstractClass(Word2007\Part\AbstractPart::class); $object->getParentWriter(); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Part/CommentsTest.php b/tests/PhpWordTests/Writer/Word2007/Part/CommentsTest.php index 383203636b..8f8c8240a9 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/CommentsTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/CommentsTest.php @@ -1,4 +1,5 @@ elementExists("{$parent}/w:i")); self::assertEquals($styles['underline'], $doc->getElementAttribute("{$parent}/w:u", 'w:val')); self::assertTrue($doc->elementExists("{$parent}/w:strike")); + self::assertFalse($doc->elementExists("{$parent}/w:dstrike")); self::assertEquals('superscript', $doc->getElementAttribute("{$parent}/w:vertAlign", 'w:val')); self::assertEquals($styles['color'], $doc->getElementAttribute("{$parent}/w:color", 'w:val')); self::assertEquals($styles['fgColor'], $doc->getElementAttribute("{$parent}/w:highlight", 'w:val')); self::assertTrue($doc->elementExists("{$parent}/w:smallCaps")); } + /** + * covers ::_writeTextStyle. + * + * @dataProvider providerFontStyleStrikethrough + */ + public function testWriteFontStyleStrikethrough( + bool $isStrikethrough, + bool $isDoubleStrikethrough, + bool $expectedStrikethrough, + bool $expectedDoubleStrikethrough + ): void { + $phpWord = new PhpWord(); + $styles['strikethrough'] = $isStrikethrough; + $styles['doublestrikethrough'] = $isDoubleStrikethrough; + + $section = $phpWord->addSection(); + $section->addText('Test', $styles); + $doc = TestHelperDOCX::getDocument($phpWord); + + $parent = '/w:document/w:body/w:p/w:r/w:rPr'; + self::assertSame($expectedStrikethrough, $doc->elementExists("{$parent}/w:strike")); + self::assertSame($expectedDoubleStrikethrough, $doc->elementExists("{$parent}/w:dstrike")); + } + + public static function providerFontStyleStrikethrough(): iterable + { + return [ + [true, true, false, true], + [true, false, true, false], + [false, true, false, true], + [false, false, false, false], + ]; + } + /** * Tests that if no color is set on a cell a border gets writen with the default color. */ diff --git a/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php b/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php index 0dc99e7e37..beb6e971e2 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/FooterTest.php @@ -1,4 +1,5 @@ elementExists('/w:document/w:body/w:p/w:r/w:footnoteReference')); self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:endnoteReference')); + + self::assertFalse($doc->elementExists('/w:document/w:body/w:p/w:r/w:footnoteReference[@w:id="0"]')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:footnoteReference[@w:id="1"]')); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php b/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php index 27e9bcb9ba..164365f113 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/HeaderTest.php @@ -1,4 +1,5 @@ addSection(); $textrun = $section->addTextRun(); $textrun->addText('سلام این یک پاراگراف راست به چپ است', ['rtl' => true, 'lang' => 'ar-DZ']); @@ -56,7 +57,7 @@ public function testFontRTL(): void public function testFontRTLNamed(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $stnam = 'fstyle'; $phpWord->addFontStyle($stnam, [ 'rtl' => true, @@ -81,7 +82,7 @@ public function testFontRTLNamed(): void public function testFontNotRTLNamed(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $stnam = 'fstyle'; $phpWord->addFontStyle($stnam, [ //'rtl' => true, @@ -106,7 +107,7 @@ public function testFontNotRTLNamed(): void public function testNoProof(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $fontStyle = [ 'noProof' => true, 'name' => 'Courier New', @@ -133,7 +134,7 @@ public function testNoProof(): void */ public function testFontWithLang(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addText('Ce texte-ci est en français.', ['lang' => \PhpOffice\PhpWord\Style\Language::FR_BE]); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); @@ -148,7 +149,7 @@ public function testFontWithLang(): void */ public function testPosition(): void { - $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $phpWord = new PhpWord(); $section = $phpWord->addSection(); $section->addText('This text is lowered', ['position' => -20]); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); diff --git a/tests/PhpWordTests/Writer/Word2007/Style/ImageTest.php b/tests/PhpWordTests/Writer/Word2007/Style/ImageTest.php index 53ecba2dd9..2b5c25e01f 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/ImageTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/ImageTest.php @@ -1,4 +1,5 @@ addSection(); diff --git a/tests/PhpWordTests/Writer/Word2007/Style/TableTest.php b/tests/PhpWordTests/Writer/Word2007/Style/TableTest.php index b072bb8ab2..b10d836568 100644 --- a/tests/PhpWordTests/Writer/Word2007/Style/TableTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Style/TableTest.php @@ -1,4 +1,5 @@ getElement($path, $file)->getAttribute($attribute); } + /** + * Return if element attribute exists. + */ + public function hasElementAttribute(string $path, string $attribute, string $file = ''): bool + { + return $this->getElement($path, $file)->hasAttribute($attribute); + } + /** * Check if element exists. */ diff --git a/tests/PhpWordTests/_files/documents/docChinese.doc b/tests/PhpWordTests/_files/documents/docChinese.doc new file mode 100644 index 0000000000..db245953e5 Binary files /dev/null and b/tests/PhpWordTests/_files/documents/docChinese.doc differ diff --git a/tests/PhpWordTests/_files/documents/docCzech.doc b/tests/PhpWordTests/_files/documents/docCzech.doc new file mode 100644 index 0000000000..8def81b13e Binary files /dev/null and b/tests/PhpWordTests/_files/documents/docCzech.doc differ diff --git a/tests/PhpWordTests/_files/documents/docSlovak.doc b/tests/PhpWordTests/_files/documents/docSlovak.doc new file mode 100644 index 0000000000..dede581e55 Binary files /dev/null and b/tests/PhpWordTests/_files/documents/docSlovak.doc differ diff --git a/tests/PhpWordTests/_files/documents/reader-styles.docx b/tests/PhpWordTests/_files/documents/reader-styles.docx new file mode 100644 index 0000000000..b02cf73c5f Binary files /dev/null and b/tests/PhpWordTests/_files/documents/reader-styles.docx differ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 845e59db70..7c4e0a3e1b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,4 +1,5 @@