diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..3245e4a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: +- package-ecosystem: composer + directory: "/" + schedule: + interval: monthly + time: "11:00" + open-pull-requests-limit: 10 + assignees: + - Progi1984 diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 0000000..69d01b3 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,98 @@ +name: PHPOffice\Common +on: [push, pull_request] +jobs: + php-cs-fixer: + name: PHP CS Fixer + runs-on: ubuntu-latest + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + extensions: mbstring, intl, gd, xml, dom, json, fileinfo, curl, zip, iconv + - uses: actions/checkout@v2 + + - name: Validate composer config + run: composer validate --strict + + - name: Composer Install + run: composer global require friendsofphp/php-cs-fixer + + - name: Add environment path + run: export PATH="$PATH:$HOME/.composer/vendor/bin" + + - name: Run PHPCSFixer + run: php-cs-fixer fix --dry-run --diff + + phpmd: + name: PHP Mess Detector + runs-on: ubuntu-latest + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + extensions: gd, xml, zip + - uses: actions/checkout@v2 + + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress + + - name: Run phpmd + run: ./vendor/bin/phpmd src/,tests/ text ./phpmd.xml.dist + + phpstan: + name: PHP Static Analysis + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['7.1', '7.2', '7.3', '7.4', '8.0'] #, '8.1' + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, xml, zip + - uses: actions/checkout@v2 + + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress + + - name: Run phpstan + run: ./vendor/bin/phpstan analyse -c phpstan.neon.dist + + phpunit: + name: PHPUnit + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['7.1', '7.2', '7.3', '7.4', '8.0'] #, '8.1' + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, xml, zip + coverage: xdebug + + - name: Generate Locale (for tests) + run: sudo locale-gen de_DE.UTF-8 && sudo update-locale + + - uses: actions/checkout@v2 + + - name: Composer Install + run: composer install --ansi --prefer-dist --no-interaction --no-progress + + - name: Run phpunit + 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 diff --git a/.gitignore b/.gitignore index 605fc80..394d588 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,7 @@ -.DS_Store -._* -.Spotlight-V100 -.Trashes -Thumbs.db -Desktop.ini -.idea -build/ -phpunit.xml -composer.phar -vendor -*.settings -*.project -*.buildpath - -/samples/results -/phpunit.bat -/todo.txt -/samples/Sample_00_Test.php -/samples/#47 -/samples/#70 -/samples/#71 -/samples/Github_*.* -/samples/#83/*.lnk +## PHPCSFixer +/.php-cs-fixer.cache +## PHPUnit +/.phpunit.result.cache +## Dependencies /composer.lock +/vendor/ \ No newline at end of file diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..532c34a --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,44 @@ +setUsingCache(true) + ->setRiskyAllowed(true) + ->setRules([ + '@Symfony' => true, + 'array_indentation' => true, + 'cast_spaces' => [ + 'space' => 'single', + ], + 'combine_consecutive_issets' => true, + 'concat_space' => [ + 'spacing' => 'one', + ], + 'error_suppression' => [ + 'mute_deprecation_error' => false, + 'noise_remaining_usages' => false, + 'noise_remaining_usages_exclude' => [], + ], + 'function_to_constant' => false, + 'method_chaining_indentation' => true, + 'no_alias_functions' => false, + 'no_superfluous_phpdoc_tags' => false, + 'non_printable_character' => [ + 'use_escape_sequences_in_strings' => true, + ], + 'phpdoc_align' => [ + 'align' => 'left', + ], + 'phpdoc_summary' => false, + 'protected_to_private' => false, + 'self_accessor' => false, + 'yoda_style' => false, + 'single_line_throw' => false, + 'no_alias_language_construct_call' => false, + ]) + ->getFinder() + ->in(__DIR__) + ->exclude('vendor'); + +return $config; \ No newline at end of file diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index 6d188be..0000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,24 +0,0 @@ -filter: - excluded_paths: [ 'vendor/*', 'tests/*', 'samples/*' ] - -before_commands: - - "composer install --prefer-source --dev" - -tools: - php_code_sniffer: - enabled: true - config: - standard: PSR2 - php_mess_detector: - enabled: true - config: - ruleset: phpmd.xml.dist - external_code_coverage: - enabled: true - timeout: 900 - php_cpd: true - # php_sim: # Temporarily disabled to allow focus on things other than duplicates - # min_mass: 40 - php_pdepend: true - php_analyzer: true - sensiolabs_security_checker: true \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e5f01f1..0000000 --- a/.travis.yml +++ /dev/null @@ -1,60 +0,0 @@ -language: php - -php: - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - 7.1 - - 7.2 - - hhvm - -matrix: - allow_failures: - - php: 7.1 - - php: 7.2 - - php: hhvm - -env: - global: - ## - secure: "LtlUOzC8FtqgbqUTmU7EU281NSCb58UFdvnz8lelNIDltBdP4eayN/TsgNIePB4jXg2d2R56ZA6j/grhE/md6jdUkulV355H3GrH/hIZmmQ+F9+87agnwLzb9+MJbqXoiE7VvjY3zGIO09G897SUfsfu6JWEcscYFlsH6KcXM6M=" - -before_script: - ## Packages - - sudo apt-get -qq update > /dev/null - - sudo apt-get -qq install graphviz > /dev/null - ## Composer - - composer self-update - - composer install --prefer-source --dev - ## PHPDocumentor - - mkdir -p build/docs - - mkdir -p build/coverage - -script: - ## PHP_CodeSniffer - - ./vendor/bin/phpcs src/ tests/ --standard=PSR2 -n - ## PHP Copy/Paste Detector - # - ./vendor/bin/phpcpd src/ - ## PHP Mess Detector - - ./vendor/bin/phpmd src/,tests/ text ./phpmd.xml.dist - ## PHPUnit - - ./vendor/bin/phpunit -c ./ --coverage-text --coverage-html ./build/coverage - ## PHPLOC - - ./vendor/bin/phploc src/ - ## PHPDocumentor - - ./vendor/bin/phpdoc -q -d ./src -t ./build/docs --template="responsive-twig" - -after_script: - ## PHPDocumentor - ## - bash .travis_shell_after_success.sh - ## Scrutinizer - - wget https://scrutinizer-ci.com/ocular.phar - - php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml - -notifications: - webhooks: - urls: - - https://webhooks.gitter.im/e/e019b92a7793d27e080c - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false \ No newline at end of file diff --git a/.travis_shell_after_success.sh b/.travis_shell_after_success.sh deleted file mode 100644 index bbfb7cb..0000000 --- a/.travis_shell_after_success.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -echo "--DEBUG--" -echo "TRAVIS_REPO_SLUG: $TRAVIS_REPO_SLUG" -echo "TRAVIS_PHP_VERSION: $TRAVIS_PHP_VERSION" -echo "TRAVIS_PULL_REQUEST: $TRAVIS_PULL_REQUEST" - -if [ "$TRAVIS_REPO_SLUG" == "PHPOffice/Common" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.5" ]; then - - echo -e "Publishing PHPDoc...\n" - - cp -R build/docs $HOME/docs-latest - cp -R build/coverage $HOME/coverage-latest - - cd $HOME - git config --global user.email "travis@travis-ci.org" - git config --global user.name "travis-ci" - git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/PHPOffice/Common gh-pages > /dev/null - - cd gh-pages - echo "--DEBUG : Suppression" - git rm -rf ./docs/$TRAVIS_BRANCH - - echo "--DEBUG : Dossier" - mkdir -p docs/$TRAVIS_BRANCH - mkdir -p coverage/$TRAVIS_BRANCH - - echo "--DEBUG : Copie" - cp -Rf $HOME/docs-latest/* ./docs/$TRAVIS_BRANCH/ - cp -Rf $HOME/coverage-latest/* ./coverage/$TRAVIS_BRANCH/ - - echo "--DEBUG : Git" - git add -f . - git commit -m "PHPDocumentor (Travis Build: $TRAVIS_BUILD_NUMBER - Branch: $TRAVIS_BRANCH)" - git push -fq origin gh-pages > /dev/null - - echo -e "Published PHPDoc to gh-pages.\n" - -fi diff --git a/README.md b/README.md index a55ff1d..e22415b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ [![Latest Stable Version](https://poser.pugx.org/phpoffice/common/v/stable.png)](https://packagist.org/packages/phpoffice/common) -[![Build Status](https://travis-ci.org/PHPOffice/Common.svg?branch=master)](https://travis-ci.org/PHPOffice/Common) -[![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/Common/badges/quality-score.png?s=b5997ce59ac2816b4514f3a38de9900f6d492c1d)](https://scrutinizer-ci.com/g/PHPOffice/Common/) -[![Code Coverage](https://scrutinizer-ci.com/g/PHPOffice/Common/badges/coverage.png?s=742a98745725c562955440edc8d2c39d7ff5ae25)](https://scrutinizer-ci.com/g/PHPOffice/Common/) +[![PHPOffice\Common](https://github.com/PHPOffice/Common/actions/workflows/php.yml/badge.svg)](https://github.com/PHPOffice/Common/actions/workflows/php.yml) +[![Coverage Status](https://coveralls.io/repos/github/PHPOffice/Common/badge.svg?branch=develop)](https://coveralls.io/github/PHPOffice/Common?branch=develop) [![Total Downloads](https://poser.pugx.org/phpoffice/common/downloads.png)](https://packagist.org/packages/phpoffice/common) [![License](https://poser.pugx.org/phpoffice/common/license.png)](https://packagist.org/packages/phpoffice/common) [![Join the chat at https://gitter.im/PHPOffice/Common](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/Common) @@ -21,7 +20,7 @@ Read more about PHPPowerPoint: PHPOffice Common requires the following: -- PHP 5.3+ +- PHP 7.1+ ## Contributing diff --git a/composer.json b/composer.json index 2a75a30..b84cb46 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "keywords": ["PHP","Office","Common","component"], "homepage": "http://phpoffice.github.io", "type": "library", - "license": "LGPL", + "license": "LGPL-3.0-only", "authors": [ { "name": "Mark Baker" @@ -15,16 +15,13 @@ } ], "require": { - "php": ">=5.3.0", + "php": ">=7.1", "pclzip/pclzip": "^2.8" }, "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.0", - "phpdocumentor/phpdocumentor":"2.*", + "phpunit/phpunit": ">=7", "phpmd/phpmd": "2.*", - "sebastian/phpcpd": "2.*", - "phploc/phploc": "2.*", - "squizlabs/php_codesniffer": "2.*" + "phpstan/phpstan": "^0.12.88" }, "autoload": { "psr-4": { diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..71cf9ba --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,12 @@ +parameters: + level: 6 + bootstrapFiles: + - tests/bootstrap.php + paths: + - src + - tests + reportUnmatchedIgnoredErrors: false + ignoreErrors: + + ## Remove after remove ArrayObject + treatPhpDocTypesAsCertain: false diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7b09d34..05dc372 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -18,7 +18,6 @@ - - + \ No newline at end of file diff --git a/src/Common/Adapter/Zip/PclZipAdapter.php b/src/Common/Adapter/Zip/PclZipAdapter.php index 053531f..9d31f1a 100644 --- a/src/Common/Adapter/Zip/PclZipAdapter.php +++ b/src/Common/Adapter/Zip/PclZipAdapter.php @@ -1,4 +1,5 @@ oPclZip = new PclZip($filename); $this->tmpDir = sys_get_temp_dir(); + return $this; } @@ -31,15 +33,16 @@ public function addFromString($localname, $contents) { $pathData = pathinfo($localname); - $hFile = fopen($this->tmpDir.'/'.$pathData['basename'], "wb"); + $hFile = fopen($this->tmpDir . '/' . $pathData['basename'], 'wb'); fwrite($hFile, $contents); fclose($hFile); - $res = $this->oPclZip->add($this->tmpDir.'/'.$pathData['basename'], PCLZIP_OPT_REMOVE_PATH, $this->tmpDir, PCLZIP_OPT_ADD_PATH, $pathData['dirname']); + $res = $this->oPclZip->add($this->tmpDir . '/' . $pathData['basename'], PCLZIP_OPT_REMOVE_PATH, $this->tmpDir, PCLZIP_OPT_ADD_PATH, $pathData['dirname']); if ($res == 0) { - throw new \Exception("Error zipping files : " . $this->oPclZip->errorInfo(true)); + throw new \Exception('Error zipping files : ' . $this->oPclZip->errorInfo(true)); } - unlink($this->tmpDir.'/'.$pathData['basename']); + unlink($this->tmpDir . '/' . $pathData['basename']); + return $this; } } diff --git a/src/Common/Adapter/Zip/ZipArchiveAdapter.php b/src/Common/Adapter/Zip/ZipArchiveAdapter.php index da2c346..a8728eb 100644 --- a/src/Common/Adapter/Zip/ZipArchiveAdapter.php +++ b/src/Common/Adapter/Zip/ZipArchiveAdapter.php @@ -35,13 +35,14 @@ public function close() if ($this->oZipArchive->close() === false) { throw new \Exception("Could not close zip file $this->filename."); } + return $this; } public function addFromString($localname, $contents) { if ($this->oZipArchive->addFromString($localname, $contents) === false) { - throw new \Exception("Error zipping files : " . $localname); + throw new \Exception('Error zipping files : ' . $localname); } return $this; diff --git a/src/Common/Adapter/Zip/ZipInterface.php b/src/Common/Adapter/Zip/ZipInterface.php index e8dbc8c..1e22790 100644 --- a/src/Common/Adapter/Zip/ZipInterface.php +++ b/src/Common/Adapter/Zip/ZipInterface.php @@ -6,24 +6,32 @@ interface ZipInterface { /** * Open a ZIP file archive + * * @param string $filename + * * @return $this + * * @throws \Exception */ public function open($filename); /** * Close the active archive (opened or newly created) + * * @return $this + * * @throws \Exception */ public function close(); /** * Add a file to a ZIP archive using its contents - * @param string $localname The name of the entry to create. + * + * @param string $localname the name of the entry to create * @param string $contents The contents to use to create the entry. It is used in a binary safe mode. + * * @return $this + * * @throws \Exception */ public function addFromString($localname, $contents); diff --git a/src/Common/Autoloader.php b/src/Common/Autoloader.php index 8b976c9..9269232 100644 --- a/src/Common/Autoloader.php +++ b/src/Common/Autoloader.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,16 +23,16 @@ class Autoloader { /** @const string */ - const NAMESPACE_PREFIX = 'PhpOffice\\Common\\'; + public const NAMESPACE_PREFIX = 'PhpOffice\\Common\\'; /** * Register * * @return void */ - public static function register() + public static function register(): void { - spl_autoload_register(array(new self, 'autoload')); + spl_autoload_register([new self(), 'autoload']); } /** @@ -39,7 +40,7 @@ public static function register() * * @param string $class */ - public static function autoload($class) + public static function autoload(string $class): void { $prefixLength = strlen(self::NAMESPACE_PREFIX); if (0 === strncmp(self::NAMESPACE_PREFIX, $class, $prefixLength)) { diff --git a/src/Common/Drawing.php b/src/Common/Drawing.php index 21417e2..2f71865 100644 --- a/src/Common/Drawing.php +++ b/src/Common/Drawing.php @@ -9,27 +9,26 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\Common; -/** - * \PhpOffice\Common\Drawing - */ class Drawing { - const DPI_96 = 96; + public const DPI_96 = 96; /** * Convert pixels to EMU * - * @param int $pValue Value in pixels - * @return int + * @param float $pValue Value in pixels + * + * @return float */ - public static function pixelsToEmu($pValue = 0) + public static function pixelsToEmu(float $pValue = 0): float { return round($pValue * 9525); } @@ -37,89 +36,116 @@ public static function pixelsToEmu($pValue = 0) /** * Convert EMU to pixels * - * @param int $pValue Value in EMU + * @param int $pValue Value in EMU + * * @return int */ - public static function emuToPixels($pValue = 0) + public static function emuToPixels(int $pValue = 0): int { if ($pValue == 0) { return 0; } - return round($pValue / 9525); + + return (int) round($pValue / 9525); } /** * Convert pixels to points * - * @param int $pValue Value in pixels + * @param int $pValue Value in pixels + * * @return float */ - public static function pixelsToPoints($pValue = 0) + public static function pixelsToPoints(int $pValue = 0): float { - return $pValue * 0.67777777; + return $pValue * 0.75; } /** * Convert points width to centimeters * - * @param int $pValue Value in points + * @param float $pValue Value in points + * * @return float */ - public static function pointsToCentimeters($pValue = 0) + public static function pointsToCentimeters(float $pValue = 0): float { if ($pValue == 0) { return 0; } - return ((($pValue * 1.333333333) / self::DPI_96) * 2.54); + + return (($pValue / 0.75) / self::DPI_96) * 2.54; } - + + /** + * Convert centimeters width to points + * + * @param float $pValue Value in centimeters + * + * @return float + */ + public static function centimetersToPoints(float $pValue = 0): float + { + if ($pValue == 0) { + return 0; + } + + return ($pValue / 2.54) * self::DPI_96 * 0.75; + } + /** * Convert points width to pixels * - * @param int $pValue Value in points + * @param float $pValue Value in points + * * @return float */ - public static function pointsToPixels($pValue = 0) + public static function pointsToPixels(float $pValue = 0): float { if ($pValue == 0) { return 0; } - return $pValue * 1.333333333; + + return $pValue / 0.75; } /** * Convert pixels to centimeters * - * @param int $pValue Value in pixels + * @param int $pValue Value in pixels + * * @return float */ - public static function pixelsToCentimeters($pValue = 0) + public static function pixelsToCentimeters(int $pValue = 0): float { //return $pValue * 0.028; - return (($pValue / self::DPI_96) * 2.54); + return ($pValue / self::DPI_96) * 2.54; } /** * Convert centimeters width to pixels * - * @param int $pValue Value in centimeters - * @return float + * @param float $pValue Value in centimeters + * + * @return int */ - public static function centimetersToPixels($pValue = 0) + public static function centimetersToPixels(float $pValue = 0): int { if ($pValue == 0) { return 0; } - return ($pValue / 2.54) * self::DPI_96; + + return (int) round((($pValue / 2.54) * self::DPI_96)); } /** * Convert degrees to angle * - * @param int $pValue Degrees + * @param int $pValue Degrees + * * @return int */ - public static function degreesToAngle($pValue = 0) + public static function degreesToAngle(int $pValue = 0): int { return (int) round($pValue * 60000); } @@ -127,111 +153,140 @@ public static function degreesToAngle($pValue = 0) /** * Convert angle to degrees * - * @param int $pValue Angle - * @return int + * @param int $pValue Angle + * + * @return float */ - public static function angleToDegrees($pValue = 0) + public static function angleToDegrees(int $pValue = 0): float { if ($pValue == 0) { return 0; } + return round($pValue / 60000); } /** * Convert centimeters width to twips * - * @param integer $pValue + * @param int $pValue + * * @return float */ - public static function centimetersToTwips($pValue = 0) + public static function centimetersToTwips(int $pValue = 0): float { if ($pValue == 0) { return 0; } + return $pValue * 566.928; } /** * Convert twips width to centimeters * - * @param integer $pValue + * @param int $pValue + * * @return float */ - public static function twipsToCentimeters($pValue = 0) + public static function twipsToCentimeters(int $pValue = 0): float { if ($pValue == 0) { return 0; } + return $pValue / 566.928; } /** * Convert inches width to twips * - * @param integer $pValue - * @return float + * @param int $pValue + * + * @return int */ - public static function inchesToTwips($pValue = 0) + public static function inchesToTwips(int $pValue = 0): int { if ($pValue == 0) { return 0; } + return $pValue * 1440; } /** * Convert twips width to inches * - * @param integer $pValue + * @param int $pValue + * * @return float */ - public static function twipsToInches($pValue = 0) + public static function twipsToInches(int $pValue = 0): float { if ($pValue == 0) { return 0; } + return $pValue / 1440; } /** * Convert twips width to pixels * - * @param integer $pValue + * @param int $pValue + * * @return float */ - public static function twipsToPixels($pValue = 0) + public static function twipsToPixels(int $pValue = 0): float { if ($pValue == 0) { return 0; } - return round($pValue / 15.873984); + + return round($pValue / 15); + } + + /** + * Convert points to emu + * + * @param float $pValue + * + * @return int + */ + public static function pointsToEmu(float $pValue = 0): int + { + if ($pValue == 0) { + return 0; + } + + return (int) round(($pValue / 0.75) / 9525); } /** * Convert HTML hexadecimal to RGB * * @param string $pValue HTML Color in hexadecimal - * @return array Value in RGB + * + * @return array|null Value in RGB */ - public static function htmlToRGB($pValue) + public static function htmlToRGB(string $pValue): ?array { if ($pValue[0] == '#') { $pValue = substr($pValue, 1); } if (strlen($pValue) == 6) { - list($colorR, $colorG, $colorB) = array($pValue[0] . $pValue[1], $pValue[2] . $pValue[3], $pValue[4] . $pValue[5]); + list($colorR, $colorG, $colorB) = [$pValue[0] . $pValue[1], $pValue[2] . $pValue[3], $pValue[4] . $pValue[5]]; } elseif (strlen($pValue) == 3) { - list($colorR, $colorG, $colorB) = array($pValue[0] . $pValue[0], $pValue[1] . $pValue[1], $pValue[2] . $pValue[2]); + list($colorR, $colorG, $colorB) = [$pValue[0] . $pValue[0], $pValue[1] . $pValue[1], $pValue[2] . $pValue[2]]; } else { - return false; + return null; } $colorR = hexdec($colorR); $colorG = hexdec($colorG); $colorB = hexdec($colorB); - return array($colorR, $colorG, $colorB); + return [$colorR, $colorG, $colorB]; } } diff --git a/src/Common/File.php b/src/Common/File.php index 8cb5907..8ab931d 100644 --- a/src/Common/File.php +++ b/src/Common/File.php @@ -9,35 +9,36 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\Common; -/** - * Drawing - */ +use ZipArchive; + class File { /** * Verify if a file exists * - * @param string $pFilename Filename + * @param string $pFilename Filename + * * @return bool */ - public static function fileExists($pFilename) + public static function fileExists(string $pFilename): bool { // Sick construction, but it seems that // file_exists returns strange values when // doing the original file_exists on ZIP archives... if (strtolower(substr($pFilename, 0, 3)) == 'zip') { // Open ZIP file and verify if the file exists - $zipFile = substr($pFilename, 6, strpos($pFilename, '#') - 6); + $zipFile = substr($pFilename, 6, strpos($pFilename, '#') - 6); $archiveFile = substr($pFilename, strpos($pFilename, '#') + 1); - $zip = new \ZipArchive(); + $zip = new ZipArchive(); if ($zip->open($zipFile) === true) { $returnValue = ($zip->getFromName($archiveFile) !== false); $zip->close(); @@ -51,29 +52,33 @@ public static function fileExists($pFilename) // Regular file_exists return file_exists($pFilename); } + /** * Returns the content of a file * - * @param string $pFilename Filename - * @return string + * @param string $pFilename Filename + * + * @return string|null */ - public static function fileGetContents($pFilename) + public static function fileGetContents(string $pFilename): ?string { if (!self::fileExists($pFilename)) { - return false; + return null; } if (strtolower(substr($pFilename, 0, 3)) == 'zip') { // Open ZIP file and verify if the file exists - $zipFile = substr($pFilename, 6, strpos($pFilename, '#') - 6); + $zipFile = substr($pFilename, 6, strpos($pFilename, '#') - 6); $archiveFile = substr($pFilename, strpos($pFilename, '#') + 1); - $zip = new \ZipArchive(); + $zip = new ZipArchive(); if ($zip->open($zipFile) === true) { $returnValue = $zip->getFromName($archiveFile); $zip->close(); + return $returnValue; } - return false; + + return null; } // Regular file contents return file_get_contents($pFilename); @@ -82,16 +87,17 @@ public static function fileGetContents($pFilename) /** * Returns canonicalized absolute pathname, also for ZIP archives * - * @param string $pFilename + * @param string $pFilename + * * @return string */ - public static function realpath($pFilename) + public static function realpath(string $pFilename): string { // Try using realpath() $returnValue = realpath($pFilename); // Found something? - if ($returnValue == '' || is_null($returnValue)) { + if (empty($returnValue)) { $pathArray = explode('/', $pFilename); while (in_array('..', $pathArray) && $pathArray[0] != '..') { $numPathArray = count($pathArray); diff --git a/src/Common/Font.php b/src/Common/Font.php index 03a8e73..38bc81d 100644 --- a/src/Common/Font.php +++ b/src/Common/Font.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -24,43 +25,47 @@ class Font /** * Calculate an (approximate) pixel size, based on a font points size * - * @param int $fontSizeInPoints Font size (in points) - * @return int Font size (in pixels) + * @param int $fontSizeInPoints Font size (in points) + * + * @return float Font size (in pixels) */ - public static function fontSizeToPixels($fontSizeInPoints = 12) + public static function fontSizeToPixels(int $fontSizeInPoints = 12): float { - return ((16 / 12) * $fontSizeInPoints); + return (16 / 12) * $fontSizeInPoints; } /** * Calculate an (approximate) pixel size, based on inch size * - * @param int $sizeInInch Font size (in inch) + * @param int $sizeInInch Font size (in inch) + * * @return int Size (in pixels) */ - public static function inchSizeToPixels($sizeInInch = 1) + public static function inchSizeToPixels(int $sizeInInch = 1): int { - return ($sizeInInch * 96); + return $sizeInInch * 96; } /** * Calculate an (approximate) pixel size, based on centimeter size * - * @param int $sizeInCm Font size (in centimeters) - * @return int Size (in pixels) + * @param int $sizeInCm Font size (in centimeters) + * + * @return float Size (in pixels) */ - public static function centimeterSizeToPixels($sizeInCm = 1) + public static function centimeterSizeToPixels(int $sizeInCm = 1): float { - return ($sizeInCm * 37.795275591); + return $sizeInCm * 37.795275591; } /** * Convert centimeter to twip * * @param int $sizeInCm - * @return double + * + * @return float */ - public static function centimeterSizeToTwips($sizeInCm = 1) + public static function centimeterSizeToTwips(int $sizeInCm = 1): float { return $sizeInCm / 2.54 * 1440; } @@ -69,9 +74,10 @@ public static function centimeterSizeToTwips($sizeInCm = 1) * Convert inch to twip * * @param int $sizeInInch - * @return double + * + * @return int */ - public static function inchSizeToTwips($sizeInInch = 1) + public static function inchSizeToTwips(int $sizeInInch = 1): int { return $sizeInInch * 1440; } @@ -80,9 +86,10 @@ public static function inchSizeToTwips($sizeInInch = 1) * Convert pixel to twip * * @param int $sizeInPixel - * @return double + * + * @return float */ - public static function pixelSizeToTwips($sizeInPixel = 1) + public static function pixelSizeToTwips(int $sizeInPixel = 1): float { return $sizeInPixel / 96 * 1440; } @@ -90,10 +97,11 @@ public static function pixelSizeToTwips($sizeInPixel = 1) /** * Calculate twip based on point size, used mainly for paragraph spacing * - * @param integer $sizeInPoint Size in point - * @return integer Size (in twips) + * @param int $sizeInPoint Size in point + * + * @return float Size (in twips) */ - public static function pointSizeToTwips($sizeInPoint = 1) + public static function pointSizeToTwips(int $sizeInPoint = 1): float { return $sizeInPoint / 72 * 1440; } diff --git a/src/Common/Microsoft/OLERead.php b/src/Common/Microsoft/OLERead.php index fa1df12..60d047b 100644 --- a/src/Common/Microsoft/OLERead.php +++ b/src/Common/Microsoft/OLERead.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -22,59 +23,93 @@ class OLERead { + /** + * @var string + */ private $data = ''; // OLE identifier - const IDENTIFIER_OLE = IDENTIFIER_OLE; + public const IDENTIFIER_OLE = IDENTIFIER_OLE; // Size of a sector = 512 bytes - const BIG_BLOCK_SIZE = 0x200; + public const BIG_BLOCK_SIZE = 0x200; // Size of a short sector = 64 bytes - const SMALL_BLOCK_SIZE = 0x40; + public const SMALL_BLOCK_SIZE = 0x40; // Size of a directory entry always = 128 bytes - const PROPERTY_STORAGE_BLOCK_SIZE = 0x80; + public const PROPERTY_STORAGE_BLOCK_SIZE = 0x80; // Minimum size of a standard stream = 4096 bytes, streams smaller than this are stored as short streams - const SMALL_BLOCK_THRESHOLD = 0x1000; + public const SMALL_BLOCK_THRESHOLD = 0x1000; // header offsets - const NUM_BIG_BLOCK_DEPOT_BLOCKS_POS = 0x2c; - const ROOT_START_BLOCK_POS = 0x30; - const SMALL_BLOCK_DEPOT_BLOCK_POS = 0x3c; - const EXTENSION_BLOCK_POS = 0x44; - const NUM_EXTENSION_BLOCK_POS = 0x48; - const BIG_BLOCK_DEPOT_BLOCKS_POS = 0x4c; + public const NUM_BIG_BLOCK_DEPOT_BLOCKS_POS = 0x2c; + public const ROOT_START_BLOCK_POS = 0x30; + public const SMALL_BLOCK_DEPOT_BLOCK_POS = 0x3c; + public const EXTENSION_BLOCK_POS = 0x44; + public const NUM_EXTENSION_BLOCK_POS = 0x48; + public const BIG_BLOCK_DEPOT_BLOCKS_POS = 0x4c; // property storage offsets (directory offsets) - const SIZE_OF_NAME_POS = 0x40; - const TYPE_POS = 0x42; - const START_BLOCK_POS = 0x74; - const SIZE_POS = 0x78; - - public $summaryInformation = null; - public $docSummaryInfos = null; - public $powerpointDocument = null; - public $currentUser = null; - public $pictures = null; - public $rootEntry = null; - public $props = array(); - public $smallBlockChain = null; - public $bigBlockChain = null; - public $entry = null; + public const SIZE_OF_NAME_POS = 0x40; + public const TYPE_POS = 0x42; + public const START_BLOCK_POS = 0x74; + public const SIZE_POS = 0x78; + + /** + * @var int|null + */ + public $summaryInformation; + /** + * @var int|null + */ + public $docSummaryInfos; + /** + * @var int|null + */ + public $powerpointDocument; + /** + * @var int|null + */ + public $currentUser; + /** + * @var int|null + */ + public $pictures; + /** + * @var int|null + */ + public $rootEntry; + /** + * @var array> + */ + public $props = []; + /** + * @var string|null + */ + public $smallBlockChain; + /** + * @var string|null + */ + public $bigBlockChain; + /** + * @var string|null + */ + public $entry; /** * Read the file * - * @param $sFileName string Filename + * @param string $sFileName Filename + * * @throws \Exception */ - public function read($sFileName) + public function read(string $sFileName): void { // Check if file exists and is readable if (!is_readable($sFileName)) { - throw new \Exception("Could not open " . $sFileName . " for reading! File does not exist, or it is not readable."); + throw new \Exception('Could not open ' . $sFileName . ' for reading! File does not exist, or it is not readable.'); } // Get the file identifier @@ -104,18 +139,18 @@ public function read($sFileName) // Total number of sectors used by MSAT $numExtensionBlocks = self::getInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS); - $bigBlockDepotBlocks = array(); + $bigBlockDepotBlocks = []; $pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS; $bbdBlocks = $numBigBlkDepotBlks; if ($numExtensionBlocks != 0) { - $bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS)/4; + $bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS) / 4; } for ($i = 0; $i < $bbdBlocks; ++$i) { - $bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos); - $pos += 4; + $bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos); + $pos += 4; } for ($j = 0; $j < $numExtensionBlocks; ++$j) { @@ -138,8 +173,8 @@ public function read($sFileName) for ($i = 0; $i < $numBigBlkDepotBlks; ++$i) { $pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE; - $this->bigBlockChain .= substr($this->data, $pos, 4*$bbs); - $pos += 4*$bbs; + $this->bigBlockChain .= substr($this->data, $pos, 4 * $bbs); + $pos += 4 * $bbs; } $sbdBlock = $sbdStartBlock; @@ -147,10 +182,10 @@ public function read($sFileName) while ($sbdBlock != -2) { $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE; - $this->smallBlockChain .= substr($this->data, $pos, 4*$bbs); - $pos += 4*$bbs; + $this->smallBlockChain .= substr($this->data, $pos, 4 * $bbs); + $pos += 4 * $bbs; - $sbdBlock = self::getInt4d($this->bigBlockChain, $sbdBlock*4); + $sbdBlock = self::getInt4d($this->bigBlockChain, $sbdBlock * 4); } // read the directory stream @@ -165,12 +200,8 @@ public function read($sFileName) * * @return string */ - public function getStream($stream) + public function getStream(int $stream): ?string { - if ($stream === null) { - return null; - } - $streamData = ''; if ($this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) { @@ -179,10 +210,10 @@ public function getStream($stream) $block = $this->props[$stream]['startBlock']; while ($block != -2) { - $pos = $block * self::SMALL_BLOCK_SIZE; + $pos = $block * self::SMALL_BLOCK_SIZE; $streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE); - $block = self::getInt4d($this->smallBlockChain, $block*4); + $block = self::getInt4d($this->smallBlockChain, $block * 4); } return $streamData; @@ -202,7 +233,7 @@ public function getStream($stream) while ($block != -2) { $pos = ($block + 1) * self::BIG_BLOCK_SIZE; $streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); - $block = self::getInt4d($this->bigBlockChain, $block*4); + $block = self::getInt4d($this->bigBlockChain, $block * 4); } return $streamData; @@ -212,9 +243,10 @@ public function getStream($stream) * Read a standard stream (by joining sectors using information from SAT) * * @param int $blID Sector ID where the stream starts + * * @return string Data for standard stream */ - private function readData($blID) + private function readData(int $blID): string { $block = $blID; $data = ''; @@ -222,15 +254,16 @@ private function readData($blID) while ($block != -2) { $pos = ($block + 1) * self::BIG_BLOCK_SIZE; $data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); - $block = self::getInt4d($this->bigBlockChain, $block*4); + $block = self::getInt4d($this->bigBlockChain, $block * 4); } + return $data; } /** * Read entries in the directory stream. */ - private function readPropertySets() + private function readPropertySets(): void { $offset = 0; @@ -241,7 +274,7 @@ private function readPropertySets() $data = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE); // size in bytes of name - $nameSize = ord($data[self::SIZE_OF_NAME_POS]) | (ord($data[self::SIZE_OF_NAME_POS+1]) << 8); + $nameSize = ord($data[self::SIZE_OF_NAME_POS]) | (ord($data[self::SIZE_OF_NAME_POS + 1]) << 8); // type of entry $type = ord($data[self::TYPE_POS]); @@ -252,13 +285,14 @@ private function readPropertySets() $size = self::getInt4d($data, self::SIZE_POS); - $name = str_replace("\x00", "", substr($data, 0, $nameSize)); + $name = str_replace("\x00", '', substr($data, 0, $nameSize)); if ($size > 0) { - $this->props[] = array ( - 'name' => $name, - 'type' => $type, - 'startBlock' => $startBlock, - 'size' => $size); + $this->props[] = [ + 'name' => $name, + 'type' => $type, + 'startBlock' => $startBlock, + 'size' => $size, + ]; // tmp helper to simplify checks $upName = strtoupper($name); @@ -268,14 +302,14 @@ private function readPropertySets() case 'R': $this->rootEntry = count($this->props) - 1; break; - case chr(1).'COMPOBJ': + case chr(1) . 'COMPOBJ': break; - case chr(1).'OLE': + case chr(1) . 'OLE': break; - case chr(5).'SUMMARYINFORMATION': + case chr(5) . 'SUMMARYINFORMATION': $this->summaryInformation = count($this->props) - 1; break; - case chr(5).'DOCUMENTSUMMARYINFORMATION': + case chr(5) . 'DOCUMENTSUMMARYINFORMATION': $this->docSummaryInfos = count($this->props) - 1; break; case 'CURRENT USER': @@ -288,7 +322,7 @@ private function readPropertySets() $this->powerpointDocument = count($this->props) - 1; break; default: - throw new \Exception('OLE Block Not defined: $upName : '.$upName. ' - $name : "'.$name.'"'); + throw new \Exception('OLE Block Not defined: $upName : ' . $upName . ' - $name : "' . $name . '"'); } } @@ -301,6 +335,7 @@ private function readPropertySets() * * @param string $data * @param int $pos + * * @return int */ private static function getInt4d($data, $pos) @@ -315,6 +350,7 @@ private static function getInt4d($data, $pos) } else { $ord24 = ($or24 & 127) << 24; } + return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $ord24; } } diff --git a/src/Common/Microsoft/PasswordEncoder.php b/src/Common/Microsoft/PasswordEncoder.php index f620f4c..097060b 100644 --- a/src/Common/Microsoft/PasswordEncoder.php +++ b/src/Common/Microsoft/PasswordEncoder.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,39 +22,43 @@ */ class PasswordEncoder { - const ALGORITHM_MD2 = 'MD2'; - const ALGORITHM_MD4 = 'MD4'; - const ALGORITHM_MD5 = 'MD5'; - const ALGORITHM_SHA_1 = 'SHA-1'; - const ALGORITHM_SHA_256 = 'SHA-256'; - const ALGORITHM_SHA_384 = 'SHA-384'; - const ALGORITHM_SHA_512 = 'SHA-512'; - const ALGORITHM_RIPEMD = 'RIPEMD'; - const ALGORITHM_RIPEMD_160 = 'RIPEMD-160'; - const ALGORITHM_MAC = 'MAC'; - const ALGORITHM_HMAC = 'HMAC'; + public const ALGORITHM_MD2 = 'MD2'; + public const ALGORITHM_MD4 = 'MD4'; + public const ALGORITHM_MD5 = 'MD5'; + public const ALGORITHM_SHA_1 = 'SHA-1'; + public const ALGORITHM_SHA_256 = 'SHA-256'; + public const ALGORITHM_SHA_384 = 'SHA-384'; + public const ALGORITHM_SHA_512 = 'SHA-512'; + public const ALGORITHM_RIPEMD = 'RIPEMD'; + public const ALGORITHM_RIPEMD_160 = 'RIPEMD-160'; + public const ALGORITHM_MAC = 'MAC'; + public const ALGORITHM_HMAC = 'HMAC'; /** * Mapping between algorithm name and algorithm ID * - * @var array + * @var array> + * * @see https://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.writeprotection.cryptographicalgorithmsid(v=office.14).aspx */ - private static $algorithmMapping = array( - self::ALGORITHM_MD2 => array(1, 'md2'), - self::ALGORITHM_MD4 => array(2, 'md4'), - self::ALGORITHM_MD5 => array(3, 'md5'), - self::ALGORITHM_SHA_1 => array(4, 'sha1'), - self::ALGORITHM_MAC => array(5, ''), // 'mac' -> not possible with hash() - self::ALGORITHM_RIPEMD => array(6, 'ripemd'), - self::ALGORITHM_RIPEMD_160 => array(7, 'ripemd160'), - self::ALGORITHM_HMAC => array(9, ''), //'hmac' -> not possible with hash() - self::ALGORITHM_SHA_256 => array(12, 'sha256'), - self::ALGORITHM_SHA_384 => array(13, 'sha384'), - self::ALGORITHM_SHA_512 => array(14, 'sha512'), - ); - - private static $initialCodeArray = array( + private static $algorithmMapping = [ + self::ALGORITHM_MD2 => [1, 'md2'], + self::ALGORITHM_MD4 => [2, 'md4'], + self::ALGORITHM_MD5 => [3, 'md5'], + self::ALGORITHM_SHA_1 => [4, 'sha1'], + self::ALGORITHM_MAC => [5, ''], // 'mac' -> not possible with hash() + self::ALGORITHM_RIPEMD => [6, 'ripemd'], + self::ALGORITHM_RIPEMD_160 => [7, 'ripemd160'], + self::ALGORITHM_HMAC => [9, ''], //'hmac' -> not possible with hash() + self::ALGORITHM_SHA_256 => [12, 'sha256'], + self::ALGORITHM_SHA_384 => [13, 'sha384'], + self::ALGORITHM_SHA_512 => [14, 'sha512'], + ]; + + /** + * @var array + */ + private static $initialCodeArray = [ 0xE1F0, 0x1D0F, 0xCC9C, @@ -69,39 +74,47 @@ class PasswordEncoder 0x280C, 0xA96A, 0x4EC3, - ); - - private static $encryptionMatrix = array( - array(0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09), - array(0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF), - array(0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0), - array(0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40), - array(0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5), - array(0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A), - array(0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9), - array(0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0), - array(0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC), - array(0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10), - array(0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168), - array(0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C), - array(0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD), - array(0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC), - array(0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4), - ); + ]; + /** + * @var array> + */ + private static $encryptionMatrix = [ + [0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09], + [0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF], + [0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0], + [0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40], + [0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5], + [0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A], + [0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9], + [0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0], + [0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC], + [0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10], + [0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168], + [0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C], + [0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD], + [0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC], + [0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4], + ]; + + /** + * @var int + */ private static $passwordMaxLength = 15; /** * Create a hashed password that MS Word will be able to work with + * * @see https://blogs.msdn.microsoft.com/vsod/2010/04/05/how-to-set-the-editing-restrictions-in-word-using-open-xml-sdk-2-0/ * * @param string $password * @param string $algorithmName * @param string $salt * @param int $spinCount + * * @return string */ - public static function hashPassword($password, $algorithmName = self::ALGORITHM_SHA_1, $salt = null, $spinCount = 10000) + public static function hashPassword(string $password, string $algorithmName = self::ALGORITHM_SHA_1, string $salt = null, int $spinCount = 10000) { $origEncoding = mb_internal_encoding(); mb_internal_encoding('UTF-8'); @@ -111,9 +124,9 @@ public static function hashPassword($password, $algorithmName = self::ALGORITHM_ // Get the single-byte values by iterating through the Unicode characters of the truncated password. // For each character, if the low byte is not equal to 0, take it. Otherwise, take the high byte. $passUtf8 = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8'); - $byteChars = array(); + $byteChars = []; - for ($i = 0; $i < mb_strlen($password); $i++) { + for ($i = 0; $i < mb_strlen($password); ++$i) { $byteChars[$i] = ord(substr($passUtf8, $i * 2, 1)); if ($byteChars[$i] == 0) { @@ -135,7 +148,7 @@ public static function hashPassword($password, $algorithmName = self::ALGORITHM_ $algorithm = self::getAlgorithm($algorithmName); $generatedKey = hash($algorithm, $salt . $generatedKey, true); - for ($i = 0; $i < $spinCount; $i++) { + for ($i = 0; $i < $spinCount; ++$i) { $generatedKey = hash($algorithm, $generatedKey . pack('CCCC', $i, $i >> 8, $i >> 16, $i >> 24), true); } $generatedKey = base64_encode($generatedKey); @@ -149,9 +162,10 @@ public static function hashPassword($password, $algorithmName = self::ALGORITHM_ * Get algorithm from self::$algorithmMapping * * @param string $algorithmName + * * @return string */ - private static function getAlgorithm($algorithmName) + private static function getAlgorithm(string $algorithmName): string { $algorithm = self::$algorithmMapping[$algorithmName][1]; if ($algorithm == '') { @@ -165,9 +179,10 @@ private static function getAlgorithm($algorithmName) * Returns the algorithm ID * * @param string $algorithmName + * * @return int */ - public static function getAlgorithmId($algorithmName) + public static function getAlgorithmId(string $algorithmName): int { return self::$algorithmMapping[$algorithmName][0]; } @@ -175,10 +190,11 @@ public static function getAlgorithmId($algorithmName) /** * Build combined key from low-order word and high-order word * - * @param array $byteChars byte array representation of password + * @param array $byteChars byte array representation of password + * * @return int */ - private static function buildCombinedKey($byteChars) + private static function buildCombinedKey(array $byteChars): int { $byteCharsLength = count($byteChars); // Compute the high-order word @@ -189,10 +205,10 @@ private static function buildCombinedKey($byteChars) // For every bit in the character, starting with the least significant and progressing to (but excluding) // the most significant, if the bit is set, XOR the key’s high-order word with the corresponding word from // the Encryption Matrix - for ($i = 0; $i < $byteCharsLength; $i++) { + for ($i = 0; $i < $byteCharsLength; ++$i) { $tmp = self::$passwordMaxLength - $byteCharsLength + $i; $matrixRow = self::$encryptionMatrix[$tmp]; - for ($intBit = 0; $intBit < 7; $intBit++) { + for ($intBit = 0; $intBit < 7; ++$intBit) { if (($byteChars[$i] & (0x0001 << $intBit)) != 0) { $highOrderWord = ($highOrderWord ^ $matrixRow[$intBit]); } @@ -203,7 +219,7 @@ private static function buildCombinedKey($byteChars) // Initialize with 0 $lowOrderWord = 0; // For each character in the password, going backwards - for ($i = $byteCharsLength - 1; $i >= 0; $i--) { + for ($i = $byteCharsLength - 1; $i >= 0; --$i) { // low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR character $lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteChars[$i]); } @@ -218,7 +234,9 @@ private static function buildCombinedKey($byteChars) * Simulate behaviour of (signed) int32 * * @codeCoverageIgnore + * * @param int $value + * * @return int */ private static function int32($value) diff --git a/src/Common/Text.php b/src/Common/Text.php index 91c790a..1410f79 100644 --- a/src/Common/Text.php +++ b/src/Common/Text.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -26,17 +27,17 @@ class Text * * @var string[] */ - private static $controlCharacters = array(); + private static $controlCharacters = []; /** * Build control characters array */ - private static function buildControlCharacters() + private static function buildControlCharacters(): void { for ($i = 0; $i <= 19; ++$i) { if ($i != 9 && $i != 10 && $i != 13) { - $find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_'; - $replace = chr($i); + $find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_'; + $replace = chr($i); self::$controlCharacters[$find] = $replace; } } @@ -53,10 +54,11 @@ private static function buildControlCharacters() * So you could end up with something like _x0008_ in a string (either in a cell value () * element or in the shared string element. * - * @param string $value Value to escape + * @param string $value Value to escape + * * @return string */ - public static function controlCharacterPHP2OOXML($value = '') + public static function controlCharacterPHP2OOXML(string $value = ''): string { if (empty(self::$controlCharacters)) { self::buildControlCharacters(); @@ -67,33 +69,41 @@ public static function controlCharacterPHP2OOXML($value = '') /** * Return a number formatted for being integrated in xml files + * * @param float $number - * @param integer $decimals + * @param int $decimals + * + * @return string */ - public static function numberFormat($number, $decimals) + public static function numberFormat(float $number, int $decimals): string { return number_format($number, $decimals, '.', ''); } /** * @param int $dec - * @link http://stackoverflow.com/a/7153133/2235790 + * + * @see http://stackoverflow.com/a/7153133/2235790 + * * @author velcrow + * + * @return string */ - public static function chr($dec) + public static function chr(int $dec): string { - if ($dec<=0x7F) { + if ($dec <= 0x7F) { return chr($dec); } - if ($dec<=0x7FF) { - return chr(($dec>>6)+192).chr(($dec&63)+128); + if ($dec <= 0x7FF) { + return chr(($dec >> 6) + 192) . chr(($dec & 63) + 128); } - if ($dec<=0xFFFF) { - return chr(($dec>>12)+224).chr((($dec>>6)&63)+128).chr(($dec&63)+128); + if ($dec <= 0xFFFF) { + return chr(($dec >> 12) + 224) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128); } - if ($dec<=0x1FFFFF) { - return chr(($dec>>18)+240).chr((($dec>>12)&63)+128).chr((($dec>>6)&63)+128).chr(($dec&63)+128); + if ($dec <= 0x1FFFFF) { + return chr(($dec >> 18) + 240) . chr((($dec >> 12) & 63) + 128) . chr((($dec >> 6) & 63) + 128) . chr(($dec & 63) + 128); } + return ''; } @@ -101,9 +111,10 @@ public static function chr($dec) * Convert from OpenXML escaped control character to PHP control character * * @param string $value Value to unescape + * * @return string */ - public static function controlCharacterOOXML2PHP($value = '') + public static function controlCharacterOOXML2PHP(string $value = ''): string { if (empty(self::$controlCharacters)) { self::buildControlCharacters(); @@ -116,9 +127,10 @@ public static function controlCharacterOOXML2PHP($value = '') * Check if a string contains UTF-8 data * * @param string $value - * @return boolean + * + * @return bool */ - public static function isUTF8($value = '') + public static function isUTF8(string $value = ''): bool { return is_string($value) && ($value === '' || preg_match('/^./su', $value) == 1); } @@ -126,10 +138,11 @@ public static function isUTF8($value = '') /** * Return UTF8 encoded value * - * @param string $value - * @return string + * @param string|null $value + * + * @return string|null */ - public static function toUTF8($value = '') + public static function toUTF8(?string $value = ''): ?string { if (!is_null($value) && !self::isUTF8($value)) { $value = utf8_encode($value); @@ -144,10 +157,12 @@ public static function toUTF8($value = '') * The function is splitted to reduce cyclomatic complexity * * @param string $text UTF8 text + * * @return string Unicode text + * * @since 0.11.0 */ - public static function toUnicode($text) + public static function toUnicode(string $text): string { return self::unicodeToEntities(self::utf8ToUnicode($text)); } @@ -156,18 +171,20 @@ public static function toUnicode($text) * Returns unicode array from UTF8 text * * @param string $text UTF8 text - * @return array + * + * @return array + * * @since 0.11.0 - * @link http://www.randomchaos.com/documents/?source=php_and_unicode + * @see http://www.randomchaos.com/documents/?source=php_and_unicode */ - public static function utf8ToUnicode($text) + public static function utf8ToUnicode(string $text): array { - $unicode = array(); - $values = array(); + $unicode = []; + $values = []; $lookingFor = 1; // Gets unicode for each character - for ($i = 0; $i < strlen($text); $i++) { + for ($i = 0; $i < strlen($text); ++$i) { $thisValue = ord($text[$i]); if ($thisValue < 128) { $unicode[] = $thisValue; @@ -183,7 +200,7 @@ public static function utf8ToUnicode($text) $number = (($values[0] % 32) * 64) + ($values[1] % 64); } $unicode[] = $number; - $values = array(); + $values = []; $lookingFor = 1; } } @@ -195,12 +212,14 @@ public static function utf8ToUnicode($text) /** * Returns entites from unicode array * - * @param array $unicode + * @param array $unicode + * * @return string + * * @since 0.11.0 - * @link http://www.randomchaos.com/documents/?source=php_and_unicode + * @see http://www.randomchaos.com/documents/?source=php_and_unicode */ - private static function unicodeToEntities($unicode) + private static function unicodeToEntities(array $unicode): string { $entities = ''; @@ -216,10 +235,11 @@ private static function unicodeToEntities($unicode) /** * Return name without underscore for < 0.10.0 variable name compatibility * - * @param string $value + * @param string|null $value + * * @return string */ - public static function removeUnderscorePrefix($value) + public static function removeUnderscorePrefix(?string $value): string { if (!is_null($value)) { if (substr($value, 0, 1) == '_') { diff --git a/src/Common/XMLReader.php b/src/Common/XMLReader.php index f804fb8..9d3f117 100644 --- a/src/Common/XMLReader.php +++ b/src/Common/XMLReader.php @@ -9,13 +9,20 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\Common; +use DOMDocument; +use DOMElement; +use DOMNodeList; +use DOMXpath; +use ZipArchive; + /** * XML Reader wrapper * @@ -26,14 +33,14 @@ class XMLReader /** * DOMDocument object * - * @var \DOMDocument + * @var DOMDocument */ private $dom = null; /** * DOMXpath object * - * @var \DOMXpath + * @var DOMXpath */ private $xpath = null; @@ -42,16 +49,18 @@ class XMLReader * * @param string $zipFile * @param string $xmlFile - * @return \DOMDocument|false + * + * @return DOMDocument|false + * * @throws \Exception */ - public function getDomFromZip($zipFile, $xmlFile) + public function getDomFromZip(string $zipFile, string $xmlFile) { if (file_exists($zipFile) === false) { throw new \Exception('Cannot find archive file.'); } - $zip = new \ZipArchive(); + $zip = new ZipArchive(); $zip->open($zipFile); $content = $zip->getFromName($xmlFile); $zip->close(); @@ -67,13 +76,15 @@ public function getDomFromZip($zipFile, $xmlFile) * Get DOMDocument from content string * * @param string $content - * @return \DOMDocument + * + * @return DOMDocument */ - public function getDomFromString($content) + public function getDomFromString(string $content) { - libxml_disable_entity_loader(true); - $this->dom = new \DOMDocument(); + $originalLibXMLEntityValue = libxml_disable_entity_loader(true); + $this->dom = new DOMDocument(); $this->dom->loadXML($content); + libxml_disable_entity_loader($originalLibXMLEntityValue); return $this->dom; } @@ -82,16 +93,17 @@ public function getDomFromString($content) * Get elements * * @param string $path - * @param \DOMElement $contextNode - * @return \DOMNodeList + * @param DOMElement $contextNode + * + * @return DOMNodeList */ - public function getElements($path, \DOMElement $contextNode = null) + public function getElements(string $path, DOMElement $contextNode = null) { if ($this->dom === null) { - return array(); + return new DOMNodeList(); } if ($this->xpath === null) { - $this->xpath = new \DOMXpath($this->dom); + $this->xpath = new DOMXpath($this->dom); } if (is_null($contextNode)) { @@ -106,7 +118,9 @@ public function getElements($path, \DOMElement $contextNode = null) * * @param string $prefix The prefix * @param string $namespaceURI The URI of the namespace + * * @return bool true on success or false on failure + * * @throws \InvalidArgumentException If called before having loaded the DOM document */ public function registerNamespace($prefix, $namespaceURI) @@ -115,8 +129,9 @@ public function registerNamespace($prefix, $namespaceURI) throw new \InvalidArgumentException('Dom needs to be loaded before registering a namespace'); } if ($this->xpath === null) { - $this->xpath = new \DOMXpath($this->dom); + $this->xpath = new DOMXpath($this->dom); } + return $this->xpath->registerNamespace($prefix, $namespaceURI); } @@ -124,14 +139,15 @@ public function registerNamespace($prefix, $namespaceURI) * Get element * * @param string $path - * @param \DOMElement $contextNode - * @return \DOMElement|null + * @param DOMElement $contextNode + * + * @return DOMElement|null */ - public function getElement($path, \DOMElement $contextNode = null) + public function getElement($path, DOMElement $contextNode = null): ?DOMElement { $elements = $this->getElements($path, $contextNode); if ($elements->length > 0) { - return $elements->item(0); + return $elements->item(0) instanceof DOMElement ? $elements->item(0) : null; } return null; @@ -141,17 +157,18 @@ public function getElement($path, \DOMElement $contextNode = null) * Get element attribute * * @param string $attribute - * @param \DOMElement $contextNode + * @param DOMElement $contextNode * @param string $path + * * @return string|null */ - public function getAttribute($attribute, \DOMElement $contextNode = null, $path = null) + public function getAttribute($attribute, DOMElement $contextNode = null, $path = null) { $return = null; if ($path !== null) { $elements = $this->getElements($path, $contextNode); if ($elements->length > 0) { - /** @var \DOMElement $node Type hint */ + /** @var DOMElement $node Type hint */ $node = $elements->item(0); $return = $node->getAttribute($attribute); } @@ -168,10 +185,11 @@ public function getAttribute($attribute, \DOMElement $contextNode = null, $path * Get element value * * @param string $path - * @param \DOMElement $contextNode + * @param DOMElement $contextNode + * * @return string|null */ - public function getValue($path, \DOMElement $contextNode = null) + public function getValue($path, DOMElement $contextNode = null) { $elements = $this->getElements($path, $contextNode); if ($elements->length > 0) { @@ -185,10 +203,11 @@ public function getValue($path, \DOMElement $contextNode = null) * Count elements * * @param string $path - * @param \DOMElement $contextNode - * @return integer + * @param DOMElement $contextNode + * + * @return int */ - public function countElements($path, \DOMElement $contextNode = null) + public function countElements($path, DOMElement $contextNode = null) { $elements = $this->getElements($path, $contextNode); @@ -199,10 +218,11 @@ public function countElements($path, \DOMElement $contextNode = null) * Element exists * * @param string $path - * @param \DOMElement $contextNode - * @return boolean + * @param DOMElement $contextNode + * + * @return bool */ - public function elementExists($path, \DOMElement $contextNode = null) + public function elementExists($path, DOMElement $contextNode = null) { return $this->getElements($path, $contextNode)->length > 0; } diff --git a/src/Common/XMLWriter.php b/src/Common/XMLWriter.php index 43e5b66..da520db 100644 --- a/src/Common/XMLWriter.php +++ b/src/Common/XMLWriter.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -35,8 +36,8 @@ class XMLWriter extends \XMLWriter { /** Temporary storage method */ - const STORAGE_MEMORY = 1; - const STORAGE_DISK = 2; + public const STORAGE_MEMORY = 1; + public const STORAGE_DISK = 2; /** * Temporary filename @@ -50,6 +51,7 @@ class XMLWriter extends \XMLWriter * * @param int $pTemporaryStorage Temporary storage location * @param string $pTemporaryStorageDir Temporary storage folder + * @param bool $compatibility */ public function __construct($pTemporaryStorage = self::STORAGE_MEMORY, $pTemporaryStorageDir = null, $compatibility = false) { @@ -86,7 +88,7 @@ public function __destruct() return; } if (PHP_OS != 'WINNT' && @unlink($this->tempFileName) === false) { - throw new \Exception('The file '.$this->tempFileName.' could not be deleted.'); + throw new \Exception('The file ' . $this->tempFileName . ' could not be deleted.'); } } @@ -102,10 +104,10 @@ public function getData() } $this->flush(); + return file_get_contents($this->tempFileName); } - /** * Write simple element and attribute(s) block * @@ -114,15 +116,16 @@ public function getData() * 2. If not, then it's a simple attribute-value pair * * @param string $element - * @param string|array $attributes + * @param string|array $attributes * @param string $value + * * @return void */ - public function writeElementBlock($element, $attributes, $value = null) + public function writeElementBlock(string $element, $attributes, string $value = null) { $this->startElement($element); if (!is_array($attributes)) { - $attributes = array($attributes => $value); + $attributes = [$attributes => $value]; } foreach ($attributes as $attribute => $value) { $this->writeAttribute($attribute, $value); @@ -135,13 +138,14 @@ public function writeElementBlock($element, $attributes, $value = null) * * @param bool $condition * @param string $element - * @param string $attribute + * @param string|null $attribute * @param mixed $value + * * @return void */ - public function writeElementIf($condition, $element, $attribute = null, $value = null) + public function writeElementIf(bool $condition, string $element, ?string $attribute = null, $value = null) { - if ($condition == true) { + if ($condition) { if (is_null($attribute)) { $this->writeElement($element, $value); } else { @@ -158,11 +162,12 @@ public function writeElementIf($condition, $element, $attribute = null, $value = * @param bool $condition * @param string $attribute * @param mixed $value + * * @return void */ - public function writeAttributeIf($condition, $attribute, $value) + public function writeAttributeIf(bool $condition, string $attribute, $value) { - if ($condition == true) { + if ($condition) { $this->writeAttribute($attribute, $value); } } @@ -170,6 +175,7 @@ public function writeAttributeIf($condition, $attribute, $value) /** * @param string $name * @param mixed $value + * * @return bool */ public function writeAttribute($name, $value) @@ -177,6 +183,7 @@ public function writeAttribute($name, $value) if (is_float($value)) { $value = json_encode($value); } + return parent::writeAttribute($name, $value); } } diff --git a/tests/Common/Tests/Adapter/Zip/AbstractZipAdapterTest.php b/tests/Common/Tests/Adapter/Zip/AbstractZipAdapterTest.php index c95eae7..3387cf4 100644 --- a/tests/Common/Tests/Adapter/Zip/AbstractZipAdapterTest.php +++ b/tests/Common/Tests/Adapter/Zip/AbstractZipAdapterTest.php @@ -2,28 +2,33 @@ namespace Common\Tests\Adapter\Zip; +use PhpOffice\Common\Adapter\Zip\ZipInterface; use PhpOffice\Common\Tests\TestHelperZip; abstract class AbstractZipAdapterTest extends \PHPUnit\Framework\TestCase { + /** + * @var string + */ protected $zipTest; /** * Returns a new instance of the adapter to test + * * @return \PhpOffice\Common\Adapter\Zip\ZipInterface */ - abstract protected function createAdapter(); + abstract protected function createAdapter(): ZipInterface; - public function setUp() + public function setUp(): void { parent::setUp(); - $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'files'.DIRECTORY_SEPARATOR; + $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR; $this->zipTest = tempnam(sys_get_temp_dir(), 'PhpOfficeCommon'); - copy($pathResources.'Sample_01_Simple.pptx', $this->zipTest); + copy($pathResources . 'Sample_01_Simple.pptx', $this->zipTest); } - public function tearDown() + public function tearDown(): void { parent::tearDown(); @@ -32,20 +37,20 @@ public function tearDown() } } - public function testOpen() + public function testOpen(): void { $adapter = $this->createAdapter(); $this->assertSame($adapter, $adapter->open($this->zipTest)); } - public function testClose() + public function testClose(): void { $adapter = $this->createAdapter(); $adapter->open($this->zipTest); $this->assertSame($adapter, $adapter->close()); } - public function testAddFromString() + public function testAddFromString(): void { $expectedPath = 'file.test'; $expectedContent = 'Content'; diff --git a/tests/Common/Tests/Adapter/Zip/PclZipAdapterTest.php b/tests/Common/Tests/Adapter/Zip/PclZipAdapterTest.php index c7535bc..48b40ed 100644 --- a/tests/Common/Tests/Adapter/Zip/PclZipAdapterTest.php +++ b/tests/Common/Tests/Adapter/Zip/PclZipAdapterTest.php @@ -3,11 +3,11 @@ namespace Common\Tests\Adapter\Zip; use PhpOffice\Common\Adapter\Zip\PclZipAdapter; -use PhpOffice\Common\Tests\TestHelperZip; +use PhpOffice\Common\Adapter\Zip\ZipInterface; class PclZipAdapterTest extends AbstractZipAdapterTest { - protected function createAdapter() + protected function createAdapter(): ZipInterface { return new PclZipAdapter(); } diff --git a/tests/Common/Tests/Adapter/Zip/ZipArchiveAdapterTest.php b/tests/Common/Tests/Adapter/Zip/ZipArchiveAdapterTest.php index 896aa3e..01518ad 100644 --- a/tests/Common/Tests/Adapter/Zip/ZipArchiveAdapterTest.php +++ b/tests/Common/Tests/Adapter/Zip/ZipArchiveAdapterTest.php @@ -3,11 +3,11 @@ namespace Common\Tests\Adapter\Zip; use PhpOffice\Common\Adapter\Zip\ZipArchiveAdapter; -use PhpOffice\Common\Tests\TestHelperZip; +use PhpOffice\Common\Adapter\Zip\ZipInterface; class ZipArchiveAdapterTest extends AbstractZipAdapterTest { - protected function createAdapter() + protected function createAdapter(): ZipInterface { return new ZipArchiveAdapter(); } diff --git a/tests/Common/Tests/AutoloaderTest.php b/tests/Common/Tests/AutoloaderTest.php index ff4c792..d20458a 100644 --- a/tests/Common/Tests/AutoloaderTest.php +++ b/tests/Common/Tests/AutoloaderTest.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -26,11 +27,11 @@ class AutoloaderTest extends \PHPUnit\Framework\TestCase /** * Register */ - public function testRegister() + public function testRegister(): void { Autoloader::register(); $this->assertContains( - array('PhpOffice\\Common\\Autoloader', 'autoload'), + ['PhpOffice\\Common\\Autoloader', 'autoload'], spl_autoload_functions() ); } @@ -38,7 +39,7 @@ public function testRegister() /** * Autoload */ - public function testAutoload() + public function testAutoload(): void { $declared = get_declared_classes(); $declaredCount = count($declared); diff --git a/tests/Common/Tests/DrawingTest.php b/tests/Common/Tests/DrawingTest.php index bbcf4e3..d8106c7 100644 --- a/tests/Common/Tests/DrawingTest.php +++ b/tests/Common/Tests/DrawingTest.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,13 +22,11 @@ /** * Test class for IOFactory * - * @coversDefaultClass PhpOffice\Common\IOFactory + * @coversDefaultClass \PhpOffice\Common\IOFactory */ class DrawingTest extends \PHPUnit\Framework\TestCase { - /** - */ - public function testDegreesAngle() + public function testDegreesAngle(): void { $value = rand(1, 100); @@ -37,55 +36,60 @@ public function testDegreesAngle() $this->assertEquals(round($value / 60000), Drawing::angleToDegrees($value)); } - /** - */ - public function testPixelsCentimeters() + public function testPixelsCentimeters(): void { $value = rand(1, 100); $this->assertEquals(0, Drawing::pixelsToCentimeters()); $this->assertEquals($value / Drawing::DPI_96 * 2.54, Drawing::pixelsToCentimeters($value)); $this->assertEquals(0, Drawing::centimetersToPixels()); - $this->assertEquals($value / 2.54 * Drawing::DPI_96, Drawing::centimetersToPixels($value)); + $this->assertEquals(round($value / 2.54 * Drawing::DPI_96), Drawing::centimetersToPixels($value)); } - /** - */ - public function testPixelsEMU() + public function testPixelsEMU(): void { $value = rand(1, 100); $this->assertEquals(0, Drawing::pixelsToEmu()); - $this->assertEquals(round($value*9525), Drawing::pixelsToEmu($value)); + $this->assertEquals(round($value * 9525), Drawing::pixelsToEmu($value)); $this->assertEquals(0, Drawing::emuToPixels()); - $this->assertEquals(round($value/9525), Drawing::emuToPixels($value)); + $this->assertEquals(round($value / 9525), Drawing::emuToPixels($value)); } - /** - */ - public function testPixelsPoints() + public function testPixelsPoints(): void { $value = rand(1, 100); $this->assertEquals(0, Drawing::pixelsToPoints()); - $this->assertEquals($value*0.67777777, Drawing::pixelsToPoints($value)); + $this->assertEquals($value * 0.75, Drawing::pixelsToPoints($value)); $this->assertEquals(0, Drawing::pointsToPixels()); - $this->assertEquals($value* 1.333333333, Drawing::pointsToPixels($value)); + $this->assertEquals($value / 0.75, Drawing::pointsToPixels($value)); } - /** - */ - public function testPointsCentimeters() + public function testPointsCentimeters(): void { $value = rand(1, 100); $this->assertEquals(0, Drawing::pointsToCentimeters()); - $this->assertEquals($value * 1.333333333 / Drawing::DPI_96 * 2.54, Drawing::pointsToCentimeters($value)); + $this->assertEquals($value / 0.75 / Drawing::DPI_96 * 2.54, Drawing::pointsToCentimeters($value)); + } + + public function testPointsEmu(): void + { + $value = rand(1, 100); + + $this->assertEquals(0, Drawing::pointsToEmu()); + $this->assertEquals(round($value / 0.75 / 9525), Drawing::pointsToEmu($value)); + } + + public function testCentimetersPoints(): void + { + $this->assertEquals(0, Drawing::centimetersToPoints()); + $this->assertEquals(28.346456692913385, Drawing::centimetersToPoints(1)); + $this->assertEquals(31.181102362204726, Drawing::centimetersToPoints(1.1)); } - /** - */ - public function testTwips() + public function testTwips(): void { $value = rand(1, 100); @@ -105,21 +109,21 @@ public function testTwips() // Pixels $this->assertEquals(0, Drawing::twipsToPixels()); - $this->assertEquals(round($value / 15.873984), Drawing::twipsToPixels($value)); + $this->assertEquals(round($value / 15), Drawing::twipsToPixels($value)); } - public function testHTML() + public function testHTML(): void { - $this->assertFalse(Drawing::htmlToRGB('0')); - $this->assertFalse(Drawing::htmlToRGB('00')); - $this->assertFalse(Drawing::htmlToRGB('0000')); - $this->assertFalse(Drawing::htmlToRGB('00000')); + $this->assertNull(Drawing::htmlToRGB('0')); + $this->assertNull(Drawing::htmlToRGB('00')); + $this->assertNull(Drawing::htmlToRGB('0000')); + $this->assertNull(Drawing::htmlToRGB('00000')); - $this->assertInternalType('array', Drawing::htmlToRGB('ABCDEF')); + $this->assertIsArray(Drawing::htmlToRGB('ABCDEF')); $this->assertCount(3, Drawing::htmlToRGB('ABCDEF')); - $this->assertEquals(array(0xAB, 0xCD, 0xEF), Drawing::htmlToRGB('ABCDEF')); - $this->assertEquals(array(0xAB, 0xCD, 0xEF), Drawing::htmlToRGB('#ABCDEF')); - $this->assertEquals(array(0xAA, 0xBB, 0xCC), Drawing::htmlToRGB('ABC')); - $this->assertEquals(array(0xAA, 0xBB, 0xCC), Drawing::htmlToRGB('#ABC')); + $this->assertEquals([0xAB, 0xCD, 0xEF], Drawing::htmlToRGB('ABCDEF')); + $this->assertEquals([0xAB, 0xCD, 0xEF], Drawing::htmlToRGB('#ABCDEF')); + $this->assertEquals([0xAA, 0xBB, 0xCC], Drawing::htmlToRGB('ABC')); + $this->assertEquals([0xAA, 0xBB, 0xCC], Drawing::htmlToRGB('#ABC')); } } diff --git a/tests/Common/Tests/FileTest.php b/tests/Common/Tests/FileTest.php index 439cc7b..557644f 100644 --- a/tests/Common/Tests/FileTest.php +++ b/tests/Common/Tests/FileTest.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,42 +22,45 @@ /** * Test class for File * - * @coversDefaultClass PhpOffice\Common\File + * @coversDefaultClass \PhpOffice\Common\File */ class FileTest extends \PHPUnit\Framework\TestCase { - /** - */ - public function testFileExists() + public function testFileExists(): void { - $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR; - $this->assertTrue(File::fileExists($pathResources.'images'.DIRECTORY_SEPARATOR.'PHPPowerPointLogo.png')); - $this->assertFalse(File::fileExists($pathResources.'images'.DIRECTORY_SEPARATOR.'PHPPowerPointLogo_404.png')); - $this->assertTrue(File::fileExists('zip://'.$pathResources.'files'.DIRECTORY_SEPARATOR.'Sample_01_Simple.pptx#[Content_Types].xml')); - $this->assertFalse(File::fileExists('zip://'.$pathResources.'files'.DIRECTORY_SEPARATOR.'Sample_01_Simple.pptx#404.xml')); - $this->assertFalse(File::fileExists('zip://'.$pathResources.'files'.DIRECTORY_SEPARATOR.'404.pptx#404.xml')); + $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR; + $this->assertTrue(File::fileExists($pathResources . 'images' . DIRECTORY_SEPARATOR . 'PHPPowerPointLogo.png')); + $this->assertFalse(File::fileExists($pathResources . 'images' . DIRECTORY_SEPARATOR . 'PHPPowerPointLogo_404.png')); + $this->assertTrue(File::fileExists('zip://' . $pathResources . 'files' . DIRECTORY_SEPARATOR . 'Sample_01_Simple.pptx#[Content_Types].xml')); + $this->assertFalse(File::fileExists('zip://' . $pathResources . 'files' . DIRECTORY_SEPARATOR . 'Sample_01_Simple.pptx#404.xml')); + $this->assertFalse(File::fileExists('zip://' . $pathResources . 'files' . DIRECTORY_SEPARATOR . '404.pptx#404.xml')); + + // Set a ZIP en ReadOnly Mode + $zipTest = tempnam(sys_get_temp_dir(), 'PhpOfficeCommon'); + copy($pathResources . 'files' . DIRECTORY_SEPARATOR . 'Sample_01_Simple.pptx', $zipTest); + chmod($zipTest, 333); + $this->assertFalse(File::fileExists('zip://' . $zipTest)); + unlink($zipTest); } - /** - */ - public function testGetFileContents() + public function testGetFileContents(): void { - $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR; - $this->assertInternalType('string', File::fileGetContents($pathResources.'images'.DIRECTORY_SEPARATOR.'PHPPowerPointLogo.png')); - $this->assertFalse(File::fileGetContents($pathResources.'images'.DIRECTORY_SEPARATOR.'PHPPowerPointLogo_404.png')); - $this->assertInternalType('string', File::fileGetContents('zip://'.$pathResources.'files'.DIRECTORY_SEPARATOR.'Sample_01_Simple.pptx#[Content_Types].xml')); - $this->assertFalse(File::fileGetContents('zip://'.$pathResources.'files'.DIRECTORY_SEPARATOR.'Sample_01_Simple.pptx#404.xml')); - $this->assertFalse(File::fileGetContents('zip://'.$pathResources.'files'.DIRECTORY_SEPARATOR.'404.pptx#404.xml')); + $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR; + $this->assertIsString(File::fileGetContents($pathResources . 'images' . DIRECTORY_SEPARATOR . 'PHPPowerPointLogo.png')); + $this->assertNull(File::fileGetContents($pathResources . 'images' . DIRECTORY_SEPARATOR . 'PHPPowerPointLogo_404.png')); + $this->assertIsString(File::fileGetContents('zip://' . $pathResources . 'files' . DIRECTORY_SEPARATOR . 'Sample_01_Simple.pptx#[Content_Types].xml')); + $this->assertNull(File::fileGetContents('zip://' . $pathResources . 'files' . DIRECTORY_SEPARATOR . 'Sample_01_Simple.pptx#404.xml')); + $this->assertNull(File::fileGetContents('zip://' . $pathResources . 'files' . DIRECTORY_SEPARATOR . '404.pptx#404.xml')); } - /** - */ - public function testRealPath() + public function testRealPath(): void { - $pathFiles = PHPOFFICE_COMMON_TESTS_BASE_DIR.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'files'.DIRECTORY_SEPARATOR; - - $this->assertEquals($pathFiles.'Sample_01_Simple.pptx', File::realpath($pathFiles.'Sample_01_Simple.pptx')); - $this->assertEquals('zip://'.$pathFiles.'Sample_01_Simple.pptx#[Content_Types].xml', File::realpath('zip://'.$pathFiles.'Sample_01_Simple.pptx#[Content_Types].xml')); - $this->assertEquals('zip://'.$pathFiles.'Sample_01_Simple.pptx#/[Content_Types].xml', File::realpath('zip://'.$pathFiles.'Sample_01_Simple.pptx#/rels/../[Content_Types].xml')); + $pathFiles = PHPOFFICE_COMMON_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR; + $this->assertEquals($pathFiles . 'Sample_01_Simple.pptx', File::realpath($pathFiles . 'Sample_01_Simple.pptx')); + $this->assertEquals( + 'zip://' . $pathFiles . 'Sample_01_Simple.pptx#[Content_Types].xml', + File::realpath('zip://' . $pathFiles . 'Sample_01_Simple.pptx#[Content_Types].xml') + ); + $this->assertEquals('zip://' . $pathFiles . 'Sample_01_Simple.pptx#/[Content_Types].xml', File::realpath('zip://' . $pathFiles . 'Sample_01_Simple.pptx#/rels/../[Content_Types].xml')); } } diff --git a/tests/Common/Tests/FontTest.php b/tests/Common/Tests/FontTest.php index c661502..d03e3e2 100644 --- a/tests/Common/Tests/FontTest.php +++ b/tests/Common/Tests/FontTest.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,13 +22,11 @@ /** * Test class for Font * - * @coversDefaultClass PhpOffice\Common\Font + * @coversDefaultClass \PhpOffice\Common\Font */ class FontTest extends \PHPUnit\Framework\TestCase { - /** - */ - public function testMath() + public function testMath(): void { $value = rand(1, 100); $this->assertEquals(16, Font::fontSizeToPixels()); diff --git a/tests/Common/Tests/Microsoft/PasswordEncoderTest.php b/tests/Common/Tests/Microsoft/PasswordEncoderTest.php index b796575..538aa4e 100644 --- a/tests/Common/Tests/Microsoft/PasswordEncoderTest.php +++ b/tests/Common/Tests/Microsoft/PasswordEncoderTest.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -20,6 +21,7 @@ /** * Test class for PhpOffice\Common\PasswordEncoder + * * @coversDefaultClass \PhpOffice\Common\PasswordEncoder */ class PasswordEncoderTest extends \PHPUnit\Framework\TestCase @@ -27,7 +29,7 @@ class PasswordEncoderTest extends \PHPUnit\Framework\TestCase /** * Test that a password can be hashed without specifying any additional parameters */ - public function testEncodePassword() + public function testEncodePassword(): void { //given $password = 'test'; @@ -42,7 +44,7 @@ public function testEncodePassword() /** * Test that a password can be hashed with a custom salt */ - public function testEncodePasswordWithSalt() + public function testEncodePasswordWithSalt(): void { //given $password = 'test'; @@ -58,7 +60,7 @@ public function testEncodePasswordWithSalt() /** * Test that the encoder falls back on SHA-1 if a non supported algorithm is given */ - public function testDefaultsToSha1IfUnsupportedAlgorithm() + public function testDefaultsToSha1IfUnsupportedAlgorithm(): void { //given $password = 'test'; @@ -74,7 +76,7 @@ public function testDefaultsToSha1IfUnsupportedAlgorithm() /** * Test that the encoder falls back on SHA-1 if a non supported algorithm is given */ - public function testEncodePasswordWithNullAsciiCodeInPassword() + public function testEncodePasswordWithNullAsciiCodeInPassword(): void { //given $password = 'test' . chr(0); diff --git a/tests/Common/Tests/TextTest.php b/tests/Common/Tests/TextTest.php index edd65e2..443163a 100644 --- a/tests/Common/Tests/TextTest.php +++ b/tests/Common/Tests/TextTest.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -17,37 +18,42 @@ namespace PhpOffice\Common\Tests; use PhpOffice\Common\Text; +use PHPUnit\Framework\TestCase; /** * Test class for Text * - * @coversDefaultClass PhpOffice\Common\Text + * @coversDefaultClass \PhpOffice\Common\Text */ -class TextTest extends \PHPUnit\Framework\TestCase +class TextTest extends TestCase { - /** - */ - public function testControlCharacters() + public function testControlCharactersPHP2OOXML(): void { $this->assertEquals('', Text::controlCharacterPHP2OOXML()); $this->assertEquals('aeiou', Text::controlCharacterPHP2OOXML('aeiou')); $this->assertEquals('àéîöù', Text::controlCharacterPHP2OOXML('àéîöù')); $value = rand(0, 8); - $this->assertEquals('_x'.sprintf('%04s', strtoupper(dechex($value))).'_', Text::controlCharacterPHP2OOXML(chr($value))); + $this->assertEquals( + '_x' . sprintf('%04s', strtoupper(dechex($value))) . '_', + Text::controlCharacterPHP2OOXML(chr($value)) + ); + } + public function testControlCharactersOOXML2PHP(): void + { $this->assertEquals('', Text::controlCharacterOOXML2PHP('')); $this->assertEquals(chr(0x08), Text::controlCharacterOOXML2PHP('_x0008_')); } - public function testNumberFormat() + public function testNumberFormat(): void { - $this->assertEquals('2.1', Text::numberFormat('2.06', 1)); - $this->assertEquals('2.1', Text::numberFormat('2.12', 1)); + $this->assertEquals('2.1', Text::numberFormat(2.06, 1)); + $this->assertEquals('2.1', Text::numberFormat(2.12, 1)); $this->assertEquals('1234.0', Text::numberFormat(1234, 1)); } - public function testChr() + public function testChr(): void { $this->assertEquals('A', Text::chr(65)); $this->assertEquals('A', Text::chr(0x41)); @@ -59,20 +65,25 @@ public function testChr() $this->assertEquals('🌃', Text::chr(0x1F303)); $this->assertEquals('', Text::chr(2097152)); } - /** - * Is UTF8 - */ - public function testIsUTF8() + + public function testIsUTF8(): void { $this->assertTrue(Text::isUTF8('')); $this->assertTrue(Text::isUTF8('éééé')); $this->assertFalse(Text::isUTF8(utf8_decode('éééé'))); } + public function testToUtf8(): void + { + $this->assertNull(Text::toUTF8(null)); + $this->assertEquals('eeee', Text::toUTF8('eeee')); + $this->assertEquals('éééé', Text::toUTF8('éééé')); + } + /** * Test unicode conversion */ - public function testToUnicode() + public function testToUnicode(): void { $this->assertEquals('a', Text::toUnicode('a')); $this->assertEquals('\uc0{\u8364}', Text::toUnicode('€')); @@ -82,7 +93,7 @@ public function testToUnicode() /** * Test remove underscore prefix */ - public function testRemoveUnderscorePrefix() + public function testRemoveUnderscorePrefix(): void { $this->assertEquals('item', Text::removeUnderscorePrefix('_item')); } diff --git a/tests/Common/Tests/XMLReaderTest.php b/tests/Common/Tests/XMLReaderTest.php index b0acde7..02603d5 100644 --- a/tests/Common/Tests/XMLReaderTest.php +++ b/tests/Common/Tests/XMLReaderTest.php @@ -9,26 +9,30 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2017 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\Common\Tests; +use Exception; +use InvalidArgumentException; use PhpOffice\Common\XMLReader; +use PHPUnit\Framework\TestCase; /** * Test class for XMLReader * - * @coversDefaultClass PhpOffice\Common\XMLReader + * @coversDefaultClass \PhpOffice\Common\XMLReader */ -class XMLReaderTest extends \PHPUnit\Framework\TestCase +class XMLReaderTest extends TestCase { /** * Test reading XML from string */ - public function testDomFromString() + public function testDomFromString(): void { $reader = new XMLReader(); $reader->getDomFromString('AAA'); @@ -43,35 +47,36 @@ public function testDomFromString() /** * Test reading XML from zip */ - public function testDomFromZip() + public function testDomFromZip(): void { - $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'files'.DIRECTORY_SEPARATOR; + $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR; $reader = new XMLReader(); - $reader->getDomFromZip($pathResources. 'reader.zip', 'test.xml'); + $reader->getDomFromZip($pathResources . 'reader.zip', 'test.xml'); $this->assertTrue($reader->elementExists('/element/child')); - $this->assertFalse($reader->getDomFromZip($pathResources. 'reader.zip', 'non_existing_xml_file.xml')); + $this->assertFalse($reader->getDomFromZip($pathResources . 'reader.zip', 'non_existing_xml_file.xml')); } /** * Test that read from non existing archive throws exception - * - * @expectedException Exception */ - public function testThrowsExceptionOnNonExistingArchive() + public function testThrowsExceptionOnNonExistingArchive(): void { - $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'files'.DIRECTORY_SEPARATOR; + $this->expectException(Exception::class); + $this->expectExceptionMessage('Cannot find archive file.'); + + $pathResources = PHPOFFICE_COMMON_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR; $reader = new XMLReader(); - $reader->getDomFromZip($pathResources. 'readers.zip', 'test.xml'); + $reader->getDomFromZip($pathResources . 'readers.zip', 'test.xml'); } /** * Test elements count */ - public function testCountElements() + public function testCountElements(): void { $reader = new XMLReader(); $reader->getDomFromString('AAABBB'); @@ -82,10 +87,10 @@ public function testCountElements() /** * Test read non existing elements */ - public function testReturnNullOnNonExistingNode() + public function testReturnNullOnNonExistingNode(): void { $reader = new XMLReader(); - $this->assertEmpty($reader->getElements('/element/children')); + $this->assertCount(0, $reader->getElements('/element/children')); $reader->getDomFromString('AAA'); $this->assertNull($reader->getElement('/element/children')); @@ -95,7 +100,7 @@ public function testReturnNullOnNonExistingNode() /** * Test that xpath fails if custom namespace is not registered */ - public function testShouldThrowExceptionIfNamespaceIsNotKnown() + public function testShouldThrowExceptionIfNamespaceIsNotKnown(): void { try { $reader = new XMLReader(); @@ -112,7 +117,7 @@ public function testShouldThrowExceptionIfNamespaceIsNotKnown() /** * Test reading XML with manually registered namespace */ - public function testShouldParseXmlWithCustomNamespace() + public function testShouldParseXmlWithCustomNamespace(): void { $reader = new XMLReader(); $reader->getDomFromString('AAA'); @@ -124,11 +129,12 @@ public function testShouldParseXmlWithCustomNamespace() /** * Test that xpath fails if custom namespace is not registered - * - * @expectedException InvalidArgumentException */ - public function testShouldThowExceptionIfTryingToRegisterNamespaceBeforeReadingDoc() + public function testShouldThowExceptionIfTryingToRegisterNamespaceBeforeReadingDoc(): void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Dom needs to be loaded before registering a namespace'); + $reader = new XMLReader(); $reader->registerNamespace('test', 'http://phpword.com/my/custom/namespace'); } diff --git a/tests/Common/Tests/XMLWriterTest.php b/tests/Common/Tests/XMLWriterTest.php index 2ff2d2c..53a237c 100644 --- a/tests/Common/Tests/XMLWriterTest.php +++ b/tests/Common/Tests/XMLWriterTest.php @@ -9,7 +9,8 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/Common/contributors. * - * @link https://github.com/PHPOffice/Common + * @see https://github.com/PHPOffice/Common + * * @copyright 2009-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ @@ -21,30 +22,52 @@ /** * Test class for XMLWriter * - * @coversDefaultClass PhpOffice\Common\XMLWriter + * @coversDefaultClass \PhpOffice\Common\XMLWriter */ class XMLWriterTest extends \PHPUnit\Framework\TestCase { - /** - */ - public function testConstruct() + public function testConstruct(): void { // Memory $object = new XMLWriter(); $object->startElement('element'); - $object->text('AAA'); + $object->text('AAA'); $object->endElement(); - $this->assertEquals('AAA'.chr(10), $object->getData()); + $this->assertEquals('AAA' . chr(10), $object->getData()); // Disk $object = new XMLWriter(XMLWriter::STORAGE_DISK); $object->startElement('element'); - $object->text('BBB'); + $object->text('BBB'); + $object->endElement(); + $this->assertEquals('BBB' . chr(10), $object->getData()); + } + + public function testConstructCompatibility(): void + { + $object = new XMLWriter(XMLWriter::STORAGE_MEMORY, null, false); + $object->startElement('element'); + $object->startElement('sub'); + $object->text('CCC'); + $object->endElement(); + $object->endElement(); + $this->assertEquals( + '' . PHP_EOL . ' CCC' . PHP_EOL . '' . PHP_EOL, + $object->getData() + ); + $object = new XMLWriter(XMLWriter::STORAGE_MEMORY, null, true); + $object->startElement('element'); + $object->startElement('sub'); + $object->text('CCC'); $object->endElement(); - $this->assertEquals('BBB'.chr(10), $object->getData()); + $object->endElement(); + $this->assertEquals( + 'CCC', + $object->getData() + ); } - public function testWriteAttribute() + public function testWriteAttribute(): void { $xmlWriter = new XMLWriter(); $xmlWriter->startElement('element'); @@ -54,7 +77,24 @@ public function testWriteAttribute() $this->assertSame('' . chr(10), $xmlWriter->getData()); } - public function testWriteAttributeShouldWriteFloatValueLocaleIndependent() + public function testWriteAttributeIf(): void + { + $xmlWriter = new XMLWriter(); + $xmlWriter->startElement('element'); + $xmlWriter->writeAttributeIf(true, 'name', 'value'); + $xmlWriter->endElement(); + + $this->assertSame('' . chr(10), $xmlWriter->getData()); + + $xmlWriter = new XMLWriter(); + $xmlWriter->startElement('element'); + $xmlWriter->writeAttributeIf(false, 'name', 'value'); + $xmlWriter->endElement(); + + $this->assertSame('' . chr(10), $xmlWriter->getData()); + } + + public function testWriteAttributeShouldWriteFloatValueLocaleIndependent(): void { $value = 1.2; @@ -63,9 +103,88 @@ public function testWriteAttributeShouldWriteFloatValueLocaleIndependent() $xmlWriter->writeAttribute('name', $value); $xmlWriter->endElement(); + // https://www.php.net/manual/en/language.types.string.php#language.types.string.casting + // As of PHP 8.0.0, the decimal point character is always .. + // Prior to PHP 8.0.0, the decimal point character is defined in the script's locale (category LC_NUMERIC). setlocale(LC_NUMERIC, 'de_DE.UTF-8', 'de'); - - $this->assertSame('1,2', (string)$value); + if (PHP_VERSION_ID > 80000) { + $this->assertSame('1.2', (string) $value); + } else { + $this->assertSame('1,2', (string) $value); + } $this->assertSame('' . chr(10), $xmlWriter->getData()); } + + public function testWriteElementBlock(): void + { + $xmlWriter = new XMLWriter(); + $xmlWriter->writeElementBlock('element', 'name'); + + $this->assertSame('' . chr(10), $xmlWriter->getData()); + + $xmlWriter = new XMLWriter(); + $xmlWriter->writeElementBlock('element', 'name', 'value'); + + $this->assertSame('' . chr(10), $xmlWriter->getData()); + + $xmlWriter = new XMLWriter(); + $xmlWriter->writeElementBlock('element', ['name' => 'value']); + + $this->assertSame('' . chr(10), $xmlWriter->getData()); + + $xmlWriter = new XMLWriter(); + $xmlWriter->writeElementBlock('element', ['name' => 'value'], 'value2'); + + $this->assertSame('' . chr(10), $xmlWriter->getData()); + } + + /** + * @dataProvider dataProviderWriteElementIf + */ + public function testWriteElementIf(bool $condition, ?string $attribute, ?string $value, string $expected): void + { + $xmlWriter = new XMLWriter(); + $xmlWriter->writeElementIf($condition, 'element', $attribute, $value); + + $this->assertSame($expected, $xmlWriter->getData()); + } + + /** + * @return array> + */ + public function dataProviderWriteElementIf(): array + { + return [ + [ + false, + null, + null, + '', + ], + [ + true, + null, + null, + '' . chr(10), + ], + [ + true, + 'attribute', + null, + '' . chr(10), + ], + [ + true, + null, + 'value', + 'value' . chr(10), + ], + [ + true, + 'attribute', + 'value', + '' . chr(10), + ], + ]; + } } diff --git a/tests/Common/Tests/_includes/TestHelperZip.php b/tests/Common/Tests/_includes/TestHelperZip.php index 6f7c54d..df59087 100644 --- a/tests/Common/Tests/_includes/TestHelperZip.php +++ b/tests/Common/Tests/_includes/TestHelperZip.php @@ -1,23 +1,27 @@ open($fileZip) !== true) { return false; } if ($oZip->statName($path) === false) { return false; } + return true; } - public static function assertFileContent($fileZip, $path, $content) + public static function assertFileContent(string $fileZip, string $path, string $content): bool { - $oZip = new \ZipArchive; + $oZip = new \ZipArchive(); if ($oZip->open($fileZip) !== true) { return false; } @@ -28,6 +32,7 @@ public static function assertFileContent($fileZip, $path, $content) if ($zipFileContent != $content) { return false; } + return true; } } diff --git a/tests/Common/Tests/_includes/XmlDocument.php b/tests/Common/Tests/_includes/XmlDocument.php index 29e9d6a..ff4ff8c 100644 --- a/tests/Common/Tests/_includes/XmlDocument.php +++ b/tests/Common/Tests/_includes/XmlDocument.php @@ -10,13 +10,20 @@ * file that was distributed with this source code. For the full list of * contributors, visit https://github.com/PHPOffice/PHPPowerPoint/contributors. * - * @link https://github.com/PHPOffice/PHPPowerPoint + * @see https://github.com/PHPOffice/PHPPowerPoint + * * @copyright 2010-2016 PHPPowerPoint contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpPowerpoint\Tests; +use DOMDocument; +use DOMElement; +use DOMNode; +use DOMNodeList; +use DOMXpath; + /** * DOM wrapper class */ @@ -25,21 +32,21 @@ class XmlDocument /** * Path * - * @var string $path + * @var string */ private $path; /** * DOMDocument object * - * @var \DOMDocument + * @var DOMDocument */ private $dom; /** * DOMXpath object * - * @var \DOMXpath + * @var DOMXpath|null */ private $xpath; @@ -55,7 +62,7 @@ class XmlDocument * * @param string $path */ - public function __construct($path) + public function __construct(string $path) { $this->path = realpath($path); } @@ -64,9 +71,10 @@ public function __construct($path) * Get DOM from file * * @param string $file - * @return \DOMDocument + * + * @return DOMDocument */ - public function getFileDom($file = 'word/document.xml') + public function getFileDom(string $file = 'word/document.xml'): DOMDocument { if (null !== $this->dom && $file === $this->file) { return $this->dom; @@ -76,8 +84,9 @@ public function getFileDom($file = 'word/document.xml') $this->file = $file; $file = $this->path . '/' . $file; - $this->dom = new \DOMDocument(); + $this->dom = new DOMDocument(); $this->dom->load($file); + return $this->dom; } @@ -86,16 +95,17 @@ public function getFileDom($file = 'word/document.xml') * * @param string $path * @param string $file - * @return \DOMNodeList + * + * @return DOMNodeList */ - public function getNodeList($path, $file = 'word/document.xml') + public function getNodeList(string $path, string $file = 'word/document.xml'): DOMNodeList { if ($this->dom === null || $file !== $this->file) { $this->getFileDom($file); } if (null === $this->xpath) { - $this->xpath = new \DOMXpath($this->dom); + $this->xpath = new DOMXpath($this->dom); } return $this->xpath->query($path); @@ -106,11 +116,13 @@ public function getNodeList($path, $file = 'word/document.xml') * * @param string $path * @param string $file - * @return \DOMElement + * + * @return DOMNode */ - public function getElement($path, $file = 'word/document.xml') + public function getElement(string $path, string $file = 'word/document.xml'): DOMNode { $elements = $this->getNodeList($path, $file); + return $elements->item(0); } @@ -119,7 +131,7 @@ public function getElement($path, $file = 'word/document.xml') * * @return string */ - public function getFile() + public function getFile(): string { return $this->file; } @@ -129,7 +141,7 @@ public function getFile() * * @return string */ - public function getPath() + public function getPath(): string { return $this->path; } @@ -137,39 +149,47 @@ public function getPath() /** * Get element attribute * - * @param string $path - * @param string $attribute - * @param string $file - * @return string + * @param string $path + * @param string $attribute + * @param string $file + * + * @return string */ - public function getElementAttribute($path, $attribute, $file = 'word/document.xml') + public function getElementAttribute(string $path, string $attribute, string $file = 'word/document.xml'): string { - return $this->getElement($path, $file)->getAttribute($attribute); + $element = $this->getElement($path, $file); + + return $element instanceof DOMElement ? $element->getAttribute($attribute) : ''; } /** * Get element attribute * - * @param string $path - * @param string $attribute - * @param string $file - * @return string + * @param string $path + * @param string $attribute + * @param string $file + * + * @return bool */ - public function attributeElementExists($path, $attribute, $file = 'word/document.xml') + public function attributeElementExists(string $path, string $attribute, string $file = 'word/document.xml'): bool { - return $this->getElement($path, $file)->hasAttribute($attribute); + $element = $this->getElement($path, $file); + + return $element instanceof DOMElement ? $element->hasAttribute($attribute) : false; } /** * Check if element exists * - * @param string $path - * @param string $file - * @return string + * @param string $path + * @param string $file + * + * @return bool */ - public function elementExists($path, $file = 'word/document.xml') + public function elementExists(string $path, string $file = 'word/document.xml'): bool { $nodeList = $this->getNodeList($path, $file); + return !($nodeList->length == 0); } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 35fd6f1..24dd4a8 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -11,9 +11,9 @@ * * @copyright 2010-2016 PHPOffice Common contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 - * @link https://github.com/PHPOffice/Common + * + * @see https://github.com/PHPOffice/Common */ - date_default_timezone_set('UTC'); // defining base dir for tests @@ -23,14 +23,14 @@ $vendor = realpath(__DIR__ . '/../vendor'); -if (file_exists($vendor . "/autoload.php")) { - require $vendor . "/autoload.php"; +if (file_exists($vendor . '/autoload.php')) { + require $vendor . '/autoload.php'; } else { $vendor = realpath(__DIR__ . '/../../../'); - if (file_exists($vendor . "/autoload.php")) { - require $vendor . "/autoload.php"; + if (file_exists($vendor . '/autoload.php')) { + require $vendor . '/autoload.php'; } else { - throw new Exception("Unable to load dependencies"); + throw new Exception('Unable to load dependencies'); } } @@ -39,7 +39,7 @@ $prefix = 'PhpOffice\\Common\\Tests'; if (strpos($class, $prefix) === 0) { $class = str_replace('\\', DIRECTORY_SEPARATOR, $class); - $class = join(DIRECTORY_SEPARATOR, array('Common', 'Tests', '_includes')) . + $class = join(DIRECTORY_SEPARATOR, ['Common', 'Tests', '_includes']) . substr($class, strlen($prefix)); $file = __DIR__ . DIRECTORY_SEPARATOR . $class . '.php'; if (file_exists($file)) { @@ -48,5 +48,5 @@ } }); -require_once __DIR__ . "/../src/Common/Autoloader.php"; +require_once __DIR__ . '/../src/Common/Autoloader.php'; \PhpOffice\Common\Autoloader::register();