Skip to content

Commit 0650e78

Browse files
authored
Merge branch 'master' into issue850
2 parents 8c70086 + 4fc82f4 commit 0650e78

File tree

17 files changed

+123
-68
lines changed

17 files changed

+123
-68
lines changed

.github/workflows/main.yml

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
uses: shivammathur/setup-php@v2
3636
with:
3737
php-version: ${{ matrix.php-version }}
38-
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
38+
extensions: ctype, dom, fileinfo, gd, iconv, intl, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
3939
coverage: none
4040

4141
- name: Get composer cache directory
@@ -82,7 +82,7 @@ jobs:
8282
uses: shivammathur/setup-php@v2
8383
with:
8484
php-version: 8.4
85-
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
85+
extensions: ctype, dom, fileinfo, gd, iconv, intl, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
8686
coverage: none
8787

8888
# This is non-ideal because it only checks for the last commit of the PR, not all of them, but better than nothing
@@ -99,7 +99,7 @@ jobs:
9999
uses: shivammathur/setup-php@v2
100100
with:
101101
php-version: 8.4
102-
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
102+
extensions: ctype, dom, fileinfo, gd, iconv, intl, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
103103
coverage: none
104104
tools: cs2pr
105105

@@ -130,7 +130,7 @@ jobs:
130130
uses: shivammathur/setup-php@v2
131131
with:
132132
php-version: 8.4
133-
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
133+
extensions: ctype, dom, fileinfo, gd, iconv, intl, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
134134
coverage: none
135135
tools: cs2pr
136136

@@ -161,7 +161,7 @@ jobs:
161161
uses: shivammathur/setup-php@v2
162162
with:
163163
php-version: 8.4
164-
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
164+
extensions: ctype, dom, fileinfo, gd, iconv, intl, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
165165
coverage: none
166166
tools: cs2pr
167167

@@ -192,7 +192,7 @@ jobs:
192192
uses: shivammathur/setup-php@v2
193193
with:
194194
php-version: 8.4
195-
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
195+
extensions: ctype, dom, fileinfo, gd, iconv, intl, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
196196
coverage: none
197197
tools: cs2pr
198198

@@ -231,7 +231,7 @@ jobs:
231231
uses: shivammathur/setup-php@v2
232232
with:
233233
php-version: 8.4
234-
extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
234+
extensions: ctype, dom, fileinfo, gd, iconv, intl, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib
235235
coverage: pcov
236236

237237
- name: Get composer cache directory
@@ -254,11 +254,12 @@ jobs:
254254
255255
- name: Upload coverage results to Coveralls
256256
env:
257-
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
258-
run: |
259-
wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.4.3/php-coveralls.phar
260-
chmod +x php-coveralls.phar
261-
php php-coveralls.phar --coverage_clover=build/clover.xml --json_path=build/coveralls-upload.json -vvv
257+
FAILURE_ACTION: "${{ true }}"
258+
uses: coverallsapp/github-action@v2
259+
with:
260+
github-token: ${{ secrets.GITHUB_TOKEN }}
261+
file: build/clover.xml
262+
format: clover
262263

