Files
PhpSpreadsheet/tests/PhpSpreadsheetTests/DocumentGeneratorTest.php
T
oleibman 31174c1c90 Set All Locale Variables at Once in a Threadsafe Manner
Fix #954, which went stale 6 years ago and which I have now reopened. The `setLocale` method in `Calculation` and `Settings` does not affect the 3 localizable properties in `StringHelper` - `currencyCode`, `decimalSeparator`, and `thousandsSeparator`. One way to work around this problem is to set those properties separately; this is probably how most people handle it. Another way is to call Php's own `setlocale` function; this does not require any foreknowledge of what the values need to be, but it comes with baggage (data is maintained at process level rather than thread level), so its use is discouraged.

This PR adds a new `setLocale` method to `StringHelper`. It sets the 3 properties and the `Calculation` language all at once. It depends on the `Intl` extension, which is a recommendation but not a formal requirement for PhpSpreadsheet; the method will return `false` if `Intl` is not available or it thinks the supplied locale is not valid.
2025-12-25 19:24:44 -08:00

206 lines
8.5 KiB
PHP

<?php
declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Category as Cat;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations;
use PhpOffice\PhpSpreadsheetInfra\DocumentGenerator;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use UnexpectedValueException;
class DocumentGeneratorTest extends TestCase
{
private static bool $succeededByName = false;
private static bool $succeededByCategory = false;
/** @param array<string, array{category: string, functionCall: array<string>|string, argumentCount: string, passCellReference?: bool, passByReference?: array<bool>, custom?: bool}> $phpSpreadsheetFunctions */
#[DataProvider('providerGenerateFunctionListByName')]
public function testGenerateFunctionListByName(array $phpSpreadsheetFunctions, string $expected): void
{
self::assertEquals($expected, DocumentGenerator::generateFunctionListByName($phpSpreadsheetFunctions));
self::$succeededByName = true;
}
/** @param array<string, array{category: string, functionCall: array<string>|string, argumentCount: string, passCellReference?: bool, passByReference?: array<bool>, custom?: bool}> $phpSpreadsheetFunctions */
#[DataProvider('providerGenerateFunctionListByCategory')]
public function testGenerateFunctionListByCategory(array $phpSpreadsheetFunctions, string $expected): void
{
self::assertEquals($expected, DocumentGenerator::generateFunctionListByCategory($phpSpreadsheetFunctions));
self::$succeededByCategory = true;
}
public static function providerGenerateFunctionListByName(): array
{
return [
[
[
'ABS' => ['category' => Cat::CATEGORY_MATH_AND_TRIG, 'functionCall' => 'abs', 'argumentCount' => '1'],
'AND' => ['category' => Cat::CATEGORY_LOGICAL, 'functionCall' => [Operations::class, 'logicalAnd'], 'argumentCount' => '2'],
'IFS' => ['category' => Cat::CATEGORY_LOGICAL, 'functionCall' => [Functions::class, 'DUMMY'], 'argumentCount' => '3'],
],
<<<'EXPECTED'
# Function list by name
A more compact list can be found [here](./function-list-by-name-compact.md)
## A
Excel Function | Category | PhpSpreadsheet Function
-------------------------|--------------------------------|--------------------------------------
ABS | CATEGORY_MATH_AND_TRIG | abs
AND | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::logicalAnd
## I
Excel Function | Category | PhpSpreadsheet Function
-------------------------|--------------------------------|--------------------------------------
IFS | CATEGORY_LOGICAL | **Not yet Implemented**
EXPECTED
],
];
}
public static function providerGenerateFunctionListByCategory(): array
{
return [
[
[
'ABS' => ['category' => Cat::CATEGORY_MATH_AND_TRIG, 'functionCall' => 'abs', 'argumentCount' => '1'],
'AND' => ['category' => Cat::CATEGORY_LOGICAL, 'functionCall' => [Operations::class, 'logicalAnd'], 'argumentCount' => '2'],
'IFS' => ['category' => Cat::CATEGORY_LOGICAL, 'functionCall' => [Functions::class, 'DUMMY'], 'argumentCount' => '3'],
],
<<<'EXPECTED'
# Function list by category
## CATEGORY_CUBE
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_DATABASE
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_DATE_AND_TIME
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_ENGINEERING
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_FINANCIAL
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_INFORMATION
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_LOGICAL
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
AND | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::logicalAnd
IFS | **Not yet Implemented**
## CATEGORY_LOOKUP_AND_REFERENCE
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_MATH_AND_TRIG
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
ABS | abs
## CATEGORY_STATISTICAL
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_TEXT_AND_DATA
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_WEB
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_UNCATEGORISED
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
## CATEGORY_MICROSOFT_INTERNAL
Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
EXPECTED
],
];
}
public function testGenerateFunctionBadArray(): void
{
$this->expectException(UnexpectedValueException::class);
$phpSpreadsheetFunctions = [
'ABS' => ['category' => Cat::CATEGORY_MATH_AND_TRIG, 'functionCall' => 1],
];
// Phpstan is right to complain about next line,
// but we still need to make sure it is handled correctly at run time.
DocumentGenerator::generateFunctionListByName(
$phpSpreadsheetFunctions //* @phpstan-ignore-line
);
}
public function testGenerateDocuments(): void
{
if (!self::$succeededByName || !self::$succeededByCategory) {
self::markTestSkipped('Not run because prior test failed');
}
$directory = 'docs/references/';
$phpSpreadsheetFunctions = Calculation::getFunctions();
ksort($phpSpreadsheetFunctions);
self::assertNotFalse(file_put_contents(
$directory . 'function-list-by-category.md',
DocumentGenerator::generateFunctionListByCategory(
$phpSpreadsheetFunctions
)
));
self::assertNotFalse(file_put_contents(
$directory . 'function-list-by-name.md',
DocumentGenerator::generateFunctionListByName(
$phpSpreadsheetFunctions
)
));
self::assertNotFalse(file_put_contents(
$directory . 'function-list-by-name-compact.md',
DocumentGenerator::generateFunctionListByName(
$phpSpreadsheetFunctions,
true
)
));
}
}