From 98d038e05d2c9c0bf483a0c22118438a69853c49 Mon Sep 17 00:00:00 2001 From: Marin Nikolli <34999323+sibalonat@users.noreply.github.com> Date: Mon, 8 Jan 2024 07:34:35 +0100 Subject: [PATCH] Added extractVariables method to IOFactory (#2515) * Added extractVariables method to IOFactory * remove var_dumps * remove vardump * fix return and fix php stan errors and instances * fix order and whitespace * extra space * remove new lines * white space * new lines * whiteline * new line * white space * fix * new line * white space * remove some unneecessary if statement * Correct Font Size Calculated by MsDoc Reader Fix #2526. Most of that issue has already been fixed. The one remaining problem was a deprecation message handling font size. The code used `dechex($operand / 2)`, and issued the deprecation message whenever `$operand` was odd because `dechex` is designed only for integer conversion. `$operand` is actually 2 times the point size, so it will be odd only when the point size is some integer plus half a point (no other fractions are allowed). At any rate, it seems that `dechex` should not be used here in the first place; font size is a numeric value, not a hex string. There are many problems with MsDoc Reader at the moment. This PR is narrowly focused on the problem at hand. Its test is, at least, more detailed than the existing MsDoc Reader test, which does nothing more than confirm that read successfully creates a PhpWord object. The new test verifies that the font size is as expected, but does not validate any other aspect of the read. * Suggestions from @Progi1984 * Typo Tolerated By Windows but Not By Unix * Correct Title Line of Change Log * Bump dompdf/dompdf from 2.0.3 to 2.0.4 Bumps [dompdf/dompdf](https://github.com/dompdf/dompdf) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/dompdf/dompdf/releases) - [Commits](https://github.com/dompdf/dompdf/compare/v2.0.3...v2.0.4) --- updated-dependencies: - dependency-name: dompdf/dompdf dependency-type: direct:development ... Signed-off-by: dependabot[bot] * Bump phpunit/phpunit from 9.6.13 to 9.6.14 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.13 to 9.6.14. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.14/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.13...9.6.14) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump mpdf/mpdf from 8.2.0 to 8.2.2 Bumps [mpdf/mpdf](https://github.com/mpdf/mpdf) from 8.2.0 to 8.2.2. - [Release notes](https://github.com/mpdf/mpdf/releases) - [Changelog](https://github.com/mpdf/mpdf/blob/development/CHANGELOG.md) - [Commits](https://github.com/mpdf/mpdf/compare/v8.2.0...v8.2.2) --- updated-dependencies: - dependency-name: mpdf/mpdf dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump phpmd/phpmd from 2.14.1 to 2.15.0 Bumps [phpmd/phpmd](https://github.com/phpmd/phpmd) from 2.14.1 to 2.15.0. - [Release notes](https://github.com/phpmd/phpmd/releases) - [Changelog](https://github.com/phpmd/phpmd/blob/master/CHANGELOG) - [Commits](https://github.com/phpmd/phpmd/compare/2.14.1...2.15.0) --- updated-dependencies: - dependency-name: phpmd/phpmd dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Updated Changelog * Bump phpunit/phpunit from 9.6.14 to 9.6.15 Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.14 to 9.6.15. - [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.15/ChangeLog-9.6.md) - [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.14...9.6.15) --- updated-dependencies: - dependency-name: phpunit/phpunit dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Updated Changelog * Bump symfony/process from 5.4.28 to 5.4.34 Bumps [symfony/process](https://github.com/symfony/process) from 5.4.28 to 5.4.34. - [Release notes](https://github.com/symfony/process/releases) - [Changelog](https://github.com/symfony/process/blob/7.0/CHANGELOG.md) - [Commits](https://github.com/symfony/process/compare/v5.4.28...v5.4.34) --- updated-dependencies: - dependency-name: symfony/process dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Updated Changelog * Added extractVariables method to IOFactory * remove var_dumps * fix return and fix php stan errors and instances * fix order and whitespace * remove new lines * white space * new lines * whiteline * new line * white space * fix * white space * remove some unneecessary if statement * variable changes * 2.0.0 md * 2.0.0 * new line at end of the file * add entry to md * additional space, type fixes in enhancement md and iofactory * some fixes on spacing * based on fixer suggestions * new line at the end of the file --------- Signed-off-by: dependabot[bot] Co-authored-by: oleibman <10341515+oleibman@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Progi1984 --- docs/changes/2.x/2.0.0.md | 2 + ..._44_ExtractVariablesFromReaderWord2007.php | 14 +++++++ ...44_ExtractVariablesFromReaderWord2007.docx | Bin 0 -> 12981 bytes src/PhpWord/IOFactory.php | 39 ++++++++++++++++++ tests/PhpWordTests/IOFactoryTest.php | 13 ++++++ .../_files/templates/extract-variable.docx | Bin 0 -> 12575 bytes 6 files changed, 68 insertions(+) create mode 100644 samples/Sample_44_ExtractVariablesFromReaderWord2007.php create mode 100644 samples/resources/Sample_44_ExtractVariablesFromReaderWord2007.docx create mode 100644 tests/PhpWordTests/_files/templates/extract-variable.docx diff --git a/docs/changes/2.x/2.0.0.md b/docs/changes/2.x/2.0.0.md index c679317049..74f2184155 100644 --- a/docs/changes/2.x/2.0.0.md +++ b/docs/changes/2.x/2.0.0.md @@ -4,6 +4,8 @@ ## Enhancements +- IOFactory : Added extractVariables method to extract variables from a document [@sibalonat](https://github.com/sibalonat) in [#2515](https://github.com/PHPOffice/PHPWord/pull/2515) + ### Bug fixes - MsDoc Reader : Correct Font Size Calculation by [@oleibman](https://github.com/oleibman) fixing [#2526](https://github.com/PHPOffice/PHPWord/issues/2526) in [#2531](https://github.com/PHPOffice/PHPWord/pull/2531) diff --git a/samples/Sample_44_ExtractVariablesFromReaderWord2007.php b/samples/Sample_44_ExtractVariablesFromReaderWord2007.php new file mode 100644 index 0000000000..24574e5fb7 --- /dev/null +++ b/samples/Sample_44_ExtractVariablesFromReaderWord2007.php @@ -0,0 +1,14 @@ +9(1d|z* z_F-_mz}24O2U?%o(ZLl}!Q$X;NGaHER@v10116W!ZQxMr+$avQ1(N*|^enmP7UzF3 z_?qBSZX`0V3J-C9wqb8=!xyghWY72*oV>0xxmSxrcr{6VCsP||CdS|7|4i}!u>Jkzrtc3YctDT|C2Y4U&C*p7|ZcePKcLaJg_{Ob^~>I%rzY zyWu;yLYyZgnzi~H_V}5)!WXZB>A&s6TPpKu{?&4P&;S6`*O%gE?_|PcVsHG>_BC$( z7O;M%O520DQ3g&BF8OdofMI&|6bMxaT=g|P7|fiy20%n{X)$pnVoN@|$&+?b%{L&a zn(7)0XA9)G+fuME$RV=`!eg~q18oL3vy}D zGf3`Cv-H8Z-=_;sMII0^XBh?wC;B#Zl2w+%jmCVZgyckL8G3BY3$3b4=BGUZT6t}G z);2H^B?bMgerX#jr$_D^x0Pg_5OGMFY8`iQr9pz8hOhRpM8{87y{K;jvFLtM$u{$% z!8gFZk$%#wzj-vxJ9Obj4Jct~Zgglh+lC9Ew!v!ukPhLv5)D-V?#|GOk`N8mVH8Nw z(=Qv0hkTTZhiUFh8!U=%xDx&G=S&*J=kSl2+2Uuky0*p<>{4;15GyD{9&$)l%h3cD ziBv%8Kt7r|57B&J{tB0=tu-T#dF5~*uZ+_buQ{PoqG+8lce8wB>>dk546%SG%0}BJ z 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 } + /** + * Loads PhpWord ${variable} from file. + * + * @param string $filename The name of the file + * + * @return array The extracted variables + */ + public static function extractVariables(string $filename, string $readerName = 'Word2007'): array + { + /** @var \PhpOffice\PhpWord\Reader\ReaderInterface $reader */ + $reader = self::createReader($readerName); + $document = $reader->load($filename); + $extractedVariables = []; + foreach ($document->getSections() as $section) { + $concatenatedText = ''; + foreach ($section->getElements() as $element) { + if ($element instanceof TextRun) { + foreach ($element->getElements() as $textElement) { + if ($textElement instanceof Text) { + $text = $textElement->getText(); + $concatenatedText .= $text; + } + } + } + } + preg_match_all('/\$\{([^}]+)\}/', $concatenatedText, $matches); + if (!empty($matches[1])) { + foreach ($matches[1] as $match) { + $trimmedMatch = trim($match); + $extractedVariables[] = $trimmedMatch; + } + } + } + + return $extractedVariables; + } + /** * Check if it's a concrete class (not abstract nor interface). * diff --git a/tests/PhpWordTests/IOFactoryTest.php b/tests/PhpWordTests/IOFactoryTest.php index ee8d7fe180..79f0fd0c76 100644 --- a/tests/PhpWordTests/IOFactoryTest.php +++ b/tests/PhpWordTests/IOFactoryTest.php @@ -116,4 +116,17 @@ public function testLoad(): void IOFactory::load($file) ); } + + /** + * Test for extractVariables method. + */ + public function testExtractVariables(): void + { + $file = __DIR__ . '/_files/templates/extract-variable.docx'; + $extractedVariables = IOFactory::extractVariables($file, 'Word2007'); + + $expectedVariables = ['date', 'A1', 'B1']; + + self::assertEquals($expectedVariables, $extractedVariables, 'Extracted variables do not match expected variables.'); + } } diff --git a/tests/PhpWordTests/_files/templates/extract-variable.docx b/tests/PhpWordTests/_files/templates/extract-variable.docx new file mode 100644 index 0000000000000000000000000000000000000000..f95ec61862f7b5bc97a8eb65f5f3ce24407dd88d GIT binary patch literal 12575 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