263264
release:
264265
permissions:

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). Thia is a
3737
- Wrapped cells and default row height. [Issue #4584](https://github.com/PHPOffice/PhpSpreadsheet/issues/4584) [PR #4645](https://github.com/PHPOffice/PhpSpreadsheet/pull/4645)
3838
- For Php8.5, replace one of our two uses of `__wakeup` with `__unserialize`, and eliminate the other. [PR #4639](https://github.com/PHPOffice/PhpSpreadsheet/pull/4639)
3939
- Use prefix _xlfn for BASE function. [Issue #4638](https://github.com/PHPOffice/PhpSpreadsheet/issues/4638) [PR #4641](https://github.com/PHPOffice/PhpSpreadsheet/pull/4641)
40+
- Warning messages with corrupt Xls file. [Issue #4647](https://github.com/PHPOffice/PhpSpreadsheet/issues/4647) [PR #4648](https://github.com/PHPOffice/PhpSpreadsheet/pull/4648)
4041
- Additional support for union and intersection. [PR #4596](https://github.com/PHPOffice/PhpSpreadsheet/pull/4596)
4142

4243
## 2025-09-03 - 5.1.0

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
"tecnickcom/tcpdf": "^6.5"
104104
},
105105
"suggest": {
106-
"ext-intl": "PHP Internationalization Functions",
106+
"ext-intl": "PHP Internationalization Functions, regquired for NumberFormat Wizard",
107107
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
108108
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
109109
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer",

composer.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/topics/Behind the Mask.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ But if we use the "pull down" for that block, we access the "Number" tab of "For
194194
This gives us access to a number of "Wizards" for different "Categories" of masking, as well as "Custom", which allows us to build our own masks.
195195

196196
Since version 1.28.0, PhpSpreadsheet has also provided a set of "Wizards", allowing for the easier creation of Mask values for most Categories.
197+
In many cases, you will need to enable PHP's `Intl` extension in order to use the Wizards.
197198

198199
## Mask Categories
199200

@@ -232,7 +233,7 @@ var_dump($worksheet->getCell('C20')
232233
var_dump($worksheet->getCell('C20')->getFormattedValue()); // "-12,345.679"
233234
```
234235

235-
PhpSpreadsheet's "Wizard" doesn't yet offer options for displaying negative values; they will simply be masked so that they always display the sign.
236+
PhpSpreadsheet's Number Wizard doesn't yet offer options for displaying negative values; they will simply be masked so that they always display the sign.
236237
But alternative masking for negative values is an option that may be added in the future.
237238

238239
### Currency
@@ -245,6 +246,7 @@ The "Symbol" dropdown provides a lot of locale-specific variants of the same cur
245246

246247
The PhpSpreadsheet Currency "Wizard" allows you to specify the currency code, number of decimals, and the use of a thousands separator.
247248
In addition, optionally, you can also specify whether the currency symbol should be leading or trailing, and whether it should be separated from the value or not.
249+
Finally, you have a choice of 4 ways of specifying negative values - minus sign, minus sign with the field in red, parentheses, and parentheses with the field in red.
248250

249251
```php
250252
use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Currency;
@@ -302,9 +304,6 @@ var_dump($worksheet->getCell('C21')->getFormattedValue()); // -12,345.68 €
302304
If we use the locale in the "Wizard", then a typical mask might look like '#,##0.00 [$€-de-DE]', with the currency wrapped in braces, a `$` to indicate that this is a localised value, and the locale included.
303305
> Note: The Wizard does not accept LCIDs.
304306
305-
PhpSpreadsheet's "Wizard" doesn't yet offer options for displaying negative values; they will simply be masked so that they always display the sign.
306-
But alternative masking for negative values is an option that may be added in the future.
307-
308307
### Accounting
309308

310309
Excel's Accounting "Wizard" is like the Currency "Wizard", but without the options for presenting negative values.
@@ -340,7 +339,6 @@ var_dump($worksheet->getCell('C20')->getFormattedValue()); // -12,345.68 €
340339
```
341340
A typical Accounting mask might look something like '_-#,##0.00 €*_-', with the currency symbol as a literal; and with placement indicators like `_-`, that ensure the alignment of the currency symbols and decimal points of numbers in a column.
342341

343-
At the moment, none of the PhpSpreadsheet Wizards provide different masks for zero and negative values; unless you have the PHP `Intl` extension enabled, and can use the locale to generate the Mask.
344342
As with using a locale with the Currency "Wizard", when you use a locale with the Accounting "Wizard" the locale value must be valid, and any additional options will be ignored.
345343
```php
346344
use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Accounting;
@@ -391,8 +389,6 @@ I've written in detail about Date Format Masks elsewhere in "The Dating Game"; b
391389
| yyyy | Year (4 digits) | 2023 |
392390

393391

394-
There is currently no PhpSpreadsheet "Wizard" for Date Masks; but this will be introduced in the 1.29.0 release.
395-
396392
### Time
397393

398394
As with Dates, when you use the Excel Time "Wizard", you can select a locale and you'll then be presented with a number of time format options that are appropriate for that locale.
@@ -411,7 +407,7 @@ I've written in detail about Time Format Masks elsewhere in "The Dating Game"; b
411407
| ss | Seconds with a leading zero | 00-59 |
412408
| AM/PM | Periods of the day <br/>(if omitted, 24-hour time format is used) | AM or PM |
413409

414-
Excel also supports Masks for Time Durations, although there is no "Wizard" for this; but the following Mask codes can be used to display Durations.
410+
Excel also supports Masks for Time Durations (note that spreadsheets using the 1904 base date can display negative durations, but those using the 1900 base date cannot). There is no "Wizard" for this; but the following Mask codes can be used to display Durations.
415411

416412
| Code | Description | Displays as |
417413
|---------|----------------------------------------------------------------|-------------|
@@ -422,8 +418,6 @@ Excel also supports Masks for Time Durations, although there is no "Wizard" for
422418
| [s] | Elapsed time in seconds | |
423419
| [ss] | Elapsed time in seconds<br>with a leading zero if less than 10 | |
424420

425-
There is currently no PhpSpreadsheet "Wizard" for Time Masks, or for Durations; but these will be introduced in the 1.29.0 release.
426-
427421
### Percentage
428422

429423
This is among the simplest of the Excel "Wizards", only allowing you to specify the number of decimals to be displayed.

src/PhpSpreadsheet/Reader/XlsBase.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,20 @@ protected function decodeCodepage(string $string): string
368368
return StringHelper::convertEncoding($string, 'UTF-8', $this->codepage);
369369
}
370370

371+
protected static function confirmPos(string $data, int $pos): void
372+
{
373+
if ($pos >= strlen($data)) {
374+
throw new PhpSpreadsheetException('File appears to be corrupt'); // @codeCoverageIgnore
375+
}
376+
}
377+
371378
/**
372379
* Read 16-bit unsigned integer.
373380
*/
374381
public static function getUInt2d(string $data, int $pos): int
375382
{
383+
self::confirmPos($data, $pos + 1);
384+
376385
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8);
377386
}
378387

@@ -381,6 +390,8 @@ public static function getUInt2d(string $data, int $pos): int
381390
*/
382391
public static function getInt2d(string $data, int $pos): int
383392
{
393+
self::confirmPos($data, $pos + 1);
394+
384395
return unpack('s', $data[$pos] . $data[$pos + 1])[1]; // @phpstan-ignore-line
385396
}
386397

@@ -389,6 +400,8 @@ public static function getInt2d(string $data, int $pos): int
389400
*/
390401
public static function getInt4d(string $data, int $pos): int
391402
{
403+
self::confirmPos($data, $pos + 3);
404+
392405
// FIX: represent numbers correctly on 64-bit system
393406
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
394407
// Changed by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems

src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@ final class Locale
1919

2020
public function __construct(?string $locale, int $style)
2121
{
22-
if (class_exists(NumberFormatter::class) === false) {
23-
throw new Exception();
24-
}
25-
2622
$formatterLocale = str_replace('-', '_', $locale ?? '');
2723
$this->formatter = new NumberFormatter($formatterLocale, $style);
2824
if ($this->formatter->getLocale() !== $formatterLocale) {

src/PhpSpreadsheet/Writer/Pdf/Dompdf.php

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,43 +44,15 @@ public function save($filename, int $flags = 0): void
4444
$orientation = ($orientation == 'L') ? 'landscape' : 'portrait';
4545

4646
// Create PDF
47-
$restoreHandler = false;
48-
if (PHP_VERSION_ID >= self::$temporaryVersionCheck) {
49-
// @codeCoverageIgnoreStart
50-
set_error_handler(self::specialErrorHandler(...));
51-
$restoreHandler = true;
52-
// @codeCoverageIgnoreEnd
53-
}
5447
$pdf = $this->createExternalWriterInstance();
5548
$pdf->setPaper($paperSize, $orientation);
5649

5750
$pdf->loadHtml($this->generateHTMLAll());
5851
$pdf->render();
5952

6053
// Write to file
61-
fwrite($fileHandle, $pdf->output() ?? '');
54+
fwrite($fileHandle, $pdf->output());
6255

63-
if ($restoreHandler) {
64-
restore_error_handler(); // @codeCoverageIgnore
65-
}
6656
parent::restoreStateAfterSave();
6757
}
68-
69-
protected static int $temporaryVersionCheck = 80500;
70-
71-
/**
72-
* Temporary handler for Php8.5 waiting for Dompdf release.
73-
*
74-
* @codeCoverageIgnore
75-
*/
76-
public function specialErrorHandler(int $errno, string $errstr, string $filename, int $lineno): bool
77-
{
78-
if ($errno === E_DEPRECATED) {
79-
if (preg_match('/canonical|imagedestroy|http_get_last_response_headers|Using null as an array offset/', $errstr) === 1) {
80-
return true;
81-
}
82-
}
83-
84-
return false; // continue error handling
85-
}
8658
}

tests/PhpSpreadsheetTests/Style/NumberFormat/Wizard/AccountingTest.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Currency;
1212
use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\CurrencyNegative;
1313
use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Number;
14+
use PHPUnit\Framework\Attributes\DataProvider;
1415
use PHPUnit\Framework\TestCase;
16+
use ReflectionMethod;
1517

1618
class AccountingTest extends TestCase
1719
{
18-
#[\PHPUnit\Framework\Attributes\DataProvider('providerAccounting')]
20+
#[DataProvider('providerAccounting')]
1921
public function testAccounting(
2022
string $expectedResultPositive,
2123
string $expectedResultNegative,
@@ -45,7 +47,7 @@ public static function providerAccounting(): array
4547
];
4648
}
4749

48-
#[\PHPUnit\Framework\Attributes\DataProvider('providerAccountingLocale')]
50+
#[DataProvider('providerAccountingLocale')]
4951
public function testAccountingLocale(
5052
string $expectedResult,
5153
string $currencyCode,
@@ -105,7 +107,7 @@ public function testIcu721(): void
105107
}
106108
}
107109

108-
#[\PHPUnit\Framework\Attributes\DataProvider('providerAccountingLocaleNoDecimals')]
110+
#[DataProvider('providerAccountingLocaleNoDecimals')]
109111
public function testAccountingLocaleNoDecimals(
110112
string $expectedResult,
111113
string $currencyCode,
@@ -170,4 +172,12 @@ public function testAccountingLocaleInvalidCode(): void
170172
$wizard = new Accounting('');
171173
$wizard->setLocale($locale);
172174
}
175+
176+
public function testLocaleNull2(): void
177+
{
178+
$wizard = new Accounting('$', 2);
179+
$reflectionMethod = new ReflectionMethod($wizard, 'formatCurrencyCode');
180+
$result = $reflectionMethod->invokeArgs($wizard, []);
181+
self::assertSame('$*', $result);
182+
}
173183
}

0 commit comments

Comments
 (0)