mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-10-07 12:27:43 +00:00
84747121a1
This PR started because the documentation on how to configure an Http client was out of date. However, as I investigated further, I found problems. GuzzleHttp, a client mentioned in the documentation, for example - it probably works fine when executed from a browser, but it does not work for `https:` requests from the Windows command line. See https://github.com/guzzle/guzzle/issues/2601, where a user notes that Guzzle's own program to demonstrate how to use it doesn't work, a result that I can confirm is still true. A linked explanation says that the solution is to explicitly specify a path to a CA bundle. For starters, this is impractical from our perspective. One possible solution is to change a php.ini option which is not needed for any other purpose, and which probably needs to change frequently - a burden on users who follow that route. An alternative solution is to use a method `request` to specify the path to the certificate store; this also will need to change from time to time, and, worse, the only method defined in ClientInterface is `sendRequest`, so using this solution isn't client-agnostic, which is a stated goal of https://github.com/PHPOffice/PhpSpreadsheet/commit/7cb4884b96174eb611621635e6fb603ef54178f7. Additionally, it is not clear why an external interface is needed rather than a call to file_get_contents, used elsewhere in PhpSpreadsheet, and not requiring a path to a certificate store. I also believe that automatically evaluating WEBSERVICE for any arbitrary argument is not a good idea. I am adding a domain whitelist which the user must populate. For domains not in the whitelist, the calculation will revert to `oldCalculatedValue`, which is good enough for pass-through purposes, which probably encompasses most cases. That is how Excel behaves by default - it disables WEBSERVICE calls when it opens a spreadsheet which contains them. For cases where the user adds a new WEBSERVICE call, there is a choice of whitelisting the domain, or getting the result in some other way and using `setCalculatedValue` to store it. Finally, when a WEBSERVICE call *is* evaluated, it will now accept a cell-address argument rather than just a literal string as is now the case.
87 lines
2.9 KiB
PHP
87 lines
2.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Web;
|
|
|
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
|
use PhpOffice\PhpSpreadsheet\Settings;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use PHPUnit\Framework\Attributes\DataProvider;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class WebServiceTest extends TestCase
|
|
{
|
|
private ?Spreadsheet $spreadsheet = null;
|
|
|
|
private const WHITELIST = [
|
|
'www.example.com',
|
|
'www.google.com',
|
|
'www.invalid.com',
|
|
];
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
Settings::setDomainWhiteList([]);
|
|
if ($this->spreadsheet !== null) {
|
|
$this->spreadsheet->disconnectWorksheets();
|
|
$this->spreadsheet = null;
|
|
}
|
|
}
|
|
|
|
#[DataProvider('providerWEBSERVICE')]
|
|
public function testWEBSERVICE(string $expectedResult, string $url): void
|
|
{
|
|
if (str_starts_with($url, 'https') && getenv('SKIP_URL_IMAGE_TEST') === '1') {
|
|
self::markTestSkipped('Skipped due to setting of environment variable');
|
|
}
|
|
Settings::setDomainWhiteList(self::WHITELIST);
|
|
$this->spreadsheet = new Spreadsheet();
|
|
$sheet = $this->spreadsheet->getActiveSheet();
|
|
$sheet->getCell('Z1')->setValue('http://www.example.com');
|
|
$sheet->getCell('Z2')->setValue(2);
|
|
if (str_starts_with($url, 'Z')) {
|
|
$sheet->getCell('A1')->setValue("=WEBSERVICE($url)");
|
|
} else {
|
|
$sheet->getCell('A1')->setValue("=WEBSERVICE(\"$url\")");
|
|
}
|
|
$result = $sheet->getCell('A1')->getCalculatedValue();
|
|
self::assertStringContainsString($expectedResult, $result);
|
|
}
|
|
|
|
public static function providerWEBSERVICE(): array
|
|
{
|
|
return require 'tests/data/Calculation/Web/WEBSERVICE.php';
|
|
}
|
|
|
|
public function testOldCalculated(): void
|
|
{
|
|
Settings::setDomainWhiteList(self::WHITELIST);
|
|
$reader = new XlsxReader();
|
|
$this->spreadsheet = $reader->load('tests/data/Reader/Xlsx/fakewebservice.xlsx');
|
|
$sheet = $this->spreadsheet->getActiveSheet();
|
|
$a1Formula = $sheet->getCell('A1')->getValue();
|
|
self::assertSame(
|
|
'=WEBSERVICE("http://www.phonydomain.com")', // not in whitelist
|
|
$a1Formula
|
|
);
|
|
self::assertSame(
|
|
'phony result',
|
|
$sheet->getCell('A1')->getCalculatedValue(),
|
|
'result should be oldCalculatedValue'
|
|
);
|
|
$sheet->getCell('A2')->setValue($a1Formula);
|
|
self::assertNull(
|
|
$sheet->getCell('A2')->getCalculatedValue(),
|
|
'no oldCalculatedValue to fall back on'
|
|
);
|
|
$sheet->getCell('A3')->setValue($a1Formula);
|
|
$sheet->getCell('A3')->setCalculatedValue('random string');
|
|
self::assertSame(
|
|
'random string',
|
|
$sheet->getCell('A3')->getCalculatedValue(),
|
|
'oldCalculatedValue explicitly set above'
|
|
);
|
|
}
|
|
}
|