Skip to content

Commit c0f2310

Browse files
authored
Merge branch 'master' into word1692
2 parents a6e8940 + 2daa50c commit c0f2310

20 files changed

+336
-136
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: 🐛 Bug Report
2+
description: Create a report to help improve PHPWord
3+
labels: [ "Bug Report" ]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
### ❗️ Read this before submitting your bug report:
9+
- **Write in English/French.** Reports in all other languages will be closed.
10+
- **Provide as much detail as possible**
11+
- Attachments : Error logs, Screenshots, Document files (generated and expected).
12+
- If the issue cannot be reproduced, it cannot be fixed.
13+
- type: textarea
14+
id: what-happened
15+
attributes:
16+
label: Describe the bug and add attachments
17+
description: What went wrong? If possible, add screenshots, error logs, document files (generated and expected) or screen recordings to help explain your problem.
18+
validations:
19+
required: true
20+
- type: textarea
21+
id: expected-behavior
22+
attributes:
23+
label: Expected behavior
24+
description: A clear and concise description of what you expected to happen.
25+
validations:
26+
required: true
27+
- type: textarea
28+
id: steps-reproduce
29+
attributes:
30+
label: Steps to reproduce
31+
description: Please provide a code sample that reproduces the issue.
32+
placeholder: |
33+
```php
34+
<?php
35+
require __DIR__ . '/vendor/autoload.php';
36+
37+
$phpWord = new \PhpOffice\PhpWord\PhpWord();
38+
$section = $phpWord->addSection();
39+
$section->...
40+
```
41+
validations:
42+
required: true
43+
- type: input
44+
id: phpword-version
45+
attributes:
46+
label: PHPWord version(s) where the bug happened
47+
placeholder: "e.g., 1.2.0 or master"
48+
validations:
49+
required: true
50+
- type: input
51+
id: php-version
52+
attributes:
53+
label: PHP version(s) where the bug happened
54+
placeholder: "e.g., 7.1 or 8.2"
55+
validations:
56+
required: true
57+
- type: checkboxes
58+
attributes:
59+
label: Priority
60+
description: Funded tickets have a higher priority.
61+
options:
62+
- label: I want to crowdfund the bug fix (with [@algora-io](https://docs.algora.io/bounties/overview)) and fund a community developer.
63+
required: false
64+
- label: I want to pay the bug fix and fund a maintainer for that. (Contact @Progi1984)
65+
required: false
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: 💡 Feature request
2+
description: Suggest an idea for this project
3+
labels: [ "Change Request" ]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
### ❗️ Read this before submitting your bug report:
9+
- **Write in English/French.** Reports in all other languages will be closed.
10+
- **Provide as much detail as possible**
11+
- Attachments : Error logs, Screenshots, Document files (generated and expected).
12+
- If the issue cannot be reproduced, it cannot be fixed.
13+
- type: textarea
14+
id: problem
15+
attributes:
16+
label: Describe the problem
17+
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
18+
validations:
19+
required: true
20+
- type: textarea
21+
id: expected-behavior
22+
attributes:
23+
label: Describe the expected behavior
24+
description: A clear and concise description of what you expected to happen. If possible, add screenshots, document files (expected).
25+
validations:
26+
required: true
27+
- type: checkboxes
28+
attributes:
29+
label: Priority
30+
description: Funded tickets have a higher priority.
31+
options:
32+
- label: I want to crowdfund the feature (with [@algora-io](https://docs.algora.io/bounties/overview)) and fund a community developer.
33+
required: false
34+
- label: I want to pay the feature and fund a maintainer for that. (Contact @Progi1984)
35+
required: false

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 0 additions & 38 deletions
This file was deleted.

.github/ISSUE_TEMPLATE/feature_request.md

Lines changed: 0 additions & 22 deletions
This file was deleted.

.github/ISSUE_TEMPLATE/how-to-use.md

Lines changed: 0 additions & 14 deletions
This file was deleted.

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Fixes # (issue)
66

77
### Checklist:
88

9-
- [ ] I have run `composer run-script check --timeout=0` and no errors were reported
10-
- [ ] The new code is covered by unit tests (check build/coverage for coverage report)
11-
- [ ] I have updated the documentation to describe the changes
9+
- [ ] My CI is :green_circle:
10+
- [ ] I have covered by unit tests my new code (check build/coverage for coverage report)
11+
- [ ] I have updated the [documentation](https://github.com/PHPOffice/PHPWord/tree/master/docs) to describe the changes
12+
- [ ] I have updated the [changelog](https://github.com/PHPOffice/PHPWord/blob/master/docs/changes/2.x/2.0.0.md)

docs/changes/1.x/1.2.0.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,5 @@
6464

6565

6666
### BC Breaks
67-
- Removed dependency `laminas/laminas-escaper`
67+
- Removed dependency `laminas/laminas-escaper`
68+
- *Unintended Break* TemplateProcessor Does Not Persist File After Destruct. [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) To be fixed by [#2545](https://github.com/PHPOffice/PHPWord/pull/2545

docs/changes/2.x/2.0.0.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44

55
## Enhancements
66

7+
- IOFactory : Added extractVariables method to extract variables from a document [@sibalonat](https://github.com/sibalonat) in [#2515](https://github.com/PHPOffice/PHPWord/pull/2515)
8+
79
### Bug fixes
810

911
- 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)
10-
- TemplateProcessor Persist File After Destruct [@oleibman](https://github.com/oleibman) fixing [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) in [#2542](https://github.com/PHPOffice/PHPWord/pull/2531)
1112
- Html Reader : Process Titles as Headings not Paragraphs [@0b10011](https://github.com/0b10011) and [@oleibman](https://github.com/oleibman) Issue [#1692](https://github.com/PHPOffice/PHPWord/issues/1692) PR [#2533](https://github.com/PHPOffice/PHPWord/pull/2533)
13+
- TemplateProcessor Persist File After Destruct [@oleibman](https://github.com/oleibman) fixing [#2539](https://github.com/PHPOffice/PHPWord/issues/2539) in [#2545](https://github.com/PHPOffice/PHPWord/pull/2545)
14+
- bug: TemplateProcessor fix multiline values [@gimler](https://github.com/gimler) fixing [#268](https://github.com/PHPOffice/PHPWord/issues/268), [#2323](https://github.com/PHPOffice/PHPWord/issues/2323) and [#2486](https://github.com/PHPOffice/PHPWord/issues/2486) in [#2522](https://github.com/PHPOffice/PHPWord/pull/2522)
15+
16+
- 32-bit Problem in PasswordEncoder [@oleibman](https://github.com/oleibman) fixing [#2550](https://github.com/PHPOffice/PHPWord/issues/2550) in [#2551](https://github.com/PHPOffice/PHPWord/pull/2551)
1217

1318
### Miscellaneous
1419

@@ -18,6 +23,7 @@
1823
- Bump phpmd/phpmd from 2.14.1 to 2.15.0 by [@dependabot](https://github.com/dependabot) in [#2538](https://github.com/PHPOffice/PHPWord/pull/2538)
1924
- Bump phpunit/phpunit from 9.6.14 to 9.6.15 by [@dependabot](https://github.com/dependabot) in [#2537](https://github.com/PHPOffice/PHPWord/pull/2537)
2025
- Bump symfony/process from 5.4.28 to 5.4.34 by [@dependabot](https://github.com/dependabot) in [#2536](https://github.com/PHPOffice/PHPWord/pull/2536)
21-
- Allow rgb() when converting Html [@oleibman](https://github.com/oleibman) fixing [#2508](https://github.com/PHPOffice/PHPWord/issues/2508) in [#2512](https://github.com/PHPOffice/PHPWord/pull/2512)
26+
- Allow rgb() when converting Html by [@oleibman](https://github.com/oleibman) fixing [#2508](https://github.com/PHPOffice/PHPWord/issues/2508) in [#2512](https://github.com/PHPOffice/PHPWord/pull/2512)
27+
- Improved Issue Template by [@Progi1984](https://github.com/Progi1984) in [#2609](https://github.com/PHPOffice/PHPWord/pull/2609)
2228

2329
### BC Breaks
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
include_once 'Sample_Header.php';
4+
5+
// Read contents
6+
$name = basename(__FILE__, '.php');
7+
8+
$source = __DIR__ . "/resources/{$name}.docx";
9+
10+
echo date('H:i:s'), " Reading contents from `{$source}`", EOL;
11+
12+
$variables = \PhpOffice\PhpWord\IOFactory::extractVariables($source);
13+
14+
var_dump($variables);
Binary file not shown.

src/PhpWord/IOFactory.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
namespace PhpOffice\PhpWord;
1919

20+
use PhpOffice\PhpWord\Element\Text;
21+
use PhpOffice\PhpWord\Element\TextRun;
2022
use PhpOffice\PhpWord\Exception\Exception;
2123
use PhpOffice\PhpWord\Reader\ReaderInterface;
2224
use PhpOffice\PhpWord\Writer\WriterInterface;
@@ -89,6 +91,43 @@ public static function load($filename, $readerName = 'Word2007')
8991
return $reader->load($filename);
9092
}
9193

94+
/**
95+
* Loads PhpWord ${variable} from file.
96+
*
97+
* @param string $filename The name of the file
98+
*
99+
* @return array The extracted variables
100+
*/
101+
public static function extractVariables(string $filename, string $readerName = 'Word2007'): array
102+
{
103+
/** @var \PhpOffice\PhpWord\Reader\ReaderInterface $reader */
104+
$reader = self::createReader($readerName);
105+
$document = $reader->load($filename);
106+
$extractedVariables = [];
107+
foreach ($document->getSections() as $section) {
108+
$concatenatedText = '';
109+
foreach ($section->getElements() as $element) {
110+
if ($element instanceof TextRun) {
111+
foreach ($element->getElements() as $textElement) {
112+
if ($textElement instanceof Text) {
113+
$text = $textElement->getText();
114+
$concatenatedText .= $text;
115+
}
116+
}
117+
}
118+
}
119+
preg_match_all('/\$\{([^}]+)\}/', $concatenatedText, $matches);
120+
if (!empty($matches[1])) {
121+
foreach ($matches[1] as $match) {
122+
$trimmedMatch = trim($match);
123+
$extractedVariables[] = $trimmedMatch;
124+
}
125+
}
126+
}
127+
128+
return $extractedVariables;
129+
}
130+
92131
/**
93132
* Check if it's a concrete class (not abstract nor interface).
94133
*

src/PhpWord/Shared/Html.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
*/
3939
class Html
4040
{
41+
private const RGB_REGEXP = '/^\s*rgb\s*[(]\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*[)]\s*$/';
42+
4143
protected static $listIndex = 0;
4244

4345
protected static $xpath;
@@ -143,7 +145,7 @@ protected static function parseInlineStyle($node, $styles = [])
143145
break;
144146
case 'bgcolor':
145147
// tables, rows, cells e.g. <tr bgColor="#FF0000">
146-
$styles['bgColor'] = trim($val, '# ');
148+
$styles['bgColor'] = self::convertRgb($val);
147149

148150
break;
149151
case 'valign':
@@ -722,11 +724,11 @@ protected static function parseStyleDeclarations(array $selectors, array $styles
722724

723725
break;
724726
case 'color':
725-
$styles['color'] = trim($value, '#');
727+
$styles['color'] = self::convertRgb($value);
726728

727729
break;
728730
case 'background-color':
729-
$styles['bgColor'] = trim($value, '#');
731+
$styles['bgColor'] = self::convertRgb($value);
730732

731733
break;
732734
case 'line-height':
@@ -1172,4 +1174,13 @@ protected static function parseHorizRule($node, $element): void
11721174
// - line - that is a shape, has different behaviour
11731175
// - repeated text, e.g. underline "_", because of unpredictable line wrapping
11741176
}
1177+
1178+
private static function convertRgb(string $rgb): string
1179+
{
1180+
if (preg_match(self::RGB_REGEXP, $rgb, $matches) === 1) {
1181+
return sprintf('%02X%02X%02X', $matches[1], $matches[2], $matches[3]);
1182+
}
1183+
1184+
return trim($rgb, '# ');
1185+
}
11751186
}

src/PhpWord/Shared/Microsoft/PasswordEncoder.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ class PasswordEncoder
3434
const ALGORITHM_MAC = 'MAC';
3535
const ALGORITHM_HMAC = 'HMAC';
3636

37+
private const ALL_ONE_BITS = (PHP_INT_SIZE > 4) ? 0xFFFFFFFF : -1;
38+
private const HIGH_ORDER_BIT = (PHP_INT_SIZE > 4) ? 0x80000000 : PHP_INT_MIN;
39+
3740
/**
3841
* Mapping between algorithm name and algorithm ID.
3942
*
@@ -128,7 +131,7 @@ public static function hashPassword($password, $algorithmName = self::ALGORITHM_
128131
// build low-order word and hig-order word and combine them
129132
$combinedKey = self::buildCombinedKey($byteChars);
130133
// build reversed hexadecimal string
131-
$hex = str_pad(strtoupper(dechex($combinedKey & 0xFFFFFFFF)), 8, '0', \STR_PAD_LEFT);
134+
$hex = str_pad(strtoupper(dechex($combinedKey & self::ALL_ONE_BITS)), 8, '0', \STR_PAD_LEFT);
132135
$reversedHex = $hex[6] . $hex[7] . $hex[4] . $hex[5] . $hex[2] . $hex[3] . $hex[0] . $hex[1];
133136

134137
$generatedKey = mb_convert_encoding($reversedHex, 'UCS-2LE', 'UTF-8');
@@ -232,10 +235,10 @@ private static function buildCombinedKey($byteChars)
232235
*/
233236
private static function int32($value)
234237
{
235-
$value = ($value & 0xFFFFFFFF);
238+
$value = $value & self::ALL_ONE_BITS;
236239

237-
if ($value & 0x80000000) {
238-
$value = -((~$value & 0xFFFFFFFF) + 1);
240+
if ($value & self::HIGH_ORDER_BIT) {
241+
$value = -((~$value & self::ALL_ONE_BITS) + 1);
239242
}
240243

241244
return $value;

0 commit comments

Comments
 (0)